Shader Decompiler: Check for shift when deriving composite samplers.
This commit is contained in:
		| @@ -19,8 +19,10 @@ namespace { | ||||
| struct ConstBufferAddr { | ||||
|     u32 index; | ||||
|     u32 offset; | ||||
|     u32 shift_left; | ||||
|     u32 secondary_index; | ||||
|     u32 secondary_offset; | ||||
|     u32 secondary_shift_left; | ||||
|     IR::U32 dynamic_offset; | ||||
|     u32 count; | ||||
|     bool has_secondary; | ||||
| @@ -182,6 +184,7 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) { | ||||
|     switch (inst->GetOpcode()) { | ||||
|     default: | ||||
|         return std::nullopt; | ||||
|     case IR::Opcode::BitwiseXor32: | ||||
|     case IR::Opcode::BitwiseOr32: { | ||||
|         std::optional lhs{Track(inst->Arg(0))}; | ||||
|         std::optional rhs{Track(inst->Arg(1))}; | ||||
| @@ -194,19 +197,33 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) { | ||||
|         if (lhs->count > 1 || rhs->count > 1) { | ||||
|             return std::nullopt; | ||||
|         } | ||||
|         if (lhs->index > rhs->index || lhs->offset > rhs->offset) { | ||||
|         if (lhs->shift_left > 0 || lhs->index > rhs->index || lhs->offset > rhs->offset) { | ||||
|             std::swap(lhs, rhs); | ||||
|         } | ||||
|         return ConstBufferAddr{ | ||||
|             .index = lhs->index, | ||||
|             .offset = lhs->offset, | ||||
|             .shift_left = lhs->shift_left, | ||||
|             .secondary_index = rhs->index, | ||||
|             .secondary_offset = rhs->offset, | ||||
|             .secondary_shift_left = rhs->shift_left, | ||||
|             .dynamic_offset = {}, | ||||
|             .count = 1, | ||||
|             .has_secondary = true, | ||||
|         }; | ||||
|     } | ||||
|     case IR::Opcode::ShiftLeftLogical32: { | ||||
|         const IR::Value shift{inst->Arg(1)}; | ||||
|         if (!shift.IsImmediate()) { | ||||
|             return std::nullopt; | ||||
|         } | ||||
|         std::optional lhs{Track(inst->Arg(0))}; | ||||
|         if (lhs) { | ||||
|             lhs->shift_left = shift.U32(); | ||||
|         } | ||||
|         return lhs; | ||||
|         break; | ||||
|     } | ||||
|     case IR::Opcode::GetCbufU32x2: | ||||
|     case IR::Opcode::GetCbufU32: | ||||
|         break; | ||||
| @@ -222,8 +239,10 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) { | ||||
|         return ConstBufferAddr{ | ||||
|             .index = index.U32(), | ||||
|             .offset = offset.U32(), | ||||
|             .shift_left = 0, | ||||
|             .secondary_index = 0, | ||||
|             .secondary_offset = 0, | ||||
|             .secondary_shift_left = 0, | ||||
|             .dynamic_offset = {}, | ||||
|             .count = 1, | ||||
|             .has_secondary = false, | ||||
| @@ -247,8 +266,10 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) { | ||||
|     return ConstBufferAddr{ | ||||
|         .index = index.U32(), | ||||
|         .offset = base_offset, | ||||
|         .shift_left = 0, | ||||
|         .secondary_index = 0, | ||||
|         .secondary_offset = 0, | ||||
|         .secondary_shift_left = 0, | ||||
|         .dynamic_offset = dynamic_offset, | ||||
|         .count = 8, | ||||
|         .has_secondary = false, | ||||
| @@ -267,8 +288,10 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { | ||||
|         addr = ConstBufferAddr{ | ||||
|             .index = env.TextureBoundBuffer(), | ||||
|             .offset = inst.Arg(0).U32(), | ||||
|             .shift_left = 0, | ||||
|             .secondary_index = 0, | ||||
|             .secondary_offset = 0, | ||||
|             .secondary_shift_left = 0, | ||||
|             .dynamic_offset = {}, | ||||
|             .count = 1, | ||||
|             .has_secondary = false, | ||||
| @@ -284,8 +307,9 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { | ||||
| TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) { | ||||
|     const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index}; | ||||
|     const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset}; | ||||
|     const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset)}; | ||||
|     const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)}; | ||||
|     const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset) << cbuf.shift_left}; | ||||
|     const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset) | ||||
|                       << cbuf.secondary_shift_left}; | ||||
|     return env.ReadTextureType(lhs_raw | rhs_raw); | ||||
| } | ||||
|  | ||||
| @@ -487,8 +511,10 @@ void TexturePass(Environment& env, IR::Program& program) { | ||||
|                     .has_secondary = cbuf.has_secondary, | ||||
|                     .cbuf_index = cbuf.index, | ||||
|                     .cbuf_offset = cbuf.offset, | ||||
|                     .shift_left = cbuf.shift_left, | ||||
|                     .secondary_cbuf_index = cbuf.secondary_index, | ||||
|                     .secondary_cbuf_offset = cbuf.secondary_offset, | ||||
|                     .secondary_shift_left = cbuf.secondary_shift_left, | ||||
|                     .count = cbuf.count, | ||||
|                     .size_shift = DESCRIPTOR_SIZE_SHIFT, | ||||
|                 }); | ||||
| @@ -499,8 +525,10 @@ void TexturePass(Environment& env, IR::Program& program) { | ||||
|                     .has_secondary = cbuf.has_secondary, | ||||
|                     .cbuf_index = cbuf.index, | ||||
|                     .cbuf_offset = cbuf.offset, | ||||
|                     .shift_left = cbuf.shift_left, | ||||
|                     .secondary_cbuf_index = cbuf.secondary_index, | ||||
|                     .secondary_cbuf_offset = cbuf.secondary_offset, | ||||
|                     .secondary_shift_left = cbuf.secondary_shift_left, | ||||
|                     .count = cbuf.count, | ||||
|                     .size_shift = DESCRIPTOR_SIZE_SHIFT, | ||||
|                 }); | ||||
|   | ||||
| @@ -61,8 +61,10 @@ struct TextureBufferDescriptor { | ||||
|     bool has_secondary; | ||||
|     u32 cbuf_index; | ||||
|     u32 cbuf_offset; | ||||
|     u32 shift_left; | ||||
|     u32 secondary_cbuf_index; | ||||
|     u32 secondary_cbuf_offset; | ||||
|     u32 secondary_shift_left; | ||||
|     u32 count; | ||||
|     u32 size_shift; | ||||
| }; | ||||
| @@ -85,8 +87,10 @@ struct TextureDescriptor { | ||||
|     bool has_secondary; | ||||
|     u32 cbuf_index; | ||||
|     u32 cbuf_offset; | ||||
|     u32 shift_left; | ||||
|     u32 secondary_cbuf_index; | ||||
|     u32 secondary_cbuf_offset; | ||||
|     u32 secondary_shift_left; | ||||
|     u32 count; | ||||
|     u32 size_shift; | ||||
| }; | ||||
|   | ||||
| @@ -100,8 +100,9 @@ void ComputePipeline::Configure() { | ||||
|                 const u32 secondary_offset{desc.secondary_cbuf_offset + index_offset}; | ||||
|                 const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].Address() + | ||||
|                                              secondary_offset}; | ||||
|                 const u32 lhs_raw{gpu_memory->Read<u32>(addr)}; | ||||
|                 const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr)}; | ||||
|                 const u32 lhs_raw{gpu_memory->Read<u32>(addr) << desc.shift_left}; | ||||
|                 const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr) | ||||
|                                   << desc.secondary_shift_left}; | ||||
|                 return TexturePair(lhs_raw | rhs_raw, via_header_index); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -312,8 +312,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|                     const u32 second_offset{desc.secondary_cbuf_offset + index_offset}; | ||||
|                     const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].address + | ||||
|                                                  second_offset}; | ||||
|                     const u32 lhs_raw{gpu_memory->Read<u32>(addr)}; | ||||
|                     const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr)}; | ||||
|                     const u32 lhs_raw{gpu_memory->Read<u32>(addr) << desc.shift_left}; | ||||
|                     const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr) | ||||
|                                       << desc.secondary_shift_left}; | ||||
|                     const u32 raw{lhs_raw | rhs_raw}; | ||||
|                     return TexturePair(raw, via_header_index); | ||||
|                 } | ||||
|   | ||||
| @@ -126,8 +126,8 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | ||||
|                 const u32 secondary_offset{desc.secondary_cbuf_offset + index_offset}; | ||||
|                 const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].Address() + | ||||
|                                              secondary_offset}; | ||||
|                 const u32 lhs_raw{gpu_memory.Read<u32>(addr)}; | ||||
|                 const u32 rhs_raw{gpu_memory.Read<u32>(separate_addr)}; | ||||
|                 const u32 lhs_raw{gpu_memory.Read<u32>(addr) << desc.shift_left}; | ||||
|                 const u32 rhs_raw{gpu_memory.Read<u32>(separate_addr) << desc.secondary_shift_left}; | ||||
|                 return TexturePair(lhs_raw | rhs_raw, via_header_index); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -314,8 +314,9 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | ||||
|                     const u32 second_offset{desc.secondary_cbuf_offset + index_offset}; | ||||
|                     const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].address + | ||||
|                                                  second_offset}; | ||||
|                     const u32 lhs_raw{gpu_memory->Read<u32>(addr)}; | ||||
|                     const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr)}; | ||||
|                     const u32 lhs_raw{gpu_memory->Read<u32>(addr) << desc.shift_left}; | ||||
|                     const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr) | ||||
|                                       << desc.secondary_shift_left}; | ||||
|                     const u32 raw{lhs_raw | rhs_raw}; | ||||
|                     return TexturePair(raw, via_header_index); | ||||
|                 } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user