From 75596c07e0fc1462c2a19484e168f4944c33d3d3 Mon Sep 17 00:00:00 2001
From: Feng Chen <VonChenPlus@gmail.com>
Date: Fri, 4 Nov 2022 14:39:42 +0800
Subject: video_core: Fix SNORM texture buffer emulating error (#9001)

---
 src/shader_recompiler/frontend/ir/ir_emitter.cpp |  5 ++++
 src/shader_recompiler/frontend/ir/opcodes.h      |  1 +
 src/shader_recompiler/frontend/ir/opcodes.inc    |  1 +
 src/shader_recompiler/frontend/ir/type.h         | 31 ++++++++++++------------
 src/shader_recompiler/frontend/ir/value.cpp      |  3 +++
 src/shader_recompiler/frontend/ir/value.h        | 12 +++++++++
 6 files changed, 38 insertions(+), 15 deletions(-)

(limited to 'src/shader_recompiler/frontend')

diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index de1ce90a31..d4425f06d9 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -691,6 +691,11 @@ IR::U32 IREmitter::BitCast<IR::U32, IR::F32>(const IR::F32& value) {
     return Inst<IR::U32>(Opcode::BitCastU32F32, value);
 }
 
+template <>
+IR::S32 IREmitter::BitCast<IR::S32, IR::F32>(const IR::F32& value) {
+    return Inst<IR::S32>(Opcode::BitCastS32F32, value);
+}
+
 template <>
 IR::F32 IREmitter::BitCast<IR::F32, IR::U32>(const IR::U32& value) {
     return Inst<IR::F32>(Opcode::BitCastF32U32, value);
diff --git a/src/shader_recompiler/frontend/ir/opcodes.h b/src/shader_recompiler/frontend/ir/opcodes.h
index 752879a186..e70d7745cd 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.h
+++ b/src/shader_recompiler/frontend/ir/opcodes.h
@@ -37,6 +37,7 @@ constexpr Type U8{Type::U8};
 constexpr Type U16{Type::U16};
 constexpr Type U32{Type::U32};
 constexpr Type U64{Type::U64};
+constexpr Type S32{Type::S32};
 constexpr Type F16{Type::F16};
 constexpr Type F32{Type::F32};
 constexpr Type F64{Type::F64};
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index f3038f2984..88aa077ee8 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -174,6 +174,7 @@ OPCODE(SelectF64,                                           F64,            U1,
 OPCODE(BitCastU16F16,                                       U16,            F16,                                                                            )
 OPCODE(BitCastU32F32,                                       U32,            F32,                                                                            )
 OPCODE(BitCastU64F64,                                       U64,            F64,                                                                            )
+OPCODE(BitCastS32F32,                                       S32,            F32,                                                                            )
 OPCODE(BitCastF16U16,                                       F16,            U16,                                                                            )
 OPCODE(BitCastF32U32,                                       F32,            U32,                                                                            )
 OPCODE(BitCastF64U64,                                       F64,            U64,                                                                            )
diff --git a/src/shader_recompiler/frontend/ir/type.h b/src/shader_recompiler/frontend/ir/type.h
index 04c8c4ddbe..5a7c706ada 100644
--- a/src/shader_recompiler/frontend/ir/type.h
+++ b/src/shader_recompiler/frontend/ir/type.h
@@ -24,21 +24,22 @@ enum class Type {
     U16 = 1 << 7,
     U32 = 1 << 8,
     U64 = 1 << 9,
-    F16 = 1 << 10,
-    F32 = 1 << 11,
-    F64 = 1 << 12,
-    U32x2 = 1 << 13,
-    U32x3 = 1 << 14,
-    U32x4 = 1 << 15,
-    F16x2 = 1 << 16,
-    F16x3 = 1 << 17,
-    F16x4 = 1 << 18,
-    F32x2 = 1 << 19,
-    F32x3 = 1 << 20,
-    F32x4 = 1 << 21,
-    F64x2 = 1 << 22,
-    F64x3 = 1 << 23,
-    F64x4 = 1 << 24,
+    S32 = 1 << 10,
+    F16 = 1 << 11,
+    F32 = 1 << 12,
+    F64 = 1 << 13,
+    U32x2 = 1 << 14,
+    U32x3 = 1 << 15,
+    U32x4 = 1 << 16,
+    F16x2 = 1 << 17,
+    F16x3 = 1 << 18,
+    F16x4 = 1 << 19,
+    F32x2 = 1 << 20,
+    F32x3 = 1 << 21,
+    F32x4 = 1 << 22,
+    F64x2 = 1 << 23,
+    F64x3 = 1 << 24,
+    F64x4 = 1 << 25,
 };
 DECLARE_ENUM_FLAG_OPERATORS(Type)
 
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp
index 3461693283..30ba12316c 100644
--- a/src/shader_recompiler/frontend/ir/value.cpp
+++ b/src/shader_recompiler/frontend/ir/value.cpp
@@ -23,6 +23,8 @@ Value::Value(u16 value) noexcept : type{Type::U16}, imm_u16{value} {}
 
 Value::Value(u32 value) noexcept : type{Type::U32}, imm_u32{value} {}
 
+Value::Value(s32 value) noexcept : type{Type::S32}, imm_s32{value} {}
+
 Value::Value(f32 value) noexcept : type{Type::F32}, imm_f32{value} {}
 
 Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {}
@@ -69,6 +71,7 @@ bool Value::operator==(const Value& other) const {
         return imm_u16 == other.imm_u16;
     case Type::U32:
     case Type::F32:
+    case Type::S32:
         return imm_u32 == other.imm_u32;
     case Type::U64:
     case Type::F64:
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index 6a673ca05a..e8bbb93a5d 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -44,6 +44,7 @@ public:
     explicit Value(u8 value) noexcept;
     explicit Value(u16 value) noexcept;
     explicit Value(u32 value) noexcept;
+    explicit Value(s32 value) noexcept;
     explicit Value(f32 value) noexcept;
     explicit Value(u64 value) noexcept;
     explicit Value(f64 value) noexcept;
@@ -66,6 +67,7 @@ public:
     [[nodiscard]] u8 U8() const;
     [[nodiscard]] u16 U16() const;
     [[nodiscard]] u32 U32() const;
+    [[nodiscard]] s32 S32() const;
     [[nodiscard]] f32 F32() const;
     [[nodiscard]] u64 U64() const;
     [[nodiscard]] f64 F64() const;
@@ -85,6 +87,7 @@ private:
         u8 imm_u8;
         u16 imm_u16;
         u32 imm_u32;
+        s32 imm_s32;
         f32 imm_f32;
         u64 imm_u64;
         f64 imm_f64;
@@ -266,6 +269,7 @@ using U8 = TypedValue<Type::U8>;
 using U16 = TypedValue<Type::U16>;
 using U32 = TypedValue<Type::U32>;
 using U64 = TypedValue<Type::U64>;
+using S32 = TypedValue<Type::S32>;
 using F16 = TypedValue<Type::F16>;
 using F32 = TypedValue<Type::F32>;
 using F64 = TypedValue<Type::F64>;
@@ -377,6 +381,14 @@ inline u32 Value::U32() const {
     return imm_u32;
 }
 
+inline s32 Value::S32() const {
+    if (IsIdentity()) {
+        return inst->Arg(0).S32();
+    }
+    DEBUG_ASSERT(type == Type::S32);
+    return imm_s32;
+}
+
 inline f32 Value::F32() const {
     if (IsIdentity()) {
         return inst->Arg(0).F32();
-- 
cgit v1.2.3-70-g09d2