[SPIR-V] Operand loading
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "xenia/gpu/spirv_shader_translator.h"
|
||||
|
||||
#include "xenia/base/math.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
||||
@@ -21,7 +23,77 @@ void SpirvShaderTranslator::ProcessAluInstruction(
|
||||
|
||||
UpdateInstructionPredication(instr.is_predicated, instr.predicate_condition);
|
||||
|
||||
// TODO(Triang3l): Translate the ALU instruction.
|
||||
// Floating-point arithmetic operations (addition, subtraction, negation,
|
||||
// multiplication, dot product, division, modulo - see isArithmeticOperation
|
||||
// in propagateNoContraction of glslang) must have the NoContraction
|
||||
// decoration to prevent reordering to make sure floating-point calculations
|
||||
// are optimized predictably and exactly the same in different shaders to
|
||||
// allow for multipass rendering (in addition to the Invariant decoration on
|
||||
// outputs).
|
||||
|
||||
// Whether the instruction has changed the predicate, and it needs to be
|
||||
// checked again later.
|
||||
bool predicate_written_vector = false;
|
||||
ProcessVectorAluOperation(instr, predicate_written_vector);
|
||||
// TODO(Triang3l): Process the ALU scalar operation.
|
||||
|
||||
if (predicate_written_vector) {
|
||||
cf_exec_predicate_written_ = true;
|
||||
CloseInstructionPredication();
|
||||
}
|
||||
}
|
||||
|
||||
spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
|
||||
const ParsedAluInstruction& instr, bool& predicate_written) {
|
||||
predicate_written = false;
|
||||
|
||||
uint32_t used_result_components =
|
||||
instr.vector_and_constant_result.GetUsedResultComponents();
|
||||
if (!used_result_components &&
|
||||
!AluVectorOpHasSideEffects(instr.vector_opcode)) {
|
||||
return spv::NoResult;
|
||||
}
|
||||
uint32_t used_result_component_count = xe::bit_count(used_result_components);
|
||||
|
||||
// Load operand storage without swizzle and sign modifiers.
|
||||
// A small shortcut, operands of cube are the same, but swizzled.
|
||||
uint32_t operand_count;
|
||||
if (instr.vector_opcode == ucode::AluVectorOpcode::kCube) {
|
||||
operand_count = 1;
|
||||
} else {
|
||||
operand_count = instr.vector_operand_count;
|
||||
}
|
||||
spv::Id operand_storage[3] = {};
|
||||
for (uint32_t i = 0; i < operand_count; ++i) {
|
||||
operand_storage[i] = LoadOperandStorage(instr.vector_operands[i]);
|
||||
}
|
||||
spv::Id result_vector_type =
|
||||
used_result_component_count
|
||||
? type_float_vectors_[used_result_component_count - 1]
|
||||
: spv::NoType;
|
||||
|
||||
// In case the paired scalar instruction (if processed first) terminates the
|
||||
// block (like via OpKill).
|
||||
EnsureBuildPointAvailable();
|
||||
|
||||
switch (instr.vector_opcode) {
|
||||
case ucode::AluVectorOpcode::kAdd: {
|
||||
spv::Id result = builder_->createBinOp(
|
||||
spv::OpFAdd, result_vector_type,
|
||||
GetOperandComponents(operand_storage[0], instr.vector_operands[0],
|
||||
used_result_components),
|
||||
GetOperandComponents(operand_storage[1], instr.vector_operands[1],
|
||||
used_result_components));
|
||||
builder_->addDecoration(result, spv::DecorationNoContraction);
|
||||
return result;
|
||||
} break;
|
||||
// TODO(Triang3l): Handle all instructions.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Invalid instruction.
|
||||
return spv::NoResult;
|
||||
}
|
||||
|
||||
} // namespace gpu
|
||||
|
||||
Reference in New Issue
Block a user