[D3D12] HLSL compilation fixes (still can't map one Halo 3 shader to vs_5_1)
This commit is contained in:
parent
7ba2526fa8
commit
36cc19017a
|
@ -34,7 +34,6 @@ void HlslShaderTranslator::Reset() {
|
||||||
depth_ = 0;
|
depth_ = 0;
|
||||||
depth_prefix_[0] = 0;
|
depth_prefix_[0] = 0;
|
||||||
|
|
||||||
cf_wrote_pc_ = false;
|
|
||||||
cf_exec_pred_ = false;
|
cf_exec_pred_ = false;
|
||||||
cf_exec_pred_cond_ = false;
|
cf_exec_pred_cond_ = false;
|
||||||
|
|
||||||
|
@ -71,11 +70,11 @@ void HlslShaderTranslator::Unindent() {
|
||||||
void HlslShaderTranslator::StartTranslation() {
|
void HlslShaderTranslator::StartTranslation() {
|
||||||
// Main function level (1).
|
// Main function level (1).
|
||||||
Indent();
|
Indent();
|
||||||
// Do while PC != 0xFFFF level (2).
|
// While level (2).
|
||||||
Indent();
|
Indent();
|
||||||
// Switch level (3).
|
EmitSourceDepth("[branch] if (xe_pc == 0u) {\n");
|
||||||
|
// If level (3).
|
||||||
Indent();
|
Indent();
|
||||||
EmitSourceDepth("case 0u:\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> HlslShaderTranslator::CompleteTranslation() {
|
std::vector<uint8_t> HlslShaderTranslator::CompleteTranslation() {
|
||||||
|
@ -85,8 +84,11 @@ std::vector<uint8_t> HlslShaderTranslator::CompleteTranslation() {
|
||||||
// Common preprocessor statements.
|
// Common preprocessor statements.
|
||||||
// 3557 is the "loop only executes for 1 iteration" warning caused by the
|
// 3557 is the "loop only executes for 1 iteration" warning caused by the
|
||||||
// control flow loop design.
|
// control flow loop design.
|
||||||
|
// 3595 is for texture fetches in loops/conditionals, which may have undefined
|
||||||
|
// gradients.
|
||||||
source.Append(
|
source.Append(
|
||||||
"#pragma warning(disable : 3557)\n"
|
"#pragma warning(disable : 3557)\n"
|
||||||
|
"#pragma warning(disable : 3595)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#define XE_FLT_MAX 3.402823466e+38\n"
|
"#define XE_FLT_MAX 3.402823466e+38\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
@ -355,27 +357,22 @@ std::vector<uint8_t> HlslShaderTranslator::CompleteTranslation() {
|
||||||
// Explicit gradients for texture fetches.
|
// Explicit gradients for texture fetches.
|
||||||
" float3 xe_texture_grad_h = float3(0.0, 0.0, 0.0);\n"
|
" float3 xe_texture_grad_h = float3(0.0, 0.0, 0.0);\n"
|
||||||
" float3 xe_texture_grad_v = float3(0.0, 0.0, 0.0);\n"
|
" float3 xe_texture_grad_v = float3(0.0, 0.0, 0.0);\n"
|
||||||
// Master loop and switch for flow control.
|
// Master loop and instruction pointer for flow control.
|
||||||
|
// It's very easy to cause internal compiler errors with anything related
|
||||||
|
// to flow control. Switch, for example, used to cause "l-value expected",
|
||||||
|
// so it was replaced with ifs (and also it's easy to fall through).
|
||||||
" uint xe_pc = 0u;\n"
|
" uint xe_pc = 0u;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" do {\n"
|
" [loop] while (xe_pc < 0xFFFFu) {\n");
|
||||||
" switch (xe_pc) {\n");
|
|
||||||
|
|
||||||
// Translated code.
|
// Translated code.
|
||||||
source.Append(source_inner_.GetString());
|
source.Append(source_inner_.GetString());
|
||||||
|
|
||||||
// Epilogue.
|
// Epilogue.
|
||||||
if (!cf_wrote_pc_) {
|
|
||||||
source.Append(
|
|
||||||
" xe_pc = 0xFFFFu;\n"
|
|
||||||
" break;\n");
|
|
||||||
}
|
|
||||||
source.Append(
|
source.Append(
|
||||||
" default:\n"
|
|
||||||
" xe_pc = 0xFFFFu;\n"
|
|
||||||
" break;\n"
|
|
||||||
" }\n"
|
" }\n"
|
||||||
" } while (xe_pc != 0xFFFFu);\n");
|
" xe_pc = 0xFFFFu;\n"
|
||||||
|
" }\n");
|
||||||
if (is_vertex_shader()) {
|
if (is_vertex_shader()) {
|
||||||
// Restore the original W if the shader has already taken its reciprocal,
|
// Restore the original W if the shader has already taken its reciprocal,
|
||||||
// and restore the original XYZ if the shader has divided them by W. Also
|
// and restore the original XYZ if the shader has divided them by W. Also
|
||||||
|
@ -424,39 +421,19 @@ std::vector<uint8_t> HlslShaderTranslator::CompleteTranslation() {
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessLabel(uint32_t cf_index) {
|
void HlslShaderTranslator::ProcessLabel(uint32_t cf_index) {
|
||||||
// 0 is always added in the beginning.
|
// 0 is always added in the beginning.
|
||||||
if (cf_index != 0) {
|
if (cf_index == 0) {
|
||||||
if (!cf_wrote_pc_) {
|
return;
|
||||||
EmitSourceDepth(" xe_pc = %uu;\n", cf_index);
|
|
||||||
EmitSourceDepth(" break;\n");
|
|
||||||
}
|
|
||||||
EmitSourceDepth("case %uu:\n", cf_index);
|
|
||||||
cf_wrote_pc_ = false;
|
|
||||||
}
|
}
|
||||||
|
Unindent();
|
||||||
|
EmitSourceDepth("}\n");
|
||||||
|
EmitSourceDepth("[branch] if (xe_pc <= %uu) {\n", cf_index);
|
||||||
|
Indent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessControlFlowNopInstruction(uint32_t cf_index) {
|
void HlslShaderTranslator::ProcessControlFlowNopInstruction(uint32_t cf_index) {
|
||||||
EmitSourceDepth("// cnop\n");
|
EmitSourceDepth("// cnop\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessControlFlowInstructionBegin(
|
|
||||||
uint32_t cf_index) {
|
|
||||||
if (cf_wrote_pc_) {
|
|
||||||
// In case there are instructions after setting the PC and breaking (if
|
|
||||||
// there's an `if` setting the PC, there's an `else` setting the PC as well
|
|
||||||
// for falling through).
|
|
||||||
EmitSourceDepth("case %uu:\n", cf_index);
|
|
||||||
cf_wrote_pc_ = false;
|
|
||||||
}
|
|
||||||
Indent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessControlFlowInstructionEnd(uint32_t cf_index) {
|
|
||||||
if (!cf_wrote_pc_) {
|
|
||||||
EmitSourceDepth("// Falling through to L%u\n", cf_index + 1);
|
|
||||||
}
|
|
||||||
Unindent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessExecInstructionBegin(
|
void HlslShaderTranslator::ProcessExecInstructionBegin(
|
||||||
const ParsedExecInstruction& instr) {
|
const ParsedExecInstruction& instr) {
|
||||||
EmitSourceDepth("// ");
|
EmitSourceDepth("// ");
|
||||||
|
@ -468,15 +445,15 @@ void HlslShaderTranslator::ProcessExecInstructionBegin(
|
||||||
EmitSourceDepth("{\n");
|
EmitSourceDepth("{\n");
|
||||||
break;
|
break;
|
||||||
case ParsedExecInstruction::Type::kConditional:
|
case ParsedExecInstruction::Type::kConditional:
|
||||||
EmitSourceDepth("if ((xe_bool_constants[%u].x & (1u << %uu)) %c= 0u) {\n",
|
EmitSourceDepth(
|
||||||
instr.bool_constant_index >> 5,
|
"[branch] if ((xe_bool_constants[%u].x & (1u << %uu)) %c= 0u) {\n",
|
||||||
instr.bool_constant_index & 31,
|
instr.bool_constant_index >> 5, instr.bool_constant_index & 31,
|
||||||
instr.condition ? '!' : '=');
|
instr.condition ? '!' : '=');
|
||||||
break;
|
break;
|
||||||
case ParsedExecInstruction::Type::kPredicated:
|
case ParsedExecInstruction::Type::kPredicated:
|
||||||
cf_exec_pred_ = true;
|
cf_exec_pred_ = true;
|
||||||
cf_exec_pred_cond_ = instr.condition;
|
cf_exec_pred_cond_ = instr.condition;
|
||||||
EmitSourceDepth("if (%cxe_p0) {\n", instr.condition ? ' ' : '!');
|
EmitSourceDepth("[branch] if (%cxe_p0) {\n", instr.condition ? ' ' : '!');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Indent();
|
Indent();
|
||||||
|
@ -484,13 +461,14 @@ void HlslShaderTranslator::ProcessExecInstructionBegin(
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessExecInstructionEnd(
|
void HlslShaderTranslator::ProcessExecInstructionEnd(
|
||||||
const ParsedExecInstruction& instr) {
|
const ParsedExecInstruction& instr) {
|
||||||
|
if (instr.is_end) {
|
||||||
|
// Break causes internal errors, set PC to 0xFFFF and go to the next
|
||||||
|
// iteration.
|
||||||
|
EmitSourceDepth("xe_pc = 0xFFFFu;\n");
|
||||||
|
EmitSourceDepth("continue;\n");
|
||||||
|
}
|
||||||
Unindent();
|
Unindent();
|
||||||
EmitSourceDepth("}\n");
|
EmitSourceDepth("}\n");
|
||||||
if (instr.is_end) {
|
|
||||||
EmitSourceDepth("xe_pc = 0xFFFFu;\n");
|
|
||||||
EmitSourceDepth("break;\n");
|
|
||||||
cf_wrote_pc_ = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessLoopStartInstruction(
|
void HlslShaderTranslator::ProcessLoopStartInstruction(
|
||||||
|
@ -512,15 +490,11 @@ void HlslShaderTranslator::ProcessLoopStartInstruction(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quick skip loop if zero count.
|
// Quick skip loop if zero count.
|
||||||
EmitSourceDepth("if (xe_loop_count.x == 0u) {\n");
|
EmitSourceDepth("[branch] if (xe_loop_count.x == 0u) {\n");
|
||||||
EmitSourceDepth(" xe_pc = %uu; // Skip loop to L%u\n",
|
EmitSourceDepth(" xe_pc = %uu; // Skip loop to L%u\n",
|
||||||
instr.loop_skip_address, instr.loop_skip_address);
|
instr.loop_skip_address, instr.loop_skip_address);
|
||||||
EmitSourceDepth("} else {\n");
|
EmitSourceDepth(" continue;\n");
|
||||||
EmitSourceDepth(" xe_pc = %uu; // Fallthrough to loop body L%u\n",
|
|
||||||
instr.dword_index + 1, instr.dword_index + 1);
|
|
||||||
EmitSourceDepth("}\n");
|
EmitSourceDepth("}\n");
|
||||||
EmitSourceDepth("break;\n");
|
|
||||||
cf_wrote_pc_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessLoopEndInstruction(
|
void HlslShaderTranslator::ProcessLoopEndInstruction(
|
||||||
|
@ -529,38 +503,31 @@ void HlslShaderTranslator::ProcessLoopEndInstruction(
|
||||||
instr.Disassemble(&source_inner_);
|
instr.Disassemble(&source_inner_);
|
||||||
|
|
||||||
// Decrement loop counter, and if we are done break out.
|
// Decrement loop counter, and if we are done break out.
|
||||||
EmitSourceDepth("if (--xe_loop_count.x == 0u");
|
EmitSourceDepth("[branch] if (--xe_loop_count.x == 0u");
|
||||||
if (instr.is_predicated_break) {
|
if (instr.is_predicated_break) {
|
||||||
// If the predicate condition is met we 'break;' out of the loop.
|
// If the predicate condition is met we break out of the loop.
|
||||||
// Need to restore stack and fall through to the next cf.
|
// Need to restore stack and fall through to the next cf.
|
||||||
EmitSource(" || %cxe_p0) {\n", instr.predicate_condition ? ' ' : '!');
|
EmitSource(" || %cxe_p0) {\n", instr.predicate_condition ? ' ' : '!');
|
||||||
} else {
|
} else {
|
||||||
EmitSource(") {\n");
|
EmitSource(") {\n");
|
||||||
}
|
}
|
||||||
Indent();
|
Indent();
|
||||||
|
|
||||||
// Loop completed - pop and fall through to next cf.
|
// Loop completed - pop and fall through to next cf.
|
||||||
EmitSourceDepth("xe_loop_count.xyz = xe_loop_count.yzw;\n");
|
EmitSourceDepth("xe_loop_count.xyz = xe_loop_count.yzw;\n");
|
||||||
EmitSourceDepth("xe_loop_count.w = 0u;\n");
|
EmitSourceDepth("xe_loop_count.w = 0u;\n");
|
||||||
EmitSourceDepth("xe_aL.xyz = xe_aL.yzw;\n");
|
EmitSourceDepth("xe_aL.xyz = xe_aL.yzw;\n");
|
||||||
EmitSourceDepth("xe_aL.w = 0;\n");
|
EmitSourceDepth("xe_aL.w = 0;\n");
|
||||||
EmitSourceDepth("xe_pc = %uu; // Exit loop to L%u\n", instr.dword_index + 1,
|
|
||||||
instr.dword_index + 1);
|
|
||||||
|
|
||||||
Unindent();
|
Unindent();
|
||||||
EmitSourceDepth("} else {\n");
|
EmitSourceDepth("} else {\n");
|
||||||
Indent();
|
Indent();
|
||||||
|
|
||||||
// Still looping. Adjust index and jump back to body.
|
// Still looping. Adjust index and jump back to body.
|
||||||
EmitSourceDepth("xe_aL.x += int(xe_loop_constants[%u].x << 8u) >> 24;\n",
|
EmitSourceDepth("xe_aL.x += int(xe_loop_constants[%u].x << 8u) >> 24;\n",
|
||||||
instr.loop_constant_index);
|
instr.loop_constant_index);
|
||||||
EmitSourceDepth("xe_pc = %uu; // Loop back to body L%u\n",
|
EmitSourceDepth("xe_pc = %uu; // Loop back to body L%u\n",
|
||||||
instr.loop_body_address, instr.loop_body_address);
|
instr.loop_body_address, instr.loop_body_address);
|
||||||
|
EmitSourceDepth("continue;\n");
|
||||||
Unindent();
|
Unindent();
|
||||||
EmitSourceDepth("}\n");
|
EmitSourceDepth("}\n");
|
||||||
EmitSourceDepth("break;\n");
|
|
||||||
cf_wrote_pc_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessCallInstruction(
|
void HlslShaderTranslator::ProcessCallInstruction(
|
||||||
|
@ -589,14 +556,14 @@ void HlslShaderTranslator::ProcessJumpInstruction(
|
||||||
case ParsedJumpInstruction::Type::kUnconditional:
|
case ParsedJumpInstruction::Type::kUnconditional:
|
||||||
break;
|
break;
|
||||||
case ParsedJumpInstruction::Type::kConditional:
|
case ParsedJumpInstruction::Type::kConditional:
|
||||||
EmitSourceDepth("if ((xe_bool_constants[%u].x & (1u << %uu)) %c= 0u) {\n",
|
EmitSourceDepth(
|
||||||
instr.bool_constant_index >> 5,
|
"[branch] if ((xe_bool_constants[%u].x & (1u << %uu)) %c= 0u) {\n",
|
||||||
instr.bool_constant_index & 31,
|
instr.bool_constant_index >> 5, instr.bool_constant_index & 31,
|
||||||
instr.condition ? '!' : '=');
|
instr.condition ? '!' : '=');
|
||||||
conditional = true;
|
conditional = true;
|
||||||
break;
|
break;
|
||||||
case ParsedJumpInstruction::Type::kPredicated:
|
case ParsedJumpInstruction::Type::kPredicated:
|
||||||
EmitSourceDepth("if (%cxe_p0) {\n", instr.condition ? ' ' : '!');
|
EmitSourceDepth("[branch] if (%cxe_p0) {\n", instr.condition ? ' ' : '!');
|
||||||
conditional = true;
|
conditional = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -605,16 +572,11 @@ void HlslShaderTranslator::ProcessJumpInstruction(
|
||||||
}
|
}
|
||||||
EmitSourceDepth("xe_pc = %uu; // L%u\n", instr.target_address,
|
EmitSourceDepth("xe_pc = %uu; // L%u\n", instr.target_address,
|
||||||
instr.target_address);
|
instr.target_address);
|
||||||
|
EmitSourceDepth("continue;\n");
|
||||||
if (conditional) {
|
if (conditional) {
|
||||||
Unindent();
|
Unindent();
|
||||||
uint32_t next_address = instr.dword_index + 1;
|
|
||||||
EmitSourceDepth("} else {\n");
|
|
||||||
EmitSourceDepth(" xe_pc = %uu; // Fallthrough to L%u\n", next_address,
|
|
||||||
next_address);
|
|
||||||
EmitSourceDepth("}\n");
|
EmitSourceDepth("}\n");
|
||||||
}
|
}
|
||||||
EmitSourceDepth("break;\n");
|
|
||||||
cf_wrote_pc_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlslShaderTranslator::ProcessAllocInstruction(
|
void HlslShaderTranslator::ProcessAllocInstruction(
|
||||||
|
@ -627,7 +589,8 @@ bool HlslShaderTranslator::BeginPredicatedInstruction(
|
||||||
bool is_predicated, bool predicate_condition) {
|
bool is_predicated, bool predicate_condition) {
|
||||||
if (is_predicated &&
|
if (is_predicated &&
|
||||||
(!cf_exec_pred_ || cf_exec_pred_cond_ != predicate_condition)) {
|
(!cf_exec_pred_ || cf_exec_pred_cond_ != predicate_condition)) {
|
||||||
EmitSourceDepth("if (%cxe_p0) {\n", predicate_condition ? ' ' : '!');
|
EmitSourceDepth("[branch] if (%cxe_p0) {\n",
|
||||||
|
predicate_condition ? ' ' : '!');
|
||||||
Indent();
|
Indent();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,8 +72,6 @@ class HlslShaderTranslator : public ShaderTranslator {
|
||||||
void ProcessLabel(uint32_t cf_index) override;
|
void ProcessLabel(uint32_t cf_index) override;
|
||||||
|
|
||||||
void ProcessControlFlowNopInstruction(uint32_t cf_index) override;
|
void ProcessControlFlowNopInstruction(uint32_t cf_index) override;
|
||||||
void ProcessControlFlowInstructionBegin(uint32_t cf_index) override;
|
|
||||||
void ProcessControlFlowInstructionEnd(uint32_t cf_index) override;
|
|
||||||
void ProcessExecInstructionBegin(const ParsedExecInstruction& instr) override;
|
void ProcessExecInstructionBegin(const ParsedExecInstruction& instr) override;
|
||||||
void ProcessExecInstructionEnd(const ParsedExecInstruction& instr) override;
|
void ProcessExecInstructionEnd(const ParsedExecInstruction& instr) override;
|
||||||
void ProcessLoopStartInstruction(
|
void ProcessLoopStartInstruction(
|
||||||
|
@ -106,7 +104,6 @@ class HlslShaderTranslator : public ShaderTranslator {
|
||||||
uint32_t depth_ = 0;
|
uint32_t depth_ = 0;
|
||||||
char depth_prefix_[32] = {0};
|
char depth_prefix_[32] = {0};
|
||||||
|
|
||||||
bool cf_wrote_pc_ = false;
|
|
||||||
bool cf_exec_pred_ = false;
|
bool cf_exec_pred_ = false;
|
||||||
bool cf_exec_pred_cond_ = false;
|
bool cf_exec_pred_cond_ = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue