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 de71ecfbf..56a6abc05 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp @@ -108,16 +108,6 @@ Id EmitUnpackSnorm2x16(EmitContext& ctx, Id value) { return ctx.OpUnpackSnorm2x16(ctx.F32[2], value); } -Id EmitUnpackSnormNz2x16(EmitContext& ctx, Id value) { - const auto [x, y] = ExtractBitFields(ctx, value, R(0, 16), R(16, 16)); - const auto unpacked{ctx.OpCompositeConstruct(ctx.S32[2], x, y)}; - constexpr s32 N = std::numeric_limits::max(); - const Id numerator = ctx.OpIAdd(ctx.S32[2], unpacked, ctx.ConstS32(N / 2, N / 2)); - const Id denom = ctx.ConstS32(N - 1, N - 1); - const Id result = ctx.OpConvertSToF(ctx.F32[2], ctx.OpUDiv(ctx.S32[2], numerator, denom)); - return ctx.OpFma(ctx.F32[2], result, ctx.ConstF32(2.0f, 2.0f), ctx.ConstF32(-1.0f, -1.0f)); -} - Id EmitPackUint2x16(EmitContext& ctx, Id value) { const auto unpacked{ctx.OpBitcast(ctx.U32[2], value)}; const auto [x, y] = ExtractComposite<2>(ctx, ctx.U32, unpacked); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 707b59383..9b7528be8 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -213,7 +213,6 @@ Id EmitPackUnorm2x16(EmitContext& ctx, Id value); Id EmitUnpackUnorm2x16(EmitContext& ctx, Id value); Id EmitPackSnorm2x16(EmitContext& ctx, Id value); Id EmitUnpackSnorm2x16(EmitContext& ctx, Id value); -Id EmitUnpackSnormNz2x16(EmitContext& ctx, Id value); Id EmitPackUint2x16(EmitContext& ctx, Id value); Id EmitUnpackUint2x16(EmitContext& ctx, Id value); Id EmitPackSint2x16(EmitContext& ctx, Id value); diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 101cd0be2..e8836bb4c 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -868,8 +868,6 @@ Value IREmitter::Unpack2x16(const AmdGpu::NumberFormat number_format, const U32& return Inst(Opcode::UnpackUnorm2x16, value); case AmdGpu::NumberFormat::Snorm: return Inst(Opcode::UnpackSnorm2x16, value); - case AmdGpu::NumberFormat::SnormNz: - return Inst(Opcode::UnpackSnormNz2x16, value); case AmdGpu::NumberFormat::Uint: return Inst(Opcode::UnpackUint2x16, value); case AmdGpu::NumberFormat::Sint: diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index 63b1f1a60..4932ff9a0 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -204,7 +204,6 @@ OPCODE(PackUnorm2x16, U32, F32x OPCODE(UnpackUnorm2x16, F32x2, U32, ) OPCODE(PackSnorm2x16, U32, F32x2, ) OPCODE(UnpackSnorm2x16, F32x2, U32, ) -OPCODE(UnpackSnormNz2x16, F32x2, U32, ) OPCODE(PackUint2x16, U32, F32x2, ) OPCODE(UnpackUint2x16, F32x2, U32, ) OPCODE(PackSint2x16, U32, F32x2, ) diff --git a/src/shader_recompiler/ir/reinterpret.h b/src/shader_recompiler/ir/reinterpret.h index b65b19928..e63aff4c9 100644 --- a/src/shader_recompiler/ir/reinterpret.h +++ b/src/shader_recompiler/ir/reinterpret.h @@ -34,6 +34,12 @@ inline F32 ApplyReadNumberConversion(IREmitter& ir, const F32& value, case AmdGpu::NumberConversion::UnormToUbnorm: // Convert 0...1 to -1...1 return ir.FPSub(ir.FPMul(value, ir.Imm32(2.f)), ir.Imm32(1.f)); + case AmdGpu::NumberConversion::SintToSnormNz: { + const IR::U32 additon = ir.IAdd(ir.IMul(ir.BitCast(value), ir.Imm32(2)), ir.Imm32(1)); + const IR::F32 left = ir.ConvertSToF(32, 32, additon); + const IR::F32 max = ir.Imm32(float(std::numeric_limits::max())); + return ir.FPDiv(left, max); + } default: UNREACHABLE(); } @@ -66,6 +72,12 @@ inline F32 ApplyWriteNumberConversion(IREmitter& ir, const F32& value, case AmdGpu::NumberConversion::UnormToUbnorm: // Convert -1...1 to 0...1 return ir.FPDiv(ir.FPAdd(value, ir.Imm32(1.f)), ir.Imm32(2.f)); + case AmdGpu::NumberConversion::SintToSnormNz: { + const IR::F32 max = ir.Imm32(float(std::numeric_limits::max())); + const IR::F32 mul = ir.FPMul(ir.FPClamp(value, ir.Imm32(-1.f), ir.Imm32(1.f)), max); + const IR::F32 left = ir.FPSub(mul, ir.Imm32(1.f)); + return ir.BitCast(U32{ir.FPDiv(left, ir.Imm32(2.f))}); + } default: UNREACHABLE(); } diff --git a/src/video_core/amdgpu/types.h b/src/video_core/amdgpu/types.h index d1cf19076..1044a1aaa 100644 --- a/src/video_core/amdgpu/types.h +++ b/src/video_core/amdgpu/types.h @@ -197,6 +197,7 @@ enum class NumberConversion : u32 { UintToUscaled = 1, SintToSscaled = 2, UnormToUbnorm = 3, + SintToSnormNz = 4, }; struct CompMapping { @@ -287,6 +288,7 @@ inline NumberFormat RemapNumberFormat(const NumberFormat format, const DataForma case NumberFormat::Uscaled: return NumberFormat::Uint; case NumberFormat::Sscaled: + case NumberFormat::SnormNz: return NumberFormat::Sint; case NumberFormat::Ubnorm: return NumberFormat::Unorm; @@ -344,6 +346,8 @@ inline NumberConversion MapNumberConversion(const NumberFormat format) { return NumberConversion::SintToSscaled; case NumberFormat::Ubnorm: return NumberConversion::UnormToUbnorm; + case NumberFormat::SnormNz: + return NumberConversion::SintToSnormNz; default: return NumberConversion::None; }