diff options
Diffstat (limited to 'src/shader_recompiler/backend/glasm/emit_glasm.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm.cpp | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 59d7c0f96..65600f58c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp | |||
| @@ -50,7 +50,7 @@ template <auto func, bool is_first_arg_inst, size_t... I> | |||
| 50 | void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence<I...>) { | 50 | void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence<I...>) { |
| 51 | using Traits = FuncTraits<decltype(func)>; | 51 | using Traits = FuncTraits<decltype(func)>; |
| 52 | if constexpr (is_first_arg_inst) { | 52 | if constexpr (is_first_arg_inst) { |
| 53 | func(ctx, inst, Arg<typename Traits::template ArgType<I + 2>>(ctx, inst->Arg(I))...); | 53 | func(ctx, *inst, Arg<typename Traits::template ArgType<I + 2>>(ctx, inst->Arg(I))...); |
| 54 | } else { | 54 | } else { |
| 55 | func(ctx, Arg<typename Traits::template ArgType<I + 1>>(ctx, inst->Arg(I))...); | 55 | func(ctx, Arg<typename Traits::template ArgType<I + 1>>(ctx, inst->Arg(I))...); |
| 56 | } | 56 | } |
| @@ -64,7 +64,7 @@ void Invoke(EmitContext& ctx, IR::Inst* inst) { | |||
| 64 | Invoke<func, false>(ctx, inst, std::make_index_sequence<0>{}); | 64 | Invoke<func, false>(ctx, inst, std::make_index_sequence<0>{}); |
| 65 | } else { | 65 | } else { |
| 66 | using FirstArgType = typename Traits::template ArgType<1>; | 66 | using FirstArgType = typename Traits::template ArgType<1>; |
| 67 | static constexpr bool is_first_arg_inst = std::is_same_v<FirstArgType, IR::Inst*>; | 67 | static constexpr bool is_first_arg_inst = std::is_same_v<FirstArgType, IR::Inst&>; |
| 68 | using Indices = std::make_index_sequence<Traits::NUM_ARGS - (is_first_arg_inst ? 2 : 1)>; | 68 | using Indices = std::make_index_sequence<Traits::NUM_ARGS - (is_first_arg_inst ? 2 : 1)>; |
| 69 | Invoke<func, is_first_arg_inst>(ctx, inst, Indices{}); | 69 | Invoke<func, is_first_arg_inst>(ctx, inst, Indices{}); |
| 70 | } | 70 | } |
| @@ -80,16 +80,76 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { | |||
| 80 | } | 80 | } |
| 81 | throw LogicError("Invalid opcode {}", inst->GetOpcode()); | 81 | throw LogicError("Invalid opcode {}", inst->GetOpcode()); |
| 82 | } | 82 | } |
| 83 | |||
| 84 | void Identity(IR::Inst& inst, const IR::Value& value) { | ||
| 85 | if (value.IsImmediate()) { | ||
| 86 | return; | ||
| 87 | } | ||
| 88 | IR::Inst* const value_inst{value.InstRecursive()}; | ||
| 89 | if (inst.GetOpcode() == IR::Opcode::Identity) { | ||
| 90 | value_inst->DestructiveAddUsage(inst.UseCount()); | ||
| 91 | value_inst->DestructiveRemoveUsage(); | ||
| 92 | } | ||
| 93 | inst.SetDefinition(value_inst->Definition<Id>()); | ||
| 94 | } | ||
| 83 | } // Anonymous namespace | 95 | } // Anonymous namespace |
| 84 | 96 | ||
| 85 | std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { | 97 | std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { |
| 86 | EmitContext ctx; | 98 | EmitContext ctx{program}; |
| 87 | for (IR::Block* const block : program.blocks) { | 99 | for (IR::Block* const block : program.blocks) { |
| 88 | for (IR::Inst& inst : block->Instructions()) { | 100 | for (IR::Inst& inst : block->Instructions()) { |
| 89 | EmitInst(ctx, &inst); | 101 | EmitInst(ctx, &inst); |
| 90 | } | 102 | } |
| 91 | } | 103 | } |
| 104 | std::string header = "!!NVcp5.0\n" | ||
| 105 | "OPTION NV_internal;"; | ||
| 106 | switch (program.stage) { | ||
| 107 | case Stage::Compute: | ||
| 108 | header += fmt::format("GROUP_SIZE {} {} {};", program.workgroup_size[0], | ||
| 109 | program.workgroup_size[1], program.workgroup_size[2]); | ||
| 110 | break; | ||
| 111 | default: | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | header += "TEMP "; | ||
| 115 | for (size_t index = 0; index < ctx.reg_alloc.NumUsedRegisters(); ++index) { | ||
| 116 | header += fmt::format("R{},", index); | ||
| 117 | } | ||
| 118 | header += "RC;"; | ||
| 119 | if (!program.info.storage_buffers_descriptors.empty()) { | ||
| 120 | header += "LONG TEMP LC;"; | ||
| 121 | } | ||
| 122 | ctx.code.insert(0, header); | ||
| 123 | ctx.code += "END"; | ||
| 92 | return ctx.code; | 124 | return ctx.code; |
| 93 | } | 125 | } |
| 94 | 126 | ||
| 127 | void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { | ||
| 128 | Identity(inst, value); | ||
| 129 | } | ||
| 130 | |||
| 131 | void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { | ||
| 132 | Identity(inst, value); | ||
| 133 | } | ||
| 134 | |||
| 135 | void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { | ||
| 136 | Identity(inst, value); | ||
| 137 | } | ||
| 138 | |||
| 139 | void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { | ||
| 140 | Identity(inst, value); | ||
| 141 | } | ||
| 142 | |||
| 143 | void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { | ||
| 144 | Identity(inst, value); | ||
| 145 | } | ||
| 146 | |||
| 147 | void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { | ||
| 148 | Identity(inst, value); | ||
| 149 | } | ||
| 150 | |||
| 151 | void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) { | ||
| 152 | Identity(inst, value); | ||
| 153 | } | ||
| 154 | |||
| 95 | } // namespace Shader::Backend::GLASM | 155 | } // namespace Shader::Backend::GLASM |