diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index f0d01727..d513c9d6 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -54,7 +54,11 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id of Id ms) { const auto& texture = ctx.images[handle & 0xFFFF]; const Id image = ctx.OpLoad(texture.image_type, texture.id); - return ctx.OpImageFetch(ctx.F32[4], image, coords, spv::ImageOperandsMask::Lod, lod); + if (Sirit::ValidId(lod)) { + return ctx.OpImageFetch(ctx.F32[4], image, coords, spv::ImageOperandsMask::Lod, lod); + } else { + return ctx.OpImageFetch(ctx.F32[4], image, coords); + } } Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index 939803a3..f64710fc 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -216,6 +216,14 @@ void Translator::S_AND_B32(const GcnInst& inst) { ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); } +void Translator::S_OR_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 result{ir.BitwiseOr(src0, src1)}; + SetDst(inst.dst[0], result); + ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); +} + void Translator::S_LSHR_B32(const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; @@ -285,4 +293,32 @@ void Translator::S_BFM_B32(const GcnInst& inst) { SetDst(inst.dst[0], ir.ShiftLeftLogical(mask, src1)); } +void Translator::S_NOT_B64(const GcnInst& inst) { + const auto get_src = [&](const InstOperand& operand) { + switch (operand.field) { + case OperandField::VccLo: + return ir.GetVcc(); + case OperandField::ExecLo: + return ir.GetExec(); + case OperandField::ScalarGPR: + return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code)); + default: + UNREACHABLE(); + } + }; + const IR::U1 src0{get_src(inst.src[0])}; + const IR::U1 result = ir.LogicalNot(src0); + ir.SetScc(result); + switch (inst.dst[0].field) { + case OperandField::VccLo: + ir.SetVcc(result); + break; + case OperandField::ScalarGPR: + ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), result); + break; + default: + UNREACHABLE(); + } +} + } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index beb2af7c..2b32b6d8 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -324,7 +324,10 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) translator.IMAGE_STORE(inst); break; case Opcode::IMAGE_LOAD_MIP: - translator.IMAGE_LOAD_MIP(inst); + translator.IMAGE_LOAD(true, inst); + break; + case Opcode::IMAGE_LOAD: + translator.IMAGE_LOAD(false, inst); break; case Opcode::V_CMP_GE_I32: translator.V_CMP_U32(ConditionOp::GE, true, false, inst); @@ -335,6 +338,9 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) case Opcode::V_CMP_LE_I32: translator.V_CMP_U32(ConditionOp::LE, true, false, inst); break; + case Opcode::V_CMP_NE_I32: + translator.V_CMP_U32(ConditionOp::LG, true, false, inst); + break; case Opcode::V_CMP_NE_U32: translator.V_CMP_U32(ConditionOp::LG, false, false, inst); break; @@ -386,6 +392,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::S_CMP_LT_U32: + translator.S_CMP(ConditionOp::LT, false, inst); + break; case Opcode::S_CMP_LG_U32: translator.S_CMP(ConditionOp::LG, false, inst); break; @@ -585,6 +594,9 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) case Opcode::S_AND_B64: translator.S_AND_B64(false, inst); break; + case Opcode::S_NOT_B64: + translator.S_NOT_B64(inst); + break; case Opcode::S_NAND_B64: translator.S_AND_B64(true, inst); break; @@ -627,6 +639,9 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) case Opcode::S_AND_B32: translator.S_AND_B32(inst); break; + case Opcode::S_OR_B32: + translator.S_OR_B32(inst); + break; case Opcode::S_LSHR_B32: translator.S_LSHR_B32(inst); break; @@ -657,9 +672,21 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) case Opcode::S_BFM_B32: translator.S_BFM_B32(inst); break; + case Opcode::V_MIN_U32: + translator.V_MIN_U32(inst); + break; + case Opcode::V_CMP_NE_U64: + translator.V_CMP_NE_U64(inst); + break; case Opcode::V_TRUNC_F32: translator.V_TRUNC_F32(inst); break; + case Opcode::V_CEIL_F32: + translator.V_CEIL_F32(inst); + break; + case Opcode::S_TTRACEDATA: + LOG_WARNING(Render_Vulkan, "S_TTRACEDATA instruction!"); + break; case Opcode::S_NOP: case Opcode::S_CBRANCH_EXECZ: case Opcode::S_CBRANCH_SCC0: diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 10a4580f..2568df30 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -45,12 +45,14 @@ public: void S_AND_B64(bool negate, const GcnInst& inst); void S_ADD_I32(const GcnInst& inst); void S_AND_B32(const GcnInst& inst); + void S_OR_B32(const GcnInst& inst); void S_LSHR_B32(const GcnInst& inst); void S_CSELECT_B32(const GcnInst& inst); void S_CSELECT_B64(const GcnInst& inst); void S_BFE_U32(const GcnInst& inst); void S_LSHL_B32(const GcnInst& inst); void S_BFM_B32(const GcnInst& inst); + void S_NOT_B64(const GcnInst& inst); // Scalar Memory void S_LOAD_DWORD(int num_dwords, const GcnInst& inst); @@ -115,6 +117,9 @@ public: void V_MIN_I32(const GcnInst& inst); void V_MUL_LO_U32(const GcnInst& inst); void V_TRUNC_F32(const GcnInst& inst); + void V_CEIL_F32(const GcnInst& inst); + void V_MIN_U32(const GcnInst& inst); + void V_CMP_NE_U64(const GcnInst& inst); // Vector Memory void BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, const GcnInst& inst); @@ -132,7 +137,7 @@ public: void IMAGE_GET_RESINFO(const GcnInst& inst); void IMAGE_SAMPLE(const GcnInst& inst); void IMAGE_STORE(const GcnInst& inst); - void IMAGE_LOAD_MIP(const GcnInst& inst); + void IMAGE_LOAD(bool has_mip, const GcnInst& inst); // Export void EXP(const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 7bad5799..b894d69f 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -430,4 +430,44 @@ void Translator::V_TRUNC_F32(const GcnInst& inst) { SetDst(inst.dst[0], ir.FPTrunc(src0)); } +void Translator::V_CEIL_F32(const GcnInst& inst) { + const IR::F32 src0{GetSrc(inst.src[0], true)}; + SetDst(inst.dst[0], ir.FPCeil(src0)); +} + +void Translator::V_MIN_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + SetDst(inst.dst[0], ir.IMin(src0, src1, false)); +} + +void Translator::V_CMP_NE_U64(const GcnInst& inst) { + const auto get_src = [&](const InstOperand& operand) { + switch (operand.field) { + case OperandField::VccLo: + return ir.GetVcc(); + case OperandField::ExecLo: + return ir.GetExec(); + case OperandField::ScalarGPR: + return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code)); + case OperandField::ConstZero: + return ir.Imm1(false); + default: + UNREACHABLE(); + } + }; + const IR::U1 src0{get_src(inst.src[0])}; + ASSERT(inst.src[1].field == OperandField::ConstZero); // src0 != 0 + switch (inst.dst[1].field) { + case OperandField::VccLo: + ir.SetVcc(src0); + break; + case OperandField::ScalarGPR: + ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[1].code), src0); + break; + default: + UNREACHABLE(); + } +} + } // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 00f7fcda..c087fcfa 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -31,7 +31,9 @@ void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) { void Translator::IMAGE_SAMPLE(const GcnInst& inst) { const auto& mimg = inst.control.mimg; - ASSERT(!mimg.da); + if (mimg.da) { + LOG_WARNING(Render_Vulkan, "Image instruction declares an array"); + } IR::VectorReg addr_reg{inst.src[0].code}; IR::VectorReg dest_reg{inst.dst[0].code}; @@ -107,7 +109,7 @@ void Translator::IMAGE_SAMPLE(const GcnInst& inst) { } } -void Translator::IMAGE_LOAD_MIP(const GcnInst& inst) { +void Translator::IMAGE_LOAD(bool has_mip, const GcnInst& inst) { const auto& mimg = inst.control.mimg; IR::VectorReg addr_reg{inst.src[0].code}; IR::VectorReg dest_reg{inst.dst[0].code}; @@ -119,7 +121,7 @@ void Translator::IMAGE_LOAD_MIP(const GcnInst& inst) { ir.GetVectorReg(addr_reg + 2), ir.GetVectorReg(addr_reg + 3)); IR::TextureInstInfo info{}; - info.explicit_lod.Assign(1); + info.explicit_lod.Assign(has_mip); const IR::Value texel = ir.ImageFetch(handle, body, {}, {}, {}, info); for (u32 i = 0; i < 4; i++) { diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index e35a6b08..306a96f0 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -251,7 +251,8 @@ IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) { IR::Inst* producer = inst.Arg(0).InstRecursive(); - ASSERT(producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2 || + ASSERT(producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2 || // IMAGE_SAMPLE (image+sampler) + producer->GetOpcode() == IR::Opcode::ReadConst || // IMAGE_LOAD (image only) producer->GetOpcode() == IR::Opcode::GetUserData); const auto [tsharp_handle, ssharp_handle] = [&] -> std::pair { if (producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2) {