diff options
| author | 2022-03-18 00:36:31 +0100 | |
|---|---|---|
| committer | 2022-03-18 00:36:31 +0100 | |
| commit | cb86e7941b87c28491114c80cf2cd3cafd316c72 (patch) | |
| tree | ecd031fac28e0bfe9c2d10855c74e01379654a4f /src/shader_recompiler/ir_opt | |
| parent | Merge pull request #8030 from liamwhite/s8d24-conversion (diff) | |
| parent | Address review comments (diff) | |
| download | yuzu-cb86e7941b87c28491114c80cf2cd3cafd316c72.tar.gz yuzu-cb86e7941b87c28491114c80cf2cd3cafd316c72.tar.xz yuzu-cb86e7941b87c28491114c80cf2cd3cafd316c72.zip | |
Merge pull request #8024 from liamwhite/const-indexing
Add shader support for const buffer indirect addressing
Diffstat (limited to 'src/shader_recompiler/ir_opt')
| -rw-r--r-- | src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | 86 |
1 files changed, 51 insertions, 35 deletions
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..0b2c60842 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,46 @@ void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) { | |||
| 29 | }); | 29 | }); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | void AddRegisterIndexedLdc(Info& info) { | ||
| 33 | info.uses_cbuf_indirect = true; | ||
| 34 | |||
| 35 | // The shader can use any possible constant buffer | ||
| 36 | info.constant_buffer_mask = (1 << Info::MAX_CBUFS) - 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 | |||
| 43 | // The shader can use any possible access size | ||
| 44 | info.constant_buffer_used_sizes[i] = 0x10'000; | ||
| 45 | } | ||
| 46 | } | ||
| 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 | |||
| 32 | void GetPatch(Info& info, IR::Patch patch) { | 72 | void GetPatch(Info& info, IR::Patch patch) { |
| 33 | if (!IR::IsGeneric(patch)) { | 73 | if (!IR::IsGeneric(patch)) { |
| 34 | throw NotImplementedException("Reading non-generic patch {}", patch); | 74 | throw NotImplementedException("Reading non-generic patch {}", patch); |
| @@ -463,42 +503,18 @@ void VisitUsages(Info& info, IR::Inst& inst) { | |||
| 463 | case IR::Opcode::GetCbufU32x2: { | 503 | case IR::Opcode::GetCbufU32x2: { |
| 464 | const IR::Value index{inst.Arg(0)}; | 504 | const IR::Value index{inst.Arg(0)}; |
| 465 | const IR::Value offset{inst.Arg(1)}; | 505 | const IR::Value offset{inst.Arg(1)}; |
| 466 | if (!index.IsImmediate()) { | 506 | if (index.IsImmediate()) { |
| 467 | throw NotImplementedException("Constant buffer with non-immediate index"); | 507 | AddConstantBufferDescriptor(info, index.U32(), 1); |
| 468 | } | 508 | u32 element_size = GetElementSize(info.used_constant_buffer_types, inst.GetOpcode()); |
| 469 | AddConstantBufferDescriptor(info, index.U32(), 1); | 509 | u32& size{info.constant_buffer_used_sizes[index.U32()]}; |
| 470 | u32 element_size{}; | 510 | if (offset.IsImmediate()) { |
| 471 | switch (inst.GetOpcode()) { | 511 | size = Common::AlignUp(std::max(size, offset.U32() + element_size), 16u); |
| 472 | case IR::Opcode::GetCbufU8: | 512 | } else { |
| 473 | case IR::Opcode::GetCbufS8: | 513 | size = 0x10'000; |
| 474 | info.used_constant_buffer_types |= IR::Type::U8; | 514 | } |
| 475 | element_size = 1; | ||
| 476 | break; | ||
| 477 | case IR::Opcode::GetCbufU16: | ||
| 478 | case IR::Opcode::GetCbufS16: | ||
| 479 | info.used_constant_buffer_types |= IR::Type::U16; | ||
| 480 | element_size = 2; | ||
| 481 | break; | ||
| 482 | case IR::Opcode::GetCbufU32: | ||
| 483 | info.used_constant_buffer_types |= IR::Type::U32; | ||
| 484 | element_size = 4; | ||
| 485 | break; | ||
| 486 | case IR::Opcode::GetCbufF32: | ||
| 487 | info.used_constant_buffer_types |= IR::Type::F32; | ||
| 488 | element_size = 4; | ||
| 489 | break; | ||
| 490 | case IR::Opcode::GetCbufU32x2: | ||
| 491 | info.used_constant_buffer_types |= IR::Type::U32x2; | ||
| 492 | element_size = 8; | ||
| 493 | break; | ||
| 494 | default: | ||
| 495 | break; | ||
| 496 | } | ||
| 497 | u32& size{info.constant_buffer_used_sizes[index.U32()]}; | ||
| 498 | if (offset.IsImmediate()) { | ||
| 499 | size = Common::AlignUp(std::max(size, offset.U32() + element_size), 16u); | ||
| 500 | } else { | 515 | } else { |
| 501 | size = 0x10'000; | 516 | AddRegisterIndexedLdc(info); |
| 517 | GetElementSize(info.used_indirect_cbuf_types, inst.GetOpcode()); | ||
| 502 | } | 518 | } |
| 503 | break; | 519 | break; |
| 504 | } | 520 | } |