diff options
| author | 2022-03-17 14:45:38 -0400 | |
|---|---|---|
| committer | 2022-03-17 14:48:18 -0400 | |
| commit | 3009d0bd7d30b341a8697d85d9d42a9ee4910d19 (patch) | |
| tree | c00cb183d00f673185e69fa0d4094b34bcabbe12 /src | |
| parent | shader_recompiler: Use functions for indirect const buffer accesses (diff) | |
| download | yuzu-3009d0bd7d30b341a8697d85d9d42a9ee4910d19.tar.gz yuzu-3009d0bd7d30b341a8697d85d9d42a9ee4910d19.tar.xz yuzu-3009d0bd7d30b341a8697d85d9d42a9ee4910d19.zip | |
Address review comments
Diffstat (limited to '')
4 files changed, 36 insertions, 52 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 9f6d5e3a5..80b4bbd27 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 | |||
| @@ -125,7 +125,6 @@ std::optional<OutAttr> OutputAttrPointer(EmitContext& ctx, IR::Attribute attr) { | |||
| 125 | Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, u32 element_size, | 125 | Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, u32 element_size, |
| 126 | const IR::Value& binding, const IR::Value& offset, const Id indirect_func) { | 126 | const IR::Value& binding, const IR::Value& offset, const Id indirect_func) { |
| 127 | Id buffer_offset; | 127 | Id buffer_offset; |
| 128 | |||
| 129 | const Id uniform_type{ctx.uniform_types.*member_ptr}; | 128 | const Id uniform_type{ctx.uniform_types.*member_ptr}; |
| 130 | if (offset.IsImmediate()) { | 129 | if (offset.IsImmediate()) { |
| 131 | // Hardware been proved to read the aligned offset (e.g. LDC.U32 at 6 will read offset 4) | 130 | // Hardware been proved to read the aligned offset (e.g. LDC.U32 at 6 will read offset 4) |
| @@ -138,16 +137,12 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr, | |||
| 138 | } else { | 137 | } else { |
| 139 | buffer_offset = ctx.Def(offset); | 138 | buffer_offset = ctx.Def(offset); |
| 140 | } | 139 | } |
| 141 | 140 | if (!binding.IsImmediate()) { | |
| 142 | if (binding.IsImmediate()) { | 141 | return ctx.OpFunctionCall(result_type, indirect_func, ctx.Def(binding), buffer_offset); |
| 143 | const Id cbuf{ctx.cbufs[binding.U32()].*member_ptr}; | ||
| 144 | const Id access_chain{ | ||
| 145 | ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)}; | ||
| 146 | return ctx.OpLoad(result_type, access_chain); | ||
| 147 | } else { | ||
| 148 | const std::array<Id, 2> arguments{ctx.Def(binding), buffer_offset}; | ||
| 149 | return ctx.OpFunctionCall(result_type, indirect_func, arguments); | ||
| 150 | } | 142 | } |
| 143 | const Id cbuf{ctx.cbufs[binding.U32()].*member_ptr}; | ||
| 144 | const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)}; | ||
| 145 | return ctx.OpLoad(result_type, access_chain); | ||
| 151 | } | 146 | } |
| 152 | 147 | ||
| 153 | Id GetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { | 148 | Id GetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index f85541a2e..aa5b6c9b7 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -994,7 +994,7 @@ void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { | |||
| 994 | } | 994 | } |
| 995 | return; | 995 | return; |
| 996 | } | 996 | } |
| 997 | IR::Type types{info.used_constant_buffer_types}; | 997 | IR::Type types{info.used_constant_buffer_types | info.used_indirect_cbuf_types}; |
| 998 | if (True(types & IR::Type::U8)) { | 998 | if (True(types & IR::Type::U8)) { |
| 999 | if (profile.support_int8) { | 999 | if (profile.support_int8) { |
| 1000 | DefineConstBuffers(*this, info, &UniformDefinitions::U8, binding, U8, 'u', sizeof(u8)); | 1000 | DefineConstBuffers(*this, info, &UniformDefinitions::U8, binding, U8, 'u', sizeof(u8)); |
| @@ -1032,7 +1032,6 @@ void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) { | |||
| 1032 | if (!info.uses_cbuf_indirect) { | 1032 | if (!info.uses_cbuf_indirect) { |
| 1033 | return; | 1033 | return; |
| 1034 | } | 1034 | } |
| 1035 | |||
| 1036 | const auto make_accessor{[&](Id buffer_type, Id UniformDefinitions::*member_ptr) { | 1035 | const auto make_accessor{[&](Id buffer_type, Id UniformDefinitions::*member_ptr) { |
| 1037 | const Id func_type{TypeFunction(buffer_type, U32[1], U32[1])}; | 1036 | const Id func_type{TypeFunction(buffer_type, U32[1], U32[1])}; |
| 1038 | const Id func{OpFunction(buffer_type, spv::FunctionControlMask::MaskNone, func_type)}; | 1037 | const Id func{OpFunction(buffer_type, spv::FunctionControlMask::MaskNone, func_type)}; |
| @@ -1050,10 +1049,8 @@ void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) { | |||
| 1050 | buf_labels[i] = OpLabel(); | 1049 | buf_labels[i] = OpLabel(); |
| 1051 | buf_literals[i] = Sirit::Literal{i}; | 1050 | buf_literals[i] = Sirit::Literal{i}; |
| 1052 | } | 1051 | } |
| 1053 | |||
| 1054 | OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); | 1052 | OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); |
| 1055 | OpSwitch(binding, buf_labels[0], buf_literals, buf_labels); | 1053 | OpSwitch(binding, buf_labels[0], buf_literals, buf_labels); |
| 1056 | |||
| 1057 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { | 1054 | for (u32 i = 0; i < Info::MAX_CBUFS; i++) { |
| 1058 | AddLabel(buf_labels[i]); | 1055 | AddLabel(buf_labels[i]); |
| 1059 | const Id cbuf{cbufs[i].*member_ptr}; | 1056 | const Id cbuf{cbufs[i].*member_ptr}; |
| @@ -1061,16 +1058,12 @@ void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) { | |||
| 1061 | const Id result{OpLoad(buffer_type, access_chain)}; | 1058 | const Id result{OpLoad(buffer_type, access_chain)}; |
| 1062 | OpReturnValue(result); | 1059 | OpReturnValue(result); |
| 1063 | } | 1060 | } |
| 1064 | |||
| 1065 | AddLabel(merge_label); | 1061 | AddLabel(merge_label); |
| 1066 | OpUnreachable(); | 1062 | OpUnreachable(); |
| 1067 | OpFunctionEnd(); | 1063 | OpFunctionEnd(); |
| 1068 | |||
| 1069 | return func; | 1064 | return func; |
| 1070 | }}; | 1065 | }}; |
| 1071 | 1066 | IR::Type types{info.used_indirect_cbuf_types}; | |
| 1072 | IR::Type types{info.used_constant_buffer_types}; | ||
| 1073 | |||
| 1074 | if (True(types & IR::Type::U8)) { | 1067 | if (True(types & IR::Type::U8)) { |
| 1075 | load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8); | 1068 | load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8); |
| 1076 | } | 1069 | } |
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 b54894a9b..0b2c60842 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | |||
| @@ -45,6 +45,30 @@ void AddRegisterIndexedLdc(Info& info) { | |||
| 45 | } | 45 | } |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | u32 GetElementSize(IR::Type& used_type, Shader::IR::Opcode opcode) { | ||
| 49 | switch (opcode) { | ||
| 50 | case IR::Opcode::GetCbufU8: | ||
| 51 | case IR::Opcode::GetCbufS8: | ||
| 52 | used_type |= IR::Type::U8; | ||
| 53 | return 1; | ||
| 54 | case IR::Opcode::GetCbufU16: | ||
| 55 | case IR::Opcode::GetCbufS16: | ||
| 56 | used_type |= IR::Type::U16; | ||
| 57 | return 2; | ||
| 58 | case IR::Opcode::GetCbufU32: | ||
| 59 | used_type |= IR::Type::U32; | ||
| 60 | return 4; | ||
| 61 | case IR::Opcode::GetCbufF32: | ||
| 62 | used_type |= IR::Type::F32; | ||
| 63 | return 4; | ||
| 64 | case IR::Opcode::GetCbufU32x2: | ||
| 65 | used_type |= IR::Type::U32x2; | ||
| 66 | return 8; | ||
| 67 | default: | ||
| 68 | throw InvalidArgument("Invalid opcode {}", opcode); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 48 | void GetPatch(Info& info, IR::Patch patch) { | 72 | void GetPatch(Info& info, IR::Patch patch) { |
| 49 | if (!IR::IsGeneric(patch)) { | 73 | if (!IR::IsGeneric(patch)) { |
| 50 | throw NotImplementedException("Reading non-generic patch {}", patch); | 74 | throw NotImplementedException("Reading non-generic patch {}", patch); |
| @@ -481,45 +505,16 @@ void VisitUsages(Info& info, IR::Inst& inst) { | |||
| 481 | const IR::Value offset{inst.Arg(1)}; | 505 | const IR::Value offset{inst.Arg(1)}; |
| 482 | if (index.IsImmediate()) { | 506 | if (index.IsImmediate()) { |
| 483 | AddConstantBufferDescriptor(info, index.U32(), 1); | 507 | AddConstantBufferDescriptor(info, index.U32(), 1); |
| 484 | } else { | 508 | u32 element_size = GetElementSize(info.used_constant_buffer_types, inst.GetOpcode()); |
| 485 | AddRegisterIndexedLdc(info); | ||
| 486 | } | ||
| 487 | |||
| 488 | u32 element_size{}; | ||
| 489 | switch (inst.GetOpcode()) { | ||
| 490 | case IR::Opcode::GetCbufU8: | ||
| 491 | case IR::Opcode::GetCbufS8: | ||
| 492 | info.used_constant_buffer_types |= IR::Type::U8; | ||
| 493 | element_size = 1; | ||
| 494 | break; | ||
| 495 | case IR::Opcode::GetCbufU16: | ||
| 496 | case IR::Opcode::GetCbufS16: | ||
| 497 | info.used_constant_buffer_types |= IR::Type::U16; | ||
| 498 | element_size = 2; | ||
| 499 | break; | ||
| 500 | case IR::Opcode::GetCbufU32: | ||
| 501 | info.used_constant_buffer_types |= IR::Type::U32; | ||
| 502 | element_size = 4; | ||
| 503 | break; | ||
| 504 | case IR::Opcode::GetCbufF32: | ||
| 505 | info.used_constant_buffer_types |= IR::Type::F32; | ||
| 506 | element_size = 4; | ||
| 507 | break; | ||
| 508 | case IR::Opcode::GetCbufU32x2: | ||
| 509 | info.used_constant_buffer_types |= IR::Type::U32x2; | ||
| 510 | element_size = 8; | ||
| 511 | break; | ||
| 512 | default: | ||
| 513 | break; | ||
| 514 | } | ||
| 515 | |||
| 516 | if (index.IsImmediate()) { | ||
| 517 | u32& size{info.constant_buffer_used_sizes[index.U32()]}; | 509 | u32& size{info.constant_buffer_used_sizes[index.U32()]}; |
| 518 | if (offset.IsImmediate()) { | 510 | if (offset.IsImmediate()) { |
| 519 | size = Common::AlignUp(std::max(size, offset.U32() + element_size), 16u); | 511 | size = Common::AlignUp(std::max(size, offset.U32() + element_size), 16u); |
| 520 | } else { | 512 | } else { |
| 521 | size = 0x10'000; | 513 | size = 0x10'000; |
| 522 | } | 514 | } |
| 515 | } else { | ||
| 516 | AddRegisterIndexedLdc(info); | ||
| 517 | GetElementSize(info.used_indirect_cbuf_types, inst.GetOpcode()); | ||
| 523 | } | 518 | } |
| 524 | break; | 519 | break; |
| 525 | } | 520 | } |
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 9cff2e42d..9d36bd9eb 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -177,6 +177,7 @@ struct Info { | |||
| 177 | 177 | ||
| 178 | IR::Type used_constant_buffer_types{}; | 178 | IR::Type used_constant_buffer_types{}; |
| 179 | IR::Type used_storage_buffer_types{}; | 179 | IR::Type used_storage_buffer_types{}; |
| 180 | IR::Type used_indirect_cbuf_types{}; | ||
| 180 | 181 | ||
| 181 | u32 constant_buffer_mask{}; | 182 | u32 constant_buffer_mask{}; |
| 182 | std::array<u32, MAX_CBUFS> constant_buffer_used_sizes{}; | 183 | std::array<u32, MAX_CBUFS> constant_buffer_used_sizes{}; |