summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Feng Chen2022-11-04 14:39:42 +0800
committerGravatar GitHub2022-11-04 02:39:42 -0400
commit75596c07e0fc1462c2a19484e168f4944c33d3d3 (patch)
tree1aa919ea76f467c51b3fc591a72c57f5ade92560
parentUI: Add options to hide extra columns (#9093) (diff)
downloadyuzu-75596c07e0fc1462c2a19484e168f4944c33d3d3.tar.gz
yuzu-75596c07e0fc1462c2a19484e168f4944c33d3d3.tar.xz
yuzu-75596c07e0fc1462c2a19484e168f4944c33d3d3.zip
video_core: Fix SNORM texture buffer emulating error (#9001)
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp4
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_instructions.h1
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp4
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_instructions.h1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp4
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_instructions.h3
-rw-r--r--src/shader_recompiler/environment.h2
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp5
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.h1
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc1
-rw-r--r--src/shader_recompiler/frontend/ir/type.h31
-rw-r--r--src/shader_recompiler/frontend/ir/value.cpp3
-rw-r--r--src/shader_recompiler/frontend/ir/value.h12
-rw-r--r--src/shader_recompiler/ir_opt/texture_pass.cpp49
-rw-r--r--src/shader_recompiler/shader_info.h10
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp15
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp10
-rw-r--r--src/video_core/shader_environment.cpp89
-rw-r--r--src/video_core/shader_environment.h12
-rw-r--r--src/video_core/texture_cache/util.cpp1
23 files changed, 224 insertions, 52 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp
index 2fc2a0ac6..5bfdecc09 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp
@@ -43,6 +43,10 @@ void EmitBitCastU64F64(EmitContext&, IR::Inst& inst, const IR::Value& value) {
43 Alias(inst, value); 43 Alias(inst, value);
44} 44}
45 45
46void EmitBitCastS32F32(EmitContext&, IR::Inst& inst, const IR::Value& value) {
47 Alias(inst, value);
48}
49
46void EmitBitCastF16U16(EmitContext&, IR::Inst& inst, const IR::Value& value) { 50void EmitBitCastF16U16(EmitContext&, IR::Inst& inst, const IR::Value& value) {
47 Alias(inst, value); 51 Alias(inst, value);
48} 52}
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
index c08f48ed9..d645fd532 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
@@ -196,6 +196,7 @@ void EmitSelectF64(EmitContext& ctx, ScalarS32 cond, Register true_value, Regist
196void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 196void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
197void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 197void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
198void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 198void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
199void EmitBitCastS32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
199void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 200void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
200void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 201void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
201void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 202void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
index 1be4a0f59..8e5e6cf1f 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
@@ -48,6 +48,10 @@ void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value)
48 ctx.AddU64("{}=doubleBitsToUint64({});", inst, value); 48 ctx.AddU64("{}=doubleBitsToUint64({});", inst, value);
49} 49}
50 50
51void EmitBitCastS32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
52 ctx.AddF32("{}=ftoi({});", inst, value);
53}
54
51void EmitBitCastF16U16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst) { 55void EmitBitCastF16U16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst) {
52 NotImplemented(); 56 NotImplemented();
53} 57}
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index 3c8bcb7e9..96e683b5e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -230,6 +230,7 @@ void EmitSelectF64(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
230void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst); 230void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst);
231void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value); 231void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
232void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value); 232void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value);
233void EmitBitCastS32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
233void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst); 234void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst);
234void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, std::string_view value); 235void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
235void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, std::string_view value); 236void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, std::string_view value);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
index c4ca28d11..50daacd95 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
@@ -18,6 +18,10 @@ void EmitBitCastU64F64(EmitContext&) {
18 throw NotImplementedException("SPIR-V Instruction"); 18 throw NotImplementedException("SPIR-V Instruction");
19} 19}
20 20
21void EmitBitCastS32F32(EmitContext&) {
22 throw NotImplementedException("SPIR-V Instruction");
23}
24
21void EmitBitCastF16U16(EmitContext&) { 25void EmitBitCastF16U16(EmitContext&) {
22 throw NotImplementedException("SPIR-V Instruction"); 26 throw NotImplementedException("SPIR-V Instruction");
23} 27}
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
index 86dd3c4f3..7070c8fda 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
@@ -178,7 +178,8 @@ Id EmitSelectF64(EmitContext& ctx, Id cond, Id true_value, Id false_value);
178void EmitBitCastU16F16(EmitContext& ctx); 178void EmitBitCastU16F16(EmitContext& ctx);
179Id EmitBitCastU32F32(EmitContext& ctx, Id value); 179Id EmitBitCastU32F32(EmitContext& ctx, Id value);
180void EmitBitCastU64F64(EmitContext& ctx); 180void EmitBitCastU64F64(EmitContext& ctx);
181void EmitBitCastF16U16(EmitContext& ctx); 181void EmitBitCastS32F32(EmitContext& ctx);
182void EmitBitCastF16U16(EmitContext&);
182Id EmitBitCastF32U32(EmitContext& ctx, Id value); 183Id EmitBitCastF32U32(EmitContext& ctx, Id value);
183void EmitBitCastF64U64(EmitContext& ctx); 184void EmitBitCastF64U64(EmitContext& ctx);
184Id EmitPackUint2x32(EmitContext& ctx, Id value); 185Id EmitPackUint2x32(EmitContext& ctx, Id value);
diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h
index 980e0e54c..402f2664f 100644
--- a/src/shader_recompiler/environment.h
+++ b/src/shader_recompiler/environment.h
@@ -22,6 +22,8 @@ public:
22 22
23 [[nodiscard]] virtual TextureType ReadTextureType(u32 raw_handle) = 0; 23 [[nodiscard]] virtual TextureType ReadTextureType(u32 raw_handle) = 0;
24 24
25 [[nodiscard]] virtual TexturePixelFormat ReadTexturePixelFormat(u32 raw_handle) = 0;
26
25 [[nodiscard]] virtual u32 ReadViewportTransformState() = 0; 27 [[nodiscard]] virtual u32 ReadViewportTransformState() = 0;
26 28
27 [[nodiscard]] virtual u32 TextureBoundBuffer() const = 0; 29 [[nodiscard]] virtual u32 TextureBoundBuffer() const = 0;
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index de1ce90a3..d4425f06d 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -692,6 +692,11 @@ IR::U32 IREmitter::BitCast<IR::U32, IR::F32>(const IR::F32& value) {
692} 692}
693 693
694template <> 694template <>
695IR::S32 IREmitter::BitCast<IR::S32, IR::F32>(const IR::F32& value) {
696 return Inst<IR::S32>(Opcode::BitCastS32F32, value);
697}
698
699template <>
695IR::F32 IREmitter::BitCast<IR::F32, IR::U32>(const IR::U32& value) { 700IR::F32 IREmitter::BitCast<IR::F32, IR::U32>(const IR::U32& value) {
696 return Inst<IR::F32>(Opcode::BitCastF32U32, value); 701 return Inst<IR::F32>(Opcode::BitCastF32U32, value);
697} 702}
diff --git a/src/shader_recompiler/frontend/ir/opcodes.h b/src/shader_recompiler/frontend/ir/opcodes.h
index 752879a18..e70d7745c 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};
37constexpr Type U16{Type::U16}; 37constexpr Type U16{Type::U16};
38constexpr Type U32{Type::U32}; 38constexpr Type U32{Type::U32};
39constexpr Type U64{Type::U64}; 39constexpr Type U64{Type::U64};
40constexpr Type S32{Type::S32};
40constexpr Type F16{Type::F16}; 41constexpr Type F16{Type::F16};
41constexpr Type F32{Type::F32}; 42constexpr Type F32{Type::F32};
42constexpr Type F64{Type::F64}; 43constexpr Type F64{Type::F64};
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index f3038f298..88aa077ee 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,
174OPCODE(BitCastU16F16, U16, F16, ) 174OPCODE(BitCastU16F16, U16, F16, )
175OPCODE(BitCastU32F32, U32, F32, ) 175OPCODE(BitCastU32F32, U32, F32, )
176OPCODE(BitCastU64F64, U64, F64, ) 176OPCODE(BitCastU64F64, U64, F64, )
177OPCODE(BitCastS32F32, S32, F32, )
177OPCODE(BitCastF16U16, F16, U16, ) 178OPCODE(BitCastF16U16, F16, U16, )
178OPCODE(BitCastF32U32, F32, U32, ) 179OPCODE(BitCastF32U32, F32, U32, )
179OPCODE(BitCastF64U64, F64, U64, ) 180OPCODE(BitCastF64U64, F64, U64, )
diff --git a/src/shader_recompiler/frontend/ir/type.h b/src/shader_recompiler/frontend/ir/type.h
index 04c8c4ddb..5a7c706ad 100644
--- a/src/shader_recompiler/frontend/ir/type.h
+++ b/src/shader_recompiler/frontend/ir/type.h
@@ -24,21 +24,22 @@ enum class Type {
24 U16 = 1 << 7, 24 U16 = 1 << 7,
25 U32 = 1 << 8, 25 U32 = 1 << 8,
26 U64 = 1 << 9, 26 U64 = 1 << 9,
27 F16 = 1 << 10, 27 S32 = 1 << 10,
28 F32 = 1 << 11, 28 F16 = 1 << 11,
29 F64 = 1 << 12, 29 F32 = 1 << 12,
30 U32x2 = 1 << 13, 30 F64 = 1 << 13,
31 U32x3 = 1 << 14, 31 U32x2 = 1 << 14,
32 U32x4 = 1 << 15, 32 U32x3 = 1 << 15,
33 F16x2 = 1 << 16, 33 U32x4 = 1 << 16,
34 F16x3 = 1 << 17, 34 F16x2 = 1 << 17,
35 F16x4 = 1 << 18, 35 F16x3 = 1 << 18,
36 F32x2 = 1 << 19, 36 F16x4 = 1 << 19,
37 F32x3 = 1 << 20, 37 F32x2 = 1 << 20,
38 F32x4 = 1 << 21, 38 F32x3 = 1 << 21,
39 F64x2 = 1 << 22, 39 F32x4 = 1 << 22,
40 F64x3 = 1 << 23, 40 F64x2 = 1 << 23,
41 F64x4 = 1 << 24, 41 F64x3 = 1 << 24,
42 F64x4 = 1 << 25,
42}; 43};
43DECLARE_ENUM_FLAG_OPERATORS(Type) 44DECLARE_ENUM_FLAG_OPERATORS(Type)
44 45
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp
index 346169328..30ba12316 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} {}
23 23
24Value::Value(u32 value) noexcept : type{Type::U32}, imm_u32{value} {} 24Value::Value(u32 value) noexcept : type{Type::U32}, imm_u32{value} {}
25 25
26Value::Value(s32 value) noexcept : type{Type::S32}, imm_s32{value} {}
27
26Value::Value(f32 value) noexcept : type{Type::F32}, imm_f32{value} {} 28Value::Value(f32 value) noexcept : type{Type::F32}, imm_f32{value} {}
27 29
28Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {} 30Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {}
@@ -69,6 +71,7 @@ bool Value::operator==(const Value& other) const {
69 return imm_u16 == other.imm_u16; 71 return imm_u16 == other.imm_u16;
70 case Type::U32: 72 case Type::U32:
71 case Type::F32: 73 case Type::F32:
74 case Type::S32:
72 return imm_u32 == other.imm_u32; 75 return imm_u32 == other.imm_u32;
73 case Type::U64: 76 case Type::U64:
74 case Type::F64: 77 case Type::F64:
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index 6a673ca05..e8bbb93a5 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -44,6 +44,7 @@ public:
44 explicit Value(u8 value) noexcept; 44 explicit Value(u8 value) noexcept;
45 explicit Value(u16 value) noexcept; 45 explicit Value(u16 value) noexcept;
46 explicit Value(u32 value) noexcept; 46 explicit Value(u32 value) noexcept;
47 explicit Value(s32 value) noexcept;
47 explicit Value(f32 value) noexcept; 48 explicit Value(f32 value) noexcept;
48 explicit Value(u64 value) noexcept; 49 explicit Value(u64 value) noexcept;
49 explicit Value(f64 value) noexcept; 50 explicit Value(f64 value) noexcept;
@@ -66,6 +67,7 @@ public:
66 [[nodiscard]] u8 U8() const; 67 [[nodiscard]] u8 U8() const;
67 [[nodiscard]] u16 U16() const; 68 [[nodiscard]] u16 U16() const;
68 [[nodiscard]] u32 U32() const; 69 [[nodiscard]] u32 U32() const;
70 [[nodiscard]] s32 S32() const;
69 [[nodiscard]] f32 F32() const; 71 [[nodiscard]] f32 F32() const;
70 [[nodiscard]] u64 U64() const; 72 [[nodiscard]] u64 U64() const;
71 [[nodiscard]] f64 F64() const; 73 [[nodiscard]] f64 F64() const;
@@ -85,6 +87,7 @@ private:
85 u8 imm_u8; 87 u8 imm_u8;
86 u16 imm_u16; 88 u16 imm_u16;
87 u32 imm_u32; 89 u32 imm_u32;
90 s32 imm_s32;
88 f32 imm_f32; 91 f32 imm_f32;
89 u64 imm_u64; 92 u64 imm_u64;
90 f64 imm_f64; 93 f64 imm_f64;
@@ -266,6 +269,7 @@ using U8 = TypedValue<Type::U8>;
266using U16 = TypedValue<Type::U16>; 269using U16 = TypedValue<Type::U16>;
267using U32 = TypedValue<Type::U32>; 270using U32 = TypedValue<Type::U32>;
268using U64 = TypedValue<Type::U64>; 271using U64 = TypedValue<Type::U64>;
272using S32 = TypedValue<Type::S32>;
269using F16 = TypedValue<Type::F16>; 273using F16 = TypedValue<Type::F16>;
270using F32 = TypedValue<Type::F32>; 274using F32 = TypedValue<Type::F32>;
271using F64 = TypedValue<Type::F64>; 275using F64 = TypedValue<Type::F64>;
@@ -377,6 +381,14 @@ inline u32 Value::U32() const {
377 return imm_u32; 381 return imm_u32;
378} 382}
379 383
384inline s32 Value::S32() const {
385 if (IsIdentity()) {
386 return inst->Arg(0).S32();
387 }
388 DEBUG_ASSERT(type == Type::S32);
389 return imm_s32;
390}
391
380inline f32 Value::F32() const { 392inline f32 Value::F32() const {
381 if (IsIdentity()) { 393 if (IsIdentity()) {
382 return inst->Arg(0).F32(); 394 return inst->Arg(0).F32();
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index e8be58357..9eff84a3d 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -7,6 +7,7 @@
7 7
8#include <boost/container/small_vector.hpp> 8#include <boost/container/small_vector.hpp>
9 9
10#include "common/settings.h"
10#include "shader_recompiler/environment.h" 11#include "shader_recompiler/environment.h"
11#include "shader_recompiler/frontend/ir/basic_block.h" 12#include "shader_recompiler/frontend/ir/basic_block.h"
12#include "shader_recompiler/frontend/ir/breadth_first_search.h" 13#include "shader_recompiler/frontend/ir/breadth_first_search.h"
@@ -363,6 +364,14 @@ TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) {
363 return env.ReadTextureType(lhs_raw | rhs_raw); 364 return env.ReadTextureType(lhs_raw | rhs_raw);
364} 365}
365 366
367TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) {
368 const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index};
369 const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset};
370 const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset)};
371 const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)};
372 return env.ReadTexturePixelFormat(lhs_raw | rhs_raw);
373}
374
366class Descriptors { 375class Descriptors {
367public: 376public:
368 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_, 377 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_,
@@ -451,6 +460,38 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
451 ir.FPMul(IR::F32(ir.CompositeExtract(coord, 1)), 460 ir.FPMul(IR::F32(ir.CompositeExtract(coord, 1)),
452 ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1)))))); 461 ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1))))));
453} 462}
463
464void PathTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) {
465 const auto it{IR::Block::InstructionList::s_iterator_to(inst)};
466 IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
467 auto get_max_value = [pixel_format]() -> float {
468 switch (pixel_format) {
469 case TexturePixelFormat::A8B8G8R8_SNORM:
470 case TexturePixelFormat::R8G8_SNORM:
471 case TexturePixelFormat::R8_SNORM:
472 return 1.f / std::numeric_limits<char>::max();
473 case TexturePixelFormat::R16G16B16A16_SNORM:
474 case TexturePixelFormat::R16G16_SNORM:
475 case TexturePixelFormat::R16_SNORM:
476 return 1.f / std::numeric_limits<short>::max();
477 default:
478 throw InvalidArgument("Invalid texture pixel format");
479 }
480 };
481
482 const IR::Value new_inst{&*block.PrependNewInst(it, inst)};
483 const IR::F32 x(ir.CompositeExtract(new_inst, 0));
484 const IR::F32 y(ir.CompositeExtract(new_inst, 1));
485 const IR::F32 z(ir.CompositeExtract(new_inst, 2));
486 const IR::F32 w(ir.CompositeExtract(new_inst, 3));
487 const IR::F16F32F64 max_value(ir.Imm32(get_max_value()));
488 const IR::Value converted =
489 ir.CompositeConstruct(ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::S32>(x)), max_value),
490 ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::S32>(y)), max_value),
491 ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::S32>(z)), max_value),
492 ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast<IR::S32>(w)), max_value));
493 inst.ReplaceUsesWith(converted);
494}
454} // Anonymous namespace 495} // Anonymous namespace
455 496
456void TexturePass(Environment& env, IR::Program& program) { 497void TexturePass(Environment& env, IR::Program& program) {
@@ -597,6 +638,14 @@ void TexturePass(Environment& env, IR::Program& program) {
597 } else { 638 } else {
598 inst->SetArg(0, IR::Value{}); 639 inst->SetArg(0, IR::Value{});
599 } 640 }
641
642 if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&
643 inst->GetOpcode() == IR::Opcode::ImageFetch && flags.type == TextureType::Buffer) {
644 const auto pixel_format = ReadTexturePixelFormat(env, cbuf);
645 if (pixel_format != TexturePixelFormat::OTHER) {
646 PathTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format);
647 }
648 }
600 } 649 }
601} 650}
602 651
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index a479e105e..f31e1f821 100644
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -29,6 +29,16 @@ enum class TextureType : u32 {
29}; 29};
30constexpr u32 NUM_TEXTURE_TYPES = 9; 30constexpr u32 NUM_TEXTURE_TYPES = 9;
31 31
32enum class TexturePixelFormat : u32 {
33 A8B8G8R8_SNORM,
34 R8_SNORM,
35 R8G8_SNORM,
36 R16G16B16A16_SNORM,
37 R16G16_SNORM,
38 R16_SNORM,
39 OTHER
40};
41
32enum class ImageFormat : u32 { 42enum class ImageFormat : u32 {
33 Typeless, 43 Typeless,
34 R8_UINT, 44 R8_UINT,
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index 08f4d69ab..6af4ae793 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -29,17 +29,17 @@ constexpr std::array PROGRAM_LUT{
29[[nodiscard]] GLenum GetTextureBufferFormat(GLenum gl_format) { 29[[nodiscard]] GLenum GetTextureBufferFormat(GLenum gl_format) {
30 switch (gl_format) { 30 switch (gl_format) {
31 case GL_RGBA8_SNORM: 31 case GL_RGBA8_SNORM:
32 return GL_RGBA8; 32 return GL_RGBA8I;
33 case GL_R8_SNORM: 33 case GL_R8_SNORM:
34 return GL_R8; 34 return GL_R8I;
35 case GL_RGBA16_SNORM: 35 case GL_RGBA16_SNORM:
36 return GL_RGBA16; 36 return GL_RGBA16I;
37 case GL_R16_SNORM: 37 case GL_R16_SNORM:
38 return GL_R16; 38 return GL_R16I;
39 case GL_RG16_SNORM: 39 case GL_RG16_SNORM:
40 return GL_RG16; 40 return GL_RG16I;
41 case GL_RG8_SNORM: 41 case GL_RG8_SNORM:
42 return GL_RG8; 42 return GL_RG8I;
43 default: 43 default:
44 return gl_format; 44 return gl_format;
45 } 45 }
@@ -96,9 +96,6 @@ GLuint Buffer::View(u32 offset, u32 size, PixelFormat format) {
96 texture.Create(GL_TEXTURE_BUFFER); 96 texture.Create(GL_TEXTURE_BUFFER);
97 const GLenum gl_format{MaxwellToGL::GetFormatTuple(format).internal_format}; 97 const GLenum gl_format{MaxwellToGL::GetFormatTuple(format).internal_format};
98 const GLenum texture_format{GetTextureBufferFormat(gl_format)}; 98 const GLenum texture_format{GetTextureBufferFormat(gl_format)};
99 if (texture_format != gl_format) {
100 LOG_WARNING(Render_OpenGL, "Emulating SNORM texture buffer with UNORM.");
101 }
102 glTextureBufferRange(texture.handle, texture_format, buffer.handle, offset, size); 99 glTextureBufferRange(texture.handle, texture_format, buffer.handle, offset, size);
103 views.push_back({ 100 views.push_back({
104 .offset = offset, 101 .offset = offset,
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index daceb05f4..c115dabe1 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -504,8 +504,8 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
504 } 504 }
505 } 505 }
506 if (info.uses_render_area) { 506 if (info.uses_render_area) {
507 const auto render_area_width(static_cast<GLfloat>(regs.render_area.width)); 507 const auto render_area_width(static_cast<GLfloat>(regs.surface_clip.width));
508 const auto render_area_height(static_cast<GLfloat>(regs.render_area.height)); 508 const auto render_area_height(static_cast<GLfloat>(regs.surface_clip.height));
509 if (use_assembly) { 509 if (use_assembly) {
510 glProgramLocalParameter4fARB(AssemblyStage(stage), 1, render_area_width, 510 glProgramLocalParameter4fARB(AssemblyStage(stage), 1, render_area_width,
511 render_area_height, 0.0f, 0.0f); 511 render_area_height, 0.0f, 0.0f);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 79d7908d4..72e314d39 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -618,11 +618,11 @@ void RasterizerOpenGL::SyncViewport() {
618 } 618 }
619 flags[Dirty::Viewport0 + index] = false; 619 flags[Dirty::Viewport0 + index] = false;
620 620
621 if (!regs.viewport_transform_enabled) { 621 if (!regs.viewport_scale_offset_enbled) {
622 const auto x = static_cast<GLfloat>(regs.render_area.x); 622 const auto x = static_cast<GLfloat>(regs.surface_clip.x);
623 const auto y = static_cast<GLfloat>(regs.render_area.y); 623 const auto y = static_cast<GLfloat>(regs.surface_clip.y);
624 const auto width = static_cast<GLfloat>(regs.render_area.width); 624 const auto width = static_cast<GLfloat>(regs.surface_clip.width);
625 const auto height = static_cast<GLfloat>(regs.render_area.height); 625 const auto height = static_cast<GLfloat>(regs.surface_clip.height);
626 glViewportIndexedf(static_cast<GLuint>(index), x, y, width != 0.0f ? width : 1.0f, 626 glViewportIndexedf(static_cast<GLuint>(index), x, y, width != 0.0f ? width : 1.0f,
627 height != 0.0f ? height : 1.0f); 627 height != 0.0f ? height : 1.0f);
628 continue; 628 continue;
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index b4372a839..81b6c372d 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -444,8 +444,8 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
444 const auto& info{stage_infos[0]}; 444 const auto& info{stage_infos[0]};
445 if (info.uses_render_area) { 445 if (info.uses_render_area) {
446 render_area.uses_render_area = true; 446 render_area.uses_render_area = true;
447 render_area.words = {static_cast<float>(regs.render_area.width), 447 render_area.words = {static_cast<float>(regs.surface_clip.width),
448 static_cast<float>(regs.render_area.height)}; 448 static_cast<float>(regs.surface_clip.height)};
449 } 449 }
450 }}; 450 }};
451 if constexpr (Spec::enabled_stages[0]) { 451 if constexpr (Spec::enabled_stages[0]) {
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 5af3c930b..f79fa8313 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -683,11 +683,11 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
683 if (!state_tracker.TouchViewports()) { 683 if (!state_tracker.TouchViewports()) {
684 return; 684 return;
685 } 685 }
686 if (!regs.viewport_transform_enabled) { 686 if (!regs.viewport_scale_offset_enbled) {
687 const auto x = static_cast<float>(regs.render_area.x); 687 const auto x = static_cast<float>(regs.surface_clip.x);
688 const auto y = static_cast<float>(regs.render_area.y); 688 const auto y = static_cast<float>(regs.surface_clip.y);
689 const auto width = static_cast<float>(regs.render_area.width); 689 const auto width = static_cast<float>(regs.surface_clip.width);
690 const auto height = static_cast<float>(regs.render_area.height); 690 const auto height = static_cast<float>(regs.surface_clip.height);
691 VkViewport viewport{ 691 VkViewport viewport{
692 .x = x, 692 .x = x,
693 .y = y, 693 .y = y,
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index 63bcf9337..37bb76b72 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -19,6 +19,7 @@
19#include "video_core/engines/kepler_compute.h" 19#include "video_core/engines/kepler_compute.h"
20#include "video_core/memory_manager.h" 20#include "video_core/memory_manager.h"
21#include "video_core/shader_environment.h" 21#include "video_core/shader_environment.h"
22#include "video_core/texture_cache/format_lookup_table.h"
22#include "video_core/textures/texture.h" 23#include "video_core/textures/texture.h"
23 24
24namespace VideoCommon { 25namespace VideoCommon {
@@ -33,7 +34,7 @@ static u64 MakeCbufKey(u32 index, u32 offset) {
33 return (static_cast<u64>(index) << 32) | offset; 34 return (static_cast<u64>(index) << 32) | offset;
34} 35}
35 36
36static Shader::TextureType ConvertType(const Tegra::Texture::TICEntry& entry) { 37static Shader::TextureType ConvertTextureType(const Tegra::Texture::TICEntry& entry) {
37 switch (entry.texture_type) { 38 switch (entry.texture_type) {
38 case Tegra::Texture::TextureType::Texture1D: 39 case Tegra::Texture::TextureType::Texture1D:
39 return Shader::TextureType::Color1D; 40 return Shader::TextureType::Color1D;
@@ -59,6 +60,26 @@ static Shader::TextureType ConvertType(const Tegra::Texture::TICEntry& entry) {
59 } 60 }
60} 61}
61 62
63static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture::TICEntry& entry) {
64 switch (PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type, entry.b_type,
65 entry.a_type, entry.srgb_conversion)) {
66 case VideoCore::Surface::PixelFormat::A8B8G8R8_SNORM:
67 return Shader::TexturePixelFormat::A8B8G8R8_SNORM;
68 case VideoCore::Surface::PixelFormat::R8_SNORM:
69 return Shader::TexturePixelFormat::R8_SNORM;
70 case VideoCore::Surface::PixelFormat::R8G8_SNORM:
71 return Shader::TexturePixelFormat::R8G8_SNORM;
72 case VideoCore::Surface::PixelFormat::R16G16B16A16_SNORM:
73 return Shader::TexturePixelFormat::R16G16B16A16_SNORM;
74 case VideoCore::Surface::PixelFormat::R16G16_SNORM:
75 return Shader::TexturePixelFormat::R16G16_SNORM;
76 case VideoCore::Surface::PixelFormat::R16_SNORM:
77 return Shader::TexturePixelFormat::R16_SNORM;
78 default:
79 return Shader::TexturePixelFormat::OTHER;
80 }
81}
82
62static std::string_view StageToPrefix(Shader::Stage stage) { 83static std::string_view StageToPrefix(Shader::Stage stage) {
63 switch (stage) { 84 switch (stage) {
64 case Shader::Stage::VertexB: 85 case Shader::Stage::VertexB:
@@ -178,10 +199,13 @@ void GenericEnvironment::Dump(u64 hash) {
178void GenericEnvironment::Serialize(std::ofstream& file) const { 199void GenericEnvironment::Serialize(std::ofstream& file) const {
179 const u64 code_size{static_cast<u64>(CachedSize())}; 200 const u64 code_size{static_cast<u64>(CachedSize())};
180 const u64 num_texture_types{static_cast<u64>(texture_types.size())}; 201 const u64 num_texture_types{static_cast<u64>(texture_types.size())};
202 const u64 num_texture_pixel_formats{static_cast<u64>(texture_pixel_formats.size())};
181 const u64 num_cbuf_values{static_cast<u64>(cbuf_values.size())}; 203 const u64 num_cbuf_values{static_cast<u64>(cbuf_values.size())};
182 204
183 file.write(reinterpret_cast<const char*>(&code_size), sizeof(code_size)) 205 file.write(reinterpret_cast<const char*>(&code_size), sizeof(code_size))
184 .write(reinterpret_cast<const char*>(&num_texture_types), sizeof(num_texture_types)) 206 .write(reinterpret_cast<const char*>(&num_texture_types), sizeof(num_texture_types))
207 .write(reinterpret_cast<const char*>(&num_texture_pixel_formats),
208 sizeof(num_texture_pixel_formats))
185 .write(reinterpret_cast<const char*>(&num_cbuf_values), sizeof(num_cbuf_values)) 209 .write(reinterpret_cast<const char*>(&num_cbuf_values), sizeof(num_cbuf_values))
186 .write(reinterpret_cast<const char*>(&local_memory_size), sizeof(local_memory_size)) 210 .write(reinterpret_cast<const char*>(&local_memory_size), sizeof(local_memory_size))
187 .write(reinterpret_cast<const char*>(&texture_bound), sizeof(texture_bound)) 211 .write(reinterpret_cast<const char*>(&texture_bound), sizeof(texture_bound))
@@ -196,6 +220,10 @@ void GenericEnvironment::Serialize(std::ofstream& file) const {
196 file.write(reinterpret_cast<const char*>(&key), sizeof(key)) 220 file.write(reinterpret_cast<const char*>(&key), sizeof(key))
197 .write(reinterpret_cast<const char*>(&type), sizeof(type)); 221 .write(reinterpret_cast<const char*>(&type), sizeof(type));
198 } 222 }
223 for (const auto& [key, format] : texture_pixel_formats) {
224 file.write(reinterpret_cast<const char*>(&key), sizeof(key))
225 .write(reinterpret_cast<const char*>(&format), sizeof(format));
226 }
199 for (const auto& [key, type] : cbuf_values) { 227 for (const auto& [key, type] : cbuf_values) {
200 file.write(reinterpret_cast<const char*>(&key), sizeof(key)) 228 file.write(reinterpret_cast<const char*>(&key), sizeof(key))
201 .write(reinterpret_cast<const char*>(&type), sizeof(type)); 229 .write(reinterpret_cast<const char*>(&type), sizeof(type));
@@ -239,15 +267,13 @@ std::optional<u64> GenericEnvironment::TryFindSize() {
239 return std::nullopt; 267 return std::nullopt;
240} 268}
241 269
242Shader::TextureType GenericEnvironment::ReadTextureTypeImpl(GPUVAddr tic_addr, u32 tic_limit, 270Tegra::Texture::TICEntry GenericEnvironment::ReadTextureInfo(GPUVAddr tic_addr, u32 tic_limit,
243 bool via_header_index, u32 raw) { 271 bool via_header_index, u32 raw) {
244 const auto handle{Tegra::Texture::TexturePair(raw, via_header_index)}; 272 const auto handle{Tegra::Texture::TexturePair(raw, via_header_index)};
245 const GPUVAddr descriptor_addr{tic_addr + handle.first * sizeof(Tegra::Texture::TICEntry)}; 273 const GPUVAddr descriptor_addr{tic_addr + handle.first * sizeof(Tegra::Texture::TICEntry)};
246 Tegra::Texture::TICEntry entry; 274 Tegra::Texture::TICEntry entry;
247 gpu_memory->ReadBlock(descriptor_addr, &entry, sizeof(entry)); 275 gpu_memory->ReadBlock(descriptor_addr, &entry, sizeof(entry));
248 const Shader::TextureType result{ConvertType(entry)}; 276 return entry;
249 texture_types.emplace(raw, result);
250 return result;
251} 277}
252 278
253GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_, 279GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
@@ -307,13 +333,26 @@ u32 GraphicsEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) {
307Shader::TextureType GraphicsEnvironment::ReadTextureType(u32 handle) { 333Shader::TextureType GraphicsEnvironment::ReadTextureType(u32 handle) {
308 const auto& regs{maxwell3d->regs}; 334 const auto& regs{maxwell3d->regs};
309 const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding}; 335 const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
310 return ReadTextureTypeImpl(regs.tex_header.Address(), regs.tex_header.limit, via_header_index, 336 auto entry =
311 handle); 337 ReadTextureInfo(regs.tex_header.Address(), regs.tex_header.limit, via_header_index, handle);
338 const Shader::TextureType result{ConvertTextureType(entry)};
339 texture_types.emplace(handle, result);
340 return result;
341}
342
343Shader::TexturePixelFormat GraphicsEnvironment::ReadTexturePixelFormat(u32 handle) {
344 const auto& regs{maxwell3d->regs};
345 const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding};
346 auto entry =
347 ReadTextureInfo(regs.tex_header.Address(), regs.tex_header.limit, via_header_index, handle);
348 const Shader::TexturePixelFormat result(ConvertTexturePixelFormat(entry));
349 texture_pixel_formats.emplace(handle, result);
350 return result;
312} 351}
313 352
314u32 GraphicsEnvironment::ReadViewportTransformState() { 353u32 GraphicsEnvironment::ReadViewportTransformState() {
315 const auto& regs{maxwell3d->regs}; 354 const auto& regs{maxwell3d->regs};
316 viewport_transform_state = regs.viewport_transform_enabled; 355 viewport_transform_state = regs.viewport_scale_offset_enbled;
317 return viewport_transform_state; 356 return viewport_transform_state;
318} 357}
319 358
@@ -345,7 +384,19 @@ u32 ComputeEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) {
345Shader::TextureType ComputeEnvironment::ReadTextureType(u32 handle) { 384Shader::TextureType ComputeEnvironment::ReadTextureType(u32 handle) {
346 const auto& regs{kepler_compute->regs}; 385 const auto& regs{kepler_compute->regs};
347 const auto& qmd{kepler_compute->launch_description}; 386 const auto& qmd{kepler_compute->launch_description};
348 return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle); 387 auto entry = ReadTextureInfo(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle);
388 const Shader::TextureType result{ConvertTextureType(entry)};
389 texture_types.emplace(handle, result);
390 return result;
391}
392
393Shader::TexturePixelFormat ComputeEnvironment::ReadTexturePixelFormat(u32 handle) {
394 const auto& regs{kepler_compute->regs};
395 const auto& qmd{kepler_compute->launch_description};
396 auto entry = ReadTextureInfo(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle);
397 const Shader::TexturePixelFormat result(ConvertTexturePixelFormat(entry));
398 texture_pixel_formats.emplace(handle, result);
399 return result;
349} 400}
350 401
351u32 ComputeEnvironment::ReadViewportTransformState() { 402u32 ComputeEnvironment::ReadViewportTransformState() {
@@ -355,9 +406,12 @@ u32 ComputeEnvironment::ReadViewportTransformState() {
355void FileEnvironment::Deserialize(std::ifstream& file) { 406void FileEnvironment::Deserialize(std::ifstream& file) {
356 u64 code_size{}; 407 u64 code_size{};
357 u64 num_texture_types{}; 408 u64 num_texture_types{};
409 u64 num_texture_pixel_formats{};
358 u64 num_cbuf_values{}; 410 u64 num_cbuf_values{};
359 file.read(reinterpret_cast<char*>(&code_size), sizeof(code_size)) 411 file.read(reinterpret_cast<char*>(&code_size), sizeof(code_size))
360 .read(reinterpret_cast<char*>(&num_texture_types), sizeof(num_texture_types)) 412 .read(reinterpret_cast<char*>(&num_texture_types), sizeof(num_texture_types))
413 .read(reinterpret_cast<char*>(&num_texture_pixel_formats),
414 sizeof(num_texture_pixel_formats))
361 .read(reinterpret_cast<char*>(&num_cbuf_values), sizeof(num_cbuf_values)) 415 .read(reinterpret_cast<char*>(&num_cbuf_values), sizeof(num_cbuf_values))
362 .read(reinterpret_cast<char*>(&local_memory_size), sizeof(local_memory_size)) 416 .read(reinterpret_cast<char*>(&local_memory_size), sizeof(local_memory_size))
363 .read(reinterpret_cast<char*>(&texture_bound), sizeof(texture_bound)) 417 .read(reinterpret_cast<char*>(&texture_bound), sizeof(texture_bound))
@@ -375,6 +429,13 @@ void FileEnvironment::Deserialize(std::ifstream& file) {
375 .read(reinterpret_cast<char*>(&type), sizeof(type)); 429 .read(reinterpret_cast<char*>(&type), sizeof(type));
376 texture_types.emplace(key, type); 430 texture_types.emplace(key, type);
377 } 431 }
432 for (size_t i = 0; i < num_texture_pixel_formats; ++i) {
433 u32 key;
434 Shader::TexturePixelFormat format;
435 file.read(reinterpret_cast<char*>(&key), sizeof(key))
436 .read(reinterpret_cast<char*>(&format), sizeof(format));
437 texture_pixel_formats.emplace(key, format);
438 }
378 for (size_t i = 0; i < num_cbuf_values; ++i) { 439 for (size_t i = 0; i < num_cbuf_values; ++i) {
379 u64 key; 440 u64 key;
380 u32 value; 441 u32 value;
@@ -422,6 +483,14 @@ Shader::TextureType FileEnvironment::ReadTextureType(u32 handle) {
422 return it->second; 483 return it->second;
423} 484}
424 485
486Shader::TexturePixelFormat FileEnvironment::ReadTexturePixelFormat(u32 handle) {
487 const auto it{texture_pixel_formats.find(handle)};
488 if (it == texture_pixel_formats.end()) {
489 throw Shader::LogicError("Uncached read texture pixel format");
490 }
491 return it->second;
492}
493
425u32 FileEnvironment::ReadViewportTransformState() { 494u32 FileEnvironment::ReadViewportTransformState() {
426 return viewport_transform_state; 495 return viewport_transform_state;
427} 496}
diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h
index a05833f38..bb55b029f 100644
--- a/src/video_core/shader_environment.h
+++ b/src/video_core/shader_environment.h
@@ -63,14 +63,15 @@ public:
63protected: 63protected:
64 std::optional<u64> TryFindSize(); 64 std::optional<u64> TryFindSize();
65 65
66 Shader::TextureType ReadTextureTypeImpl(GPUVAddr tic_addr, u32 tic_limit, bool via_header_index, 66 Tegra::Texture::TICEntry ReadTextureInfo(GPUVAddr tic_addr, u32 tic_limit,
67 u32 raw); 67 bool via_header_index, u32 raw);
68 68
69 Tegra::MemoryManager* gpu_memory{}; 69 Tegra::MemoryManager* gpu_memory{};
70 GPUVAddr program_base{}; 70 GPUVAddr program_base{};
71 71
72 std::vector<u64> code; 72 std::vector<u64> code;
73 std::unordered_map<u32, Shader::TextureType> texture_types; 73 std::unordered_map<u32, Shader::TextureType> texture_types;
74 std::unordered_map<u32, Shader::TexturePixelFormat> texture_pixel_formats;
74 std::unordered_map<u64, u32> cbuf_values; 75 std::unordered_map<u64, u32> cbuf_values;
75 76
76 u32 local_memory_size{}; 77 u32 local_memory_size{};
@@ -104,6 +105,8 @@ public:
104 105
105 Shader::TextureType ReadTextureType(u32 handle) override; 106 Shader::TextureType ReadTextureType(u32 handle) override;
106 107
108 Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;
109
107 u32 ReadViewportTransformState() override; 110 u32 ReadViewportTransformState() override;
108 111
109private: 112private:
@@ -124,6 +127,8 @@ public:
124 127
125 Shader::TextureType ReadTextureType(u32 handle) override; 128 Shader::TextureType ReadTextureType(u32 handle) override;
126 129
130 Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;
131
127 u32 ReadViewportTransformState() override; 132 u32 ReadViewportTransformState() override;
128 133
129private: 134private:
@@ -149,6 +154,8 @@ public:
149 154
150 [[nodiscard]] Shader::TextureType ReadTextureType(u32 handle) override; 155 [[nodiscard]] Shader::TextureType ReadTextureType(u32 handle) override;
151 156
157 [[nodiscard]] Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override;
158
152 [[nodiscard]] u32 ReadViewportTransformState() override; 159 [[nodiscard]] u32 ReadViewportTransformState() override;
153 160
154 [[nodiscard]] u32 LocalMemorySize() const override; 161 [[nodiscard]] u32 LocalMemorySize() const override;
@@ -164,6 +171,7 @@ public:
164private: 171private:
165 std::unique_ptr<u64[]> code; 172 std::unique_ptr<u64[]> code;
166 std::unordered_map<u32, Shader::TextureType> texture_types; 173 std::unordered_map<u32, Shader::TextureType> texture_types;
174 std::unordered_map<u32, Shader::TexturePixelFormat> texture_pixel_formats;
167 std::unordered_map<u64, u32> cbuf_values; 175 std::unordered_map<u64, u32> cbuf_values;
168 std::array<u32, 3> workgroup_size{}; 176 std::array<u32, 3> workgroup_size{};
169 u32 local_memory_size{}; 177 u32 local_memory_size{};
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index 1223df5a0..e8c908b42 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -516,7 +516,6 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
516 const u32 num_blocks_per_layer = NumBlocks(level_size, tile_size); 516 const u32 num_blocks_per_layer = NumBlocks(level_size, tile_size);
517 const u32 host_bytes_per_layer = num_blocks_per_layer * bytes_per_block; 517 const u32 host_bytes_per_layer = num_blocks_per_layer * bytes_per_block;
518 518
519 UNIMPLEMENTED_IF(info.tile_width_spacing > 0);
520 UNIMPLEMENTED_IF(copy.image_offset.x != 0); 519 UNIMPLEMENTED_IF(copy.image_offset.x != 0);
521 UNIMPLEMENTED_IF(copy.image_offset.y != 0); 520 UNIMPLEMENTED_IF(copy.image_offset.y != 0);
522 UNIMPLEMENTED_IF(copy.image_offset.z != 0); 521 UNIMPLEMENTED_IF(copy.image_offset.z != 0);