From 52895fab674cb160f2559d08c21333f52d6deced Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 14 Mar 2022 19:35:48 -0400 Subject: shader: add support for const buffer indirect addressing --- .../ir_opt/collect_shader_info_pass.cpp | 35 +++++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'src/shader_recompiler/ir_opt') 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 bfd2ae650..1a50dd382 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -29,6 +29,20 @@ void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) { }); } +void AddRegisterIndexedLdc(Info& info) { + // The shader can use any possible constant buffer + info.constant_buffer_mask = (1 << Info::MAX_CBUFS) - 1; + + auto& cbufs{info.constant_buffer_descriptors}; + cbufs.clear(); + for (u32 i = 0; i < Info::MAX_CBUFS; i++) { + cbufs.push_back(ConstantBufferDescriptor{.index = i, .count = 1}); + + // The shader can use any possible access size + info.constant_buffer_used_sizes[i] = 0x10'000; + } +} + void GetPatch(Info& info, IR::Patch patch) { if (!IR::IsGeneric(patch)) { throw NotImplementedException("Reading non-generic patch {}", patch); @@ -463,10 +477,12 @@ void VisitUsages(Info& info, IR::Inst& inst) { case IR::Opcode::GetCbufU32x2: { const IR::Value index{inst.Arg(0)}; const IR::Value offset{inst.Arg(1)}; - if (!index.IsImmediate()) { - throw NotImplementedException("Constant buffer with non-immediate index"); + if (index.IsImmediate()) { + AddConstantBufferDescriptor(info, index.U32(), 1); + } else { + AddRegisterIndexedLdc(info); } - AddConstantBufferDescriptor(info, index.U32(), 1); + u32 element_size{}; switch (inst.GetOpcode()) { case IR::Opcode::GetCbufU8: @@ -494,11 +510,14 @@ void VisitUsages(Info& info, IR::Inst& inst) { default: break; } - u32& size{info.constant_buffer_used_sizes[index.U32()]}; - if (offset.IsImmediate()) { - size = Common::AlignUp(std::max(size, offset.U32() + element_size), 16u); - } else { - size = 0x10'000; + + if (index.IsImmediate()) { + u32& size{info.constant_buffer_used_sizes[index.U32()]}; + if (offset.IsImmediate()) { + size = Common::AlignUp(std::max(size, offset.U32() + element_size), 16u); + } else { + size = 0x10'000; + } } break; } -- cgit v1.2.3 From e228a40db807c20a2484169bd0a1447a081ea1ce Mon Sep 17 00:00:00 2001 From: Liam Date: Thu, 17 Mar 2022 13:30:21 -0400 Subject: shader_recompiler: Use functions for indirect const buffer accesses --- src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/shader_recompiler/ir_opt') 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 1a50dd382..b54894a9b 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -30,6 +30,8 @@ void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) { } void AddRegisterIndexedLdc(Info& info) { + info.uses_cbuf_indirect = true; + // The shader can use any possible constant buffer info.constant_buffer_mask = (1 << Info::MAX_CBUFS) - 1; -- cgit v1.2.3 From 3009d0bd7d30b341a8697d85d9d42a9ee4910d19 Mon Sep 17 00:00:00 2001 From: Liam Date: Thu, 17 Mar 2022 14:45:38 -0400 Subject: Address review comments --- .../ir_opt/collect_shader_info_pass.cpp | 61 ++++++++++------------ 1 file changed, 28 insertions(+), 33 deletions(-) (limited to 'src/shader_recompiler/ir_opt') 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) { } } +u32 GetElementSize(IR::Type& used_type, Shader::IR::Opcode opcode) { + switch (opcode) { + case IR::Opcode::GetCbufU8: + case IR::Opcode::GetCbufS8: + used_type |= IR::Type::U8; + return 1; + case IR::Opcode::GetCbufU16: + case IR::Opcode::GetCbufS16: + used_type |= IR::Type::U16; + return 2; + case IR::Opcode::GetCbufU32: + used_type |= IR::Type::U32; + return 4; + case IR::Opcode::GetCbufF32: + used_type |= IR::Type::F32; + return 4; + case IR::Opcode::GetCbufU32x2: + used_type |= IR::Type::U32x2; + return 8; + default: + throw InvalidArgument("Invalid opcode {}", opcode); + } +} + void GetPatch(Info& info, IR::Patch patch) { if (!IR::IsGeneric(patch)) { throw NotImplementedException("Reading non-generic patch {}", patch); @@ -481,45 +505,16 @@ void VisitUsages(Info& info, IR::Inst& inst) { const IR::Value offset{inst.Arg(1)}; if (index.IsImmediate()) { AddConstantBufferDescriptor(info, index.U32(), 1); - } else { - AddRegisterIndexedLdc(info); - } - - u32 element_size{}; - switch (inst.GetOpcode()) { - case IR::Opcode::GetCbufU8: - case IR::Opcode::GetCbufS8: - info.used_constant_buffer_types |= IR::Type::U8; - element_size = 1; - break; - case IR::Opcode::GetCbufU16: - case IR::Opcode::GetCbufS16: - info.used_constant_buffer_types |= IR::Type::U16; - element_size = 2; - break; - case IR::Opcode::GetCbufU32: - info.used_constant_buffer_types |= IR::Type::U32; - element_size = 4; - break; - case IR::Opcode::GetCbufF32: - info.used_constant_buffer_types |= IR::Type::F32; - element_size = 4; - break; - case IR::Opcode::GetCbufU32x2: - info.used_constant_buffer_types |= IR::Type::U32x2; - element_size = 8; - break; - default: - break; - } - - if (index.IsImmediate()) { + u32 element_size = GetElementSize(info.used_constant_buffer_types, inst.GetOpcode()); u32& size{info.constant_buffer_used_sizes[index.U32()]}; if (offset.IsImmediate()) { size = Common::AlignUp(std::max(size, offset.U32() + element_size), 16u); } else { size = 0x10'000; } + } else { + AddRegisterIndexedLdc(info); + GetElementSize(info.used_indirect_cbuf_types, inst.GetOpcode()); } break; } -- cgit v1.2.3