mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
[SPIR-V] Instruction predication
This commit is contained in:
parent
556c8de2ab
commit
1c83c8dcfa
|
|
@ -827,6 +827,51 @@ void SpirvShaderTranslator::UpdateExecConditionals(
|
||||||
builder_->setBuildPoint(&inner_block);
|
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() {
|
void SpirvShaderTranslator::CloseInstructionPredication() {
|
||||||
if (!cf_instruction_predicate_merge_) {
|
if (!cf_instruction_predicate_merge_) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||||
const ParsedLoopEndInstruction& instr) override;
|
const ParsedLoopEndInstruction& instr) override;
|
||||||
void ProcessJumpInstruction(const ParsedJumpInstruction& instr) override;
|
void ProcessJumpInstruction(const ParsedJumpInstruction& instr) override;
|
||||||
|
|
||||||
|
void ProcessAluInstruction(const ParsedAluInstruction& instr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO(Triang3l): Depth-only pixel shader.
|
// TODO(Triang3l): Depth-only pixel shader.
|
||||||
bool IsSpirvVertexOrTessEvalShader() const { return is_vertex_shader(); }
|
bool IsSpirvVertexOrTessEvalShader() const { return is_vertex_shader(); }
|
||||||
|
|
@ -96,6 +98,9 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||||
// needed (for example, in jumps).
|
// needed (for example, in jumps).
|
||||||
void UpdateExecConditionals(ParsedExecInstruction::Type type,
|
void UpdateExecConditionals(ParsedExecInstruction::Type type,
|
||||||
uint32_t bool_constant_index, bool condition);
|
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
|
// 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
|
// a control flow instruction needs to do some code which needs to respect the
|
||||||
// current exec conditional, but can't itself be predicated.
|
// current exec conditional, but can't itself be predicated.
|
||||||
|
|
|
||||||
28
src/xenia/gpu/spirv_shader_translator_alu.cc
Normal file
28
src/xenia/gpu/spirv_shader_translator_alu.cc
Normal file
|
|
@ -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 a new issue