From c03f0b3c893f2bc2ae4f1e1825c5ac1453c36710 Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Fri, 18 Aug 2023 18:30:31 +0200
Subject: Shader Recomnpiler: implement textuzreGrad 3D emulation constant
 propagation

---
 .../backend/glasm/emit_glasm_image.cpp             | 23 ++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

(limited to 'src/shader_recompiler/backend/glasm/emit_glasm_image.cpp')

diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
index 85ee273339..d0e3081249 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
@@ -558,12 +558,15 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
                        const IR::Value& coord, const IR::Value& derivatives,
                        const IR::Value& offset, const IR::Value& lod_clamp) {
     const auto info{inst.Flags<IR::TextureInstInfo>()};
-    ScopedRegister dpdx, dpdy;
+    ScopedRegister dpdx, dpdy, coords;
     const bool multi_component{info.num_derivates > 1 || info.has_lod_clamp};
     if (multi_component) {
         // Allocate this early to avoid aliasing other registers
         dpdx = ScopedRegister{ctx.reg_alloc};
         dpdy = ScopedRegister{ctx.reg_alloc};
+        if (info.num_derivates >= 3) {
+            coords = ScopedRegister{ctx.reg_alloc};
+        }
     }
     const auto sparse_inst{PrepareSparse(inst)};
     const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""};
@@ -580,15 +583,27 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
                 "MOV.F {}.y,{}.w;",
                 dpdx.reg, derivatives_vec, dpdx.reg, derivatives_vec, dpdy.reg, derivatives_vec,
                 dpdy.reg, derivatives_vec);
+        Register final_coord;
+        if (info.num_derivates >= 3) {
+            ctx.Add("MOV.F {}.z,{}.x;"
+                    "MOV.F {}.z,{}.y;",
+                    dpdx.reg, coord_vec, dpdy.reg, coord_vec);
+            ctx.Add("MOV.F {}.x,0;"
+                    "MOV.F {}.y,0;",
+                    "MOV.F {}.z,0;", coords.reg, coords.reg, coords.reg);
+            final_coord = coords.reg;
+        } else {
+            final_coord = coord_vec;
+        }
         if (info.has_lod_clamp) {
             const ScalarF32 lod_clamp_value{ctx.reg_alloc.Consume(lod_clamp)};
             ctx.Add("MOV.F {}.w,{};"
                     "TXD.F.LODCLAMP{} {},{},{},{},{},{}{};",
-                    dpdy.reg, lod_clamp_value, sparse_mod, ret, coord_vec, dpdx.reg, dpdy.reg,
+                    dpdy.reg, lod_clamp_value, sparse_mod, ret, final_coord, dpdx.reg, dpdy.reg,
                     texture, type, offset_vec);
         } else {
-            ctx.Add("TXD.F{} {},{},{},{},{},{}{};", sparse_mod, ret, coord_vec, dpdx.reg, dpdy.reg,
-                    texture, type, offset_vec);
+            ctx.Add("TXD.F{} {},{},{},{},{},{}{};", sparse_mod, ret, final_coord, dpdx.reg,
+                    dpdy.reg, texture, type, offset_vec);
         }
     } else {
         ctx.Add("TXD.F{} {},{},{}.x,{}.y,{},{}{};", sparse_mod, ret, coord_vec, derivatives_vec,
-- 
cgit v1.2.3-70-g09d2