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 src1;\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() {
|
||||
// End of master switch.
|
||||
EmitSourceDepth("default: pc = 0xFFFF; break;\n");
|
||||
EmitSourceDepth("}; // switch\n");
|
||||
Unindent();
|
||||
EmitSourceDepth("} // while\n");
|
||||
|
||||
// End of process*() function.
|
||||
EmitSource("}\n");
|
||||
|
||||
return source_.ToBytes();
|
||||
}
|
||||
|
||||
void GlslShaderTranslator::ProcessLabel(uint32_t cf_index) {
|
||||
EmitUnimplementedTranslationError();
|
||||
}
|
||||
void GlslShaderTranslator::ProcessLabel(uint32_t cf_index) {}
|
||||
|
||||
void GlslShaderTranslator::ProcessControlFlowNopInstruction() {
|
||||
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(
|
||||
const ParsedExecInstruction& instr) {
|
||||
EmitSource("// ");
|
||||
|
@ -330,6 +357,10 @@ void GlslShaderTranslator::ProcessExecInstructionEnd(
|
|||
const ParsedExecInstruction& instr) {
|
||||
Unindent();
|
||||
EmitSourceDepth("}\n");
|
||||
if (instr.is_end) {
|
||||
EmitSourceDepth("pc = 0xFFFF;\n");
|
||||
cf_wrote_pc_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GlslShaderTranslator::ProcessLoopStartInstruction(
|
||||
|
@ -369,7 +400,39 @@ void GlslShaderTranslator::ProcessJumpInstruction(
|
|||
EmitSource("// ");
|
||||
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(
|
||||
|
|
|
@ -40,6 +40,8 @@ class GlslShaderTranslator : public ShaderTranslator {
|
|||
|
||||
void ProcessLabel(uint32_t cf_index) 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 ProcessExecInstructionEnd(const ParsedExecInstruction& instr) override;
|
||||
void ProcessLoopStartInstruction(
|
||||
|
@ -70,6 +72,7 @@ class GlslShaderTranslator : public ShaderTranslator {
|
|||
StringBuffer source_;
|
||||
int depth_ = 0;
|
||||
char depth_prefix_[16] = {0};
|
||||
bool cf_wrote_pc_ = false;
|
||||
|
||||
void ProcessVectorAluInstruction(const ParsedAluInstruction& instr);
|
||||
void ProcessScalarAluInstruction(const ParsedAluInstruction& instr);
|
||||
|
|
|
@ -195,6 +195,8 @@ struct ParsedExecInstruction {
|
|||
// Required condition value of the comparision (true or false).
|
||||
bool condition = false;
|
||||
|
||||
// Whether this exec ends the shader.
|
||||
bool is_end = false;
|
||||
// Whether to reset the current predicate.
|
||||
bool clean = true;
|
||||
// ?
|
||||
|
|
|
@ -303,22 +303,28 @@ bool ShaderTranslator::TranslateBlocks() {
|
|||
ControlFlowInstruction cf_b;
|
||||
UnpackControlFlowInstructions(ucode_dwords_ + i, &cf_a, &cf_b);
|
||||
|
||||
cf_index_ = cf_index;
|
||||
MarkUcodeInstruction(i);
|
||||
if (label_addresses.count(cf_index)) {
|
||||
AppendUcodeDisasmFormat(" label L%u\n", cf_index);
|
||||
ProcessLabel(cf_index);
|
||||
}
|
||||
AppendUcodeDisasmFormat("/* %4u.0 */ ", cf_index / 2);
|
||||
ProcessControlFlowInstructionBegin(cf_index);
|
||||
TranslateControlFlowInstruction(cf_a);
|
||||
ProcessControlFlowInstructionEnd(cf_index);
|
||||
++cf_index;
|
||||
|
||||
cf_index_ = cf_index;
|
||||
MarkUcodeInstruction(i);
|
||||
if (label_addresses.count(cf_index)) {
|
||||
AppendUcodeDisasmFormat(" label L%u\n", cf_index);
|
||||
ProcessLabel(cf_index);
|
||||
}
|
||||
AppendUcodeDisasmFormat("/* %4u.1 */ ", cf_index / 2);
|
||||
ProcessControlFlowInstructionBegin(cf_index);
|
||||
TranslateControlFlowInstruction(cf_b);
|
||||
ProcessControlFlowInstructionEnd(cf_index);
|
||||
++cf_index;
|
||||
}
|
||||
|
||||
|
@ -399,12 +405,13 @@ void ShaderTranslator::TranslateControlFlowNop(
|
|||
void ShaderTranslator::TranslateControlFlowExec(
|
||||
const ControlFlowExecInstruction& cf) {
|
||||
ParsedExecInstruction i;
|
||||
i.dword_index = 0;
|
||||
i.dword_index = cf_index_;
|
||||
i.opcode = cf.opcode();
|
||||
i.opcode_name = cf.opcode() == ControlFlowOpcode::kExecEnd ? "exece" : "exec";
|
||||
i.instruction_address = cf.address();
|
||||
i.instruction_count = cf.count();
|
||||
i.type = ParsedExecInstruction::Type::kUnconditional;
|
||||
i.is_end = cf.opcode() == ControlFlowOpcode::kExecEnd;
|
||||
i.clean = cf.clean();
|
||||
i.is_yield = cf.is_yield();
|
||||
i.sequence = cf.sequence();
|
||||
|
@ -415,13 +422,14 @@ void ShaderTranslator::TranslateControlFlowExec(
|
|||
void ShaderTranslator::TranslateControlFlowCondExec(
|
||||
const ControlFlowCondExecInstruction& cf) {
|
||||
ParsedExecInstruction i;
|
||||
i.dword_index = 0;
|
||||
i.dword_index = cf_index_;
|
||||
i.opcode = cf.opcode();
|
||||
i.opcode_name = "cexec";
|
||||
switch (cf.opcode()) {
|
||||
case ControlFlowOpcode::kCondExecEnd:
|
||||
case ControlFlowOpcode::kCondExecPredCleanEnd:
|
||||
i.opcode_name = "cexece";
|
||||
i.is_end = true;
|
||||
break;
|
||||
}
|
||||
i.instruction_address = cf.address();
|
||||
|
@ -444,7 +452,7 @@ void ShaderTranslator::TranslateControlFlowCondExec(
|
|||
void ShaderTranslator::TranslateControlFlowCondExecPred(
|
||||
const ControlFlowCondExecPredInstruction& cf) {
|
||||
ParsedExecInstruction i;
|
||||
i.dword_index = 0;
|
||||
i.dword_index = cf_index_;
|
||||
i.opcode = cf.opcode();
|
||||
i.opcode_name =
|
||||
cf.opcode() == ControlFlowOpcode::kCondExecPredEnd ? "exece" : "exec";
|
||||
|
@ -452,6 +460,7 @@ void ShaderTranslator::TranslateControlFlowCondExecPred(
|
|||
i.instruction_count = cf.count();
|
||||
i.type = ParsedExecInstruction::Type::kPredicated;
|
||||
i.condition = cf.condition();
|
||||
i.is_end = cf.opcode() == ControlFlowOpcode::kCondExecPredEnd;
|
||||
i.clean = cf.clean();
|
||||
i.is_yield = cf.is_yield();
|
||||
i.sequence = cf.sequence();
|
||||
|
@ -462,7 +471,7 @@ void ShaderTranslator::TranslateControlFlowCondExecPred(
|
|||
void ShaderTranslator::TranslateControlFlowLoopStart(
|
||||
const ControlFlowLoopStartInstruction& cf) {
|
||||
ParsedLoopStartInstruction i;
|
||||
i.dword_index = 0;
|
||||
i.dword_index = cf_index_;
|
||||
i.loop_constant_index = cf.loop_id();
|
||||
i.is_repeat = cf.is_repeat();
|
||||
i.loop_skip_address = cf.address();
|
||||
|
@ -475,7 +484,7 @@ void ShaderTranslator::TranslateControlFlowLoopStart(
|
|||
void ShaderTranslator::TranslateControlFlowLoopEnd(
|
||||
const ControlFlowLoopEndInstruction& cf) {
|
||||
ParsedLoopEndInstruction i;
|
||||
i.dword_index = 0;
|
||||
i.dword_index = cf_index_;
|
||||
i.is_predicated_break = cf.is_predicated_break();
|
||||
i.predicate_condition = cf.condition();
|
||||
i.loop_constant_index = cf.loop_id();
|
||||
|
@ -489,7 +498,7 @@ void ShaderTranslator::TranslateControlFlowLoopEnd(
|
|||
void ShaderTranslator::TranslateControlFlowCondCall(
|
||||
const ControlFlowCondCallInstruction& cf) {
|
||||
ParsedCallInstruction i;
|
||||
i.dword_index = 0;
|
||||
i.dword_index = cf_index_;
|
||||
i.target_address = cf.address();
|
||||
if (cf.is_unconditional()) {
|
||||
i.type = ParsedCallInstruction::Type::kUnconditional;
|
||||
|
@ -510,7 +519,7 @@ void ShaderTranslator::TranslateControlFlowCondCall(
|
|||
void ShaderTranslator::TranslateControlFlowReturn(
|
||||
const ControlFlowReturnInstruction& cf) {
|
||||
ParsedReturnInstruction i;
|
||||
i.dword_index = 0;
|
||||
i.dword_index = cf_index_;
|
||||
|
||||
i.Disassemble(&ucode_disasm_buffer_);
|
||||
|
||||
|
@ -520,7 +529,7 @@ void ShaderTranslator::TranslateControlFlowReturn(
|
|||
void ShaderTranslator::TranslateControlFlowCondJmp(
|
||||
const ControlFlowCondJmpInstruction& cf) {
|
||||
ParsedJumpInstruction i;
|
||||
i.dword_index = 0;
|
||||
i.dword_index = cf_index_;
|
||||
i.target_address = cf.address();
|
||||
if (cf.is_unconditional()) {
|
||||
i.type = ParsedJumpInstruction::Type::kUnconditional;
|
||||
|
@ -541,7 +550,7 @@ void ShaderTranslator::TranslateControlFlowCondJmp(
|
|||
void ShaderTranslator::TranslateControlFlowAlloc(
|
||||
const ControlFlowAllocInstruction& cf) {
|
||||
ParsedAllocInstruction i;
|
||||
i.dword_index = 0;
|
||||
i.dword_index = cf_index_;
|
||||
i.type = cf.alloc_type();
|
||||
i.count = cf.size();
|
||||
i.is_vertex_shader = is_vertex_shader();
|
||||
|
|
|
@ -74,6 +74,11 @@ class ShaderTranslator {
|
|||
|
||||
// Handles translation for control flow nop instructions.
|
||||
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
|
||||
// contained ALU/fetch instructions.
|
||||
virtual void ProcessExecInstructionBegin(const ParsedExecInstruction& instr) {
|
||||
|
@ -166,6 +171,9 @@ class ShaderTranslator {
|
|||
// Accumulated translation errors.
|
||||
std::vector<Shader::Error> errors_;
|
||||
|
||||
// Current control flow dword index.
|
||||
uint32_t cf_index_ = 0;
|
||||
|
||||
// Microcode disassembly buffer, accumulated throughout the translation.
|
||||
StringBuffer ucode_disasm_buffer_;
|
||||
// Current line number in the disasm, which can be used for source annotation.
|
||||
|
|
Loading…
Reference in New Issue