[SPIR-V] Instruction predication
This commit is contained in:
parent
556c8de2ab
commit
1c83c8dcfa
|
@ -827,6 +827,51 @@ void SpirvShaderTranslator::UpdateExecConditionals(
|
|||
builder_->setBuildPoint(&inner_block);
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::UpdateInstructionPredication(bool predicated,
|
||||
bool condition) {
|
||||
if (!predicated) {
|
||||
CloseInstructionPredication();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cf_instruction_predicate_merge_) {
|
||||
if (cf_instruction_predicate_condition_ == condition) {
|
||||
// Already in the needed instruction-level conditional.
|
||||
return;
|
||||
}
|
||||
CloseInstructionPredication();
|
||||
}
|
||||
|
||||
// If the instruction predicate condition is the same as the exec predicate
|
||||
// condition, no need to open a check. However, if there was a `setp` prior
|
||||
// to this instruction, the predicate value now may be different than it was
|
||||
// in the beginning of the exec.
|
||||
if (!cf_exec_predicate_written_ && cf_exec_conditional_merge_ &&
|
||||
cf_exec_bool_constant_or_predicate_ == kCfExecBoolConstantPredicate &&
|
||||
cf_exec_condition_ == condition) {
|
||||
return;
|
||||
}
|
||||
|
||||
cf_instruction_predicate_condition_ = condition;
|
||||
EnsureBuildPointAvailable();
|
||||
spv::Id predicate_id =
|
||||
builder_->createLoad(var_main_predicate_, spv::NoPrecision);
|
||||
spv::Block& predicated_block = builder_->makeNewBlock();
|
||||
cf_instruction_predicate_merge_ = &builder_->makeNewBlock();
|
||||
{
|
||||
std::unique_ptr<spv::Instruction> selection_merge_op =
|
||||
std::make_unique<spv::Instruction>(spv::OpSelectionMerge);
|
||||
selection_merge_op->addIdOperand(cf_instruction_predicate_merge_->getId());
|
||||
selection_merge_op->addImmediateOperand(spv::SelectionControlMaskNone);
|
||||
builder_->getBuildPoint()->addInstruction(std::move(selection_merge_op));
|
||||
}
|
||||
builder_->createConditionalBranch(
|
||||
predicate_id,
|
||||
condition ? &predicated_block : cf_instruction_predicate_merge_,
|
||||
condition ? cf_instruction_predicate_merge_ : &predicated_block);
|
||||
builder_->setBuildPoint(&predicated_block);
|
||||
}
|
||||
|
||||
void SpirvShaderTranslator::CloseInstructionPredication() {
|
||||
if (!cf_instruction_predicate_merge_) {
|
||||
return;
|
||||
|
|
|
@ -66,6 +66,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
const ParsedLoopEndInstruction& instr) override;
|
||||
void ProcessJumpInstruction(const ParsedJumpInstruction& instr) override;
|
||||
|
||||
void ProcessAluInstruction(const ParsedAluInstruction& instr) override;
|
||||
|
||||
private:
|
||||
// TODO(Triang3l): Depth-only pixel shader.
|
||||
bool IsSpirvVertexOrTessEvalShader() const { return is_vertex_shader(); }
|
||||
|
@ -96,6 +98,9 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
|||
// needed (for example, in jumps).
|
||||
void UpdateExecConditionals(ParsedExecInstruction::Type type,
|
||||
uint32_t bool_constant_index, bool condition);
|
||||
// Opens or reopens the predicate check conditional for the instruction.
|
||||
// Should be called before processing a non-control-flow instruction.
|
||||
void UpdateInstructionPredication(bool predicated, bool condition);
|
||||
// Closes the instruction-level predicate conditional if it's open, useful if
|
||||
// a control flow instruction needs to do some code which needs to respect the
|
||||
// current exec conditional, but can't itself be predicated.
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/gpu/spirv_shader_translator.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
void SpirvShaderTranslator::ProcessAluInstruction(
|
||||
const ParsedAluInstruction& instr) {
|
||||
if (instr.IsNop()) {
|
||||
// Don't even disassemble or update predication.
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateInstructionPredication(instr.is_predicated, instr.predicate_condition);
|
||||
|
||||
// TODO(Triang3l): Translate the ALU instruction.
|
||||
}
|
||||
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
Loading…
Reference in New Issue