summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv
diff options
context:
space:
mode:
authorGravatar Liam2022-03-17 13:30:21 -0400
committerGravatar Liam2022-03-17 13:30:21 -0400
commite228a40db807c20a2484169bd0a1447a081ea1ce (patch)
treecd69df019ebf505189e5ee897ae042f9bc131119 /src/shader_recompiler/backend/spirv
parentAddress review comments (diff)
downloadyuzu-e228a40db807c20a2484169bd0a1447a081ea1ce.tar.gz
yuzu-e228a40db807c20a2484169bd0a1447a081ea1ce.tar.xz
yuzu-e228a40db807c20a2484169bd0a1447a081ea1ce.zip
shader_recompiler: Use functions for indirect const buffer accesses
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp58
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp64
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h8
3 files changed, 91 insertions, 39 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 264646115..9f6d5e3a5 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -123,7 +123,7 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) {
123} 123}
124 124
125Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, u32 element_size, 125Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, u32 element_size,
126 const IR::Value& binding, const IR::Value& offset) { 126 const IR::Value& binding, const IR::Value& offset, const Id indirect_func) {
127 Id buffer_offset; 127 Id buffer_offset;
128 128
129 const Id uniform_type{ctx.uniform_types.*member_ptr}; 129 const Id uniform_type{ctx.uniform_types.*member_ptr};
@@ -145,42 +145,19 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr,
145 ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)}; 145 ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)};
146 return ctx.OpLoad(result_type, access_chain); 146 return ctx.OpLoad(result_type, access_chain);
147 } else { 147 } else {
148 const Id index{ctx.Def(binding)}; 148 const std::array<Id, 2> arguments{ctx.Def(binding), buffer_offset};
149 const Id merge_label = ctx.OpLabel(); 149 return ctx.OpFunctionCall(result_type, indirect_func, arguments);
150
151 std::array<Id, Info::MAX_CBUFS> buf_labels;
152 std::array<Sirit::Literal, Info::MAX_CBUFS> buf_literals;
153 for (u32 i = 0; i < Info::MAX_CBUFS; i++) {
154 buf_labels[i] = ctx.OpLabel();
155 buf_literals[i] = Sirit::Literal{i};
156 }
157
158 ctx.OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone);
159 ctx.OpSwitch(index, buf_labels[0], buf_literals, buf_labels);
160
161 std::array<Id, Info::MAX_CBUFS * 2> phi_targets;
162 for (u32 i = 0; i < Info::MAX_CBUFS; i++) {
163 ctx.AddLabel(buf_labels[i]);
164 const Id cbuf{ctx.cbufs[i].*member_ptr};
165 const Id access_chain{
166 ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)};
167 phi_targets[2 * i + 0] = ctx.OpLoad(result_type, access_chain);
168 phi_targets[2 * i + 1] = buf_labels[i];
169 ctx.OpBranch(merge_label);
170 }
171
172 ctx.AddLabel(merge_label);
173
174 return ctx.OpPhi(result_type, phi_targets);
175 } 150 }
176} 151}
177 152
178Id GetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 153Id GetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
179 return GetCbuf(ctx, ctx.U32[1], &UniformDefinitions::U32, sizeof(u32), binding, offset); 154 return GetCbuf(ctx, ctx.U32[1], &UniformDefinitions::U32, sizeof(u32), binding, offset,
155 ctx.load_const_func_u32);
180} 156}
181 157
182Id GetCbufU32x4(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 158Id GetCbufU32x4(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
183 return GetCbuf(ctx, ctx.U32[4], &UniformDefinitions::U32x4, sizeof(u32[4]), binding, offset); 159 return GetCbuf(ctx, ctx.U32[4], &UniformDefinitions::U32x4, sizeof(u32[4]), binding, offset,
160 ctx.load_const_func_u32x4);
184} 161}
185 162
186Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 index_offset) { 163Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 index_offset) {
@@ -231,7 +208,8 @@ void EmitGetIndirectBranchVariable(EmitContext&) {
231 208
232Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 209Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
233 if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) { 210 if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) {
234 const Id load{GetCbuf(ctx, ctx.U8, &UniformDefinitions::U8, sizeof(u8), binding, offset)}; 211 const Id load{GetCbuf(ctx, ctx.U8, &UniformDefinitions::U8, sizeof(u8), binding, offset,
212 ctx.load_const_func_u8)};
235 return ctx.OpUConvert(ctx.U32[1], load); 213 return ctx.OpUConvert(ctx.U32[1], load);
236 } 214 }
237 Id element{}; 215 Id element{};
@@ -247,7 +225,8 @@ Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& of
247 225
248Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 226Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
249 if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) { 227 if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) {
250 const Id load{GetCbuf(ctx, ctx.S8, &UniformDefinitions::S8, sizeof(s8), binding, offset)}; 228 const Id load{GetCbuf(ctx, ctx.S8, &UniformDefinitions::S8, sizeof(s8), binding, offset,
229 ctx.load_const_func_u8)};
251 return ctx.OpSConvert(ctx.U32[1], load); 230 return ctx.OpSConvert(ctx.U32[1], load);
252 } 231 }
253 Id element{}; 232 Id element{};
@@ -263,8 +242,8 @@ Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& of
263 242
264Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 243Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
265 if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16) { 244 if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16) {
266 const Id load{ 245 const Id load{GetCbuf(ctx, ctx.U16, &UniformDefinitions::U16, sizeof(u16), binding, offset,
267 GetCbuf(ctx, ctx.U16, &UniformDefinitions::U16, sizeof(u16), binding, offset)}; 246 ctx.load_const_func_u16)};
268 return ctx.OpUConvert(ctx.U32[1], load); 247 return ctx.OpUConvert(ctx.U32[1], load);
269 } 248 }
270 Id element{}; 249 Id element{};
@@ -280,8 +259,8 @@ Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& o
280 259
281Id EmitGetCbufS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 260Id EmitGetCbufS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
282 if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16) { 261 if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16) {
283 const Id load{ 262 const Id load{GetCbuf(ctx, ctx.S16, &UniformDefinitions::S16, sizeof(s16), binding, offset,
284 GetCbuf(ctx, ctx.S16, &UniformDefinitions::S16, sizeof(s16), binding, offset)}; 263 ctx.load_const_func_u16)};
285 return ctx.OpSConvert(ctx.U32[1], load); 264 return ctx.OpSConvert(ctx.U32[1], load);
286 } 265 }
287 Id element{}; 266 Id element{};
@@ -306,7 +285,8 @@ Id EmitGetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& o
306 285
307Id EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 286Id EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
308 if (ctx.profile.support_descriptor_aliasing) { 287 if (ctx.profile.support_descriptor_aliasing) {
309 return GetCbuf(ctx, ctx.F32[1], &UniformDefinitions::F32, sizeof(f32), binding, offset); 288 return GetCbuf(ctx, ctx.F32[1], &UniformDefinitions::F32, sizeof(f32), binding, offset,
289 ctx.load_const_func_f32);
310 } else { 290 } else {
311 const Id vector{GetCbufU32x4(ctx, binding, offset)}; 291 const Id vector{GetCbufU32x4(ctx, binding, offset)};
312 return ctx.OpBitcast(ctx.F32[1], GetCbufElement(ctx, vector, offset, 0u)); 292 return ctx.OpBitcast(ctx.F32[1], GetCbufElement(ctx, vector, offset, 0u));
@@ -315,8 +295,8 @@ Id EmitGetCbufF32(EmitContext& ctx, const IR::Value& binding, const IR::Value& o
315 295
316Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 296Id EmitGetCbufU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
317 if (ctx.profile.support_descriptor_aliasing) { 297 if (ctx.profile.support_descriptor_aliasing) {
318 return GetCbuf(ctx, ctx.U32[2], &UniformDefinitions::U32x2, sizeof(u32[2]), binding, 298 return GetCbuf(ctx, ctx.U32[2], &UniformDefinitions::U32x2, sizeof(u32[2]), binding, offset,
319 offset); 299 ctx.load_const_func_u32x2);
320 } else { 300 } else {
321 const Id vector{GetCbufU32x4(ctx, binding, offset)}; 301 const Id vector{GetCbufU32x4(ctx, binding, offset)};
322 return ctx.OpCompositeConstruct(ctx.U32[2], GetCbufElement(ctx, vector, offset, 0u), 302 return ctx.OpCompositeConstruct(ctx.U32[2], GetCbufElement(ctx, vector, offset, 0u),
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index cd90c084a..f85541a2e 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -464,6 +464,7 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf
464 DefineSharedMemory(program); 464 DefineSharedMemory(program);
465 DefineSharedMemoryFunctions(program); 465 DefineSharedMemoryFunctions(program);
466 DefineConstantBuffers(program.info, uniform_binding); 466 DefineConstantBuffers(program.info, uniform_binding);
467 DefineConstantBufferIndirectFunctions(program.info);
467 DefineStorageBuffers(program.info, storage_binding); 468 DefineStorageBuffers(program.info, storage_binding);
468 DefineTextureBuffers(program.info, texture_binding); 469 DefineTextureBuffers(program.info, texture_binding);
469 DefineImageBuffers(program.info, image_binding); 470 DefineImageBuffers(program.info, image_binding);
@@ -1027,6 +1028,69 @@ void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) {
1027 binding += static_cast<u32>(info.constant_buffer_descriptors.size()); 1028 binding += static_cast<u32>(info.constant_buffer_descriptors.size());
1028} 1029}
1029 1030
1031void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) {
1032 if (!info.uses_cbuf_indirect) {
1033 return;
1034 }
1035
1036 const auto make_accessor{[&](Id buffer_type, Id UniformDefinitions::*member_ptr) {
1037 const Id func_type{TypeFunction(buffer_type, U32[1], U32[1])};
1038 const Id func{OpFunction(buffer_type, spv::FunctionControlMask::MaskNone, func_type)};
1039 const Id binding{OpFunctionParameter(U32[1])};
1040 const Id offset{OpFunctionParameter(U32[1])};
1041
1042 AddLabel();
1043
1044 const Id merge_label{OpLabel()};
1045 const Id uniform_type{uniform_types.*member_ptr};
1046
1047 std::array<Id, Info::MAX_CBUFS> buf_labels;
1048 std::array<Sirit::Literal, Info::MAX_CBUFS> buf_literals;
1049 for (u32 i = 0; i < Info::MAX_CBUFS; i++) {
1050 buf_labels[i] = OpLabel();
1051 buf_literals[i] = Sirit::Literal{i};
1052 }
1053
1054 OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone);
1055 OpSwitch(binding, buf_labels[0], buf_literals, buf_labels);
1056
1057 for (u32 i = 0; i < Info::MAX_CBUFS; i++) {
1058 AddLabel(buf_labels[i]);
1059 const Id cbuf{cbufs[i].*member_ptr};
1060 const Id access_chain{OpAccessChain(uniform_type, cbuf, u32_zero_value, offset)};
1061 const Id result{OpLoad(buffer_type, access_chain)};
1062 OpReturnValue(result);
1063 }
1064
1065 AddLabel(merge_label);
1066 OpUnreachable();
1067 OpFunctionEnd();
1068
1069 return func;
1070 }};
1071
1072 IR::Type types{info.used_constant_buffer_types};
1073
1074 if (True(types & IR::Type::U8)) {
1075 load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8);
1076 }
1077 if (True(types & IR::Type::U16)) {
1078 load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16);
1079 }
1080 if (True(types & IR::Type::F32)) {
1081 load_const_func_f32 = make_accessor(F32[1], &UniformDefinitions::F32);
1082 }
1083 if (True(types & IR::Type::U32)) {
1084 load_const_func_u32 = make_accessor(U32[1], &UniformDefinitions::U32);
1085 }
1086 if (True(types & IR::Type::U32x2)) {
1087 load_const_func_u32x2 = make_accessor(U32[2], &UniformDefinitions::U32x2);
1088 }
1089 if (True(types & IR::Type::U32x4)) {
1090 load_const_func_u32x4 = make_accessor(U32[4], &UniformDefinitions::U32x4);
1091 }
1092}
1093
1030void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) { 1094void EmitContext::DefineStorageBuffers(const Info& info, u32& binding) {
1031 if (info.storage_buffers_descriptors.empty()) { 1095 if (info.storage_buffers_descriptors.empty()) {
1032 return; 1096 return;
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
index f87138f7e..906a1dc2c 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
@@ -294,6 +294,13 @@ public:
294 294
295 std::vector<Id> interfaces; 295 std::vector<Id> interfaces;
296 296
297 Id load_const_func_u8{};
298 Id load_const_func_u16{};
299 Id load_const_func_u32{};
300 Id load_const_func_f32{};
301 Id load_const_func_u32x2{};
302 Id load_const_func_u32x4{};
303
297private: 304private:
298 void DefineCommonTypes(const Info& info); 305 void DefineCommonTypes(const Info& info);
299 void DefineCommonConstants(); 306 void DefineCommonConstants();
@@ -302,6 +309,7 @@ private:
302 void DefineSharedMemory(const IR::Program& program); 309 void DefineSharedMemory(const IR::Program& program);
303 void DefineSharedMemoryFunctions(const IR::Program& program); 310 void DefineSharedMemoryFunctions(const IR::Program& program);
304 void DefineConstantBuffers(const Info& info, u32& binding); 311 void DefineConstantBuffers(const Info& info, u32& binding);
312 void DefineConstantBufferIndirectFunctions(const Info& info);
305 void DefineStorageBuffers(const Info& info, u32& binding); 313 void DefineStorageBuffers(const Info& info, u32& binding);
306 void DefineTextureBuffers(const Info& info, u32& binding); 314 void DefineTextureBuffers(const Info& info, u32& binding);
307 void DefineImageBuffers(const Info& info, u32& binding); 315 void DefineImageBuffers(const Info& info, u32& binding);