[DXBC] Control flow to new DXBC code

This commit is contained in:
Triang3l 2020-04-25 19:30:01 +03:00
parent fb39bac2a1
commit 1799585e92
4 changed files with 154 additions and 526 deletions

View File

@ -2233,9 +2233,9 @@ void DxbcShaderTranslator::StoreResult(const InstructionResult& result,
} }
} }
void DxbcShaderTranslator::UpdateExecConditionals( void DxbcShaderTranslator::UpdateExecConditionalsAndEmitDisassembly(
ParsedExecInstruction::Type type, uint32_t bool_constant_index, ParsedExecInstruction::Type type, uint32_t bool_constant_index,
bool condition, bool emit_disassembly) { bool condition) {
// Check if we can merge the new exec with the previous one, or the jump with // Check if we can merge the new exec with the previous one, or the jump with
// the previous exec. The instruction-level predicate check is also merged in // the previous exec. The instruction-level predicate check is also merged in
// this case. // this case.
@ -2264,72 +2264,35 @@ void DxbcShaderTranslator::UpdateExecConditionals(
if (merge) { if (merge) {
// Emit the disassembly for the exec/jump merged with the previous one. // Emit the disassembly for the exec/jump merged with the previous one.
if (emit_disassembly) { EmitInstructionDisassembly();
EmitInstructionDisassembly();
}
return; return;
} }
CloseExecConditionals(); CloseExecConditionals();
// Emit the disassembly for the new exec/jump. // Emit the disassembly for the new exec/jump.
if (emit_disassembly) { EmitInstructionDisassembly();
EmitInstructionDisassembly();
}
D3D10_SB_INSTRUCTION_TEST_BOOLEAN test =
condition ? D3D10_SB_INSTRUCTION_TEST_NONZERO
: D3D10_SB_INSTRUCTION_TEST_ZERO;
if (type == ParsedExecInstruction::Type::kConditional) { if (type == ParsedExecInstruction::Type::kConditional) {
uint32_t bool_constant_test_register = PushSystemTemp(); uint32_t bool_constant_test_temp = PushSystemTemp();
// Check the bool constant value. // Check the bool constant value.
if (cbuffer_index_bool_loop_constants_ == kCbufferIndexUnallocated) { if (cbuffer_index_bool_loop_constants_ == kCbufferIndexUnallocated) {
cbuffer_index_bool_loop_constants_ = cbuffer_count_++; cbuffer_index_bool_loop_constants_ = cbuffer_count_++;
} }
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_AND) | DxbcOpAnd(DxbcDest::R(bool_constant_test_temp, 0b0001),
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(9)); DxbcSrc::CB(cbuffer_index_bool_loop_constants_,
shader_code_.push_back( uint32_t(CbufferRegister::kBoolLoopConstants),
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1)); bool_constant_index >> 7)
shader_code_.push_back(bool_constant_test_register); .Select((bool_constant_index >> 5) & 3),
shader_code_.push_back( DxbcSrc::LU(uint32_t(1) << (bool_constant_index & 31)));
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER,
(bool_constant_index >> 5) & 3, 3));
shader_code_.push_back(cbuffer_index_bool_loop_constants_);
shader_code_.push_back(uint32_t(CbufferRegister::kBoolLoopConstants));
shader_code_.push_back(bool_constant_index >> 7);
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(1u << (bool_constant_index & 31));
++stat_.instruction_count;
++stat_.uint_instruction_count;
// Open the new `if`. // Open the new `if`.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IF) | DxbcOpIf(condition, DxbcSrc::R(bool_constant_test_temp, DxbcSrc::kXXXX));
ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(test) | // Release bool_constant_test_temp.
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3));
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(bool_constant_test_register);
++stat_.instruction_count;
++stat_.dynamic_flow_control_count;
// Release bool_constant_test_register.
PopSystemTemp(); PopSystemTemp();
cf_exec_bool_constant_ = bool_constant_index; cf_exec_bool_constant_ = bool_constant_index;
cf_exec_bool_constant_condition_ = condition; cf_exec_bool_constant_condition_ = condition;
} else if (type == ParsedExecInstruction::Type::kPredicated) { } else if (type == ParsedExecInstruction::Type::kPredicated) {
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IF) | DxbcOpIf(condition, DxbcSrc::R(system_temp_ps_pc_p0_a0_, DxbcSrc::kZZZZ));
ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(test) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3));
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 2, 1));
shader_code_.push_back(system_temp_ps_pc_p0_a0_);
++stat_.instruction_count;
++stat_.dynamic_flow_control_count;
cf_exec_predicated_ = true; cf_exec_predicated_ = true;
cf_exec_predicate_condition_ = condition; cf_exec_predicate_condition_ = condition;
} }
@ -2341,9 +2304,7 @@ void DxbcShaderTranslator::CloseExecConditionals() {
// Exec level. // Exec level.
if (cf_exec_bool_constant_ != kCfExecBoolConstantNone || if (cf_exec_bool_constant_ != kCfExecBoolConstantNone ||
cf_exec_predicated_) { cf_exec_predicated_) {
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ENDIF) | DxbcOpEndIf();
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
cf_exec_bool_constant_ = kCfExecBoolConstantNone; cf_exec_bool_constant_ = kCfExecBoolConstantNone;
cf_exec_predicated_ = false; cf_exec_predicated_ = false;
} }
@ -2351,80 +2312,51 @@ void DxbcShaderTranslator::CloseExecConditionals() {
cf_exec_predicate_written_ = false; cf_exec_predicate_written_ = false;
} }
void DxbcShaderTranslator::UpdateInstructionPredication(bool predicated, void DxbcShaderTranslator::UpdateInstructionPredicationAndEmitDisassembly(
bool condition, bool predicated, bool condition) {
bool emit_disassembly) { if (!predicated) {
if (predicated) { CloseInstructionPredication();
if (cf_instruction_predicate_if_open_) { EmitInstructionDisassembly();
if (cf_instruction_predicate_condition_ == condition) { return;
// Already in the needed instruction-level `if`. }
if (emit_disassembly) {
EmitInstructionDisassembly();
}
return;
}
CloseInstructionPredication();
}
// Emit the disassembly before opening (or not opening) the new conditional. if (cf_instruction_predicate_if_open_) {
if (emit_disassembly) { if (cf_instruction_predicate_condition_ == condition) {
// Already in the needed instruction-level `if`.
EmitInstructionDisassembly(); EmitInstructionDisassembly();
}
// 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_predicated_ &&
cf_exec_predicate_condition_ == condition) {
return; return;
} }
D3D10_SB_INSTRUCTION_TEST_BOOLEAN test =
condition ? D3D10_SB_INSTRUCTION_TEST_NONZERO
: D3D10_SB_INSTRUCTION_TEST_ZERO;
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IF) |
ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(test) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3));
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 2, 1));
shader_code_.push_back(system_temp_ps_pc_p0_a0_);
++stat_.instruction_count;
++stat_.dynamic_flow_control_count;
cf_instruction_predicate_if_open_ = true;
cf_instruction_predicate_condition_ = condition;
} else {
CloseInstructionPredication(); CloseInstructionPredication();
if (emit_disassembly) {
EmitInstructionDisassembly();
}
} }
// Emit the disassembly before opening (or not opening) the new conditional.
EmitInstructionDisassembly();
// 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_predicated_ &&
cf_exec_predicate_condition_ == condition) {
return;
}
DxbcOpIf(condition, DxbcSrc::R(system_temp_ps_pc_p0_a0_, DxbcSrc::kZZZZ));
cf_instruction_predicate_if_open_ = true;
cf_instruction_predicate_condition_ = condition;
} }
void DxbcShaderTranslator::CloseInstructionPredication() { void DxbcShaderTranslator::CloseInstructionPredication() {
if (cf_instruction_predicate_if_open_) { if (cf_instruction_predicate_if_open_) {
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ENDIF) | DxbcOpEndIf();
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
cf_instruction_predicate_if_open_ = false; cf_instruction_predicate_if_open_ = false;
} }
} }
void DxbcShaderTranslator::JumpToLabel(uint32_t address) { void DxbcShaderTranslator::JumpToLabel(uint32_t address) {
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) | DxbcOpMov(DxbcDest::R(system_temp_ps_pc_p0_a0_, 0b0010),
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5)); DxbcSrc::LU(address));
shader_code_.push_back( DxbcOpContinue();
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0010, 1));
shader_code_.push_back(system_temp_ps_pc_p0_a0_);
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(address);
++stat_.instruction_count;
++stat_.mov_instruction_count;
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_CONTINUE) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
} }
void DxbcShaderTranslator::ProcessLabel(uint32_t cf_index) { void DxbcShaderTranslator::ProcessLabel(uint32_t cf_index) {
@ -2432,72 +2364,27 @@ void DxbcShaderTranslator::ProcessLabel(uint32_t cf_index) {
// 0 already added in the beginning. // 0 already added in the beginning.
return; return;
} }
// Close flow control on the deeper levels below - prevent attempts to merge // Close flow control on the deeper levels below - prevent attempts to merge
// execs across labels. // execs across labels.
CloseExecConditionals(); CloseExecConditionals();
if (UseSwitchForControlFlow()) { if (UseSwitchForControlFlow()) {
// Fallthrough to the label from the previous one on the next iteration if // Fallthrough to the label from the previous one on the next iteration if
// no `continue` was done. Can't simply fallthrough because in DXBC, a // no `continue` was done. Can't simply fallthrough because in DXBC, a
// non-empty switch case must end with a break. // non-empty switch case must end with a break.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) | JumpToLabel(cf_index);
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5));
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0010, 1));
shader_code_.push_back(system_temp_ps_pc_p0_a0_);
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(cf_index);
++stat_.instruction_count;
++stat_.mov_instruction_count;
shader_code_.push_back(
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_CONTINUE) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
// Close the previous label. // Close the previous label.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_BREAK) | DxbcOpBreak();
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
// Go to the next label. // Go to the next label.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_CASE) | DxbcOpCase(DxbcSrc::LU(cf_index));
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3));
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(cf_index);
++stat_.instruction_count;
++stat_.static_flow_control_count;
} else { } else {
// Close the previous label. // Close the previous label.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ENDIF) | DxbcOpEndIf();
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
// pc <= cf_index
uint32_t test_register = PushSystemTemp();
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_UGE) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(7));
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1));
shader_code_.push_back(test_register);
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(cf_index);
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 1, 1));
shader_code_.push_back(system_temp_ps_pc_p0_a0_);
++stat_.instruction_count;
++stat_.uint_instruction_count;
// if (pc <= cf_index) // if (pc <= cf_index)
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IF) | uint32_t test_temp = PushSystemTemp();
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3) | DxbcOpUGE(DxbcDest::R(test_temp, 0b0001), DxbcSrc::LU(cf_index),
ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN( DxbcSrc::R(system_temp_ps_pc_p0_a0_, DxbcSrc::kYYYY));
D3D10_SB_INSTRUCTION_TEST_NONZERO)); DxbcOpIf(true, DxbcSrc::R(test_temp, DxbcSrc::kXXXX));
shader_code_.push_back( // Release test_temp.
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(test_register);
++stat_.instruction_count;
++stat_.dynamic_flow_control_count;
PopSystemTemp(); PopSystemTemp();
} }
} }
@ -2507,43 +2394,24 @@ void DxbcShaderTranslator::ProcessExecInstructionBegin(
if (emit_source_map_) { if (emit_source_map_) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted by UpdateExecConditionals.
} }
UpdateExecConditionals(instr.type, instr.bool_constant_index, instr.condition, UpdateExecConditionalsAndEmitDisassembly(
true); instr.type, instr.bool_constant_index, instr.condition);
// TODO(Triang3l): Find out what PredicateClean=false in exec actually means
// (execs containing setp have PredicateClean=false, it possibly means that
// the predicate is dirty after the exec).
} }
void DxbcShaderTranslator::ProcessExecInstructionEnd( void DxbcShaderTranslator::ProcessExecInstructionEnd(
const ParsedExecInstruction& instr) { const ParsedExecInstruction& instr) {
// TODO(Triang3l): Check whether is_end is conditional or not.
if (instr.is_end) { if (instr.is_end) {
// Break out of the main loop. // Break out of the main loop.
CloseInstructionPredication(); CloseInstructionPredication();
if (UseSwitchForControlFlow()) { if (UseSwitchForControlFlow()) {
// Write an invalid value to pc. // Write an invalid value to pc.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) | DxbcOpMov(DxbcDest::R(system_temp_ps_pc_p0_a0_, 0b0010),
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5)); DxbcSrc::LU(UINT32_MAX));
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0010, 1));
shader_code_.push_back(system_temp_ps_pc_p0_a0_);
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(0xFFFFFFFFu);
++stat_.instruction_count;
++stat_.mov_instruction_count;
// Go to the next iteration, where switch cases won't be reached. // Go to the next iteration, where switch cases won't be reached.
shader_code_.push_back( DxbcOpContinue();
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_CONTINUE) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
} else { } else {
shader_code_.push_back( DxbcOpBreak();
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_BREAK) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
} }
} }
} }
@ -2561,103 +2429,37 @@ void DxbcShaderTranslator::ProcessLoopStartInstruction(
EmitInstructionDisassembly(); EmitInstructionDisassembly();
} }
uint32_t loop_count_and_aL = PushSystemTemp(); // Count (as uint) in bits 0:7 of the loop constant, initial aL in 8:15.
// Starting from vector 2 because of bool constants.
// Count (as uint) in bits 0:7 of the loop constant, aL in 8:15.
if (cbuffer_index_bool_loop_constants_ == kCbufferIndexUnallocated) { if (cbuffer_index_bool_loop_constants_ == kCbufferIndexUnallocated) {
cbuffer_index_bool_loop_constants_ = cbuffer_count_++; cbuffer_index_bool_loop_constants_ = cbuffer_count_++;
} }
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D11_SB_OPCODE_UBFE) | DxbcSrc loop_constant_src(
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(17)); DxbcSrc::CB(cbuffer_index_bool_loop_constants_,
shader_code_.push_back( uint32_t(CbufferRegister::kBoolLoopConstants),
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0011, 1)); 2 + (instr.loop_constant_index >> 2))
shader_code_.push_back(loop_count_and_aL); .Select(instr.loop_constant_index & 3));
shader_code_.push_back(EncodeVectorSwizzledOperand(
D3D10_SB_OPERAND_TYPE_IMMEDIATE32, kSwizzleXYZW, 0));
shader_code_.push_back(8);
shader_code_.push_back(8);
shader_code_.push_back(0);
shader_code_.push_back(0);
shader_code_.push_back(EncodeVectorSwizzledOperand(
D3D10_SB_OPERAND_TYPE_IMMEDIATE32, kSwizzleXYZW, 0));
shader_code_.push_back(0);
shader_code_.push_back(8);
shader_code_.push_back(0);
shader_code_.push_back(0);
shader_code_.push_back(EncodeVectorReplicatedOperand(
D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER, instr.loop_constant_index & 3, 3));
shader_code_.push_back(cbuffer_index_bool_loop_constants_);
shader_code_.push_back(uint32_t(CbufferRegister::kBoolLoopConstants));
// 2 because of bool constants.
shader_code_.push_back(2 + (instr.loop_constant_index >> 2));
++stat_.instruction_count;
++stat_.uint_instruction_count;
// Push the count to the loop count stack - move XYZ to YZW and set X to this // Push the count to the loop count stack - move XYZ to YZW and set X to this
// loop count. // loop count.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) | DxbcOpMov(DxbcDest::R(system_temp_loop_count_, 0b1110),
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5)); DxbcSrc::R(system_temp_loop_count_, 0b10010000));
shader_code_.push_back( DxbcOpAnd(DxbcDest::R(system_temp_loop_count_, 0b0001), loop_constant_src,
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b1110, 1)); DxbcSrc::LU(UINT8_MAX));
shader_code_.push_back(system_temp_loop_count_);
shader_code_.push_back(
EncodeVectorSwizzledOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b10010000, 1));
shader_code_.push_back(system_temp_loop_count_);
++stat_.instruction_count;
++stat_.mov_instruction_count;
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5));
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1));
shader_code_.push_back(system_temp_loop_count_);
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(loop_count_and_aL);
++stat_.instruction_count;
++stat_.mov_instruction_count;
// Push aL - keep the same value as in the previous loop if repeating, or the // Push aL - keep the same value as in the previous loop if repeating, or the
// new one otherwise. // new one otherwise.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) | DxbcOpMov(DxbcDest::R(system_temp_aL_, instr.is_repeat ? 0b1111 : 0b1110),
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5)); DxbcSrc::R(system_temp_aL_, 0b10010000));
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b1111, 1));
shader_code_.push_back(system_temp_aL_);
shader_code_.push_back(
EncodeVectorSwizzledOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b10010000, 1));
shader_code_.push_back(system_temp_aL_);
++stat_.instruction_count;
++stat_.mov_instruction_count;
if (!instr.is_repeat) { if (!instr.is_repeat) {
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) | DxbcOpUBFE(DxbcDest::R(system_temp_aL_, 0b0001), DxbcSrc::LU(8),
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5)); DxbcSrc::LU(8), loop_constant_src);
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1));
shader_code_.push_back(system_temp_aL_);
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 1, 1));
shader_code_.push_back(loop_count_and_aL);
++stat_.instruction_count;
++stat_.mov_instruction_count;
} }
// Release loop_count_and_aL. // Break if the loop counter is 0 (since the condition is checked in the end).
PopSystemTemp(); DxbcOpIf(false, DxbcSrc::R(system_temp_loop_count_, DxbcSrc::kXXXX));
// Short-circuit if loop counter is 0.
shader_code_.push_back(
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IF) |
ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(D3D10_SB_INSTRUCTION_TEST_ZERO) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3));
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(system_temp_loop_count_);
++stat_.instruction_count;
++stat_.dynamic_flow_control_count;
JumpToLabel(instr.loop_skip_address); JumpToLabel(instr.loop_skip_address);
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ENDIF) | DxbcOpEndIf();
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
} }
void DxbcShaderTranslator::ProcessLoopEndInstruction( void DxbcShaderTranslator::ProcessLoopEndInstruction(
@ -2674,153 +2476,68 @@ void DxbcShaderTranslator::ProcessLoopEndInstruction(
} }
// Subtract 1 from the loop counter. // Subtract 1 from the loop counter.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IADD) | DxbcOpIAdd(DxbcDest::R(system_temp_loop_count_, 0b0001),
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(7)); DxbcSrc::R(system_temp_loop_count_, DxbcSrc::kXXXX),
shader_code_.push_back( DxbcSrc::LI(-1));
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1));
shader_code_.push_back(system_temp_loop_count_);
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(system_temp_loop_count_);
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(uint32_t(-1));
++stat_.instruction_count;
++stat_.int_instruction_count;
// Break case.
if (instr.is_predicated_break) { if (instr.is_predicated_break) {
// if (loop_count.x == 0 || [!]p0) // if (loop_count.x == 0 || [!]p0)
uint32_t break_case_temp = PushSystemTemp(); uint32_t break_case_temp = PushSystemTemp();
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOVC) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(9));
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1));
shader_code_.push_back(break_case_temp);
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 2, 1));
shader_code_.push_back(system_temp_ps_pc_p0_a0_);
if (instr.predicate_condition) { if (instr.predicate_condition) {
// If p0 is non-zero, set the test value to 0 (since if_z is used, // If p0 is non-zero, set the test value to 0 (since if_z is used,
// otherwise check if the loop counter is zero). // otherwise check if the loop counter is zero).
shader_code_.push_back( DxbcOpMovC(DxbcDest::R(break_case_temp, 0b0001),
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0)); DxbcSrc::R(system_temp_ps_pc_p0_a0_, DxbcSrc::kZZZZ),
shader_code_.push_back(0); DxbcSrc::LU(0),
} DxbcSrc::R(system_temp_loop_count_, DxbcSrc::kXXXX));
shader_code_.push_back( } else {
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(system_temp_loop_count_);
if (!instr.predicate_condition) {
// If p0 is zero, set the test value to 0 (since if_z is used, otherwise // If p0 is zero, set the test value to 0 (since if_z is used, otherwise
// check if the loop counter is zero). // check if the loop counter is zero).
shader_code_.push_back( DxbcOpMovC(DxbcDest::R(break_case_temp, 0b0001),
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0)); DxbcSrc::R(system_temp_ps_pc_p0_a0_, DxbcSrc::kZZZZ),
shader_code_.push_back(0); DxbcSrc::R(system_temp_loop_count_, DxbcSrc::kXXXX),
DxbcSrc::LU(0));
} }
++stat_.instruction_count; DxbcOpIf(false, DxbcSrc::R(break_case_temp, DxbcSrc::kXXXX));
++stat_.movc_instruction_count; // Release break_case_temp.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IF) |
ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(
D3D10_SB_INSTRUCTION_TEST_ZERO) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3));
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(break_case_temp);
PopSystemTemp(); PopSystemTemp();
} else { } else {
// if (loop_count.x == 0) // if (loop_count.x == 0)
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IF) | DxbcOpIf(false, DxbcSrc::R(system_temp_loop_count_, DxbcSrc::kXXXX));
ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(
D3D10_SB_INSTRUCTION_TEST_ZERO) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3));
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(system_temp_loop_count_);
} }
++stat_.instruction_count; {
++stat_.dynamic_flow_control_count; // Break case.
// Pop the current loop off the stack, move YZW to XYZ and set W to 0.
// Pop the current loop off the stack, move YZW to XYZ and set W to 0. DxbcOpMov(DxbcDest::R(system_temp_loop_count_, 0b0111),
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) | DxbcSrc::R(system_temp_loop_count_, 0b111001));
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5)); DxbcOpMov(DxbcDest::R(system_temp_loop_count_, 0b1000), DxbcSrc::LU(0));
shader_code_.push_back( // Now going to fall through to the next exec (no need to jump).
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0111, 1));
shader_code_.push_back(system_temp_loop_count_);
shader_code_.push_back(
EncodeVectorSwizzledOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b11111001, 1));
shader_code_.push_back(system_temp_loop_count_);
++stat_.instruction_count;
++stat_.mov_instruction_count;
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5));
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b1000, 1));
shader_code_.push_back(system_temp_loop_count_);
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(0);
++stat_.instruction_count;
++stat_.mov_instruction_count;
// Now going to fall through to the next exec (no need to jump).
// Continue case.
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ELSE) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
uint32_t aL_add_temp = PushSystemTemp();
// Extract the value to add to aL (in bits 16:23 of the loop constant).
if (cbuffer_index_bool_loop_constants_ == kCbufferIndexUnallocated) {
cbuffer_index_bool_loop_constants_ = cbuffer_count_++;
} }
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D11_SB_OPCODE_UBFE) | DxbcOpElse();
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(11)); {
shader_code_.push_back( // Continue case.
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1)); uint32_t aL_add_temp = PushSystemTemp();
shader_code_.push_back(aL_add_temp); // Extract the value to add to aL (in bits 16:23 of the loop constant).
shader_code_.push_back( // Starting from vector 2 because of bool constants.
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0)); if (cbuffer_index_bool_loop_constants_ == kCbufferIndexUnallocated) {
shader_code_.push_back(8); cbuffer_index_bool_loop_constants_ = cbuffer_count_++;
shader_code_.push_back( }
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0)); DxbcOpUBFE(DxbcDest::R(aL_add_temp, 0b0001), DxbcSrc::LU(8),
shader_code_.push_back(16); DxbcSrc::LU(16),
shader_code_.push_back(EncodeVectorSelectOperand( DxbcSrc::CB(cbuffer_index_bool_loop_constants_,
D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER, instr.loop_constant_index & 3, 3)); uint32_t(CbufferRegister::kBoolLoopConstants),
shader_code_.push_back(cbuffer_index_bool_loop_constants_); 2 + (instr.loop_constant_index >> 2))
shader_code_.push_back(uint32_t(CbufferRegister::kBoolLoopConstants)); .Select(instr.loop_constant_index & 3));
// 2 because of bool constants. // Add the needed value to aL.
shader_code_.push_back(2 + (instr.loop_constant_index >> 2)); DxbcOpIAdd(DxbcDest::R(system_temp_aL_, 0b0001),
++stat_.instruction_count; DxbcSrc::R(system_temp_aL_, DxbcSrc::kXXXX),
++stat_.uint_instruction_count; DxbcSrc::R(aL_add_temp, DxbcSrc::kXXXX));
// Release aL_add_temp.
// Add the needed value to aL. PopSystemTemp();
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IADD) | // Jump back to the beginning of the loop body.
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(7)); JumpToLabel(instr.loop_body_address);
shader_code_.push_back( }
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1)); DxbcOpEndIf();
shader_code_.push_back(system_temp_aL_);
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(system_temp_aL_);
shader_code_.push_back(
EncodeVectorSelectOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0, 1));
shader_code_.push_back(aL_add_temp);
++stat_.instruction_count;
++stat_.int_instruction_count;
// Release aL_add_temp.
PopSystemTemp();
// Jump back to the beginning of the loop body.
JumpToLabel(instr.loop_body_address);
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ENDIF) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
} }
void DxbcShaderTranslator::ProcessJumpInstruction( void DxbcShaderTranslator::ProcessJumpInstruction(
@ -2828,7 +2545,6 @@ void DxbcShaderTranslator::ProcessJumpInstruction(
if (emit_source_map_) { if (emit_source_map_) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted by UpdateExecConditionals.
} }
// Treat like exec, merge with execs if possible, since it's an if too. // Treat like exec, merge with execs if possible, since it's an if too.
@ -2840,13 +2556,13 @@ void DxbcShaderTranslator::ProcessJumpInstruction(
} else { } else {
type = ParsedExecInstruction::Type::kUnconditional; type = ParsedExecInstruction::Type::kUnconditional;
} }
UpdateExecConditionals(type, instr.bool_constant_index, instr.condition, UpdateExecConditionalsAndEmitDisassembly(type, instr.bool_constant_index,
true); instr.condition);
// UpdateExecConditionals may not necessarily close the instruction-level // UpdateExecConditionalsAndEmitDisassembly may not necessarily close the
// predicate check (it's not necessary if the execs are merged), but here the // instruction-level predicate check (it's not necessary if the execs are
// instruction itself is on the flow control level, so the predicate check is // merged), but here the instruction itself is on the flow control level, so
// on the flow control level too. // the predicate check is on the flow control level too.
CloseInstructionPredication(); CloseInstructionPredication();
JumpToLabel(instr.target_address); JumpToLabel(instr.target_address);

View File

@ -1078,6 +1078,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
kCall = 4, kCall = 4,
kCallC = 5, kCallC = 5,
kCase = 6, kCase = 6,
kContinue = 7,
kDefault = 10, kDefault = 10,
kDiscard = 13, kDiscard = 13,
kDiv = 14, kDiv = 14,
@ -1268,6 +1269,10 @@ class DxbcShaderTranslator : public ShaderTranslator {
DxbcEmitFlowOp(DxbcOpcode::kCase, src); DxbcEmitFlowOp(DxbcOpcode::kCase, src);
++stat_.static_flow_control_count; ++stat_.static_flow_control_count;
} }
void DxbcOpContinue() {
shader_code_.push_back(DxbcOpcodeToken(DxbcOpcode::kContinue, 0));
++stat_.instruction_count;
}
void DxbcOpDefault() { void DxbcOpDefault() {
shader_code_.push_back(DxbcOpcodeToken(DxbcOpcode::kDefault, 0)); shader_code_.push_back(DxbcOpcodeToken(DxbcOpcode::kDefault, 0));
++stat_.instruction_count; ++stat_.instruction_count;
@ -2077,21 +2082,21 @@ class DxbcShaderTranslator : public ShaderTranslator {
// of exec and in jumps), closing the previous conditionals if needed. // of exec and in jumps), closing the previous conditionals if needed.
// However, if the condition is not different, the instruction-level predicate // However, if the condition is not different, the instruction-level predicate
// `if` also won't be closed - this must be checked separately if needed (for // `if` also won't be closed - this must be checked separately if needed (for
// example, in jumps). If emit_disassembly is true, this function emits the // example, in jumps). Also emits the last disassembly written to
// last disassembly written to instruction_disassembly_buffer_ after closing // instruction_disassembly_buffer_ after closing the previous conditional and
// the previous conditional and before opening a new one. // before opening a new one.
void UpdateExecConditionals(ParsedExecInstruction::Type type, void UpdateExecConditionalsAndEmitDisassembly(
uint32_t bool_constant_index, bool condition, ParsedExecInstruction::Type type, uint32_t bool_constant_index,
bool emit_disassembly); bool condition);
// Closes `if`s opened by exec and instructions within them (but not by // Closes `if`s opened by exec and instructions within them (but not by
// labels) and updates the state accordingly. // labels) and updates the state accordingly.
void CloseExecConditionals(); void CloseExecConditionals();
// Opens or reopens the predicate check conditional for the instruction. If // Opens or reopens the predicate check conditional for the instruction, and
// emit_disassembly is true, this function emits the last disassembly written // emits the last disassembly written to instruction_disassembly_buffer_ after
// to instruction_disassembly_buffer_ after closing the previous predicate // closing the previous predicate conditional and before opening a new one.
// conditional and before opening a new one. // This should be called before processing a non-control-flow instruction.
void UpdateInstructionPredication(bool predicated, bool condition, void UpdateInstructionPredicationAndEmitDisassembly(bool predicated,
bool emit_disassembly); bool condition);
// Closes the instruction-level predicate `if` if it's open, useful if a flow // Closes the instruction-level predicate `if` if it's open, useful if a flow
// control instruction needs to do some code which needs to respect the exec's // control instruction needs to do some code which needs to respect the exec's
// conditional, but can't itself be predicated. // conditional, but can't itself be predicated.

View File

@ -2428,10 +2428,9 @@ void DxbcShaderTranslator::ProcessAluInstruction(
if (emit_source_map_) { if (emit_source_map_) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted by UpdateInstructionPredication.
} }
UpdateInstructionPredication(instr.is_predicated, instr.predicate_condition, UpdateInstructionPredicationAndEmitDisassembly(instr.is_predicated,
true); instr.predicate_condition);
// Whether the instruction has changed the predicate and it needs to be // Whether the instruction has changed the predicate and it needs to be
// checked again later. // checked again later.

View File

@ -324,10 +324,9 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
if (emit_source_map_) { if (emit_source_map_) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted by UpdateInstructionPredication.
} }
UpdateInstructionPredication(instr.is_predicated, instr.predicate_condition, UpdateInstructionPredicationAndEmitDisassembly(instr.is_predicated,
true); instr.predicate_condition);
// Convert the index to an integer, according to // Convert the index to an integer, according to
// http://web.archive.org/web/20100302145413/http://msdn.microsoft.com:80/en-us/library/bb313960.aspx // http://web.archive.org/web/20100302145413/http://msdn.microsoft.com:80/en-us/library/bb313960.aspx
@ -1162,75 +1161,9 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
if (emit_source_map_) { if (emit_source_map_) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted later explicitly or by UpdateInstructionPredication.
}
// Predication should not affect derivative calculation:
// https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx9-graphics-reference-asm-ps-registers-output-color
// Do the part involving derivative calculation unconditionally, and re-enter
// the predicate check before writing the result.
bool suppress_predication = false;
if (IsDxbcPixelShader()) {
if (instr.opcode == FetchOpcode::kGetTextureComputedLod ||
instr.opcode == FetchOpcode::kGetTextureGradients) {
suppress_predication = true;
} else if (instr.opcode == FetchOpcode::kTextureFetch) {
suppress_predication = instr.attributes.use_computed_lod &&
!instr.attributes.use_register_lod;
}
}
uint32_t exec_p0_temp = UINT32_MAX;
if (suppress_predication) {
// Emit the disassembly before all this to indicate the reason of going
// unconditional.
EmitInstructionDisassembly();
// Close instruction-level predication.
CloseInstructionPredication();
// Temporarily close exec-level predication - will reopen at the end, so not
// changing cf_exec_predicated_.
if (cf_exec_predicated_) {
if (cf_exec_predicate_written_) {
// Restore the predicate value in the beginning of the exec and put it
// in exec_p0_temp.
exec_p0_temp = PushSystemTemp();
// `if` case - the value was cf_exec_predicate_condition_.
shader_code_.push_back(
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5));
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1));
shader_code_.push_back(exec_p0_temp);
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(cf_exec_predicate_condition_ ? 0xFFFFFFFFu : 0u);
++stat_.instruction_count;
++stat_.mov_instruction_count;
shader_code_.push_back(
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ELSE) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
// `else` case - the value was !cf_exec_predicate_condition_.
shader_code_.push_back(
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_MOV) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(5));
shader_code_.push_back(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_TEMP, 0b0001, 1));
shader_code_.push_back(exec_p0_temp);
shader_code_.push_back(
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_IMMEDIATE32, 0));
shader_code_.push_back(cf_exec_predicate_condition_ ? 0u : 0xFFFFFFFFu);
++stat_.instruction_count;
++stat_.mov_instruction_count;
}
shader_code_.push_back(
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_ENDIF) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1));
++stat_.instruction_count;
}
} else {
UpdateInstructionPredication(instr.is_predicated, instr.predicate_condition,
true);
} }
UpdateInstructionPredicationAndEmitDisassembly(instr.is_predicated,
instr.predicate_condition);
bool store_result = false; bool store_result = false;
// Whether the result is only in X and all components should be remapped to X // Whether the result is only in X and all components should be remapped to X
@ -2964,31 +2897,6 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
UnloadDxbcSourceOperand(operand); UnloadDxbcSourceOperand(operand);
} }
// Re-enter conditional execution if closed it.
if (suppress_predication) {
// Re-enter exec-level predication.
if (cf_exec_predicated_) {
D3D10_SB_INSTRUCTION_TEST_BOOLEAN test =
cf_exec_predicate_condition_ ? D3D10_SB_INSTRUCTION_TEST_NONZERO
: D3D10_SB_INSTRUCTION_TEST_ZERO;
shader_code_.push_back(ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_IF) |
ENCODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(test) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(3));
shader_code_.push_back(EncodeVectorSelectOperand(
D3D10_SB_OPERAND_TYPE_TEMP, exec_p0_temp != UINT32_MAX ? 0 : 2, 1));
shader_code_.push_back(
exec_p0_temp != UINT32_MAX ? exec_p0_temp : system_temp_ps_pc_p0_a0_);
++stat_.instruction_count;
++stat_.dynamic_flow_control_count;
if (exec_p0_temp != UINT32_MAX) {
PopSystemTemp();
}
}
// Update instruction-level predication to the one needed by this tfetch.
UpdateInstructionPredication(instr.is_predicated, instr.predicate_condition,
false);
}
if (store_result) { if (store_result) {
StoreResult(instr.result, system_temp_pv_, replicate_result); StoreResult(instr.result, system_temp_pv_, replicate_result);
} }