Shader/GLSL: Fix CALLC not actually being conditional

This commit is contained in:
Tony Wasserka 2024-10-17 03:57:34 +02:00
parent 3cb55e40d2
commit 89ea258347

View file

@ -836,6 +836,29 @@ static std::string FunctionName(ShaderCodeOffset entry) {
// TODO: Un-global-ify
static std::map<int, std::string> reg_index_map;
static std::string WriteCondition(Instruction::FlowControlType instr) {
auto component = [&](int i) {
auto ref = (i == 0) ? instr.refx.Value() : instr.refy.Value();
return fmt::format("{}cond.{}", (ref ? "" : "!"), "xy"[i]);
};
using Op = Instruction::FlowControlType::Op;
switch (instr.op) {
case Op::Or:
return component(0) + " || " + component(1);
case Op::And:
return component(0) + " && " + component(1);
case Op::JustX:
return component(0);
case Op::JustY:
return component(1);
}
}
static std::string TranslateToGLSL(Context& context, Instruction instr) {
// TODO: Turn these into proper functions instead
static auto select_input_register = [](SourceRegister reg, std::optional<unsigned> address_register_index) {
@ -1187,11 +1210,17 @@ static std::string TranslateToGLSL(Context& context, Instruction instr) {
case OpCode::Id::CALL:
case OpCode::Id::CALLC:
case OpCode::Id::CALLU:
{
std::string prefix;
if (instr.opcode.Value() == OpCode::Id::CALLC) {
prefix = fmt::format("if ({}) ", WriteCondition(instr.flow_control));
}
if (instr.opcode.Value() != OpCode::Id::CALLU || context.shader_uniforms.b[instr.flow_control.bool_uniform_id]) {
return FunctionName(ShaderCodeOffset { instr.flow_control.dest_offset }) + "();";
return prefix + FunctionName(ShaderCodeOffset { instr.flow_control.dest_offset }) + "();";
} else {
return "// Conditional call (statically omitted)";
}
}
case OpCode::Id::IFU:
case OpCode::Id::IFC:
@ -1213,29 +1242,6 @@ static std::string TranslateToGLSL(Context& context, Instruction instr) {
}
}
static std::string WriteCondition(Instruction::FlowControlType instr) {
auto component = [&](int i) {
auto ref = (i == 0) ? instr.refx.Value() : instr.refy.Value();
return fmt::format("{}cond.{}", (ref ? "" : "!"), "xy"[i]);
};
using Op = Instruction::FlowControlType::Op;
switch (instr.op) {
case Op::Or:
return component(0) + " || " + component(1);
case Op::And:
return component(0) + " && " + component(1);
case Op::JustX:
return component(0);
case Op::JustY:
return component(1);
}
}
void WriteBlocksFromTo(Context& context, std::string& glsl, const AnalyzedProgram& program, const ShaderCodeOffset block_offset, const ShaderCodeOffset end) {
auto& block = program.blocks.at(block_offset);