From ba34cf0a691bc73ae6b2d8db6019b1f10d22dde5 Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Sun, 6 Mar 2022 19:54:40 +0100
Subject: Shader Decompiler: Check for shift when deriving composite samplers.

---
 src/shader_recompiler/ir_opt/texture_pass.cpp | 34 ++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

(limited to 'src/shader_recompiler/ir_opt/texture_pass.cpp')

diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index 597112ba47..4bad811c22 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -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,
                 });
-- 
cgit v1.2.3-70-g09d2