summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
authorGravatar ameerj2021-06-11 21:49:33 -0400
committerGravatar ameerj2021-07-22 21:51:38 -0400
commit84c86e03cda7d8c146d8afdbba3ddf628914819b (patch)
treed89b315c29b8cb631ed260ce5655ca230504be95 /src/shader_recompiler/backend
parentglsl: Address more feedback. Implement indexed texture reads (diff)
downloadyuzu-84c86e03cda7d8c146d8afdbba3ddf628914819b.tar.gz
yuzu-84c86e03cda7d8c146d8afdbba3ddf628914819b.tar.xz
yuzu-84c86e03cda7d8c146d8afdbba3ddf628914819b.zip
glsl: Refactor GetCbuf functions to reduce code duplication
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp170
1 files changed, 66 insertions, 104 deletions
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
index 711b568b1..5861c4d4c 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
@@ -33,144 +33,106 @@ std::string InputVertexIndex(EmitContext& ctx, std::string_view vertex) {
33std::string OutputVertexIndex(EmitContext& ctx) { 33std::string OutputVertexIndex(EmitContext& ctx) {
34 return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : ""; 34 return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
35} 35}
36} // Anonymous namespace
37 36
38void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, 37void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const IR::Value& offset,
39 const IR::Value& offset) { 38 u32 num_bits, std::string_view cast = {}, bool component_indexing_bug = false,
40 const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; 39 std::string_view bit_offset = {}) {
41 if (offset.IsImmediate()) { 40 const bool is_immediate{offset.IsImmediate()};
42 ctx.AddU32("{}=bitfieldExtract(ftou({}[{}].{}),int({}),8);", inst, cbuf, offset.U32() / 16,
43 OffsetSwizzle(offset.U32()), (offset.U32() % 4) * 8);
44 return;
45 }
46 const auto offset_var{ctx.var_alloc.Consume(offset)}; 41 const auto offset_var{ctx.var_alloc.Consume(offset)};
47 if (!ctx.profile.has_gl_component_indexing_bug) { 42 const auto index{is_immediate ? fmt::format("{}", offset.U32() / 16)
48 ctx.AddU32("{}=bitfieldExtract(ftou({}[{}>>4][({}>>2)%4]),int(({}%4)*8),8);", inst, cbuf, 43 : fmt::format("{}>>4", offset_var)};
49 offset_var, offset_var, offset_var); 44 const auto swizzle{is_immediate ? fmt::format(".{}", OffsetSwizzle(offset.U32()))
45 : fmt::format("[({}>>2)%4]", offset_var)};
46
47 const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())};
48 const auto cbuf_cast{fmt::format("{}({}[{}]{{}})", cast, cbuf, index)};
49 const auto extraction{num_bits == 32 ? cbuf_cast
50 : fmt ::format("bitfieldExtract({},int({}),{})", cbuf_cast,
51 bit_offset, num_bits)};
52 if (!component_indexing_bug) {
53 const auto result{fmt::format(extraction, swizzle)};
54 ctx.AddU32("{}={};", inst, result);
50 return; 55 return;
51 } 56 }
52 const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)}; 57 const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
53 const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; 58 const auto cbuf_offset{fmt::format("{}>>2", offset_var)};
54 for (u32 swizzle = 0; swizzle < 4; ++swizzle) { 59 for (u32 i = 0; i < 4; ++i) {
55 ctx.Add("if(({}&3)=={}){}=bitfieldExtract(ftou({}[{}>>4].{}),int(({}%4)*8),8);", 60 const auto swizzle_string{fmt::format(".{}", "xyzw"[i])};
56 cbuf_offset, swizzle, ret, cbuf, offset_var, "xyzw"[swizzle], offset_var); 61 const auto result{fmt::format(extraction, swizzle_string)};
62 ctx.Add("if(({}&3)=={}){}={};", cbuf_offset, i, ret, result);
57 } 63 }
58} 64}
59 65
60void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, 66void GetCbuf8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const IR::Value& offset,
61 const IR::Value& offset) { 67 std::string_view cast) {
62 const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())};
63 if (offset.IsImmediate()) { 68 if (offset.IsImmediate()) {
64 ctx.AddU32("{}=bitfieldExtract(ftoi({}[{}].{}),int({}),8);", inst, cbuf, offset.U32() / 16, 69 const auto bit_offset{fmt::format("{}", (offset.U32() % 4) * 8)};
65 OffsetSwizzle(offset.U32()), (offset.U32() % 4) * 8); 70 GetCbuf(ctx, inst, binding, offset, 8, cast, false, bit_offset);
66 return; 71 } else {
67 } 72 const auto offset_var{ctx.var_alloc.Consume(offset)};
68 const auto offset_var{ctx.var_alloc.Consume(offset)}; 73 const auto bit_offset{fmt::format("({}%4)*8", offset_var)};
69 if (!ctx.profile.has_gl_component_indexing_bug) { 74 GetCbuf(ctx, inst, binding, offset, 8, cast, ctx.profile.has_gl_component_indexing_bug,
70 ctx.AddU32("{}=bitfieldExtract(ftoi({}[{}>>4][({}>>2)%4]),int(({}%4)*8),8);", inst, cbuf, 75 bit_offset);
71 offset_var, offset_var, offset_var);
72 return;
73 } 76 }
74 const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)}; 77}
75 const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; 78
76 for (u32 swizzle = 0; swizzle < 4; ++swizzle) { 79void GetCbuf16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, const IR::Value& offset,
77 ctx.Add("if(({}&3)=={}){}=bitfieldExtract(ftoi({}[{}>>4].{}),int(({}%4)*8),8);", 80 std::string_view cast) {
78 cbuf_offset, swizzle, ret, cbuf, offset_var, "xyzw"[swizzle], offset_var); 81 if (offset.IsImmediate()) {
82 const auto bit_offset{fmt::format("{}", ((offset.U32() / 2) % 2) * 16)};
83 GetCbuf(ctx, inst, binding, offset, 16, cast, false, bit_offset);
84 } else {
85 const auto offset_var{ctx.var_alloc.Consume(offset)};
86 const auto bit_offset{fmt::format("(({}>>1)%2)*16", offset_var)};
87 GetCbuf(ctx, inst, binding, offset, 16, cast, ctx.profile.has_gl_component_indexing_bug,
88 bit_offset);
79 } 89 }
80} 90}
91} // Anonymous namespace
92
93void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
94 const IR::Value& offset) {
95 GetCbuf8(ctx, inst, binding, offset, "ftou");
96}
97
98void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
99 const IR::Value& offset) {
100 GetCbuf8(ctx, inst, binding, offset, "ftoi");
101}
81 102
82void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, 103void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
83 const IR::Value& offset) { 104 const IR::Value& offset) {
84 const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; 105 GetCbuf16(ctx, inst, binding, offset, "ftou");
85 if (offset.IsImmediate()) {
86 ctx.AddU32("{}=bitfieldExtract(ftou({}[{}].{}),int({}),16);", inst, cbuf, offset.U32() / 16,
87 OffsetSwizzle(offset.U32()), ((offset.U32() / 2) % 2) * 16);
88 return;
89 }
90 const auto offset_var{ctx.var_alloc.Consume(offset)};
91 if (!ctx.profile.has_gl_component_indexing_bug) {
92 ctx.AddU32("{}=bitfieldExtract(ftou({}[{}>>4][({}>>2)%4]),int((({}>>1)%2)*16),16);", inst,
93 cbuf, offset_var, offset_var, offset_var);
94 return;
95 }
96 const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
97 const auto cbuf_offset{fmt::format("{}>>2", offset_var)};
98 for (u32 swizzle = 0; swizzle < 4; ++swizzle) {
99 ctx.Add("if(({}&3)=={}){}=bitfieldExtract(ftou({}[{}>>4].{}),int((({}>>1)%2)*16),16);",
100 cbuf_offset, swizzle, ret, cbuf, offset_var, "xyzw"[swizzle], offset_var);
101 }
102} 106}
103 107
104void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, 108void EmitGetCbufS16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
105 const IR::Value& offset) { 109 const IR::Value& offset) {
106 const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; 110 GetCbuf16(ctx, inst, binding, offset, "ftoi");
107 if (offset.IsImmediate()) {
108 ctx.AddU32("{}=bitfieldExtract(ftoi({}[{}].{}),int({}),16);", inst, cbuf, offset.U32() / 16,
109 OffsetSwizzle(offset.U32()), ((offset.U32() / 2) % 2) * 16);
110 return;
111 }
112 const auto offset_var{ctx.var_alloc.Consume(offset)};
113 if (!ctx.profile.has_gl_component_indexing_bug) {
114 ctx.AddU32("{}=bitfieldExtract(ftoi({}[{}>>4][({}>>2)%4]),int((({}>>1)%2)*16),16);", inst,
115 cbuf, offset_var, offset_var, offset_var);
116 return;
117 }
118 const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
119 const auto cbuf_offset{fmt::format("{}>>2", offset_var)};
120 for (u32 swizzle = 0; swizzle < 4; ++swizzle) {
121 ctx.Add("if(({}&3)=={}){}=bitfieldExtract(ftoi({}[{}>>4].{}),int((({}>>1)%2)*16),16);",
122 cbuf_offset, swizzle, ret, cbuf, offset_var, "xyzw"[swizzle], offset_var);
123 }
124} 111}
125 112
126void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, 113void EmitGetCbufU32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
127 const IR::Value& offset) { 114 const IR::Value& offset) {
128 const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; 115 GetCbuf(ctx, inst, binding, offset, 32, "ftou");
129 if (offset.IsImmediate()) {
130 ctx.AddU32("{}=ftou({}[{}].{});", inst, cbuf, offset.U32() / 16,
131 OffsetSwizzle(offset.U32()));
132 return;
133 }
134 const auto offset_var{ctx.var_alloc.Consume(offset)};
135 if (!ctx.profile.has_gl_component_indexing_bug) {
136 ctx.AddU32("{}=ftou({}[{}>>4][({}>>2)%4]);", inst, cbuf, offset_var, offset_var);
137 return;
138 }
139 const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32)};
140 const auto cbuf_offset{fmt::format("{}>>2", offset_var)};
141 for (u32 swizzle = 0; swizzle < 4; ++swizzle) {
142 ctx.Add("if(({}&3)=={}){}=ftou({}[{}>>4].{});", cbuf_offset, swizzle, ret, cbuf, offset_var,
143 "xyzw"[swizzle]);
144 }
145} 116}
146 117
147void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, 118void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
148 const IR::Value& offset) { 119 const IR::Value& offset) {
149 const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; 120 GetCbuf(ctx, inst, binding, offset, 32);
150 if (offset.IsImmediate()) {
151 ctx.AddF32("{}={}[{}].{};", inst, cbuf, offset.U32() / 16, OffsetSwizzle(offset.U32()));
152 return;
153 }
154 const auto offset_var{ctx.var_alloc.Consume(offset)};
155 if (!ctx.profile.has_gl_component_indexing_bug) {
156 ctx.AddF32("{}={}[{}>>4][({}>>2)%4];", inst, cbuf, offset_var, offset_var);
157 return;
158 }
159 const auto ret{ctx.var_alloc.Define(inst, GlslVarType::F32)};
160 const auto cbuf_offset{fmt::format("{}>>2", offset_var)};
161 for (u32 swizzle = 0; swizzle < 4; ++swizzle) {
162 ctx.Add("if(({}&3)=={}){}={}[{}>>4].{};", cbuf_offset, swizzle, ret, cbuf, offset_var,
163 "xyzw"[swizzle]);
164 }
165} 121}
166 122
167void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, 123void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
168 const IR::Value& offset) { 124 const IR::Value& offset) {
169 const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; 125 const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())};
170 if (offset.IsImmediate()) { 126 if (offset.IsImmediate()) {
171 ctx.AddU32x2("{}=uvec2(ftou({}[{}].{}),ftou({}[{}].{}));", inst, cbuf, offset.U32() / 16, 127 const u32 u32_offset{offset.U32()};
172 OffsetSwizzle(offset.U32()), cbuf, (offset.U32() + 4) / 16, 128 if (u32_offset % 2 == 0) {
173 OffsetSwizzle(offset.U32() + 4)); 129 ctx.AddU32x2("{}=ftou({}[{}].{}{});", inst, cbuf, u32_offset / 16,
130 OffsetSwizzle(u32_offset), OffsetSwizzle(u32_offset + 4));
131 } else {
132 ctx.AddU32x2("{}=uvec2(ftou({}[{}].{}),ftou({}[{}].{}));", inst, cbuf, u32_offset / 16,
133 OffsetSwizzle(u32_offset), cbuf, (u32_offset + 4) / 16,
134 OffsetSwizzle(u32_offset + 4));
135 }
174 return; 136 return;
175 } 137 }
176 const auto offset_var{ctx.var_alloc.Consume(offset)}; 138 const auto offset_var{ctx.var_alloc.Consume(offset)};