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