diff options
Diffstat (limited to 'src/shader_recompiler')
6 files changed, 51 insertions, 25 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 0c1fbc7b1..282668b36 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 | |||
| @@ -35,6 +35,15 @@ std::string_view OutputVertexIndex(EmitContext& ctx) { | |||
| 35 | return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : ""; | 35 | return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : ""; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | std::string ChooseCbuf(EmitContext& ctx, const IR::Value& binding, std::string_view index) { | ||
| 39 | if (binding.IsImmediate()) { | ||
| 40 | return fmt::format("{}_cbuf{}[{}]", ctx.stage_name, binding.U32(), index); | ||
| 41 | } else { | ||
| 42 | const auto binding_var{ctx.var_alloc.Consume(binding)}; | ||
| 43 | return fmt::format("GetCbufIndirect({},{})", binding_var, index); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 38 | void GetCbuf(EmitContext& ctx, std::string_view ret, const IR::Value& binding, | 47 | void GetCbuf(EmitContext& ctx, std::string_view ret, const IR::Value& binding, |
| 39 | const IR::Value& offset, u32 num_bits, std::string_view cast = {}, | 48 | const IR::Value& offset, u32 num_bits, std::string_view cast = {}, |
| 40 | std::string_view bit_offset = {}) { | 49 | std::string_view bit_offset = {}) { |
| @@ -55,8 +64,8 @@ void GetCbuf(EmitContext& ctx, std::string_view ret, const IR::Value& binding, | |||
| 55 | const auto swizzle{is_immediate ? fmt::format(".{}", OffsetSwizzle(offset.U32())) | 64 | const auto swizzle{is_immediate ? fmt::format(".{}", OffsetSwizzle(offset.U32())) |
| 56 | : fmt::format("[({}>>2)%4]", offset_var)}; | 65 | : fmt::format("[({}>>2)%4]", offset_var)}; |
| 57 | 66 | ||
| 58 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | 67 | const auto cbuf{ChooseCbuf(ctx, binding, index)}; |
| 59 | const auto cbuf_cast{fmt::format("{}({}[{}]{{}})", cast, cbuf, index)}; | 68 | const auto cbuf_cast{fmt::format("{}({}{{}})", cast, cbuf)}; |
| 60 | const auto extraction{num_bits == 32 ? cbuf_cast | 69 | const auto extraction{num_bits == 32 ? cbuf_cast |
| 61 | : fmt::format("bitfieldExtract({},int({}),{})", cbuf_cast, | 70 | : fmt::format("bitfieldExtract({},int({}),{})", cbuf_cast, |
| 62 | bit_offset, num_bits)}; | 71 | bit_offset, num_bits)}; |
| @@ -140,9 +149,9 @@ void EmitGetCbufF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | |||
| 140 | 149 | ||
| 141 | void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, | 150 | void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, |
| 142 | const IR::Value& offset) { | 151 | const IR::Value& offset) { |
| 143 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | ||
| 144 | const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "" : "ftou"}; | 152 | const auto cast{ctx.profile.has_gl_cbuf_ftou_bug ? "" : "ftou"}; |
| 145 | if (offset.IsImmediate()) { | 153 | if (offset.IsImmediate()) { |
| 154 | const auto cbuf{fmt::format("{}_cbuf{}", ctx.stage_name, binding.U32())}; | ||
| 146 | static constexpr u32 cbuf_size{0x10000}; | 155 | static constexpr u32 cbuf_size{0x10000}; |
| 147 | const u32 u32_offset{offset.U32()}; | 156 | const u32 u32_offset{offset.U32()}; |
| 148 | const s32 signed_offset{static_cast<s32>(offset.U32())}; | 157 | const s32 signed_offset{static_cast<s32>(offset.U32())}; |
| @@ -162,17 +171,17 @@ void EmitGetCbufU32x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding | |||
| 162 | return; | 171 | return; |
| 163 | } | 172 | } |
| 164 | const auto offset_var{ctx.var_alloc.Consume(offset)}; | 173 | const auto offset_var{ctx.var_alloc.Consume(offset)}; |
| 174 | const auto cbuf{ChooseCbuf(ctx, binding, fmt::format("{}>>4", offset_var))}; | ||
| 165 | if (!ctx.profile.has_gl_component_indexing_bug) { | 175 | if (!ctx.profile.has_gl_component_indexing_bug) { |
| 166 | ctx.AddU32x2("{}=uvec2({}({}[{}>>4][({}>>2)%4]),{}({}[({}+4)>>4][(({}+4)>>2)%4]));", inst, | 176 | ctx.AddU32x2("{}=uvec2({}({}[({}>>2)%4]),{}({}[(({}+4)>>2)%4]));", inst, cast, cbuf, |
| 167 | cast, cbuf, offset_var, offset_var, cast, cbuf, offset_var, offset_var); | 177 | offset_var, cast, cbuf, offset_var); |
| 168 | return; | 178 | return; |
| 169 | } | 179 | } |
| 170 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x2)}; | 180 | const auto ret{ctx.var_alloc.Define(inst, GlslVarType::U32x2)}; |
| 171 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; | 181 | const auto cbuf_offset{fmt::format("{}>>2", offset_var)}; |
| 172 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { | 182 | for (u32 swizzle = 0; swizzle < 4; ++swizzle) { |
| 173 | ctx.Add("if(({}&3)=={}){}=uvec2({}({}[{}>>4].{}),{}({}[({}+4)>>4].{}));", cbuf_offset, | 183 | ctx.Add("if(({}&3)=={}){}=uvec2({}({}.{}),{}({}.{}));", cbuf_offset, swizzle, ret, cast, |
| 174 | swizzle, ret, cast, cbuf, offset_var, "xyzw"[swizzle], cast, cbuf, offset_var, | 184 | cbuf, "xyzw"[swizzle], cast, cbuf, "xyzw"[(swizzle + 1) % 4]); |
| 175 | "xyzw"[(swizzle + 1) % 4]); | ||
| 176 | } | 185 | } |
| 177 | } | 186 | } |
| 178 | 187 | ||
diff --git a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp index e816a93ec..17266f40d 100644 --- a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp +++ b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp | |||
| @@ -359,6 +359,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile | |||
| 359 | header += "layout(location=0) uniform vec4 scaling;"; | 359 | header += "layout(location=0) uniform vec4 scaling;"; |
| 360 | } | 360 | } |
| 361 | DefineConstantBuffers(bindings); | 361 | DefineConstantBuffers(bindings); |
| 362 | DefineConstantBufferIndirect(); | ||
| 362 | DefineStorageBuffers(bindings); | 363 | DefineStorageBuffers(bindings); |
| 363 | SetupImages(bindings); | 364 | SetupImages(bindings); |
| 364 | SetupTextures(bindings); | 365 | SetupTextures(bindings); |
| @@ -436,6 +437,24 @@ void EmitContext::DefineConstantBuffers(Bindings& bindings) { | |||
| 436 | } | 437 | } |
| 437 | } | 438 | } |
| 438 | 439 | ||
| 440 | void EmitContext::DefineConstantBufferIndirect() { | ||
| 441 | if (!info.uses_cbuf_indirect) { | ||
| 442 | return; | ||
| 443 | } | ||
| 444 | |||
| 445 | header += profile.has_gl_cbuf_ftou_bug ? "uvec4 " : "vec4 "; | ||
| 446 | header += "GetCbufIndirect(uint binding, uint offset){" | ||
| 447 | "switch(binding){" | ||
| 448 | "default:"; | ||
| 449 | |||
| 450 | for (const auto& desc : info.constant_buffer_descriptors) { | ||
| 451 | header += | ||
| 452 | fmt::format("case {}:return {}_cbuf{}[offset];", desc.index, stage_name, desc.index); | ||
| 453 | } | ||
| 454 | |||
| 455 | header += "}}"; | ||
| 456 | } | ||
| 457 | |||
| 439 | void EmitContext::DefineStorageBuffers(Bindings& bindings) { | 458 | void EmitContext::DefineStorageBuffers(Bindings& bindings) { |
| 440 | if (info.storage_buffers_descriptors.empty()) { | 459 | if (info.storage_buffers_descriptors.empty()) { |
| 441 | return; | 460 | return; |
diff --git a/src/shader_recompiler/backend/glsl/glsl_emit_context.h b/src/shader_recompiler/backend/glsl/glsl_emit_context.h index d9b639d29..2b13db6e6 100644 --- a/src/shader_recompiler/backend/glsl/glsl_emit_context.h +++ b/src/shader_recompiler/backend/glsl/glsl_emit_context.h | |||
| @@ -162,6 +162,7 @@ public: | |||
| 162 | private: | 162 | private: |
| 163 | void SetupExtensions(); | 163 | void SetupExtensions(); |
| 164 | void DefineConstantBuffers(Bindings& bindings); | 164 | void DefineConstantBuffers(Bindings& bindings); |
| 165 | void DefineConstantBufferIndirect(); | ||
| 165 | void DefineStorageBuffers(Bindings& bindings); | 166 | void DefineStorageBuffers(Bindings& bindings); |
| 166 | void DefineGenericOutput(size_t index, u32 invocations); | 167 | void DefineGenericOutput(size_t index, u32 invocations); |
| 167 | void DefineHelperFunctions(); | 168 | void DefineHelperFunctions(); |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 28f6a6184..9c83cd2e4 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -1043,15 +1043,15 @@ void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) { | |||
| 1043 | const Id merge_label{OpLabel()}; | 1043 | const Id merge_label{OpLabel()}; |
| 1044 | const Id uniform_type{uniform_types.*member_ptr}; | 1044 | const Id uniform_type{uniform_types.*member_ptr}; |
| 1045 | 1045 | ||
| 1046 | std::array<Id, Info::MAX_CBUFS> buf_labels; | 1046 | std::array<Id, Info::MAX_INDIRECT_CBUFS> buf_labels; |
| 1047 | std::array<Sirit::Literal, Info::MAX_CBUFS> buf_literals; | 1047 | std::array<Sirit::Literal, Info::MAX_INDIRECT_CBUFS> buf_literals; |
| 1048 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | 1048 | for (u32 i = 0; i < Info::MAX_INDIRECT_CBUFS; i++) { |
| 1049 | buf_labels[i] = OpLabel(); | 1049 | buf_labels[i] = OpLabel(); |
| 1050 | buf_literals[i] = Sirit::Literal{i}; | 1050 | buf_literals[i] = Sirit::Literal{i}; |
| 1051 | } | 1051 | } |
| 1052 | OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); | 1052 | OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); |
| 1053 | OpSwitch(binding, buf_labels[0], buf_literals, buf_labels); | 1053 | OpSwitch(binding, buf_labels[0], buf_literals, buf_labels); |
| 1054 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | 1054 | for (u32 i = 0; i < Info::MAX_INDIRECT_CBUFS; i++) { |
| 1055 | AddLabel(buf_labels[i]); | 1055 | AddLabel(buf_labels[i]); |
| 1056 | const Id cbuf{cbufs[i].*member_ptr}; | 1056 | const Id cbuf{cbufs[i].*member_ptr}; |
| 1057 | const Id access_chain{OpAccessChain(uniform_type, cbuf, u32_zero_value, offset)}; | 1057 | const Id access_chain{OpAccessChain(uniform_type, cbuf, u32_zero_value, offset)}; |
| @@ -1064,22 +1064,23 @@ void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) { | |||
| 1064 | return func; | 1064 | return func; |
| 1065 | }}; | 1065 | }}; |
| 1066 | IR::Type types{info.used_indirect_cbuf_types}; | 1066 | IR::Type types{info.used_indirect_cbuf_types}; |
| 1067 | if (True(types & IR::Type::U8)) { | 1067 | bool supports_aliasing = profile.support_descriptor_aliasing; |
| 1068 | if (supports_aliasing && True(types & IR::Type::U8)) { | ||
| 1068 | load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8); | 1069 | load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8); |
| 1069 | } | 1070 | } |
| 1070 | if (True(types & IR::Type::U16)) { | 1071 | if (supports_aliasing && True(types & IR::Type::U16)) { |
| 1071 | load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16); | 1072 | load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16); |
| 1072 | } | 1073 | } |
| 1073 | if (True(types & IR::Type::F32)) { | 1074 | if (supports_aliasing && True(types & IR::Type::F32)) { |
| 1074 | load_const_func_f32 = make_accessor(F32[1], &UniformDefinitions::F32); | 1075 | load_const_func_f32 = make_accessor(F32[1], &UniformDefinitions::F32); |
| 1075 | } | 1076 | } |
| 1076 | if (True(types & IR::Type::U32)) { | 1077 | if (supports_aliasing && True(types & IR::Type::U32)) { |
| 1077 | load_const_func_u32 = make_accessor(U32[1], &UniformDefinitions::U32); | 1078 | load_const_func_u32 = make_accessor(U32[1], &UniformDefinitions::U32); |
| 1078 | } | 1079 | } |
| 1079 | if (True(types & IR::Type::U32x2)) { | 1080 | if (supports_aliasing && True(types & IR::Type::U32x2)) { |
| 1080 | load_const_func_u32x2 = make_accessor(U32[2], &UniformDefinitions::U32x2); | 1081 | load_const_func_u32x2 = make_accessor(U32[2], &UniformDefinitions::U32x2); |
| 1081 | } | 1082 | } |
| 1082 | if (True(types & IR::Type::U32x4)) { | 1083 | if (!supports_aliasing || True(types & IR::Type::U32x4)) { |
| 1083 | load_const_func_u32x4 = make_accessor(U32[4], &UniformDefinitions::U32x4); | 1084 | load_const_func_u32x4 = make_accessor(U32[4], &UniformDefinitions::U32x4); |
| 1084 | } | 1085 | } |
| 1085 | } | 1086 | } |
diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index 0b2c60842..16278faab 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | |||
| @@ -32,13 +32,8 @@ void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) { | |||
| 32 | void AddRegisterIndexedLdc(Info& info) { | 32 | void AddRegisterIndexedLdc(Info& info) { |
| 33 | info.uses_cbuf_indirect = true; | 33 | info.uses_cbuf_indirect = true; |
| 34 | 34 | ||
| 35 | // The shader can use any possible constant buffer | 35 | for (u32 i = 0; i < Info::MAX_INDIRECT_CBUFS; i++) { |
| 36 | info.constant_buffer_mask = (1 << Info::MAX_CBUFS) - 1; | 36 | AddConstantBufferDescriptor(info, i, 1); |
| 37 | |||
| 38 | auto& cbufs{info.constant_buffer_descriptors}; | ||
| 39 | cbufs.clear(); | ||
| 40 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | ||
| 41 | cbufs.push_back(ConstantBufferDescriptor{.index = i, .count = 1}); | ||
| 42 | 37 | ||
| 43 | // The shader can use any possible access size | 38 | // The shader can use any possible access size |
| 44 | info.constant_buffer_used_sizes[i] = 0x10'000; | 39 | info.constant_buffer_used_sizes[i] = 0x10'000; |
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 9d36bd9eb..a3a09c71c 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -105,6 +105,7 @@ struct ImageDescriptor { | |||
| 105 | using ImageDescriptors = boost::container::small_vector<ImageDescriptor, 4>; | 105 | using ImageDescriptors = boost::container::small_vector<ImageDescriptor, 4>; |
| 106 | 106 | ||
| 107 | struct Info { | 107 | struct Info { |
| 108 | static constexpr size_t MAX_INDIRECT_CBUFS{14}; | ||
| 108 | static constexpr size_t MAX_CBUFS{18}; | 109 | static constexpr size_t MAX_CBUFS{18}; |
| 109 | static constexpr size_t MAX_SSBOS{32}; | 110 | static constexpr size_t MAX_SSBOS{32}; |
| 110 | 111 | ||