summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-05-10 19:32:10 -0300
committerGravatar ameerj2021-07-22 21:51:31 -0400
commit8c81a20ace8c65d0a9d58b9cf333049a2bc0383a (patch)
tree86c653e99c02225f7ed5ee93b42d272b11404a93 /src
parentglasm: Enable unintentionally disabled register aliasing on GLASM (diff)
downloadyuzu-8c81a20ace8c65d0a9d58b9cf333049a2bc0383a.tar.gz
yuzu-8c81a20ace8c65d0a9d58b9cf333049a2bc0383a.tar.xz
yuzu-8c81a20ace8c65d0a9d58b9cf333049a2bc0383a.zip
glasm: Ensure reg alloc order across compilers on GLASM
Use a struct constructor to serialize register allocation arguments to ensure registers are allocated in the same order regardless of the compiler used. The A and B functions can be called in any order when passed as arguments to "foo": foo(A(), B()) But the order is guaranteed for curly-braced constructor calls in classes: Foo{A(), B()} Use this to get consistent behavior.
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm.cpp25
1 files changed, 14 insertions, 11 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
index c90b80e48..047b2f89c 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
@@ -128,24 +128,27 @@ auto Arg(EmitContext& ctx, const IR::Value& arg) {
128 } 128 }
129} 129}
130 130
131template <auto func, bool is_first_arg_inst, typename... Args> 131template <auto func, bool is_first_arg_inst>
132void InvokeCall(EmitContext& ctx, IR::Inst* inst, Args&&... args) { 132struct InvokeCall {
133 if constexpr (is_first_arg_inst) { 133 template <typename... Args>
134 func(ctx, *inst, args.Extract()...); 134 InvokeCall(EmitContext& ctx, IR::Inst* inst, Args&&... args) {
135 } else { 135 if constexpr (is_first_arg_inst) {
136 func(ctx, args.Extract()...); 136 func(ctx, *inst, args.Extract()...);
137 } else {
138 func(ctx, args.Extract()...);
139 }
137 } 140 }
138} 141};
139 142
140template <auto func, bool is_first_arg_inst, size_t... I> 143template <auto func, bool is_first_arg_inst, size_t... I>
141void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence<I...>) { 144void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence<I...>) {
142 using Traits = FuncTraits<decltype(func)>; 145 using Traits = FuncTraits<decltype(func)>;
143 if constexpr (is_first_arg_inst) { 146 if constexpr (is_first_arg_inst) {
144 InvokeCall<func, is_first_arg_inst>( 147 InvokeCall<func, is_first_arg_inst>{
145 ctx, inst, Arg<typename Traits::template ArgType<I + 2>>(ctx, inst->Arg(I))...); 148 ctx, inst, Arg<typename Traits::template ArgType<I + 2>>(ctx, inst->Arg(I))...};
146 } else { 149 } else {
147 InvokeCall<func, is_first_arg_inst>( 150 InvokeCall<func, is_first_arg_inst>{
148 ctx, inst, Arg<typename Traits::template ArgType<I + 1>>(ctx, inst->Arg(I))...); 151 ctx, inst, Arg<typename Traits::template ArgType<I + 1>>(ctx, inst->Arg(I))...};
149 } 152 }
150} 153}
151 154