[GPU] Store ALU result after both vector and scalar instructions

This commit is contained in:
Triang3l
2019-04-20 20:25:27 +03:00
parent cd1aadef74
commit 66a9c9d812
10 changed files with 421 additions and 403 deletions

View File

@@ -2000,17 +2000,60 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
void SpirvShaderTranslator::ProcessAluInstruction(
const ParsedAluInstruction& instr) {
if (instr.is_nop()) {
return;
}
auto& b = *builder_;
switch (instr.type) {
case ParsedAluInstruction::Type::kNop:
b.createNoResultOp(spv::Op::OpNop);
break;
case ParsedAluInstruction::Type::kVector:
ProcessVectorAluInstruction(instr);
break;
case ParsedAluInstruction::Type::kScalar:
ProcessScalarAluInstruction(instr);
break;
// 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.createSelectionMerge(predicated_block_end_,
spv::SelectionControlMaskNone);
b.createConditionalBranch(pred_cond, block, predicated_block_end_);
b.setBuildPoint(block);
}
bool close_predicated_block_vector = false;
bool store_vector =
ProcessVectorAluOperation(instr, close_predicated_block_vector);
bool close_predicated_block_scalar = false;
bool store_scalar =
ProcessScalarAluOperation(instr, close_predicated_block_scalar);
if (store_vector) {
StoreToResult(b.createLoad(pv_), instr.vector_result);
}
if (store_scalar) {
StoreToResult(b.createLoad(ps_), instr.scalar_result);
}
if ((close_predicated_block_vector || close_predicated_block_scalar) &&
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;
}
}
@@ -2202,45 +2245,23 @@ spv::Function* SpirvShaderTranslator::CreateCubeFunction() {
return function;
}
void SpirvShaderTranslator::ProcessVectorAluInstruction(
const ParsedAluInstruction& instr) {
bool SpirvShaderTranslator::ProcessVectorAluOperation(
const ParsedAluInstruction& instr, bool& close_predicated_block) {
close_predicated_block = false;
if (!instr.has_vector_op) {
return false;
}
auto& b = *builder_;
// 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.createSelectionMerge(predicated_block_end_,
spv::SelectionControlMaskNone);
b.createConditionalBranch(pred_cond, block, predicated_block_end_);
b.setBuildPoint(block);
}
// TODO: If we have identical operands, reuse previous one.
Id sources[3] = {0};
Id dest = vec4_float_zero_;
for (size_t i = 0; i < instr.operand_count; i++) {
sources[i] = LoadFromOperand(instr.operands[i]);
for (size_t i = 0; i < instr.vector_operand_count; i++) {
sources[i] = LoadFromOperand(instr.vector_operands[i]);
}
bool close_predicated_block = false;
switch (instr.vector_opcode) {
case AluVectorOpcode::kAdd: {
dest = b.createBinOp(spv::Op::OpFAdd, vec4_float_type_, sources[0],
@@ -2603,58 +2624,30 @@ void SpirvShaderTranslator::ProcessVectorAluInstruction(
assert_true(b.getTypeId(dest) == vec4_float_type_);
if (dest) {
b.createStore(dest, pv_);
StoreToResult(dest, instr.result);
}
if (close_predicated_block && 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;
return true;
}
return false;
}
void SpirvShaderTranslator::ProcessScalarAluInstruction(
const ParsedAluInstruction& instr) {
bool SpirvShaderTranslator::ProcessScalarAluOperation(
const ParsedAluInstruction& instr, bool& close_predicated_block) {
close_predicated_block = false;
if (!instr.has_scalar_op) {
return false;
}
auto& b = *builder_;
// 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.createSelectionMerge(predicated_block_end_,
spv::SelectionControlMaskNone);
b.createConditionalBranch(pred_cond, block, predicated_block_end_);
b.setBuildPoint(block);
}
// TODO: If we have identical operands, reuse previous one.
Id sources[3] = {0};
Id dest = b.makeFloatConstant(0);
for (size_t i = 0, x = 0; i < instr.operand_count; i++) {
auto src = LoadFromOperand(instr.operands[i]);
for (size_t i = 0, x = 0; i < instr.scalar_operand_count; i++) {
auto src = LoadFromOperand(instr.scalar_operands[i]);
// Pull components out of the vector operands and use them as sources.
if (instr.operands[i].component_count > 1) {
for (int j = 0; j < instr.operands[i].component_count; j++) {
if (instr.scalar_operands[i].component_count > 1) {
for (int j = 0; j < instr.scalar_operands[i].component_count; j++) {
sources[x++] = b.createCompositeExtract(src, float_type_, j);
}
} else {
@@ -2662,7 +2655,6 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
}
}
bool close_predicated_block = false;
switch (instr.scalar_opcode) {
case AluScalarOpcode::kAdds:
case AluScalarOpcode::kAddsc0:
@@ -3073,16 +3065,9 @@ void SpirvShaderTranslator::ProcessScalarAluInstruction(
assert_true(b.getTypeId(dest) == float_type_);
if (dest) {
b.createStore(dest, ps_);
StoreToResult(dest, instr.result);
}
if (close_predicated_block && 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;
return true;
}
return false;
}
Id SpirvShaderTranslator::CreateGlslStd450InstructionCall(