SPIR-V: Batch predicated instructions together into a single block.
Add Post-Translation validation. Fix a couple of type-related typos.
This commit is contained in:
parent
a1c9540063
commit
b7f2c93d73
|
@ -986,16 +986,19 @@ void ShaderTranslator::TranslateAluInstruction(const AluInstruction& op) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParsedAluInstruction instr;
|
||||||
if (op.has_vector_op()) {
|
if (op.has_vector_op()) {
|
||||||
const auto& opcode_info =
|
const auto& opcode_info =
|
||||||
alu_vector_opcode_infos_[static_cast<int>(op.vector_opcode())];
|
alu_vector_opcode_infos_[static_cast<int>(op.vector_opcode())];
|
||||||
ParseAluVectorInstruction(op, opcode_info);
|
ParseAluVectorInstruction(op, opcode_info, instr);
|
||||||
|
ProcessAluInstruction(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op.has_scalar_op()) {
|
if (op.has_scalar_op()) {
|
||||||
const auto& opcode_info =
|
const auto& opcode_info =
|
||||||
alu_scalar_opcode_infos_[static_cast<int>(op.scalar_opcode())];
|
alu_scalar_opcode_infos_[static_cast<int>(op.scalar_opcode())];
|
||||||
ParseAluScalarInstruction(op, opcode_info);
|
ParseAluScalarInstruction(op, opcode_info, instr);
|
||||||
|
ProcessAluInstruction(instr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1088,8 +1091,8 @@ void ParseAluInstructionOperandSpecial(const AluInstruction& op,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderTranslator::ParseAluVectorInstruction(
|
void ShaderTranslator::ParseAluVectorInstruction(
|
||||||
const AluInstruction& op, const AluOpcodeInfo& opcode_info) {
|
const AluInstruction& op, const AluOpcodeInfo& opcode_info,
|
||||||
ParsedAluInstruction i;
|
ParsedAluInstruction& i) {
|
||||||
i.dword_index = 0;
|
i.dword_index = 0;
|
||||||
i.type = ParsedAluInstruction::Type::kVector;
|
i.type = ParsedAluInstruction::Type::kVector;
|
||||||
i.vector_opcode = op.vector_opcode();
|
i.vector_opcode = op.vector_opcode();
|
||||||
|
@ -1203,13 +1206,11 @@ void ShaderTranslator::ParseAluVectorInstruction(
|
||||||
}
|
}
|
||||||
|
|
||||||
i.Disassemble(&ucode_disasm_buffer_);
|
i.Disassemble(&ucode_disasm_buffer_);
|
||||||
|
|
||||||
ProcessAluInstruction(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderTranslator::ParseAluScalarInstruction(
|
void ShaderTranslator::ParseAluScalarInstruction(
|
||||||
const AluInstruction& op, const AluOpcodeInfo& opcode_info) {
|
const AluInstruction& op, const AluOpcodeInfo& opcode_info,
|
||||||
ParsedAluInstruction i;
|
ParsedAluInstruction& i) {
|
||||||
i.dword_index = 0;
|
i.dword_index = 0;
|
||||||
i.type = ParsedAluInstruction::Type::kScalar;
|
i.type = ParsedAluInstruction::Type::kScalar;
|
||||||
i.scalar_opcode = op.scalar_opcode();
|
i.scalar_opcode = op.scalar_opcode();
|
||||||
|
@ -1319,8 +1320,6 @@ void ShaderTranslator::ParseAluScalarInstruction(
|
||||||
}
|
}
|
||||||
|
|
||||||
i.Disassemble(&ucode_disasm_buffer_);
|
i.Disassemble(&ucode_disasm_buffer_);
|
||||||
|
|
||||||
ProcessAluInstruction(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gpu
|
} // namespace gpu
|
||||||
|
|
|
@ -173,9 +173,11 @@ class ShaderTranslator {
|
||||||
|
|
||||||
void TranslateAluInstruction(const ucode::AluInstruction& op);
|
void TranslateAluInstruction(const ucode::AluInstruction& op);
|
||||||
void ParseAluVectorInstruction(const ucode::AluInstruction& op,
|
void ParseAluVectorInstruction(const ucode::AluInstruction& op,
|
||||||
const AluOpcodeInfo& opcode_info);
|
const AluOpcodeInfo& opcode_info,
|
||||||
|
ParsedAluInstruction& instr);
|
||||||
void ParseAluScalarInstruction(const ucode::AluInstruction& op,
|
void ParseAluScalarInstruction(const ucode::AluInstruction& op,
|
||||||
const AluOpcodeInfo& opcode_info);
|
const AluOpcodeInfo& opcode_info,
|
||||||
|
ParsedAluInstruction& instr);
|
||||||
|
|
||||||
// Input shader metadata and microcode.
|
// Input shader metadata and microcode.
|
||||||
ShaderType shader_type_;
|
ShaderType shader_type_;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
* Copyright 2016 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
@ -85,16 +85,14 @@ void SpirvShaderTranslator::StartTranslation() {
|
||||||
"ps");
|
"ps");
|
||||||
pv_ = b.createVariable(spv::StorageClass::StorageClassFunction,
|
pv_ = b.createVariable(spv::StorageClass::StorageClassFunction,
|
||||||
vec4_float_type_, "pv");
|
vec4_float_type_, "pv");
|
||||||
a0_ = b.createVariable(spv::StorageClass::StorageClassFunction,
|
a0_ = b.createVariable(spv::StorageClass::StorageClassFunction, int_type_,
|
||||||
b.makeUintType(32), "a0");
|
"a0");
|
||||||
|
|
||||||
// Uniform constants.
|
// Uniform constants.
|
||||||
Id float_consts_type =
|
Id float_consts_type =
|
||||||
b.makeArrayType(vec4_float_type_, b.makeUintConstant(512), 1);
|
b.makeArrayType(vec4_float_type_, b.makeUintConstant(512), 1);
|
||||||
Id loop_consts_type =
|
Id loop_consts_type = b.makeArrayType(uint_type_, b.makeUintConstant(32), 1);
|
||||||
b.makeArrayType(b.makeUintType(32), b.makeUintConstant(32), 1);
|
Id bool_consts_type = b.makeArrayType(uint_type_, b.makeUintConstant(8), 1);
|
||||||
Id bool_consts_type =
|
|
||||||
b.makeArrayType(b.makeUintType(32), b.makeUintConstant(8), 1);
|
|
||||||
|
|
||||||
Id consts_struct_type = b.makeStructType(
|
Id consts_struct_type = b.makeStructType(
|
||||||
{float_consts_type, loop_consts_type, bool_consts_type}, "consts_type");
|
{float_consts_type, loop_consts_type, bool_consts_type}, "consts_type");
|
||||||
|
@ -242,6 +240,13 @@ void SpirvShaderTranslator::StartTranslation() {
|
||||||
interpolators_ = b.createVariable(spv::StorageClass::StorageClassOutput,
|
interpolators_ = b.createVariable(spv::StorageClass::StorageClassOutput,
|
||||||
interpolators_type, "interpolators");
|
interpolators_type, "interpolators");
|
||||||
b.addDecoration(interpolators_, spv::Decoration::DecorationLocation, 0);
|
b.addDecoration(interpolators_, spv::Decoration::DecorationLocation, 0);
|
||||||
|
for (uint32_t i = 0; i < 16; i++) {
|
||||||
|
// Zero interpolators.
|
||||||
|
auto ptr = b.createAccessChain(spv::StorageClass::StorageClassOutput,
|
||||||
|
interpolators_,
|
||||||
|
std::vector<Id>({b.makeUintConstant(i)}));
|
||||||
|
b.createStore(vec4_float_zero_, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
pos_ = b.createVariable(spv::StorageClass::StorageClassOutput,
|
pos_ = b.createVariable(spv::StorageClass::StorageClassOutput,
|
||||||
vec4_float_type_, "gl_Position");
|
vec4_float_type_, "gl_Position");
|
||||||
|
@ -338,6 +343,9 @@ void SpirvShaderTranslator::StartTranslation() {
|
||||||
std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
|
std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
|
||||||
auto& b = *builder_;
|
auto& b = *builder_;
|
||||||
|
|
||||||
|
assert_false(open_predicated_block_);
|
||||||
|
auto block = &b.makeNewBlock();
|
||||||
|
b.createBranch(block);
|
||||||
b.makeReturn(false);
|
b.makeReturn(false);
|
||||||
|
|
||||||
// main() entry point.
|
// main() entry point.
|
||||||
|
@ -397,9 +405,10 @@ std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
|
||||||
b.createStore(p, pos_);
|
b.createStore(p, pos_);
|
||||||
} else {
|
} else {
|
||||||
// Alpha test
|
// Alpha test
|
||||||
auto alpha_test_x = b.createCompositeExtract(
|
auto alpha_test_x = b.createCompositeExtract(push_consts_, float_type_,
|
||||||
push_consts_, float_type_, std::vector<uint32_t>{2, 0});
|
std::vector<uint32_t>{2, 0});
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, alpha_test_x, b.makeFloatConstant(1.f));
|
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, alpha_test_x,
|
||||||
|
b.makeFloatConstant(1.f));
|
||||||
|
|
||||||
spv::Builder::If alpha_if(cond, b);
|
spv::Builder::If alpha_if(cond, b);
|
||||||
|
|
||||||
|
@ -433,16 +442,26 @@ std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvShaderTranslator::PostTranslation(Shader* shader) {
|
void SpirvShaderTranslator::PostTranslation(Shader* shader) {
|
||||||
|
// Validation.
|
||||||
|
// TODO(DrChat): Only do this if a flag is set (this is pretty slow).
|
||||||
|
auto validation = validator_.Validate(
|
||||||
|
reinterpret_cast<const uint32_t*>(shader->translated_binary().data()),
|
||||||
|
shader->translated_binary().size() / 4);
|
||||||
|
if (validation->has_error()) {
|
||||||
|
XELOGE("SPIR-V Shader Validation failed! Error: %s",
|
||||||
|
validation->error_string());
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(benvanik): only if needed? could be slowish.
|
// TODO(benvanik): only if needed? could be slowish.
|
||||||
auto disasm = disassembler_.Disassemble(
|
auto disasm = disassembler_.Disassemble(
|
||||||
reinterpret_cast<const uint32_t*>(shader->translated_binary().data()),
|
reinterpret_cast<const uint32_t*>(shader->translated_binary().data()),
|
||||||
shader->translated_binary().size() / 4);
|
shader->translated_binary().size() / 4);
|
||||||
if (disasm->has_error()) {
|
if (disasm->has_error()) {
|
||||||
XELOGE("Failed to disassemble SPIRV - invalid?");
|
XELOGE("Failed to disassemble SPIRV - invalid?");
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
set_host_disassembly(shader, disasm->to_string());
|
set_host_disassembly(shader, disasm->to_string());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SpirvShaderTranslator::PreProcessControlFlowInstruction(
|
void SpirvShaderTranslator::PreProcessControlFlowInstruction(
|
||||||
uint32_t cf_index) {
|
uint32_t cf_index) {
|
||||||
|
@ -475,13 +494,18 @@ void SpirvShaderTranslator::ProcessControlFlowInstructionEnd(
|
||||||
void SpirvShaderTranslator::ProcessControlFlowNopInstruction() {
|
void SpirvShaderTranslator::ProcessControlFlowNopInstruction() {
|
||||||
auto& b = *builder_;
|
auto& b = *builder_;
|
||||||
|
|
||||||
b.createNoResultOp(spv::Op::OpNop);
|
// b.createNoResultOp(spv::Op::OpNop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvShaderTranslator::ProcessExecInstructionBegin(
|
void SpirvShaderTranslator::ProcessExecInstructionBegin(
|
||||||
const ParsedExecInstruction& instr) {
|
const ParsedExecInstruction& instr) {
|
||||||
auto& b = *builder_;
|
auto& b = *builder_;
|
||||||
|
|
||||||
|
assert_false(open_predicated_block_);
|
||||||
|
open_predicated_block_ = false;
|
||||||
|
predicated_block_cond_ = false;
|
||||||
|
predicated_block_end_ = nullptr;
|
||||||
|
|
||||||
// Head has the logic to check if the body should execute.
|
// Head has the logic to check if the body should execute.
|
||||||
auto head = cf_blocks_[instr.dword_index];
|
auto head = cf_blocks_[instr.dword_index];
|
||||||
b.setBuildPoint(head);
|
b.setBuildPoint(head);
|
||||||
|
@ -500,7 +524,7 @@ void SpirvShaderTranslator::ProcessExecInstructionBegin(
|
||||||
v = b.createLoad(v);
|
v = b.createLoad(v);
|
||||||
|
|
||||||
// Bitfield extract the bool constant.
|
// Bitfield extract the bool constant.
|
||||||
v = b.createTriOp(spv::Op::OpBitFieldUExtract, b.makeUintType(32), v,
|
v = b.createTriOp(spv::Op::OpBitFieldUExtract, uint_type_, v,
|
||||||
b.makeUintConstant(instr.bool_constant_index % 32),
|
b.makeUintConstant(instr.bool_constant_index % 32),
|
||||||
b.makeUintConstant(1));
|
b.makeUintConstant(1));
|
||||||
|
|
||||||
|
@ -519,6 +543,7 @@ void SpirvShaderTranslator::ProcessExecInstructionBegin(
|
||||||
b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_),
|
b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_),
|
||||||
b.makeBoolConstant(instr.condition));
|
b.makeBoolConstant(instr.condition));
|
||||||
b.createConditionalBranch(cond, body, cf_blocks_[instr.dword_index + 1]);
|
b.createConditionalBranch(cond, body, cf_blocks_[instr.dword_index + 1]);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
b.setBuildPoint(body);
|
b.setBuildPoint(body);
|
||||||
|
@ -528,6 +553,14 @@ void SpirvShaderTranslator::ProcessExecInstructionEnd(
|
||||||
const ParsedExecInstruction& instr) {
|
const ParsedExecInstruction& instr) {
|
||||||
auto& b = *builder_;
|
auto& b = *builder_;
|
||||||
|
|
||||||
|
if (open_predicated_block_) {
|
||||||
|
b.createBranch(predicated_block_end_);
|
||||||
|
b.setBuildPoint(predicated_block_end_);
|
||||||
|
open_predicated_block_ = false;
|
||||||
|
predicated_block_cond_ = false;
|
||||||
|
predicated_block_end_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (instr.is_end) {
|
if (instr.is_end) {
|
||||||
b.makeReturn(false);
|
b.makeReturn(false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -671,7 +704,30 @@ void SpirvShaderTranslator::ProcessVertexFetchInstruction(
|
||||||
assert_true(is_vertex_shader());
|
assert_true(is_vertex_shader());
|
||||||
assert_not_zero(vertex_id_);
|
assert_not_zero(vertex_id_);
|
||||||
|
|
||||||
// TODO: instr.is_predicated
|
// Close the open predicated block if this instr isn't predicated or the
|
||||||
|
// conditions do not match.
|
||||||
|
if (open_predicated_block_ &&
|
||||||
|
(!instr.is_predicated ||
|
||||||
|
instr.predicate_condition != predicated_block_cond_)) {
|
||||||
|
b.createBranch(predicated_block_end_);
|
||||||
|
b.setBuildPoint(predicated_block_end_);
|
||||||
|
open_predicated_block_ = false;
|
||||||
|
predicated_block_cond_ = false;
|
||||||
|
predicated_block_end_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!open_predicated_block_ && instr.is_predicated) {
|
||||||
|
Id pred_cond =
|
||||||
|
b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_),
|
||||||
|
b.makeBoolConstant(instr.predicate_condition));
|
||||||
|
auto block = &b.makeNewBlock();
|
||||||
|
open_predicated_block_ = true;
|
||||||
|
predicated_block_cond_ = instr.predicate_condition;
|
||||||
|
predicated_block_end_ = &b.makeNewBlock();
|
||||||
|
|
||||||
|
b.createConditionalBranch(pred_cond, block, predicated_block_end_);
|
||||||
|
b.setBuildPoint(block);
|
||||||
|
}
|
||||||
|
|
||||||
// Operand 0 is the index
|
// Operand 0 is the index
|
||||||
// Operand 1 is the binding
|
// Operand 1 is the binding
|
||||||
|
@ -726,7 +782,31 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
|
||||||
const ParsedTextureFetchInstruction& instr) {
|
const ParsedTextureFetchInstruction& instr) {
|
||||||
auto& b = *builder_;
|
auto& b = *builder_;
|
||||||
|
|
||||||
// TODO: instr.is_predicated
|
// Close the open predicated block if this instr isn't predicated or the
|
||||||
|
// conditions do not match.
|
||||||
|
if (open_predicated_block_ &&
|
||||||
|
(!instr.is_predicated ||
|
||||||
|
instr.predicate_condition != predicated_block_cond_)) {
|
||||||
|
b.createBranch(predicated_block_end_);
|
||||||
|
b.setBuildPoint(predicated_block_end_);
|
||||||
|
open_predicated_block_ = false;
|
||||||
|
predicated_block_cond_ = false;
|
||||||
|
predicated_block_end_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!open_predicated_block_ && instr.is_predicated) {
|
||||||
|
Id pred_cond =
|
||||||
|
b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_),
|
||||||
|
b.makeBoolConstant(instr.predicate_condition));
|
||||||
|
auto block = &b.makeNewBlock();
|
||||||
|
open_predicated_block_ = true;
|
||||||
|
predicated_block_cond_ = instr.predicate_condition;
|
||||||
|
predicated_block_end_ = &b.makeNewBlock();
|
||||||
|
|
||||||
|
b.createConditionalBranch(pred_cond, block, predicated_block_end_);
|
||||||
|
b.setBuildPoint(block);
|
||||||
|
}
|
||||||
|
|
||||||
// Operand 0 is the offset
|
// Operand 0 is the offset
|
||||||
// Operand 1 is the sampler index
|
// Operand 1 is the sampler index
|
||||||
Id dest = 0;
|
Id dest = 0;
|
||||||
|
@ -804,13 +884,32 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
sources[i] = LoadFromOperand(instr.operands[i]);
|
sources[i] = LoadFromOperand(instr.operands[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id pred_cond = 0;
|
// Close the open predicated block if this instr isn't predicated or the
|
||||||
if (instr.is_predicated) {
|
// conditions do not match.
|
||||||
pred_cond =
|
if (open_predicated_block_ &&
|
||||||
b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_),
|
(!instr.is_predicated ||
|
||||||
b.makeBoolConstant(instr.predicate_condition));
|
instr.predicate_condition != predicated_block_cond_)) {
|
||||||
|
b.createBranch(predicated_block_end_);
|
||||||
|
b.setBuildPoint(predicated_block_end_);
|
||||||
|
open_predicated_block_ = false;
|
||||||
|
predicated_block_cond_ = false;
|
||||||
|
predicated_block_end_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!open_predicated_block_ && instr.is_predicated) {
|
||||||
|
Id pred_cond =
|
||||||
|
b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_),
|
||||||
|
b.makeBoolConstant(instr.predicate_condition));
|
||||||
|
auto block = &b.makeNewBlock();
|
||||||
|
open_predicated_block_ = true;
|
||||||
|
predicated_block_cond_ = instr.predicate_condition;
|
||||||
|
predicated_block_end_ = &b.makeNewBlock();
|
||||||
|
|
||||||
|
b.createConditionalBranch(pred_cond, block, predicated_block_end_);
|
||||||
|
b.setBuildPoint(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool close_predicated_block = false;
|
||||||
switch (instr.vector_opcode) {
|
switch (instr.vector_opcode) {
|
||||||
case AluVectorOpcode::kAdd: {
|
case AluVectorOpcode::kAdd: {
|
||||||
dest = b.createBinOp(spv::Op::OpFAdd, vec4_float_type_, sources[0],
|
dest = b.createBinOp(spv::Op::OpFAdd, vec4_float_type_, sources[0],
|
||||||
|
@ -863,8 +962,8 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
auto src1_xy = b.createOp(spv::Op::OpVectorShuffle, vec2_float_type_,
|
auto src1_xy = b.createOp(spv::Op::OpVectorShuffle, vec2_float_type_,
|
||||||
{sources[1], sources[1], 0, 1});
|
{sources[1], sources[1], 0, 1});
|
||||||
auto src2_x = b.createCompositeExtract(sources[2], float_type_, 0);
|
auto src2_x = b.createCompositeExtract(sources[2], float_type_, 0);
|
||||||
auto dot = b.createBinOp(spv::Op::OpDot, float_type_, src0_xy, src1_xy);
|
dest = b.createBinOp(spv::Op::OpDot, float_type_, src0_xy, src1_xy);
|
||||||
dest = b.createBinOp(spv::Op::OpFAdd, float_type_, dot, src2_x);
|
dest = b.createBinOp(spv::Op::OpFAdd, float_type_, dest, src2_x);
|
||||||
dest = b.smearScalar(spv::NoPrecision, dest, vec4_float_type_);
|
dest = b.smearScalar(spv::NoPrecision, dest, vec4_float_type_);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -873,12 +972,13 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
{sources[0], sources[0], 0, 1, 2});
|
{sources[0], sources[0], 0, 1, 2});
|
||||||
auto src1_xyz = b.createOp(spv::Op::OpVectorShuffle, vec3_float_type_,
|
auto src1_xyz = b.createOp(spv::Op::OpVectorShuffle, vec3_float_type_,
|
||||||
{sources[1], sources[1], 0, 1, 2});
|
{sources[1], sources[1], 0, 1, 2});
|
||||||
auto dot = b.createBinOp(spv::Op::OpDot, float_type_, src0_xyz, src1_xyz);
|
dest = b.createBinOp(spv::Op::OpDot, float_type_, src0_xyz, src1_xyz);
|
||||||
dest = b.smearScalar(spv::NoPrecision, dot, vec4_float_type_);
|
dest = b.smearScalar(spv::NoPrecision, dest, vec4_float_type_);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case AluVectorOpcode::kDp4: {
|
case AluVectorOpcode::kDp4: {
|
||||||
dest = b.createBinOp(spv::Op::OpDot, float_type_, sources[0], sources[1]);
|
dest = b.createBinOp(spv::Op::OpDot, float_type_, sources[0], sources[1]);
|
||||||
|
dest = b.smearScalar(spv::NoPrecision, dest, vec4_float_type_);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case AluVectorOpcode::kFloor: {
|
case AluVectorOpcode::kFloor: {
|
||||||
|
@ -899,10 +999,6 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_,
|
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, vec4_bool_type_,
|
||||||
sources[0], sources[1]);
|
sources[0], sources[1]);
|
||||||
cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond);
|
cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond);
|
||||||
if (pred_cond) {
|
|
||||||
cond =
|
|
||||||
b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, cond, pred_cond);
|
|
||||||
}
|
|
||||||
b.createConditionalBranch(cond, kill_block, continue_block);
|
b.createConditionalBranch(cond, kill_block, continue_block);
|
||||||
|
|
||||||
b.setBuildPoint(kill_block);
|
b.setBuildPoint(kill_block);
|
||||||
|
@ -918,10 +1014,6 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual,
|
auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual,
|
||||||
vec4_bool_type_, sources[0], sources[1]);
|
vec4_bool_type_, sources[0], sources[1]);
|
||||||
cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond);
|
cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond);
|
||||||
if (pred_cond) {
|
|
||||||
cond =
|
|
||||||
b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, cond, pred_cond);
|
|
||||||
}
|
|
||||||
b.createConditionalBranch(cond, kill_block, continue_block);
|
b.createConditionalBranch(cond, kill_block, continue_block);
|
||||||
|
|
||||||
b.setBuildPoint(kill_block);
|
b.setBuildPoint(kill_block);
|
||||||
|
@ -937,10 +1029,6 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThan, vec4_bool_type_,
|
auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThan, vec4_bool_type_,
|
||||||
sources[0], sources[1]);
|
sources[0], sources[1]);
|
||||||
cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond);
|
cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond);
|
||||||
if (pred_cond) {
|
|
||||||
cond =
|
|
||||||
b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, cond, pred_cond);
|
|
||||||
}
|
|
||||||
b.createConditionalBranch(cond, kill_block, continue_block);
|
b.createConditionalBranch(cond, kill_block, continue_block);
|
||||||
|
|
||||||
b.setBuildPoint(kill_block);
|
b.setBuildPoint(kill_block);
|
||||||
|
@ -956,10 +1044,6 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdNotEqual, vec4_bool_type_,
|
auto cond = b.createBinOp(spv::Op::OpFOrdNotEqual, vec4_bool_type_,
|
||||||
sources[0], sources[1]);
|
sources[0], sources[1]);
|
||||||
cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond);
|
cond = b.createUnaryOp(spv::Op::OpAny, bool_type_, cond);
|
||||||
if (pred_cond) {
|
|
||||||
cond =
|
|
||||||
b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, cond, pred_cond);
|
|
||||||
}
|
|
||||||
b.createConditionalBranch(cond, kill_block, continue_block);
|
b.createConditionalBranch(cond, kill_block, continue_block);
|
||||||
|
|
||||||
b.setBuildPoint(kill_block);
|
b.setBuildPoint(kill_block);
|
||||||
|
@ -1053,6 +1137,7 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
|
|
||||||
// p0
|
// p0
|
||||||
b.createStore(c_and_w, p0_);
|
b.createStore(c_and_w, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
// dest
|
// dest
|
||||||
auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0);
|
auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0);
|
||||||
|
@ -1076,6 +1161,7 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
|
|
||||||
// p0
|
// p0
|
||||||
b.createStore(c_and_w, p0_);
|
b.createStore(c_and_w, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
// dest
|
// dest
|
||||||
auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0);
|
auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0);
|
||||||
|
@ -1099,6 +1185,7 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
|
|
||||||
// p0
|
// p0
|
||||||
b.createStore(c_and_w, p0_);
|
b.createStore(c_and_w, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
// dest
|
// dest
|
||||||
auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0);
|
auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0);
|
||||||
|
@ -1122,6 +1209,7 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
|
|
||||||
// p0
|
// p0
|
||||||
b.createStore(c_and_w, p0_);
|
b.createStore(c_and_w, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
// dest
|
// dest
|
||||||
auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0);
|
auto s0_x = b.createCompositeExtract(sources[0], float_type_, 0);
|
||||||
|
@ -1177,15 +1265,16 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
|
||||||
|
|
||||||
assert_not_zero(dest);
|
assert_not_zero(dest);
|
||||||
if (dest) {
|
if (dest) {
|
||||||
// If predicated, discard the result from the instruction.
|
b.createStore(dest, pv_);
|
||||||
Id pv_dest = dest;
|
StoreToResult(dest, instr.result);
|
||||||
if (instr.is_predicated) {
|
|
||||||
pv_dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, pred_cond,
|
|
||||||
dest, b.createLoad(pv_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.createStore(pv_dest, pv_);
|
if (close_predicated_block && open_predicated_block_) {
|
||||||
StoreToResult(dest, instr.result, pred_cond);
|
b.createBranch(predicated_block_end_);
|
||||||
|
b.setBuildPoint(predicated_block_end_);
|
||||||
|
open_predicated_block_ = false;
|
||||||
|
predicated_block_cond_ = false;
|
||||||
|
predicated_block_end_ = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1229,13 +1318,32 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Id pred_cond = 0;
|
// Close the open predicated block if this instr isn't predicated or the
|
||||||
if (instr.is_predicated) {
|
// conditions do not match.
|
||||||
pred_cond =
|
if (open_predicated_block_ &&
|
||||||
b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_),
|
(!instr.is_predicated ||
|
||||||
b.makeBoolConstant(instr.predicate_condition));
|
instr.predicate_condition != predicated_block_cond_)) {
|
||||||
|
b.createBranch(predicated_block_end_);
|
||||||
|
b.setBuildPoint(predicated_block_end_);
|
||||||
|
open_predicated_block_ = false;
|
||||||
|
predicated_block_cond_ = false;
|
||||||
|
predicated_block_end_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!open_predicated_block_ && instr.is_predicated) {
|
||||||
|
Id pred_cond =
|
||||||
|
b.createBinOp(spv::Op::OpLogicalEqual, bool_type_, b.createLoad(p0_),
|
||||||
|
b.makeBoolConstant(instr.predicate_condition));
|
||||||
|
auto block = &b.makeNewBlock();
|
||||||
|
open_predicated_block_ = true;
|
||||||
|
predicated_block_cond_ = instr.predicate_condition;
|
||||||
|
predicated_block_end_ = &b.makeNewBlock();
|
||||||
|
|
||||||
|
b.createConditionalBranch(pred_cond, block, predicated_block_end_);
|
||||||
|
b.setBuildPoint(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool close_predicated_block = false;
|
||||||
switch (instr.scalar_opcode) {
|
switch (instr.scalar_opcode) {
|
||||||
case AluScalarOpcode::kAdds:
|
case AluScalarOpcode::kAdds:
|
||||||
case AluScalarOpcode::kAddsc0:
|
case AluScalarOpcode::kAddsc0:
|
||||||
|
@ -1276,10 +1384,6 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
auto kill_block = &b.makeNewBlock();
|
auto kill_block = &b.makeNewBlock();
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
||||||
b.makeFloatConstant(0.f));
|
b.makeFloatConstant(0.f));
|
||||||
if (pred_cond) {
|
|
||||||
cond =
|
|
||||||
b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, cond, pred_cond);
|
|
||||||
}
|
|
||||||
b.createConditionalBranch(cond, kill_block, continue_block);
|
b.createConditionalBranch(cond, kill_block, continue_block);
|
||||||
|
|
||||||
b.setBuildPoint(kill_block);
|
b.setBuildPoint(kill_block);
|
||||||
|
@ -1294,10 +1398,6 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
auto kill_block = &b.makeNewBlock();
|
auto kill_block = &b.makeNewBlock();
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual, bool_type_,
|
auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThanEqual, bool_type_,
|
||||||
sources[0], b.makeFloatConstant(0.f));
|
sources[0], b.makeFloatConstant(0.f));
|
||||||
if (pred_cond) {
|
|
||||||
cond =
|
|
||||||
b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, cond, pred_cond);
|
|
||||||
}
|
|
||||||
b.createConditionalBranch(cond, kill_block, continue_block);
|
b.createConditionalBranch(cond, kill_block, continue_block);
|
||||||
|
|
||||||
b.setBuildPoint(kill_block);
|
b.setBuildPoint(kill_block);
|
||||||
|
@ -1312,10 +1412,6 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
auto kill_block = &b.makeNewBlock();
|
auto kill_block = &b.makeNewBlock();
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_,
|
auto cond = b.createBinOp(spv::Op::OpFOrdGreaterThan, bool_type_,
|
||||||
sources[0], b.makeFloatConstant(0.f));
|
sources[0], b.makeFloatConstant(0.f));
|
||||||
if (pred_cond) {
|
|
||||||
cond =
|
|
||||||
b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, cond, pred_cond);
|
|
||||||
}
|
|
||||||
b.createConditionalBranch(cond, kill_block, continue_block);
|
b.createConditionalBranch(cond, kill_block, continue_block);
|
||||||
|
|
||||||
b.setBuildPoint(kill_block);
|
b.setBuildPoint(kill_block);
|
||||||
|
@ -1330,10 +1426,6 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
auto kill_block = &b.makeNewBlock();
|
auto kill_block = &b.makeNewBlock();
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdNotEqual, bool_type_, sources[0],
|
auto cond = b.createBinOp(spv::Op::OpFOrdNotEqual, bool_type_, sources[0],
|
||||||
b.makeFloatConstant(0.f));
|
b.makeFloatConstant(0.f));
|
||||||
if (pred_cond) {
|
|
||||||
cond =
|
|
||||||
b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, cond, pred_cond);
|
|
||||||
}
|
|
||||||
b.createConditionalBranch(cond, kill_block, continue_block);
|
b.createConditionalBranch(cond, kill_block, continue_block);
|
||||||
|
|
||||||
b.setBuildPoint(kill_block);
|
b.setBuildPoint(kill_block);
|
||||||
|
@ -1348,10 +1440,6 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
auto kill_block = &b.makeNewBlock();
|
auto kill_block = &b.makeNewBlock();
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
||||||
b.makeFloatConstant(1.f));
|
b.makeFloatConstant(1.f));
|
||||||
if (pred_cond) {
|
|
||||||
cond =
|
|
||||||
b.createBinOp(spv::Op::OpLogicalAnd, bool_type_, cond, pred_cond);
|
|
||||||
}
|
|
||||||
b.createConditionalBranch(cond, kill_block, continue_block);
|
b.createConditionalBranch(cond, kill_block, continue_block);
|
||||||
|
|
||||||
b.setBuildPoint(kill_block);
|
b.setBuildPoint(kill_block);
|
||||||
|
@ -1448,7 +1536,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
b.makeFloatConstant(0.f));
|
b.makeFloatConstant(0.f));
|
||||||
auto d = b.createBinOp(spv::Op::OpFDiv, float_type_,
|
auto d = b.createBinOp(spv::Op::OpFDiv, float_type_,
|
||||||
b.makeFloatConstant(1.f), sources[0]);
|
b.makeFloatConstant(1.f), sources[0]);
|
||||||
dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c,
|
dest = b.createTriOp(spv::Op::OpSelect, float_type_, c,
|
||||||
b.makeFloatConstant(0.f), d);
|
b.makeFloatConstant(0.f), d);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -1462,10 +1550,10 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
// dest = src0 != 0.0 ? inversesqrt(src0) : 0.0;
|
// dest = src0 != 0.0 ? inversesqrt(src0) : 0.0;
|
||||||
auto c = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
auto c = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
||||||
b.makeFloatConstant(0.f));
|
b.makeFloatConstant(0.f));
|
||||||
auto d = CreateGlslStd450InstructionCall(
|
auto d = CreateGlslStd450InstructionCall(spv::NoPrecision, float_type_,
|
||||||
spv::NoPrecision, vec4_float_type_, spv::GLSLstd450::kInverseSqrt,
|
spv::GLSLstd450::kInverseSqrt,
|
||||||
{sources[0]});
|
{sources[0]});
|
||||||
dest = b.createTriOp(spv::Op::OpSelect, vec4_float_type_, c,
|
dest = b.createTriOp(spv::Op::OpSelect, float_type_, c,
|
||||||
b.makeFloatConstant(0.f), d);
|
b.makeFloatConstant(0.f), d);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -1503,6 +1591,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
|
|
||||||
case AluScalarOpcode::kSetpClr: {
|
case AluScalarOpcode::kSetpClr: {
|
||||||
b.createStore(b.makeBoolConstant(false), p0_);
|
b.createStore(b.makeBoolConstant(false), p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
dest = b.makeFloatConstant(FLT_MAX);
|
dest = b.makeFloatConstant(FLT_MAX);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -1511,6 +1600,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
b.makeFloatConstant(0.f));
|
b.makeFloatConstant(0.f));
|
||||||
// p0 = cond
|
// p0 = cond
|
||||||
b.createStore(cond, p0_);
|
b.createStore(cond, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
// dest = cond ? 0.f : 1.f;
|
// dest = cond ? 0.f : 1.f;
|
||||||
dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond,
|
dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond,
|
||||||
|
@ -1522,6 +1612,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
sources[0], b.makeFloatConstant(0.f));
|
sources[0], b.makeFloatConstant(0.f));
|
||||||
// p0 = cond
|
// p0 = cond
|
||||||
b.createStore(cond, p0_);
|
b.createStore(cond, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
// dest = cond ? 0.f : 1.f;
|
// dest = cond ? 0.f : 1.f;
|
||||||
dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond,
|
dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond,
|
||||||
|
@ -1533,6 +1624,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
sources[0], b.makeFloatConstant(0.f));
|
sources[0], b.makeFloatConstant(0.f));
|
||||||
// p0 = cond
|
// p0 = cond
|
||||||
b.createStore(cond, p0_);
|
b.createStore(cond, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
// dest = cond ? 0.f : 1.f;
|
// dest = cond ? 0.f : 1.f;
|
||||||
dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond,
|
dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond,
|
||||||
|
@ -1544,6 +1636,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
auto cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
||||||
b.makeFloatConstant(1.f));
|
b.makeFloatConstant(1.f));
|
||||||
b.createStore(cond, p0_);
|
b.createStore(cond, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
// if (!cond) dest = src0 == 0.0 ? 1.0 : src0;
|
// if (!cond) dest = src0 == 0.0 ? 1.0 : src0;
|
||||||
auto dst_cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_,
|
auto dst_cond = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_,
|
||||||
|
@ -1560,6 +1653,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
|
|
||||||
// p0 = cond
|
// p0 = cond
|
||||||
b.createStore(cond, p0_);
|
b.createStore(cond, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
// dest = cond ? 0.f : 1.f;
|
// dest = cond ? 0.f : 1.f;
|
||||||
dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond,
|
dest = b.createTriOp(spv::Op::OpSelect, float_type_, cond,
|
||||||
|
@ -1572,6 +1666,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
auto c = b.createBinOp(spv::Op::OpFOrdLessThanEqual, bool_type_, src,
|
auto c = b.createBinOp(spv::Op::OpFOrdLessThanEqual, bool_type_, src,
|
||||||
b.makeFloatConstant(0.f));
|
b.makeFloatConstant(0.f));
|
||||||
b.createStore(c, p0_);
|
b.createStore(c, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
|
|
||||||
dest = CreateGlslStd450InstructionCall(
|
dest = CreateGlslStd450InstructionCall(
|
||||||
spv::NoPrecision, float_type_, GLSLstd450::kFMax,
|
spv::NoPrecision, float_type_, GLSLstd450::kFMax,
|
||||||
|
@ -1582,6 +1677,7 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
auto c = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
auto c = b.createBinOp(spv::Op::OpFOrdEqual, bool_type_, sources[0],
|
||||||
b.makeFloatConstant(0.f));
|
b.makeFloatConstant(0.f));
|
||||||
b.createStore(c, p0_);
|
b.createStore(c, p0_);
|
||||||
|
close_predicated_block = true;
|
||||||
dest = sources[0];
|
dest = sources[0];
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -1618,15 +1714,16 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
|
||||||
|
|
||||||
assert_not_zero(dest);
|
assert_not_zero(dest);
|
||||||
if (dest) {
|
if (dest) {
|
||||||
// If predicated, discard the result from the instruction.
|
b.createStore(dest, ps_);
|
||||||
Id ps_dest = dest;
|
StoreToResult(dest, instr.result);
|
||||||
if (instr.is_predicated) {
|
|
||||||
ps_dest = b.createTriOp(spv::Op::OpSelect, float_type_, pred_cond, dest,
|
|
||||||
b.createLoad(ps_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.createStore(ps_dest, ps_);
|
if (close_predicated_block && open_predicated_block_) {
|
||||||
StoreToResult(dest, instr.result, pred_cond);
|
b.createBranch(predicated_block_end_);
|
||||||
|
b.setBuildPoint(predicated_block_end_);
|
||||||
|
open_predicated_block_ = false;
|
||||||
|
predicated_block_cond_ = false;
|
||||||
|
predicated_block_end_ = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1763,8 +1860,7 @@ Id SpirvShaderTranslator::LoadFromOperand(const InstructionOperand& op) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvShaderTranslator::StoreToResult(Id source_value_id,
|
void SpirvShaderTranslator::StoreToResult(Id source_value_id,
|
||||||
const InstructionResult& result,
|
const InstructionResult& result) {
|
||||||
Id predicate_cond) {
|
|
||||||
auto& b = *builder_;
|
auto& b = *builder_;
|
||||||
|
|
||||||
if (result.storage_target == InstructionStorageTarget::kNone) {
|
if (result.storage_target == InstructionStorageTarget::kNone) {
|
||||||
|
@ -1865,7 +1961,7 @@ void SpirvShaderTranslator::StoreToResult(Id source_value_id,
|
||||||
|
|
||||||
// Only load from storage if we need it later.
|
// Only load from storage if we need it later.
|
||||||
Id storage_value = 0;
|
Id storage_value = 0;
|
||||||
if (!result.has_all_writes() || predicate_cond) {
|
if (!result.has_all_writes()) {
|
||||||
storage_value = b.createLoad(storage_pointer);
|
storage_value = b.createLoad(storage_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1965,13 +2061,8 @@ void SpirvShaderTranslator::StoreToResult(Id source_value_id,
|
||||||
assert_true(b.getNumComponents(source_value_id) ==
|
assert_true(b.getNumComponents(source_value_id) ==
|
||||||
b.getNumTypeComponents(storage_type));
|
b.getNumTypeComponents(storage_type));
|
||||||
|
|
||||||
// Discard if predicate condition is false.
|
assert_true(b.getTypeId(source_value_id) ==
|
||||||
if (predicate_cond) {
|
b.getDerefTypeId(storage_pointer));
|
||||||
source_value_id =
|
|
||||||
b.createTriOp(spv::Op::OpSelect, storage_type, predicate_cond,
|
|
||||||
source_value_id, storage_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
b.createStore(source_value_id, storage_pointer);
|
b.createStore(source_value_id, storage_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
* Copyright 2016 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
#include "third_party/spirv/GLSL.std.450.hpp11"
|
#include "third_party/spirv/GLSL.std.450.hpp11"
|
||||||
#include "xenia/gpu/shader_translator.h"
|
#include "xenia/gpu/shader_translator.h"
|
||||||
#include "xenia/ui/spirv/spirv_disassembler.h"
|
#include "xenia/ui/spirv/spirv_disassembler.h"
|
||||||
|
#include "xenia/ui/spirv/spirv_validator.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
@ -91,10 +92,15 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||||
// Stores a value based on the specified result information.
|
// Stores a value based on the specified result information.
|
||||||
// The value will be transformed into the appropriate form for the result and
|
// The value will be transformed into the appropriate form for the result and
|
||||||
// the proper components will be selected.
|
// the proper components will be selected.
|
||||||
void StoreToResult(spv::Id source_value_id, const InstructionResult& result,
|
void StoreToResult(spv::Id source_value_id, const InstructionResult& result);
|
||||||
spv::Id predicate_cond = 0);
|
|
||||||
|
|
||||||
xe::ui::spirv::SpirvDisassembler disassembler_;
|
xe::ui::spirv::SpirvDisassembler disassembler_;
|
||||||
|
xe::ui::spirv::SpirvValidator validator_;
|
||||||
|
|
||||||
|
// True if there's an open predicated block
|
||||||
|
bool open_predicated_block_ = false;
|
||||||
|
bool predicated_block_cond_ = false;
|
||||||
|
spv::Block* predicated_block_end_ = nullptr;
|
||||||
|
|
||||||
// TODO(benvanik): replace with something better, make reusable, etc.
|
// TODO(benvanik): replace with something better, make reusable, etc.
|
||||||
std::unique_ptr<spv::Builder> builder_;
|
std::unique_ptr<spv::Builder> builder_;
|
||||||
|
|
Loading…
Reference in New Issue