mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 23:41:19 -06:00
The case-insensitive fallback search() in GetHostPath is only invoked for patch_path and host_path, so mods whose file or folder capitalization does not exactly match the guest path are silently bypassed even when the files are present. Mirror the existing search(patch_path) pass for mods_path, placed first to preserve mod > patch > base precedence. Co-authored-by: Matías Buzzo <matias@mbuzzo.com>
This commit is contained in:
parent
f98f1aac5a
commit
fba374442c
@ -39,11 +39,7 @@ Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
||||
return Decorate(ctx, inst, ctx.OpFma(ctx.F64[1], a, b, c));
|
||||
}
|
||||
|
||||
Id EmitFPMax32(EmitContext& ctx, Id a, Id b, bool is_legacy) {
|
||||
if (is_legacy) {
|
||||
return ctx.OpNMax(ctx.F32[1], a, b);
|
||||
}
|
||||
|
||||
Id EmitFPMax32(EmitContext& ctx, Id a, Id b) {
|
||||
return ctx.OpFMax(ctx.F32[1], a, b);
|
||||
}
|
||||
|
||||
@ -51,11 +47,7 @@ Id EmitFPMax64(EmitContext& ctx, Id a, Id b) {
|
||||
return ctx.OpFMax(ctx.F64[1], a, b);
|
||||
}
|
||||
|
||||
Id EmitFPMin32(EmitContext& ctx, Id a, Id b, bool is_legacy) {
|
||||
if (is_legacy) {
|
||||
return ctx.OpNMin(ctx.F32[1], a, b);
|
||||
}
|
||||
|
||||
Id EmitFPMin32(EmitContext& ctx, Id a, Id b) {
|
||||
return ctx.OpFMin(ctx.F32[1], a, b);
|
||||
}
|
||||
|
||||
|
||||
@ -237,9 +237,9 @@ Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||
Id EmitFPSub32(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
|
||||
Id EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c);
|
||||
Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c);
|
||||
Id EmitFPMax32(EmitContext& ctx, Id a, Id b, bool is_legacy = false);
|
||||
Id EmitFPMax32(EmitContext& ctx, Id a, Id b);
|
||||
Id EmitFPMax64(EmitContext& ctx, Id a, Id b);
|
||||
Id EmitFPMin32(EmitContext& ctx, Id a, Id b, bool is_legacy = false);
|
||||
Id EmitFPMin32(EmitContext& ctx, Id a, Id b);
|
||||
Id EmitFPMin64(EmitContext& ctx, Id a, Id b);
|
||||
Id EmitFPMinTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
Id EmitFPMaxTri32(EmitContext& ctx, Id a, Id b, Id c);
|
||||
|
||||
@ -527,13 +527,25 @@ void Translator::V_MUL_I32_I24(const GcnInst& inst, bool is_signed) {
|
||||
void Translator::V_MIN_F32(const GcnInst& inst, bool is_legacy) {
|
||||
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
|
||||
const IR::F32 src1{GetSrc<IR::F32>(inst.src[1])};
|
||||
SetDst(inst.dst[0], ir.FPMin(src0, src1, is_legacy));
|
||||
|
||||
const IR::F32 fpmin = ir.FPMin(src0, src1);
|
||||
const IR::F32 result =
|
||||
is_legacy
|
||||
? IR::F32{ir.Select(ir.LogicalOr(ir.FPIsNan(src0), ir.FPIsNan(src1)), src1, fpmin)}
|
||||
: fpmin;
|
||||
SetDst(inst.dst[0], result);
|
||||
}
|
||||
|
||||
void Translator::V_MAX_F32(const GcnInst& inst, bool is_legacy) {
|
||||
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
|
||||
const IR::F32 src1{GetSrc<IR::F32>(inst.src[1])};
|
||||
SetDst(inst.dst[0], ir.FPMax(src0, src1, is_legacy));
|
||||
|
||||
const IR::F32 fpmax = ir.FPMax(src0, src1);
|
||||
const IR::F32 result =
|
||||
is_legacy
|
||||
? IR::F32{ir.Select(ir.LogicalOr(ir.FPIsNan(src0), ir.FPIsNan(src1)), src1, fpmax)}
|
||||
: fpmax;
|
||||
SetDst(inst.dst[0], result);
|
||||
}
|
||||
|
||||
void Translator::V_MIN_I32(const GcnInst& inst) {
|
||||
|
||||
@ -1386,35 +1386,29 @@ U1 IREmitter::FPUnordered(const F32F64& lhs, const F32F64& rhs) {
|
||||
return LogicalOr(FPIsNan(lhs), FPIsNan(rhs));
|
||||
}
|
||||
|
||||
F32F64 IREmitter::FPMax(const F32F64& lhs, const F32F64& rhs, bool is_legacy) {
|
||||
F32F64 IREmitter::FPMax(const F32F64& lhs, const F32F64& rhs) {
|
||||
if (lhs.Type() != rhs.Type()) {
|
||||
UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type());
|
||||
}
|
||||
|
||||
switch (lhs.Type()) {
|
||||
case Type::F32:
|
||||
return Inst<F32>(Opcode::FPMax32, lhs, rhs, is_legacy);
|
||||
return Inst<F32>(Opcode::FPMax32, lhs, rhs);
|
||||
case Type::F64:
|
||||
if (is_legacy) {
|
||||
UNREACHABLE_MSG("F64 cannot be used with LEGACY ops");
|
||||
}
|
||||
return Inst<F64>(Opcode::FPMax64, lhs, rhs);
|
||||
default:
|
||||
ThrowInvalidType(lhs.Type());
|
||||
}
|
||||
}
|
||||
|
||||
F32F64 IREmitter::FPMin(const F32F64& lhs, const F32F64& rhs, bool is_legacy) {
|
||||
F32F64 IREmitter::FPMin(const F32F64& lhs, const F32F64& rhs) {
|
||||
if (lhs.Type() != rhs.Type()) {
|
||||
UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type());
|
||||
}
|
||||
switch (lhs.Type()) {
|
||||
case Type::F32:
|
||||
return Inst<F32>(Opcode::FPMin32, lhs, rhs, is_legacy);
|
||||
return Inst<F32>(Opcode::FPMin32, lhs, rhs);
|
||||
case Type::F64:
|
||||
if (is_legacy) {
|
||||
UNREACHABLE_MSG("F64 cannot be used with LEGACY ops");
|
||||
}
|
||||
return Inst<F64>(Opcode::FPMin64, lhs, rhs);
|
||||
default:
|
||||
ThrowInvalidType(lhs.Type());
|
||||
|
||||
@ -259,8 +259,8 @@ public:
|
||||
[[nodiscard]] U1 FPCmpClass32(const F32& value, const U32& op);
|
||||
[[nodiscard]] U1 FPOrdered(const F32F64& lhs, const F32F64& rhs);
|
||||
[[nodiscard]] U1 FPUnordered(const F32F64& lhs, const F32F64& rhs);
|
||||
[[nodiscard]] F32F64 FPMax(const F32F64& lhs, const F32F64& rhs, bool is_legacy = false);
|
||||
[[nodiscard]] F32F64 FPMin(const F32F64& lhs, const F32F64& rhs, bool is_legacy = false);
|
||||
[[nodiscard]] F32F64 FPMax(const F32F64& lhs, const F32F64& rhs);
|
||||
[[nodiscard]] F32F64 FPMin(const F32F64& lhs, const F32F64& rhs);
|
||||
[[nodiscard]] F32F64 FPMinTri(const F32F64& a, const F32F64& b, const F32F64& c);
|
||||
[[nodiscard]] F32F64 FPMaxTri(const F32F64& a, const F32F64& b, const F32F64& c);
|
||||
[[nodiscard]] F32F64 FPMedTri(const F32F64& a, const F32F64& b, const F32F64& c);
|
||||
|
||||
@ -236,9 +236,9 @@ OPCODE(FPAdd64, F64, F64,
|
||||
OPCODE(FPSub32, F32, F32, F32, )
|
||||
OPCODE(FPFma32, F32, F32, F32, F32, )
|
||||
OPCODE(FPFma64, F64, F64, F64, F64, )
|
||||
OPCODE(FPMax32, F32, F32, F32, U1, )
|
||||
OPCODE(FPMax32, F32, F32, F32, )
|
||||
OPCODE(FPMax64, F64, F64, F64, )
|
||||
OPCODE(FPMin32, F32, F32, F32, U1, )
|
||||
OPCODE(FPMin32, F32, F32, F32, )
|
||||
OPCODE(FPMin64, F64, F64, F64, )
|
||||
OPCODE(FPMinTri32, F32, F32, F32, F32, )
|
||||
OPCODE(FPMaxTri32, F32, F32, F32, F32, )
|
||||
|
||||
@ -121,3 +121,43 @@ TEST_F(GcnTest, sub_f16) {
|
||||
EXPECT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, F16x2{half(-1.0f)}); //confirmed with neo
|
||||
}
|
||||
|
||||
TEST_F(GcnTest, mul_legacy_nan) {
|
||||
auto runner = gcn_test::Runner::instance().value();
|
||||
|
||||
auto spirv = TranslateToSpirv(VOP2(OpcodeVOP2::V_MUL_LEGACY_F32, VOperand8::V0, SOperand9::V0, VOperand8::V1).Get());
|
||||
auto result = runner->run<u32>(spirv, std::array{u32(0), u32(0x7fc00000)});
|
||||
|
||||
EXPECT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, 0);
|
||||
}
|
||||
|
||||
TEST_F(GcnTest, mul_nan) {
|
||||
auto runner = gcn_test::Runner::instance().value();
|
||||
|
||||
auto spirv = TranslateToSpirv(VOP2(OpcodeVOP2::V_MUL_F32, VOperand8::V0, SOperand9::V0, VOperand8::V1).Get());
|
||||
auto result = runner->run<float>(spirv, std::array{u32(0), u32(0x7fc00000)});
|
||||
|
||||
EXPECT_TRUE(result.has_value());
|
||||
EXPECT_TRUE(std::isnan(*result));
|
||||
}
|
||||
|
||||
TEST_F(GcnTest, min_legacy_nan) {
|
||||
auto runner = gcn_test::Runner::instance().value();
|
||||
|
||||
auto spirv = TranslateToSpirv(VOP2(OpcodeVOP2::V_MIN_LEGACY_F32, VOperand8::V0, SOperand9::V0, VOperand8::V1).Get());
|
||||
auto result = runner->run<u32>(spirv, std::array{u32(0), u32(0x7fc00000)});
|
||||
|
||||
EXPECT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, 0x7fc00000);
|
||||
}
|
||||
|
||||
TEST_F(GcnTest, min_nan) {
|
||||
auto runner = gcn_test::Runner::instance().value();
|
||||
|
||||
auto spirv = TranslateToSpirv(VOP2(OpcodeVOP2::V_MIN_F32, VOperand8::V0, SOperand9::V0, VOperand8::V1).Get());
|
||||
auto result = runner->run<float>(spirv, std::array{u32(0), u32(0x7fc00000)});
|
||||
|
||||
EXPECT_TRUE(result.has_value());
|
||||
EXPECT_EQ(*result, 0);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user