[SPIR-V] Cleanup ALU emulation conditionals
This commit is contained in:
parent
eede38ff63
commit
64d2a80f79
|
@ -571,6 +571,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||||
// must be called with absolute values of operands - use GetAbsoluteOperand!
|
// must be called with absolute values of operands - use GetAbsoluteOperand!
|
||||||
spv::Id ZeroIfAnyOperandIsZero(spv::Id value, spv::Id operand_0_abs,
|
spv::Id ZeroIfAnyOperandIsZero(spv::Id value, spv::Id operand_0_abs,
|
||||||
spv::Id operand_1_abs);
|
spv::Id operand_1_abs);
|
||||||
|
// Conditionally discard the current fragment. Changes the build point.
|
||||||
|
void KillPixel(spv::Id condition);
|
||||||
// Return type is a xe::bit_count(result.GetUsedResultComponents())-component
|
// Return type is a xe::bit_count(result.GetUsedResultComponents())-component
|
||||||
// float vector or a single float, depending on whether it's a reduction
|
// float vector or a single float, depending on whether it's a reduction
|
||||||
// instruction (check getTypeId of the result), or returns spv::NoResult if
|
// instruction (check getTypeId of the result), or returns spv::NoResult if
|
||||||
|
|
|
@ -42,6 +42,33 @@ spv::Id SpirvShaderTranslator::ZeroIfAnyOperandIsZero(spv::Id value,
|
||||||
const_float_vectors_0_[num_components - 1], value);
|
const_float_vectors_0_[num_components - 1], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpirvShaderTranslator::KillPixel(spv::Id condition) {
|
||||||
|
// Same calls as in spv::Builder::If.
|
||||||
|
spv::Function& function = builder_->getBuildPoint()->getParent();
|
||||||
|
spv::Block* kill_block = new spv::Block(builder_->getUniqueId(), function);
|
||||||
|
spv::Block* merge_block = new spv::Block(builder_->getUniqueId(), function);
|
||||||
|
spv::Block& header_block = *builder_->getBuildPoint();
|
||||||
|
|
||||||
|
function.addBlock(kill_block);
|
||||||
|
builder_->setBuildPoint(kill_block);
|
||||||
|
// Kill without influencing the control flow in the translated shader.
|
||||||
|
if (var_main_kill_pixel_ != spv::NoResult) {
|
||||||
|
builder_->createStore(builder_->makeBoolConstant(true),
|
||||||
|
var_main_kill_pixel_);
|
||||||
|
}
|
||||||
|
if (features_.demote_to_helper_invocation) {
|
||||||
|
builder_->createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
|
||||||
|
}
|
||||||
|
builder_->createBranch(merge_block);
|
||||||
|
|
||||||
|
builder_->setBuildPoint(&header_block);
|
||||||
|
SpirvCreateSelectionMerge(merge_block->getId());
|
||||||
|
builder_->createConditionalBranch(condition, kill_block, merge_block);
|
||||||
|
|
||||||
|
function.addBlock(merge_block);
|
||||||
|
builder_->setBuildPoint(merge_block);
|
||||||
|
}
|
||||||
|
|
||||||
void SpirvShaderTranslator::ProcessAluInstruction(
|
void SpirvShaderTranslator::ProcessAluInstruction(
|
||||||
const ParsedAluInstruction& instr) {
|
const ParsedAluInstruction& instr) {
|
||||||
if (instr.IsNop()) {
|
if (instr.IsNop()) {
|
||||||
|
@ -560,133 +587,122 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
|
||||||
builder_->addDecoration(operand_neg[2], spv::DecorationNoContraction);
|
builder_->addDecoration(operand_neg[2], spv::DecorationNoContraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spv::Id ma_z_result[4] = {}, ma_yx_result[4] = {};
|
||||||
|
|
||||||
// Check if the major axis is Z (abs(z) >= abs(x) && abs(z) >= abs(y)).
|
// Check if the major axis is Z (abs(z) >= abs(x) && abs(z) >= abs(y)).
|
||||||
// Selection merge must be the penultimate instruction in the block, check
|
spv::Builder::If ma_z_if(
|
||||||
// the condition before it.
|
builder_->createBinOp(
|
||||||
spv::Id ma_z_condition = builder_->createBinOp(
|
spv::OpLogicalAnd, type_bool_,
|
||||||
spv::OpLogicalAnd, type_bool_,
|
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
|
||||||
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
|
operand_abs[2], operand_abs[0]),
|
||||||
operand_abs[2], operand_abs[0]),
|
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
|
||||||
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
|
operand_abs[2], operand_abs[1])),
|
||||||
operand_abs[2], operand_abs[1]));
|
spv::SelectionControlMaskNone, *builder_);
|
||||||
spv::Function& function = builder_->getBuildPoint()->getParent();
|
{
|
||||||
spv::Block& ma_z_block = builder_->makeNewBlock();
|
// The major axis is Z.
|
||||||
spv::Block& ma_yx_block = builder_->makeNewBlock();
|
// tc = -y
|
||||||
spv::Block* ma_merge_block =
|
ma_z_result[0] = operand_neg[1];
|
||||||
new spv::Block(builder_->getUniqueId(), function);
|
// ma/2 = z
|
||||||
SpirvCreateSelectionMerge(ma_merge_block->getId());
|
ma_z_result[2] = operand[2];
|
||||||
builder_->createConditionalBranch(ma_z_condition, &ma_z_block,
|
if (used_result_components & 0b1010) {
|
||||||
&ma_yx_block);
|
spv::Id z_is_neg = builder_->createBinOp(
|
||||||
|
spv::OpFOrdLessThan, type_bool_, operand[2], const_float_0_);
|
||||||
builder_->setBuildPoint(&ma_z_block);
|
if (used_result_components & 0b0010) {
|
||||||
// The major axis is Z.
|
// sc = z < 0.0 ? -x : x
|
||||||
spv::Id ma_z_result[4] = {};
|
ma_z_result[1] =
|
||||||
// tc = -y
|
builder_->createTriOp(spv::OpSelect, type_float_, z_is_neg,
|
||||||
ma_z_result[0] = operand_neg[1];
|
operand_neg[0], operand[0]);
|
||||||
// ma/2 = z
|
}
|
||||||
ma_z_result[2] = operand[2];
|
if (used_result_components & 0b1000) {
|
||||||
if (used_result_components & 0b1010) {
|
// id = z < 0.0 ? 5.0 : 4.0
|
||||||
spv::Id z_is_neg = builder_->createBinOp(
|
ma_z_result[3] =
|
||||||
spv::OpFOrdLessThan, type_bool_, operand[2], const_float_0_);
|
builder_->createTriOp(spv::OpSelect, type_float_, z_is_neg,
|
||||||
if (used_result_components & 0b0010) {
|
builder_->makeFloatConstant(5.0f),
|
||||||
// sc = z < 0.0 ? -x : x
|
builder_->makeFloatConstant(4.0f));
|
||||||
ma_z_result[1] = builder_->createTriOp(
|
}
|
||||||
spv::OpSelect, type_float_, z_is_neg, operand_neg[0], operand[0]);
|
|
||||||
}
|
|
||||||
if (used_result_components & 0b1000) {
|
|
||||||
// id = z < 0.0 ? 5.0 : 4.0
|
|
||||||
ma_z_result[3] =
|
|
||||||
builder_->createTriOp(spv::OpSelect, type_float_, z_is_neg,
|
|
||||||
builder_->makeFloatConstant(5.0f),
|
|
||||||
builder_->makeFloatConstant(4.0f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder_->createBranch(ma_merge_block);
|
spv::Block& ma_z_end_block = *builder_->getBuildPoint();
|
||||||
|
ma_z_if.makeBeginElse();
|
||||||
|
{
|
||||||
|
spv::Id ma_y_result[4] = {}, ma_x_result[4] = {};
|
||||||
|
|
||||||
builder_->setBuildPoint(&ma_yx_block);
|
// The major axis is not Z - create an inner conditional to check if the
|
||||||
// The major axis is not Z - create an inner conditional to check if the
|
// major axis is Y (abs(y) >= abs(x)).
|
||||||
// major axis is Y (abs(y) >= abs(x)).
|
spv::Builder::If ma_y_if(
|
||||||
// Selection merge must be the penultimate instruction in the block, check
|
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
|
||||||
// the condition before it.
|
operand_abs[1], operand_abs[0]),
|
||||||
spv::Id ma_y_condition =
|
spv::SelectionControlMaskNone, *builder_);
|
||||||
builder_->createBinOp(spv::OpFOrdGreaterThanEqual, type_bool_,
|
{
|
||||||
operand_abs[1], operand_abs[0]);
|
// The major axis is Y.
|
||||||
spv::Block& ma_y_block = builder_->makeNewBlock();
|
// sc = x
|
||||||
spv::Block& ma_x_block = builder_->makeNewBlock();
|
ma_y_result[1] = operand[0];
|
||||||
spv::Block& ma_yx_merge_block = builder_->makeNewBlock();
|
// ma/2 = y
|
||||||
SpirvCreateSelectionMerge(ma_yx_merge_block.getId());
|
ma_y_result[2] = operand[1];
|
||||||
builder_->createConditionalBranch(ma_y_condition, &ma_y_block,
|
if (used_result_components & 0b1001) {
|
||||||
&ma_x_block);
|
spv::Id y_is_neg = builder_->createBinOp(
|
||||||
|
spv::OpFOrdLessThan, type_bool_, operand[1], const_float_0_);
|
||||||
|
if (used_result_components & 0b0001) {
|
||||||
|
// tc = y < 0.0 ? -z : z
|
||||||
|
ma_y_result[0] =
|
||||||
|
builder_->createTriOp(spv::OpSelect, type_float_, y_is_neg,
|
||||||
|
operand_neg[2], operand[2]);
|
||||||
|
// id = y < 0.0 ? 3.0 : 2.0
|
||||||
|
ma_y_result[3] =
|
||||||
|
builder_->createTriOp(spv::OpSelect, type_float_, y_is_neg,
|
||||||
|
builder_->makeFloatConstant(3.0f),
|
||||||
|
builder_->makeFloatConstant(2.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spv::Block& ma_y_end_block = *builder_->getBuildPoint();
|
||||||
|
ma_y_if.makeBeginElse();
|
||||||
|
{
|
||||||
|
// The major axis is X.
|
||||||
|
// tc = -y
|
||||||
|
ma_x_result[0] = operand_neg[1];
|
||||||
|
// ma/2 = x
|
||||||
|
ma_x_result[2] = operand[0];
|
||||||
|
if (used_result_components & 0b1010) {
|
||||||
|
spv::Id x_is_neg = builder_->createBinOp(
|
||||||
|
spv::OpFOrdLessThan, type_bool_, operand[0], const_float_0_);
|
||||||
|
if (used_result_components & 0b0010) {
|
||||||
|
// sc = x < 0.0 ? z : -z
|
||||||
|
ma_x_result[1] =
|
||||||
|
builder_->createTriOp(spv::OpSelect, type_float_, x_is_neg,
|
||||||
|
operand[2], operand_neg[2]);
|
||||||
|
}
|
||||||
|
if (used_result_components & 0b1000) {
|
||||||
|
// id = x < 0.0 ? 1.0 : 0.0
|
||||||
|
ma_x_result[3] =
|
||||||
|
builder_->createTriOp(spv::OpSelect, type_float_, x_is_neg,
|
||||||
|
const_float_1_, const_float_0_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spv::Block& ma_x_end_block = *builder_->getBuildPoint();
|
||||||
|
ma_y_if.makeEndIf();
|
||||||
|
|
||||||
builder_->setBuildPoint(&ma_y_block);
|
// The major axis is Y or X - choose the options of the result from Y
|
||||||
// The major axis is Y.
|
// and X.
|
||||||
spv::Id ma_y_result[4] = {};
|
for (uint32_t i = 0; i < 4; ++i) {
|
||||||
// sc = x
|
if (!(used_result_components & (1 << i))) {
|
||||||
ma_y_result[1] = operand[0];
|
continue;
|
||||||
// ma/2 = y
|
}
|
||||||
ma_y_result[2] = operand[1];
|
std::unique_ptr<spv::Instruction> phi_op =
|
||||||
if (used_result_components & 0b1001) {
|
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
|
||||||
spv::Id y_is_neg = builder_->createBinOp(
|
type_float_, spv::OpPhi);
|
||||||
spv::OpFOrdLessThan, type_bool_, operand[1], const_float_0_);
|
phi_op->addIdOperand(ma_y_result[i]);
|
||||||
if (used_result_components & 0b0001) {
|
phi_op->addIdOperand(ma_y_end_block.getId());
|
||||||
// tc = y < 0.0 ? -z : z
|
phi_op->addIdOperand(ma_x_result[i]);
|
||||||
ma_y_result[0] = builder_->createTriOp(
|
phi_op->addIdOperand(ma_x_end_block.getId());
|
||||||
spv::OpSelect, type_float_, y_is_neg, operand_neg[2], operand[2]);
|
ma_yx_result[i] = phi_op->getResultId();
|
||||||
// id = y < 0.0 ? 3.0 : 2.0
|
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
|
||||||
ma_y_result[3] =
|
|
||||||
builder_->createTriOp(spv::OpSelect, type_float_, y_is_neg,
|
|
||||||
builder_->makeFloatConstant(3.0f),
|
|
||||||
builder_->makeFloatConstant(2.0f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder_->createBranch(&ma_yx_merge_block);
|
spv::Block& ma_yx_end_block = *builder_->getBuildPoint();
|
||||||
|
ma_z_if.makeEndIf();
|
||||||
|
|
||||||
builder_->setBuildPoint(&ma_x_block);
|
|
||||||
// The major axis is X.
|
|
||||||
spv::Id ma_x_result[4] = {};
|
|
||||||
// tc = -y
|
|
||||||
ma_x_result[0] = operand_neg[1];
|
|
||||||
// ma/2 = x
|
|
||||||
ma_x_result[2] = operand[0];
|
|
||||||
if (used_result_components & 0b1010) {
|
|
||||||
spv::Id x_is_neg = builder_->createBinOp(
|
|
||||||
spv::OpFOrdLessThan, type_bool_, operand[0], const_float_0_);
|
|
||||||
if (used_result_components & 0b0010) {
|
|
||||||
// sc = x < 0.0 ? z : -z
|
|
||||||
ma_x_result[1] = builder_->createTriOp(
|
|
||||||
spv::OpSelect, type_float_, x_is_neg, operand[2], operand_neg[2]);
|
|
||||||
}
|
|
||||||
if (used_result_components & 0b1000) {
|
|
||||||
// id = x < 0.0 ? 1.0 : 0.0
|
|
||||||
ma_x_result[3] =
|
|
||||||
builder_->createTriOp(spv::OpSelect, type_float_, x_is_neg,
|
|
||||||
const_float_1_, const_float_0_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
builder_->createBranch(&ma_yx_merge_block);
|
|
||||||
|
|
||||||
builder_->setBuildPoint(&ma_yx_merge_block);
|
|
||||||
// The major axis is Y or X - choose the options of the result from Y and
|
|
||||||
// X.
|
|
||||||
spv::Id ma_yx_result[4] = {};
|
|
||||||
for (uint32_t i = 0; i < 4; ++i) {
|
|
||||||
if (!(used_result_components & (1 << i))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::unique_ptr<spv::Instruction> phi_op =
|
|
||||||
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
|
|
||||||
type_float_, spv::OpPhi);
|
|
||||||
phi_op->addIdOperand(ma_y_result[i]);
|
|
||||||
phi_op->addIdOperand(ma_y_block.getId());
|
|
||||||
phi_op->addIdOperand(ma_x_result[i]);
|
|
||||||
phi_op->addIdOperand(ma_x_block.getId());
|
|
||||||
ma_yx_result[i] = phi_op->getResultId();
|
|
||||||
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
|
|
||||||
}
|
|
||||||
builder_->createBranch(ma_merge_block);
|
|
||||||
|
|
||||||
function.addBlock(ma_merge_block);
|
|
||||||
builder_->setBuildPoint(ma_merge_block);
|
|
||||||
// Choose the result options from Z and YX cases.
|
// Choose the result options from Z and YX cases.
|
||||||
id_vector_temp_.clear();
|
id_vector_temp_.clear();
|
||||||
for (uint32_t i = 0; i < 4; ++i) {
|
for (uint32_t i = 0; i < 4; ++i) {
|
||||||
|
@ -697,9 +713,9 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
|
||||||
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
|
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
|
||||||
type_float_, spv::OpPhi);
|
type_float_, spv::OpPhi);
|
||||||
phi_op->addIdOperand(ma_z_result[i]);
|
phi_op->addIdOperand(ma_z_result[i]);
|
||||||
phi_op->addIdOperand(ma_z_block.getId());
|
phi_op->addIdOperand(ma_z_end_block.getId());
|
||||||
phi_op->addIdOperand(ma_yx_result[i]);
|
phi_op->addIdOperand(ma_yx_result[i]);
|
||||||
phi_op->addIdOperand(ma_yx_merge_block.getId());
|
phi_op->addIdOperand(ma_yx_end_block.getId());
|
||||||
id_vector_temp_.push_back(phi_op->getResultId());
|
id_vector_temp_.push_back(phi_op->getResultId());
|
||||||
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
|
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
|
||||||
}
|
}
|
||||||
|
@ -815,31 +831,14 @@ spv::Id SpirvShaderTranslator::ProcessVectorAluOperation(
|
||||||
case ucode::AluVectorOpcode::kKillGt:
|
case ucode::AluVectorOpcode::kKillGt:
|
||||||
case ucode::AluVectorOpcode::kKillGe:
|
case ucode::AluVectorOpcode::kKillGe:
|
||||||
case ucode::AluVectorOpcode::kKillNe: {
|
case ucode::AluVectorOpcode::kKillNe: {
|
||||||
// Selection merge must be the penultimate instruction in the block, check
|
KillPixel(builder_->createUnaryOp(
|
||||||
// the condition before it.
|
|
||||||
spv::Id condition = builder_->createUnaryOp(
|
|
||||||
spv::OpAny, type_bool_,
|
spv::OpAny, type_bool_,
|
||||||
builder_->createBinOp(
|
builder_->createBinOp(
|
||||||
spv::Op(kOps[size_t(instr.vector_opcode)]), type_bool4_,
|
spv::Op(kOps[size_t(instr.vector_opcode)]), type_bool4_,
|
||||||
GetOperandComponents(operand_storage[0], instr.vector_operands[0],
|
GetOperandComponents(operand_storage[0], instr.vector_operands[0],
|
||||||
0b1111),
|
0b1111),
|
||||||
GetOperandComponents(operand_storage[1], instr.vector_operands[1],
|
GetOperandComponents(operand_storage[1], instr.vector_operands[1],
|
||||||
0b1111)));
|
0b1111))));
|
||||||
spv::Block& kill_block = builder_->makeNewBlock();
|
|
||||||
spv::Block& merge_block = builder_->makeNewBlock();
|
|
||||||
SpirvCreateSelectionMerge(merge_block.getId());
|
|
||||||
builder_->createConditionalBranch(condition, &kill_block, &merge_block);
|
|
||||||
builder_->setBuildPoint(&kill_block);
|
|
||||||
// Kill without influencing the control flow in the translated shader.
|
|
||||||
if (var_main_kill_pixel_ != spv::NoResult) {
|
|
||||||
builder_->createStore(builder_->makeBoolConstant(true),
|
|
||||||
var_main_kill_pixel_);
|
|
||||||
}
|
|
||||||
if (features_.demote_to_helper_invocation) {
|
|
||||||
builder_->createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
|
|
||||||
}
|
|
||||||
builder_->createBranch(&merge_block);
|
|
||||||
builder_->setBuildPoint(&merge_block);
|
|
||||||
return const_float_0_;
|
return const_float_0_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1091,47 +1090,34 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
|
||||||
spv::OpLogicalAnd, type_bool_, condition,
|
spv::OpLogicalAnd, type_bool_, condition,
|
||||||
builder_->createBinOp(spv::OpFOrdGreaterThan, type_bool_, b,
|
builder_->createBinOp(spv::OpFOrdGreaterThan, type_bool_, b,
|
||||||
const_float_0_));
|
const_float_0_));
|
||||||
spv::Block& multiply_block = builder_->makeNewBlock();
|
spv::Block& pre_multiply_if_block = *builder_->getBuildPoint();
|
||||||
spv::Block& merge_block = builder_->makeNewBlock();
|
spv::Id product;
|
||||||
SpirvCreateSelectionMerge(merge_block.getId());
|
spv::Builder::If multiply_if(condition, spv::SelectionControlMaskNone,
|
||||||
|
*builder_);
|
||||||
{
|
{
|
||||||
std::unique_ptr<spv::Instruction> branch_conditional_op =
|
// Multiplication case.
|
||||||
std::make_unique<spv::Instruction>(spv::OpBranchConditional);
|
spv::Id a = instr.scalar_operands[0].GetComponent(0) !=
|
||||||
branch_conditional_op->addIdOperand(condition);
|
instr.scalar_operands[0].GetComponent(1)
|
||||||
branch_conditional_op->addIdOperand(multiply_block.getId());
|
? GetOperandComponents(operand_storage[0],
|
||||||
branch_conditional_op->addIdOperand(merge_block.getId());
|
instr.scalar_operands[0], 0b0001)
|
||||||
// More likely to multiply that to return -FLT_MAX.
|
: b;
|
||||||
branch_conditional_op->addImmediateOperand(2);
|
product = builder_->createBinOp(spv::OpFMul, type_float_, a, ps);
|
||||||
branch_conditional_op->addImmediateOperand(1);
|
builder_->addDecoration(product, spv::DecorationNoContraction);
|
||||||
builder_->getBuildPoint()->addInstruction(
|
// Shader Model 3: +0 or denormal * anything = +-0.
|
||||||
std::move(branch_conditional_op));
|
product = ZeroIfAnyOperandIsZero(
|
||||||
|
product, GetAbsoluteOperand(a, instr.scalar_operands[0]), ps_abs);
|
||||||
}
|
}
|
||||||
spv::Block& head_block = *builder_->getBuildPoint();
|
spv::Block& multiply_end_block = *builder_->getBuildPoint();
|
||||||
multiply_block.addPredecessor(&head_block);
|
multiply_if.makeEndIf();
|
||||||
merge_block.addPredecessor(&head_block);
|
// Merge - choose between the product and -FLT_MAX.
|
||||||
// Multiplication case.
|
|
||||||
builder_->setBuildPoint(&multiply_block);
|
|
||||||
spv::Id a = instr.scalar_operands[0].GetComponent(0) !=
|
|
||||||
instr.scalar_operands[0].GetComponent(1)
|
|
||||||
? GetOperandComponents(operand_storage[0],
|
|
||||||
instr.scalar_operands[0], 0b0001)
|
|
||||||
: b;
|
|
||||||
spv::Id product = builder_->createBinOp(spv::OpFMul, type_float_, a, ps);
|
|
||||||
builder_->addDecoration(product, spv::DecorationNoContraction);
|
|
||||||
// Shader Model 3: +0 or denormal * anything = +-0.
|
|
||||||
product = ZeroIfAnyOperandIsZero(
|
|
||||||
product, GetAbsoluteOperand(a, instr.scalar_operands[0]), ps_abs);
|
|
||||||
builder_->createBranch(&merge_block);
|
|
||||||
// Merge case - choose between the product and -FLT_MAX.
|
|
||||||
builder_->setBuildPoint(&merge_block);
|
|
||||||
{
|
{
|
||||||
std::unique_ptr<spv::Instruction> phi_op =
|
std::unique_ptr<spv::Instruction> phi_op =
|
||||||
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
|
std::make_unique<spv::Instruction>(builder_->getUniqueId(),
|
||||||
type_float_, spv::OpPhi);
|
type_float_, spv::OpPhi);
|
||||||
phi_op->addIdOperand(product);
|
phi_op->addIdOperand(product);
|
||||||
phi_op->addIdOperand(multiply_block.getId());
|
phi_op->addIdOperand(multiply_end_block.getId());
|
||||||
phi_op->addIdOperand(const_float_max_neg);
|
phi_op->addIdOperand(const_float_max_neg);
|
||||||
phi_op->addIdOperand(head_block.getId());
|
phi_op->addIdOperand(pre_multiply_if_block.getId());
|
||||||
spv::Id phi_result = phi_op->getResultId();
|
spv::Id phi_result = phi_op->getResultId();
|
||||||
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
|
builder_->getBuildPoint()->addInstruction(std::move(phi_op));
|
||||||
return phi_result;
|
return phi_result;
|
||||||
|
@ -1375,30 +1361,13 @@ spv::Id SpirvShaderTranslator::ProcessScalarAluOperation(
|
||||||
case ucode::AluScalarOpcode::kKillsGe:
|
case ucode::AluScalarOpcode::kKillsGe:
|
||||||
case ucode::AluScalarOpcode::kKillsNe:
|
case ucode::AluScalarOpcode::kKillsNe:
|
||||||
case ucode::AluScalarOpcode::kKillsOne: {
|
case ucode::AluScalarOpcode::kKillsOne: {
|
||||||
// Selection merge must be the penultimate instruction in the block, check
|
KillPixel(builder_->createBinOp(
|
||||||
// the condition before it.
|
|
||||||
spv::Id condition = builder_->createBinOp(
|
|
||||||
spv::Op(kOps[size_t(instr.scalar_opcode)]), type_bool_,
|
spv::Op(kOps[size_t(instr.scalar_opcode)]), type_bool_,
|
||||||
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
|
GetOperandComponents(operand_storage[0], instr.scalar_operands[0],
|
||||||
0b0001),
|
0b0001),
|
||||||
instr.scalar_opcode == ucode::AluScalarOpcode::kKillsOne
|
instr.scalar_opcode == ucode::AluScalarOpcode::kKillsOne
|
||||||
? const_float_1_
|
? const_float_1_
|
||||||
: const_float_0_);
|
: const_float_0_));
|
||||||
spv::Block& kill_block = builder_->makeNewBlock();
|
|
||||||
spv::Block& merge_block = builder_->makeNewBlock();
|
|
||||||
SpirvCreateSelectionMerge(merge_block.getId());
|
|
||||||
builder_->createConditionalBranch(condition, &kill_block, &merge_block);
|
|
||||||
builder_->setBuildPoint(&kill_block);
|
|
||||||
// Kill without influencing the control flow in the translated shader.
|
|
||||||
if (var_main_kill_pixel_ != spv::NoResult) {
|
|
||||||
builder_->createStore(builder_->makeBoolConstant(true),
|
|
||||||
var_main_kill_pixel_);
|
|
||||||
}
|
|
||||||
if (features_.demote_to_helper_invocation) {
|
|
||||||
builder_->createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
|
|
||||||
}
|
|
||||||
builder_->createBranch(&merge_block);
|
|
||||||
builder_->setBuildPoint(&merge_block);
|
|
||||||
return const_float_0_;
|
return const_float_0_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue