From 97a555b7361198c57bf98b23d9bcd33455c53d6f Mon Sep 17 00:00:00 2001 From: Vinicius Rangel Date: Sun, 11 Aug 2024 19:20:03 -0300 Subject: [PATCH] spirv: fix image sample offsets --- .../frontend/translate/vector_memory.cpp | 4 +- src/shader_recompiler/ir/ir_emitter.cpp | 8 ++-- src/shader_recompiler/ir/ir_emitter.h | 8 ++-- src/shader_recompiler/ir/opcodes.inc | 8 ++-- .../ir/passes/resource_tracking_pass.cpp | 39 +++++++++++++------ 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 244a7fe2a..bb202e426 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -135,8 +135,8 @@ void Translator::IMAGE_SAMPLE(const GcnInst& inst) { // Load first address components as denoted in 8.2.4 VGPR Usage Sea Islands Series Instruction // Set Architecture - const IR::Value offset = - flags.test(MimgModifier::Offset) ? ir.GetVectorReg(addr_reg++) : IR::Value{}; + const IR::U32 offset = + flags.test(MimgModifier::Offset) ? ir.GetVectorReg(addr_reg++) : IR::U32{}; const IR::F32 bias = flags.test(MimgModifier::LodBias) ? ir.GetVectorReg(addr_reg++) : IR::F32{}; const IR::F32 dref = diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 373eb532a..bc584158d 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -1375,24 +1375,24 @@ Value IREmitter::ImageAtomicExchange(const Value& handle, const Value& coords, c } Value IREmitter::ImageSampleImplicitLod(const Value& handle, const Value& body, const F32& bias, - const Value& offset, TextureInstInfo info) { + const U32& offset, TextureInstInfo info) { return Inst(Opcode::ImageSampleImplicitLod, Flags{info}, handle, body, bias, offset); } -Value IREmitter::ImageSampleExplicitLod(const Value& handle, const Value& body, const Value& offset, +Value IREmitter::ImageSampleExplicitLod(const Value& handle, const Value& body, const U32& offset, TextureInstInfo info) { return Inst(Opcode::ImageSampleExplicitLod, Flags{info}, handle, body, offset); } F32 IREmitter::ImageSampleDrefImplicitLod(const Value& handle, const Value& body, const F32& dref, - const F32& bias, const Value& offset, + const F32& bias, const U32& offset, TextureInstInfo info) { return Inst(Opcode::ImageSampleDrefImplicitLod, Flags{info}, handle, body, dref, bias, offset); } F32 IREmitter::ImageSampleDrefExplicitLod(const Value& handle, const Value& body, const F32& dref, - const Value& offset, TextureInstInfo info) { + const U32& offset, TextureInstInfo info) { return Inst(Opcode::ImageSampleDrefExplicitLod, Flags{info}, handle, body, dref, offset); } diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index 337a9c7f5..fda206394 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -242,18 +242,18 @@ public: const Value& value, TextureInstInfo info); [[nodiscard]] Value ImageSampleImplicitLod(const Value& handle, const Value& body, - const F32& bias, const Value& offset, + const F32& bias, const U32& offset, TextureInstInfo info); [[nodiscard]] Value ImageSampleExplicitLod(const Value& handle, const Value& body, - const Value& offset, TextureInstInfo info); + const U32& offset, TextureInstInfo info); [[nodiscard]] F32 ImageSampleDrefImplicitLod(const Value& handle, const Value& body, const F32& dref, const F32& bias, - const Value& offset, TextureInstInfo info); + const U32& offset, TextureInstInfo info); [[nodiscard]] F32 ImageSampleDrefExplicitLod(const Value& handle, const Value& body, - const F32& dref, const Value& offset, + const F32& dref, const U32& offset, TextureInstInfo info); [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod, diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index f2e94daab..ef7b4bad5 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -298,10 +298,10 @@ OPCODE(ConvertU16U32, U16, U32, OPCODE(ConvertU32U16, U32, U16, ) // Image operations -OPCODE(ImageSampleImplicitLod, F32x4, Opaque, Opaque, F32, Opaque, ) -OPCODE(ImageSampleExplicitLod, F32x4, Opaque, Opaque, Opaque, ) -OPCODE(ImageSampleDrefImplicitLod, F32, Opaque, Opaque, F32, F32, Opaque, ) -OPCODE(ImageSampleDrefExplicitLod, F32, Opaque, Opaque, F32, Opaque, ) +OPCODE(ImageSampleImplicitLod, F32x4, Opaque, Opaque, F32, U32, ) +OPCODE(ImageSampleExplicitLod, F32x4, Opaque, Opaque, U32, ) +OPCODE(ImageSampleDrefImplicitLod, F32, Opaque, Opaque, F32, F32, U32, ) +OPCODE(ImageSampleDrefExplicitLod, F32, Opaque, Opaque, F32, U32, ) OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, Opaque, ) OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, Opaque, F32, ) OPCODE(ImageFetch, F32x4, Opaque, Opaque, Opaque, U32, Opaque, ) diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index 950b9d43f..7a21dd378 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -567,19 +567,36 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip if (inst_info.has_offset) { // The offsets are six-bit signed integers: X=[5:0], Y=[13:8], and Z=[21:16]. - const bool is_gather = inst.GetOpcode() == IR::Opcode::ImageGather || - inst.GetOpcode() == IR::Opcode::ImageGatherDref; - const u32 arg_pos = is_gather ? 2 : (inst_info.is_depth ? 4 : 3); + const bool is_second = inst.GetOpcode() == IR::Opcode::ImageGather || + inst.GetOpcode() == IR::Opcode::ImageGatherDref || + inst.GetOpcode() == IR::Opcode::ImageSampleExplicitLod || + inst.GetOpcode() == IR::Opcode::ImageSampleDrefExplicitLod; + const u32 arg_pos = [&]() -> u32 { + switch (inst.GetOpcode()) { + case IR::Opcode::ImageGather: + case IR::Opcode::ImageGatherDref: + case IR::Opcode::ImageSampleExplicitLod: + return 2; + case IR::Opcode::ImageSampleImplicitLod: + case IR::Opcode::ImageSampleDrefExplicitLod: + return 3; + case IR::Opcode::ImageSampleDrefImplicitLod: + return 4; + default: + break; + } + return inst_info.is_depth ? 4 : 3; + }(); const IR::Value arg = inst.Arg(arg_pos); ASSERT_MSG(arg.Type() == IR::Type::U32, "Unexpected offset type"); - const auto sign_ext = [&](u32 value) { return ir.Imm32(s32(value << 24) >> 24); }; - union { - u32 raw; - BitField<0, 6, u32> x; - BitField<8, 6, u32> y; - BitField<16, 6, u32> z; - } offset{arg.U32()}; - const IR::Value value = ir.CompositeConstruct(sign_ext(offset.x), sign_ext(offset.y)); + const auto f = [&](IR::Value value, u32 offset) -> auto { + return ir.BitFieldExtract(IR::U32{arg}, ir.Imm32(offset), ir.Imm32(6), true); + }; + + const auto x = f(arg, 0); + const auto y = f(arg, 6); + const auto z = f(arg, 16); + const IR::Value value = ir.CompositeConstruct(x, y, z); inst.SetArg(arg_pos, value); }