From 5da79d479854a866b893a70d2d1575a8d681727d Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Sat, 29 Jun 2024 14:05:05 +0300 Subject: [PATCH] spirv: Add fragdepth and implement image query --- .../backend/spirv/emit_spirv.cpp | 2 ++ .../spirv/emit_spirv_context_get_set.cpp | 2 ++ .../backend/spirv/emit_spirv_image.cpp | 27 ++++++++++++++++--- .../backend/spirv/emit_spirv_instructions.h | 3 +-- .../backend/spirv/spirv_emit_context.cpp | 1 + .../backend/spirv/spirv_emit_context.h | 1 + .../frontend/translate/scalar_alu.cpp | 4 +-- .../frontend/translate/translate.cpp | 15 ++++++++--- .../frontend/translate/translate.h | 2 +- .../frontend/translate/vector_memory.cpp | 11 ++++---- 10 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 1c7ed215..7933ecd7 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -31,6 +31,8 @@ ArgType Arg(EmitContext& ctx, const IR::Value& arg) { return arg.U32(); } else if constexpr (std::is_same_v) { return arg.U64(); + } else if constexpr (std::is_same_v) { + return arg.U1(); } else if constexpr (std::is_same_v) { return arg.Attribute(); } else if constexpr (std::is_same_v) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 4ebbd465..9793db13 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -31,6 +31,8 @@ Id OutputAttrPointer(EmitContext& ctx, IR::Attribute attr, u32 element) { return ctx.frag_color[index]; } } + case IR::Attribute::Depth: + return ctx.frag_depth; default: throw NotImplementedException("Read attribute {}", attr); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index d513c9d6..b04a5fd6 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -61,9 +61,30 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id of } } -Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, - const IR::Value& skip_mips_val) { - throw NotImplementedException("SPIR-V Instruction"); +Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool skip_mips) { + const auto& texture = ctx.images[handle & 0xFFFF]; + const Id image = ctx.OpLoad(texture.image_type, texture.id); + const auto type = ctx.info.images[handle & 0xFFFF].type; + const Id zero = ctx.u32_zero_value; + const auto mips{[&] { return skip_mips ? zero : ctx.OpImageQueryLevels(ctx.U32[1], image); }}; + const bool uses_lod{type != AmdGpu::ImageType::Color2DMsaa && type != AmdGpu::ImageType::Buffer}; + const auto query{[&](Id type) { + return uses_lod ? ctx.OpImageQuerySizeLod(type, image, lod) + : ctx.OpImageQuerySize(type, image); + }}; + switch (type) { + case AmdGpu::ImageType::Color1D: + return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips()); + case AmdGpu::ImageType::Color1DArray: + case AmdGpu::ImageType::Color2D: + case AmdGpu::ImageType::Cube: + return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips()); + case AmdGpu::ImageType::Color2DArray: + case AmdGpu::ImageType::Color3D: + return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[3]), mips()); + default: + throw NotImplementedException("SPIR-V Instruction"); + } } Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 204c89fa..2774bc2c 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -348,8 +348,7 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, const IR::Value& offset, const IR::Value& offset2, Id dref); Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id offset, Id lod, Id ms); -Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, - const IR::Value& skip_mips); +Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool skip_mips); Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id derivatives, const IR::Value& offset, Id lod_clamp); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 1ac25886..0844adbb 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -187,6 +187,7 @@ void EmitContext::DefineInputs(const Info& info) { Decorate(subgroup_local_invocation_id, spv::Decoration::Flat); } frag_coord = DefineVariable(F32[4], spv::BuiltIn::FragCoord, spv::StorageClass::Input); + frag_depth = DefineVariable(F32[1], spv::BuiltIn::FragDepth, spv::StorageClass::Output); front_facing = DefineVariable(U1[1], spv::BuiltIn::FrontFacing, spv::StorageClass::Input); for (const auto& input : info.ps_inputs) { const u32 semantic = input.param_index; diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 49dd181f..941b3d30 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -160,6 +160,7 @@ public: Id base_vertex{}; Id frag_coord{}; Id front_facing{}; + Id frag_depth{}; std::array frag_color{}; std::array frag_num_comp{}; diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index 8b8c7c0f..1b762c3a 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -104,7 +104,7 @@ void Translator::S_MOV_B64(const GcnInst& inst) { } } -void Translator::S_OR_B64(NegateMode negate, const GcnInst& inst) { +void Translator::S_OR_B64(NegateMode negate, bool is_xor, const GcnInst& inst) { const auto get_src = [&](const InstOperand& operand) { switch (operand.field) { case OperandField::ExecLo: @@ -123,7 +123,7 @@ void Translator::S_OR_B64(NegateMode negate, const GcnInst& inst) { if (negate == NegateMode::Src1) { src1 = ir.LogicalNot(src1); } - IR::U1 result = ir.LogicalOr(src0, src1); + IR::U1 result = is_xor ? ir.LogicalXor(src0, src1) : ir.LogicalOr(src0, src1); if (negate == NegateMode::Result) { result = ir.LogicalNot(result); } diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index b7593c1a..a19ade4b 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -406,6 +406,9 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) case Opcode::V_CMP_NLT_F32: translator.V_CMP_F32(ConditionOp::GE, false, inst); break; + case Opcode::V_CMP_NGT_F32: + translator.V_CMP_F32(ConditionOp::LE, false, inst); + break; case Opcode::S_CMP_LT_U32: translator.S_CMP(ConditionOp::LT, false, inst); break; @@ -473,7 +476,7 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) translator.S_AND_B64(NegateMode::Src1, inst); break; case Opcode::S_ORN2_B64: - translator.S_OR_B64(NegateMode::Src1, inst); + translator.S_OR_B64(NegateMode::Src1, false, inst); break; case Opcode::V_SIN_F32: translator.V_SIN_F32(inst); @@ -612,10 +615,13 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) translator.V_CMP_U32(ConditionOp::TRU, false, true, inst); break; case Opcode::S_OR_B64: - translator.S_OR_B64(NegateMode::None, inst); + translator.S_OR_B64(NegateMode::None, false, inst); break; case Opcode::S_NOR_B64: - translator.S_OR_B64(NegateMode::Result, inst); + translator.S_OR_B64(NegateMode::Result, false, inst); + break; + case Opcode::S_XOR_B64: + translator.S_OR_B64(NegateMode::None, true, inst); break; case Opcode::S_AND_B64: translator.S_AND_B64(NegateMode::None, inst); @@ -739,6 +745,9 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) case Opcode::V_RCP_IFLAG_F32: translator.V_RCP_F32(inst); break; + case Opcode::IMAGE_GET_RESINFO: + translator.IMAGE_GET_RESINFO(inst); + break; case Opcode::S_TTRACEDATA: LOG_WARNING(Render_Vulkan, "S_TTRACEDATA instruction!"); break; diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 4f10c49a..e52b4fb0 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -46,7 +46,7 @@ public: void S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst); void S_AND_SAVEEXEC_B64(const GcnInst& inst); void S_MOV_B64(const GcnInst& inst); - void S_OR_B64(NegateMode negate, const GcnInst& inst); + void S_OR_B64(NegateMode negate, bool is_xor, const GcnInst& inst); void S_AND_B64(NegateMode negate, const GcnInst& inst); void S_ADD_I32(const GcnInst& inst); void S_AND_B32(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index c087fcfa..fc2b453d 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -6,14 +6,13 @@ namespace Shader::Gcn { void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) { - IR::VectorReg dst_reg{inst.src[1].code}; + IR::VectorReg dst_reg{inst.dst[0].code}; const IR::ScalarReg tsharp_reg{inst.src[2].code}; const auto flags = ImageResFlags(inst.control.mimg.dmask); + const bool has_mips = flags.test(ImageResComponent::MipCount); const IR::U32 lod = ir.GetVectorReg(IR::VectorReg(inst.src[0].code)); - const IR::Value tsharp = - ir.CompositeConstruct(ir.GetScalarReg(tsharp_reg), ir.GetScalarReg(tsharp_reg + 1), - ir.GetScalarReg(tsharp_reg + 2), ir.GetScalarReg(tsharp_reg + 3)); - const IR::Value size = ir.ImageQueryDimension(tsharp, lod, ir.Imm1(false)); + const IR::Value tsharp = ir.GetScalarReg(tsharp_reg); + const IR::Value size = ir.ImageQueryDimension(tsharp, lod, ir.Imm1(has_mips)); if (flags.test(ImageResComponent::Width)) { ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 0)}); @@ -24,7 +23,7 @@ void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) { if (flags.test(ImageResComponent::Depth)) { ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 2)}); } - if (flags.test(ImageResComponent::MipCount)) { + if (has_mips) { ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 3)}); } }