Basic control flow skeleton and jumps implemented.
A-train's trees draw right now! Helps a bit with #473 but still need to implement loops.
This commit is contained in:
parent
934b0d5bbc
commit
280c0b35f6
|
@ -287,23 +287,50 @@ void main() {
|
||||||
EmitSource(" vec4 src0;\n");
|
EmitSource(" vec4 src0;\n");
|
||||||
EmitSource(" vec4 src1;\n");
|
EmitSource(" vec4 src1;\n");
|
||||||
EmitSource(" vec4 src2;\n");
|
EmitSource(" vec4 src2;\n");
|
||||||
|
|
||||||
|
// Master loop and switch for flow control.
|
||||||
|
EmitSourceDepth("int pc = 0;\n");
|
||||||
|
EmitSourceDepth("while (pc != 0xFFFF) {\n");
|
||||||
|
Indent();
|
||||||
|
EmitSourceDepth("switch (pc) {\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> GlslShaderTranslator::CompleteTranslation() {
|
std::vector<uint8_t> GlslShaderTranslator::CompleteTranslation() {
|
||||||
|
// End of master switch.
|
||||||
|
EmitSourceDepth("default: pc = 0xFFFF; break;\n");
|
||||||
|
EmitSourceDepth("}; // switch\n");
|
||||||
|
Unindent();
|
||||||
|
EmitSourceDepth("} // while\n");
|
||||||
|
|
||||||
// End of process*() function.
|
// End of process*() function.
|
||||||
EmitSource("}\n");
|
EmitSource("}\n");
|
||||||
|
|
||||||
return source_.ToBytes();
|
return source_.ToBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlslShaderTranslator::ProcessLabel(uint32_t cf_index) {
|
void GlslShaderTranslator::ProcessLabel(uint32_t cf_index) {}
|
||||||
EmitUnimplementedTranslationError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GlslShaderTranslator::ProcessControlFlowNopInstruction() {
|
void GlslShaderTranslator::ProcessControlFlowNopInstruction() {
|
||||||
EmitSource("// cnop\n");
|
EmitSource("// cnop\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlslShaderTranslator::ProcessControlFlowInstructionBegin(
|
||||||
|
uint32_t cf_index) {
|
||||||
|
cf_wrote_pc_ = false;
|
||||||
|
EmitSourceDepth("case 0x%X: // L%d\n", cf_index, cf_index);
|
||||||
|
Indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlslShaderTranslator::ProcessControlFlowInstructionEnd(uint32_t cf_index) {
|
||||||
|
if (!cf_wrote_pc_) {
|
||||||
|
uint32_t next_index = cf_index + 1;
|
||||||
|
EmitSourceDepth("pc = 0x%X; // Fallthrough to L%d\n", next_index,
|
||||||
|
next_index);
|
||||||
|
}
|
||||||
|
EmitSourceDepth("break;\n");
|
||||||
|
Unindent();
|
||||||
|
}
|
||||||
|
|
||||||
void GlslShaderTranslator::ProcessExecInstructionBegin(
|
void GlslShaderTranslator::ProcessExecInstructionBegin(
|
||||||
const ParsedExecInstruction& instr) {
|
const ParsedExecInstruction& instr) {
|
||||||
EmitSource("// ");
|
EmitSource("// ");
|
||||||
|
@ -330,6 +357,10 @@ void GlslShaderTranslator::ProcessExecInstructionEnd(
|
||||||
const ParsedExecInstruction& instr) {
|
const ParsedExecInstruction& instr) {
|
||||||
Unindent();
|
Unindent();
|
||||||
EmitSourceDepth("}\n");
|
EmitSourceDepth("}\n");
|
||||||
|
if (instr.is_end) {
|
||||||
|
EmitSourceDepth("pc = 0xFFFF;\n");
|
||||||
|
cf_wrote_pc_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlslShaderTranslator::ProcessLoopStartInstruction(
|
void GlslShaderTranslator::ProcessLoopStartInstruction(
|
||||||
|
@ -369,7 +400,39 @@ void GlslShaderTranslator::ProcessJumpInstruction(
|
||||||
EmitSource("// ");
|
EmitSource("// ");
|
||||||
instr.Disassemble(&source_);
|
instr.Disassemble(&source_);
|
||||||
|
|
||||||
EmitUnimplementedTranslationError();
|
bool needs_fallthrough = false;
|
||||||
|
switch (instr.type) {
|
||||||
|
case ParsedJumpInstruction::Type::kUnconditional:
|
||||||
|
EmitSourceDepth("{\n");
|
||||||
|
break;
|
||||||
|
case ParsedJumpInstruction::Type::kConditional:
|
||||||
|
EmitSourceDepth("if ((state.bool_consts[%d] & (1 << %d)) == %c) {\n",
|
||||||
|
instr.bool_constant_index / 32,
|
||||||
|
instr.bool_constant_index % 32,
|
||||||
|
instr.condition ? '1' : '0');
|
||||||
|
needs_fallthrough = true;
|
||||||
|
break;
|
||||||
|
case ParsedJumpInstruction::Type::kPredicated:
|
||||||
|
EmitSourceDepth("if (%cp0) {\n", instr.condition ? ' ' : '!');
|
||||||
|
needs_fallthrough = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Indent();
|
||||||
|
|
||||||
|
EmitSourceDepth("pc = 0x%X; // L%d\n", instr.target_address,
|
||||||
|
instr.target_address);
|
||||||
|
cf_wrote_pc_ = true;
|
||||||
|
|
||||||
|
Unindent();
|
||||||
|
if (needs_fallthrough) {
|
||||||
|
uint32_t next_address = instr.dword_index + 1;
|
||||||
|
EmitSourceDepth("} else {\n");
|
||||||
|
EmitSourceDepth(" pc = 0x%X; // Fallthrough to L%d\n", next_address,
|
||||||
|
next_address);
|
||||||
|
EmitSourceDepth("}\n");
|
||||||
|
} else {
|
||||||
|
EmitSourceDepth("}\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlslShaderTranslator::ProcessAllocInstruction(
|
void GlslShaderTranslator::ProcessAllocInstruction(
|
||||||
|
|
|
@ -40,6 +40,8 @@ class GlslShaderTranslator : public ShaderTranslator {
|
||||||
|
|
||||||
void ProcessLabel(uint32_t cf_index) override;
|
void ProcessLabel(uint32_t cf_index) override;
|
||||||
void ProcessControlFlowNopInstruction() override;
|
void ProcessControlFlowNopInstruction() 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(
|
||||||
|
@ -70,6 +72,7 @@ class GlslShaderTranslator : public ShaderTranslator {
|
||||||
StringBuffer source_;
|
StringBuffer source_;
|
||||||
int depth_ = 0;
|
int depth_ = 0;
|
||||||
char depth_prefix_[16] = {0};
|
char depth_prefix_[16] = {0};
|
||||||
|
bool cf_wrote_pc_ = false;
|
||||||
|
|
||||||
void ProcessVectorAluInstruction(const ParsedAluInstruction& instr);
|
void ProcessVectorAluInstruction(const ParsedAluInstruction& instr);
|
||||||
void ProcessScalarAluInstruction(const ParsedAluInstruction& instr);
|
void ProcessScalarAluInstruction(const ParsedAluInstruction& instr);
|
||||||
|
|
|
@ -195,6 +195,8 @@ struct ParsedExecInstruction {
|
||||||
// Required condition value of the comparision (true or false).
|
// Required condition value of the comparision (true or false).
|
||||||
bool condition = false;
|
bool condition = false;
|
||||||
|
|
||||||
|
// Whether this exec ends the shader.
|
||||||
|
bool is_end = false;
|
||||||
// Whether to reset the current predicate.
|
// Whether to reset the current predicate.
|
||||||
bool clean = true;
|
bool clean = true;
|
||||||
// ?
|
// ?
|
||||||
|
|
|
@ -303,22 +303,28 @@ bool ShaderTranslator::TranslateBlocks() {
|
||||||
ControlFlowInstruction cf_b;
|
ControlFlowInstruction cf_b;
|
||||||
UnpackControlFlowInstructions(ucode_dwords_ + i, &cf_a, &cf_b);
|
UnpackControlFlowInstructions(ucode_dwords_ + i, &cf_a, &cf_b);
|
||||||
|
|
||||||
|
cf_index_ = cf_index;
|
||||||
MarkUcodeInstruction(i);
|
MarkUcodeInstruction(i);
|
||||||
if (label_addresses.count(cf_index)) {
|
if (label_addresses.count(cf_index)) {
|
||||||
AppendUcodeDisasmFormat(" label L%u\n", cf_index);
|
AppendUcodeDisasmFormat(" label L%u\n", cf_index);
|
||||||
ProcessLabel(cf_index);
|
ProcessLabel(cf_index);
|
||||||
}
|
}
|
||||||
AppendUcodeDisasmFormat("/* %4u.0 */ ", cf_index / 2);
|
AppendUcodeDisasmFormat("/* %4u.0 */ ", cf_index / 2);
|
||||||
|
ProcessControlFlowInstructionBegin(cf_index);
|
||||||
TranslateControlFlowInstruction(cf_a);
|
TranslateControlFlowInstruction(cf_a);
|
||||||
|
ProcessControlFlowInstructionEnd(cf_index);
|
||||||
++cf_index;
|
++cf_index;
|
||||||
|
|
||||||
|
cf_index_ = cf_index;
|
||||||
MarkUcodeInstruction(i);
|
MarkUcodeInstruction(i);
|
||||||
if (label_addresses.count(cf_index)) {
|
if (label_addresses.count(cf_index)) {
|
||||||
AppendUcodeDisasmFormat(" label L%u\n", cf_index);
|
AppendUcodeDisasmFormat(" label L%u\n", cf_index);
|
||||||
ProcessLabel(cf_index);
|
ProcessLabel(cf_index);
|
||||||
}
|
}
|
||||||
AppendUcodeDisasmFormat("/* %4u.1 */ ", cf_index / 2);
|
AppendUcodeDisasmFormat("/* %4u.1 */ ", cf_index / 2);
|
||||||
|
ProcessControlFlowInstructionBegin(cf_index);
|
||||||
TranslateControlFlowInstruction(cf_b);
|
TranslateControlFlowInstruction(cf_b);
|
||||||
|
ProcessControlFlowInstructionEnd(cf_index);
|
||||||
++cf_index;
|
++cf_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,12 +405,13 @@ void ShaderTranslator::TranslateControlFlowNop(
|
||||||
void ShaderTranslator::TranslateControlFlowExec(
|
void ShaderTranslator::TranslateControlFlowExec(
|
||||||
const ControlFlowExecInstruction& cf) {
|
const ControlFlowExecInstruction& cf) {
|
||||||
ParsedExecInstruction i;
|
ParsedExecInstruction i;
|
||||||
i.dword_index = 0;
|
i.dword_index = cf_index_;
|
||||||
i.opcode = cf.opcode();
|
i.opcode = cf.opcode();
|
||||||
i.opcode_name = cf.opcode() == ControlFlowOpcode::kExecEnd ? "exece" : "exec";
|
i.opcode_name = cf.opcode() == ControlFlowOpcode::kExecEnd ? "exece" : "exec";
|
||||||
i.instruction_address = cf.address();
|
i.instruction_address = cf.address();
|
||||||
i.instruction_count = cf.count();
|
i.instruction_count = cf.count();
|
||||||
i.type = ParsedExecInstruction::Type::kUnconditional;
|
i.type = ParsedExecInstruction::Type::kUnconditional;
|
||||||
|
i.is_end = cf.opcode() == ControlFlowOpcode::kExecEnd;
|
||||||
i.clean = cf.clean();
|
i.clean = cf.clean();
|
||||||
i.is_yield = cf.is_yield();
|
i.is_yield = cf.is_yield();
|
||||||
i.sequence = cf.sequence();
|
i.sequence = cf.sequence();
|
||||||
|
@ -415,13 +422,14 @@ void ShaderTranslator::TranslateControlFlowExec(
|
||||||
void ShaderTranslator::TranslateControlFlowCondExec(
|
void ShaderTranslator::TranslateControlFlowCondExec(
|
||||||
const ControlFlowCondExecInstruction& cf) {
|
const ControlFlowCondExecInstruction& cf) {
|
||||||
ParsedExecInstruction i;
|
ParsedExecInstruction i;
|
||||||
i.dword_index = 0;
|
i.dword_index = cf_index_;
|
||||||
i.opcode = cf.opcode();
|
i.opcode = cf.opcode();
|
||||||
i.opcode_name = "cexec";
|
i.opcode_name = "cexec";
|
||||||
switch (cf.opcode()) {
|
switch (cf.opcode()) {
|
||||||
case ControlFlowOpcode::kCondExecEnd:
|
case ControlFlowOpcode::kCondExecEnd:
|
||||||
case ControlFlowOpcode::kCondExecPredCleanEnd:
|
case ControlFlowOpcode::kCondExecPredCleanEnd:
|
||||||
i.opcode_name = "cexece";
|
i.opcode_name = "cexece";
|
||||||
|
i.is_end = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i.instruction_address = cf.address();
|
i.instruction_address = cf.address();
|
||||||
|
@ -444,7 +452,7 @@ void ShaderTranslator::TranslateControlFlowCondExec(
|
||||||
void ShaderTranslator::TranslateControlFlowCondExecPred(
|
void ShaderTranslator::TranslateControlFlowCondExecPred(
|
||||||
const ControlFlowCondExecPredInstruction& cf) {
|
const ControlFlowCondExecPredInstruction& cf) {
|
||||||
ParsedExecInstruction i;
|
ParsedExecInstruction i;
|
||||||
i.dword_index = 0;
|
i.dword_index = cf_index_;
|
||||||
i.opcode = cf.opcode();
|
i.opcode = cf.opcode();
|
||||||
i.opcode_name =
|
i.opcode_name =
|
||||||
cf.opcode() == ControlFlowOpcode::kCondExecPredEnd ? "exece" : "exec";
|
cf.opcode() == ControlFlowOpcode::kCondExecPredEnd ? "exece" : "exec";
|
||||||
|
@ -452,6 +460,7 @@ void ShaderTranslator::TranslateControlFlowCondExecPred(
|
||||||
i.instruction_count = cf.count();
|
i.instruction_count = cf.count();
|
||||||
i.type = ParsedExecInstruction::Type::kPredicated;
|
i.type = ParsedExecInstruction::Type::kPredicated;
|
||||||
i.condition = cf.condition();
|
i.condition = cf.condition();
|
||||||
|
i.is_end = cf.opcode() == ControlFlowOpcode::kCondExecPredEnd;
|
||||||
i.clean = cf.clean();
|
i.clean = cf.clean();
|
||||||
i.is_yield = cf.is_yield();
|
i.is_yield = cf.is_yield();
|
||||||
i.sequence = cf.sequence();
|
i.sequence = cf.sequence();
|
||||||
|
@ -462,7 +471,7 @@ void ShaderTranslator::TranslateControlFlowCondExecPred(
|
||||||
void ShaderTranslator::TranslateControlFlowLoopStart(
|
void ShaderTranslator::TranslateControlFlowLoopStart(
|
||||||
const ControlFlowLoopStartInstruction& cf) {
|
const ControlFlowLoopStartInstruction& cf) {
|
||||||
ParsedLoopStartInstruction i;
|
ParsedLoopStartInstruction i;
|
||||||
i.dword_index = 0;
|
i.dword_index = cf_index_;
|
||||||
i.loop_constant_index = cf.loop_id();
|
i.loop_constant_index = cf.loop_id();
|
||||||
i.is_repeat = cf.is_repeat();
|
i.is_repeat = cf.is_repeat();
|
||||||
i.loop_skip_address = cf.address();
|
i.loop_skip_address = cf.address();
|
||||||
|
@ -475,7 +484,7 @@ void ShaderTranslator::TranslateControlFlowLoopStart(
|
||||||
void ShaderTranslator::TranslateControlFlowLoopEnd(
|
void ShaderTranslator::TranslateControlFlowLoopEnd(
|
||||||
const ControlFlowLoopEndInstruction& cf) {
|
const ControlFlowLoopEndInstruction& cf) {
|
||||||
ParsedLoopEndInstruction i;
|
ParsedLoopEndInstruction i;
|
||||||
i.dword_index = 0;
|
i.dword_index = cf_index_;
|
||||||
i.is_predicated_break = cf.is_predicated_break();
|
i.is_predicated_break = cf.is_predicated_break();
|
||||||
i.predicate_condition = cf.condition();
|
i.predicate_condition = cf.condition();
|
||||||
i.loop_constant_index = cf.loop_id();
|
i.loop_constant_index = cf.loop_id();
|
||||||
|
@ -489,7 +498,7 @@ void ShaderTranslator::TranslateControlFlowLoopEnd(
|
||||||
void ShaderTranslator::TranslateControlFlowCondCall(
|
void ShaderTranslator::TranslateControlFlowCondCall(
|
||||||
const ControlFlowCondCallInstruction& cf) {
|
const ControlFlowCondCallInstruction& cf) {
|
||||||
ParsedCallInstruction i;
|
ParsedCallInstruction i;
|
||||||
i.dword_index = 0;
|
i.dword_index = cf_index_;
|
||||||
i.target_address = cf.address();
|
i.target_address = cf.address();
|
||||||
if (cf.is_unconditional()) {
|
if (cf.is_unconditional()) {
|
||||||
i.type = ParsedCallInstruction::Type::kUnconditional;
|
i.type = ParsedCallInstruction::Type::kUnconditional;
|
||||||
|
@ -510,7 +519,7 @@ void ShaderTranslator::TranslateControlFlowCondCall(
|
||||||
void ShaderTranslator::TranslateControlFlowReturn(
|
void ShaderTranslator::TranslateControlFlowReturn(
|
||||||
const ControlFlowReturnInstruction& cf) {
|
const ControlFlowReturnInstruction& cf) {
|
||||||
ParsedReturnInstruction i;
|
ParsedReturnInstruction i;
|
||||||
i.dword_index = 0;
|
i.dword_index = cf_index_;
|
||||||
|
|
||||||
i.Disassemble(&ucode_disasm_buffer_);
|
i.Disassemble(&ucode_disasm_buffer_);
|
||||||
|
|
||||||
|
@ -520,7 +529,7 @@ void ShaderTranslator::TranslateControlFlowReturn(
|
||||||
void ShaderTranslator::TranslateControlFlowCondJmp(
|
void ShaderTranslator::TranslateControlFlowCondJmp(
|
||||||
const ControlFlowCondJmpInstruction& cf) {
|
const ControlFlowCondJmpInstruction& cf) {
|
||||||
ParsedJumpInstruction i;
|
ParsedJumpInstruction i;
|
||||||
i.dword_index = 0;
|
i.dword_index = cf_index_;
|
||||||
i.target_address = cf.address();
|
i.target_address = cf.address();
|
||||||
if (cf.is_unconditional()) {
|
if (cf.is_unconditional()) {
|
||||||
i.type = ParsedJumpInstruction::Type::kUnconditional;
|
i.type = ParsedJumpInstruction::Type::kUnconditional;
|
||||||
|
@ -541,7 +550,7 @@ void ShaderTranslator::TranslateControlFlowCondJmp(
|
||||||
void ShaderTranslator::TranslateControlFlowAlloc(
|
void ShaderTranslator::TranslateControlFlowAlloc(
|
||||||
const ControlFlowAllocInstruction& cf) {
|
const ControlFlowAllocInstruction& cf) {
|
||||||
ParsedAllocInstruction i;
|
ParsedAllocInstruction i;
|
||||||
i.dword_index = 0;
|
i.dword_index = cf_index_;
|
||||||
i.type = cf.alloc_type();
|
i.type = cf.alloc_type();
|
||||||
i.count = cf.size();
|
i.count = cf.size();
|
||||||
i.is_vertex_shader = is_vertex_shader();
|
i.is_vertex_shader = is_vertex_shader();
|
||||||
|
|
|
@ -74,6 +74,11 @@ class ShaderTranslator {
|
||||||
|
|
||||||
// Handles translation for control flow nop instructions.
|
// Handles translation for control flow nop instructions.
|
||||||
virtual void ProcessControlFlowNopInstruction() {}
|
virtual void ProcessControlFlowNopInstruction() {}
|
||||||
|
// Handles the start of a control flow instruction at the given address.
|
||||||
|
virtual void ProcessControlFlowInstructionBegin(uint32_t cf_index) {}
|
||||||
|
// Handles the end of a control flow instruction that began at the given
|
||||||
|
// address.
|
||||||
|
virtual void ProcessControlFlowInstructionEnd(uint32_t cf_index) {}
|
||||||
// Handles translation for control flow exec instructions prior to their
|
// Handles translation for control flow exec instructions prior to their
|
||||||
// contained ALU/fetch instructions.
|
// contained ALU/fetch instructions.
|
||||||
virtual void ProcessExecInstructionBegin(const ParsedExecInstruction& instr) {
|
virtual void ProcessExecInstructionBegin(const ParsedExecInstruction& instr) {
|
||||||
|
@ -166,6 +171,9 @@ class ShaderTranslator {
|
||||||
// Accumulated translation errors.
|
// Accumulated translation errors.
|
||||||
std::vector<Shader::Error> errors_;
|
std::vector<Shader::Error> errors_;
|
||||||
|
|
||||||
|
// Current control flow dword index.
|
||||||
|
uint32_t cf_index_ = 0;
|
||||||
|
|
||||||
// Microcode disassembly buffer, accumulated throughout the translation.
|
// Microcode disassembly buffer, accumulated throughout the translation.
|
||||||
StringBuffer ucode_disasm_buffer_;
|
StringBuffer ucode_disasm_buffer_;
|
||||||
// Current line number in the disasm, which can be used for source annotation.
|
// Current line number in the disasm, which can be used for source annotation.
|
||||||
|
|
Loading…
Reference in New Issue