summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/glasm/emit_glasm.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-05-08 16:28:52 -0300
committerGravatar ameerj2021-07-22 21:51:30 -0400
commit6fd190d1ae4275a06ed2e488401e1d63912954be (patch)
treeece4681d18c7b0b5bcb6b540ea4a21b32c19b363 /src/shader_recompiler/backend/glasm/emit_glasm.cpp
parentglasm: Changes to GLASM register allocator and emit context (diff)
downloadyuzu-6fd190d1ae4275a06ed2e488401e1d63912954be.tar.gz
yuzu-6fd190d1ae4275a06ed2e488401e1d63912954be.tar.xz
yuzu-6fd190d1ae4275a06ed2e488401e1d63912954be.zip
glasm: Implement basic GLASM instructions
Diffstat (limited to 'src/shader_recompiler/backend/glasm/emit_glasm.cpp')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm.cpp66
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>
50void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence<I...>) { 50void 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
84void 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
85std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { 97std::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
127void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) {
128 Identity(inst, value);
129}
130
131void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) {
132 Identity(inst, value);
133}
134
135void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) {
136 Identity(inst, value);
137}
138
139void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) {
140 Identity(inst, value);
141}
142
143void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) {
144 Identity(inst, value);
145}
146
147void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value) {
148 Identity(inst, value);
149}
150
151void 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