shader: Rename, implement FADD.SAT and P2R (imm)

This commit is contained in:
ReinUsesLisp 2021-02-21 17:50:14 -03:00 committed by ameerj
parent e2bc05b17d
commit 704c6f353f
18 changed files with 213 additions and 127 deletions

View file

@ -74,9 +74,10 @@ add_library(shader_recompiler STATIC
frontend/maxwell/translate/impl/integer_short_multiply_add.cpp frontend/maxwell/translate/impl/integer_short_multiply_add.cpp
frontend/maxwell/translate/impl/load_store_attribute.cpp frontend/maxwell/translate/impl/load_store_attribute.cpp
frontend/maxwell/translate/impl/load_store_memory.cpp frontend/maxwell/translate/impl/load_store_memory.cpp
frontend/maxwell/translate/impl/not_implemented.cpp frontend/maxwell/translate/impl/move_predicate_to_register.cpp
frontend/maxwell/translate/impl/move_register.cpp frontend/maxwell/translate/impl/move_register.cpp
frontend/maxwell/translate/impl/move_special_register.cpp frontend/maxwell/translate/impl/move_special_register.cpp
frontend/maxwell/translate/impl/not_implemented.cpp
frontend/maxwell/translate/translate.cpp frontend/maxwell/translate/translate.cpp
frontend/maxwell/translate/translate.h frontend/maxwell/translate/translate.h
ir_opt/collect_shader_info_pass.cpp ir_opt/collect_shader_info_pass.cpp

View file

@ -110,7 +110,7 @@ void EmitCompositeExtractF64x3(EmitContext& ctx);
void EmitCompositeExtractF64x4(EmitContext& ctx); void EmitCompositeExtractF64x4(EmitContext& ctx);
void EmitSelect8(EmitContext& ctx); void EmitSelect8(EmitContext& ctx);
void EmitSelect16(EmitContext& ctx); void EmitSelect16(EmitContext& ctx);
void EmitSelect32(EmitContext& ctx); Id EmitSelect32(EmitContext& ctx, Id cond, Id true_value, Id false_value);
void EmitSelect64(EmitContext& ctx); void EmitSelect64(EmitContext& ctx);
void EmitBitCastU16F16(EmitContext& ctx); void EmitBitCastU16F16(EmitContext& ctx);
Id EmitBitCastU32F32(EmitContext& ctx, Id value); Id EmitBitCastU32F32(EmitContext& ctx, Id value);
@ -130,9 +130,9 @@ void EmitGetZeroFromOp(EmitContext& ctx);
void EmitGetSignFromOp(EmitContext& ctx); void EmitGetSignFromOp(EmitContext& ctx);
void EmitGetCarryFromOp(EmitContext& ctx); void EmitGetCarryFromOp(EmitContext& ctx);
void EmitGetOverflowFromOp(EmitContext& ctx); void EmitGetOverflowFromOp(EmitContext& ctx);
void EmitFPAbs16(EmitContext& ctx); Id EmitFPAbs16(EmitContext& ctx, Id value);
void EmitFPAbs32(EmitContext& ctx); Id EmitFPAbs32(EmitContext& ctx, Id value);
void EmitFPAbs64(EmitContext& ctx); Id EmitFPAbs64(EmitContext& ctx, Id value);
Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
@ -146,9 +146,9 @@ void EmitFPMin64(EmitContext& ctx);
Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b);
void EmitFPNeg16(EmitContext& ctx); Id EmitFPNeg16(EmitContext& ctx, Id value);
void EmitFPNeg32(EmitContext& ctx); Id EmitFPNeg32(EmitContext& ctx, Id value);
void EmitFPNeg64(EmitContext& ctx); Id EmitFPNeg64(EmitContext& ctx, Id value);
void EmitFPRecip32(EmitContext& ctx); void EmitFPRecip32(EmitContext& ctx);
void EmitFPRecip64(EmitContext& ctx); void EmitFPRecip64(EmitContext& ctx);
void EmitFPRecipSqrt32(EmitContext& ctx); void EmitFPRecipSqrt32(EmitContext& ctx);
@ -161,9 +161,9 @@ void EmitFPExp2NotReduced(EmitContext& ctx);
void EmitFPCos(EmitContext& ctx); void EmitFPCos(EmitContext& ctx);
void EmitFPCosNotReduced(EmitContext& ctx); void EmitFPCosNotReduced(EmitContext& ctx);
void EmitFPLog2(EmitContext& ctx); void EmitFPLog2(EmitContext& ctx);
void EmitFPSaturate16(EmitContext& ctx); Id EmitFPSaturate16(EmitContext& ctx, Id value);
void EmitFPSaturate32(EmitContext& ctx); Id EmitFPSaturate32(EmitContext& ctx, Id value);
void EmitFPSaturate64(EmitContext& ctx); Id EmitFPSaturate64(EmitContext& ctx, Id value);
Id EmitFPRoundEven16(EmitContext& ctx, Id value); Id EmitFPRoundEven16(EmitContext& ctx, Id value);
Id EmitFPRoundEven32(EmitContext& ctx, Id value); Id EmitFPRoundEven32(EmitContext& ctx, Id value);
Id EmitFPRoundEven64(EmitContext& ctx, Id value); Id EmitFPRoundEven64(EmitContext& ctx, Id value);
@ -186,21 +186,21 @@ void EmitIAbs32(EmitContext& ctx);
Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift);
void EmitShiftRightLogical32(EmitContext& ctx); void EmitShiftRightLogical32(EmitContext& ctx);
void EmitShiftRightArithmetic32(EmitContext& ctx); void EmitShiftRightArithmetic32(EmitContext& ctx);
void EmitBitwiseAnd32(EmitContext& ctx); Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b);
void EmitBitwiseOr32(EmitContext& ctx); Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b);
void EmitBitwiseXor32(EmitContext& ctx); Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b);
void EmitBitFieldInsert(EmitContext& ctx); void EmitBitFieldInsert(EmitContext& ctx);
void EmitBitFieldSExtract(EmitContext& ctx); void EmitBitFieldSExtract(EmitContext& ctx);
Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count); Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count);
Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs); Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs);
void EmitULessThan(EmitContext& ctx); Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs);
void EmitIEqual(EmitContext& ctx); Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs);
void EmitSLessThanEqual(EmitContext& ctx); Id EmitSLessThanEqual(EmitContext& ctx, Id lhs, Id rhs);
void EmitULessThanEqual(EmitContext& ctx); Id EmitULessThanEqual(EmitContext& ctx, Id lhs, Id rhs);
Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs); Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs);
void EmitUGreaterThan(EmitContext& ctx); Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs);
void EmitINotEqual(EmitContext& ctx); Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs);
void EmitSGreaterThanEqual(EmitContext& ctx); Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs);
Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs);
void EmitLogicalOr(EmitContext& ctx); void EmitLogicalOr(EmitContext& ctx);
void EmitLogicalAnd(EmitContext& ctx); void EmitLogicalAnd(EmitContext& ctx);

View file

@ -12,37 +12,21 @@ Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) {
if (flags.no_contraction) { if (flags.no_contraction) {
ctx.Decorate(op, spv::Decoration::NoContraction); ctx.Decorate(op, spv::Decoration::NoContraction);
} }
switch (flags.rounding) {
case IR::FpRounding::DontCare:
break;
case IR::FpRounding::RN:
ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTE);
break;
case IR::FpRounding::RM:
ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTN);
break;
case IR::FpRounding::RP:
ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTP);
break;
case IR::FpRounding::RZ:
ctx.Decorate(op, spv::Decoration::FPRoundingMode, spv::FPRoundingMode::RTZ);
break;
}
return op; return op;
} }
} // Anonymous namespace } // Anonymous namespace
void EmitFPAbs16(EmitContext&) { Id EmitFPAbs16(EmitContext& ctx, Id value) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpFAbs(ctx.F16[1], value);
} }
void EmitFPAbs32(EmitContext&) { Id EmitFPAbs32(EmitContext& ctx, Id value) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpFAbs(ctx.F32[1], value);
} }
void EmitFPAbs64(EmitContext&) { Id EmitFPAbs64(EmitContext& ctx, Id value) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpFAbs(ctx.F64[1], value);
} }
Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
@ -97,16 +81,16 @@ Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b)); return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b));
} }
void EmitFPNeg16(EmitContext&) { Id EmitFPNeg16(EmitContext& ctx, Id value) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpFNegate(ctx.F16[1], value);
} }
void EmitFPNeg32(EmitContext&) { Id EmitFPNeg32(EmitContext& ctx, Id value) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpFNegate(ctx.F32[1], value);
} }
void EmitFPNeg64(EmitContext&) { Id EmitFPNeg64(EmitContext& ctx, Id value) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpFNegate(ctx.F64[1], value);
} }
void EmitFPRecip32(EmitContext&) { void EmitFPRecip32(EmitContext&) {
@ -157,16 +141,22 @@ void EmitFPLog2(EmitContext&) {
throw NotImplementedException("SPIR-V Instruction"); throw NotImplementedException("SPIR-V Instruction");
} }
void EmitFPSaturate16(EmitContext&) { Id EmitFPSaturate16(EmitContext& ctx, Id value) {
throw NotImplementedException("SPIR-V Instruction"); const Id zero{ctx.Constant(ctx.F16[1], u16{0})};
const Id one{ctx.Constant(ctx.F16[1], u16{0x3c00})};
return ctx.OpFClamp(ctx.F32[1], value, zero, one);
} }
void EmitFPSaturate32(EmitContext&) { Id EmitFPSaturate32(EmitContext& ctx, Id value) {
throw NotImplementedException("SPIR-V Instruction"); const Id zero{ctx.Constant(ctx.F32[1], f32{0.0})};
const Id one{ctx.Constant(ctx.F32[1], f32{1.0})};
return ctx.OpFClamp(ctx.F32[1], value, zero, one);
} }
void EmitFPSaturate64(EmitContext&) { Id EmitFPSaturate64(EmitContext& ctx, Id value) {
throw NotImplementedException("SPIR-V Instruction"); const Id zero{ctx.Constant(ctx.F64[1], f64{0.0})};
const Id one{ctx.Constant(ctx.F64[1], f64{1.0})};
return ctx.OpFClamp(ctx.F64[1], value, zero, one);
} }
Id EmitFPRoundEven16(EmitContext& ctx, Id value) { Id EmitFPRoundEven16(EmitContext& ctx, Id value) {

View file

@ -7,10 +7,39 @@
namespace Shader::Backend::SPIRV { namespace Shader::Backend::SPIRV {
Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
if (inst->HasAssociatedPseudoOperation()) { Id result{};
throw NotImplementedException("Pseudo-operations on IAdd32"); if (IR::Inst* const carry{inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp)}) {
const Id carry_type{ctx.TypeStruct(ctx.U32[1], ctx.U32[1])};
const Id carry_result{ctx.OpIAddCarry(carry_type, a, b)};
result = ctx.OpCompositeExtract(ctx.U32[1], carry_result, 0U);
const Id carry_value{ctx.OpCompositeExtract(ctx.U32[1], carry_result, 1U)};
carry->SetDefinition(ctx.OpINotEqual(ctx.U1, carry_value, ctx.u32_zero_value));
carry->Invalidate();
} else {
result = ctx.OpIAdd(ctx.U32[1], a, b);
} }
return ctx.OpIAdd(ctx.U32[1], a, b); if (IR::Inst* const zero{inst->GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)}) {
zero->SetDefinition(ctx.OpIEqual(ctx.U1, result, ctx.u32_zero_value));
zero->Invalidate();
}
if (IR::Inst* const sign{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)}) {
sign->SetDefinition(ctx.OpSLessThan(ctx.U1, result, ctx.u32_zero_value));
sign->Invalidate();
}
if (IR::Inst * overflow{inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)}) {
// https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c
constexpr u32 s32_max{static_cast<u32>(std::numeric_limits<s32>::max())};
const Id is_positive{ctx.OpSGreaterThanEqual(ctx.U1, a, ctx.u32_zero_value)};
const Id sub_a{ctx.OpISub(ctx.U32[1], ctx.Constant(ctx.U32[1], s32_max), a)};
const Id positive_test{ctx.OpSGreaterThan(ctx.U1, b, sub_a)};
const Id negative_test{ctx.OpSLessThan(ctx.U1, b, sub_a)};
const Id carry_flag{ctx.OpSelect(ctx.U1, is_positive, positive_test, negative_test)};
overflow->SetDefinition(carry_flag);
overflow->Invalidate();
}
return result;
} }
void EmitIAdd64(EmitContext&) { void EmitIAdd64(EmitContext&) {
@ -49,16 +78,16 @@ void EmitShiftRightArithmetic32(EmitContext&) {
throw NotImplementedException("SPIR-V Instruction"); throw NotImplementedException("SPIR-V Instruction");
} }
void EmitBitwiseAnd32(EmitContext&) { Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpBitwiseAnd(ctx.U32[1], a, b);
} }
void EmitBitwiseOr32(EmitContext&) { Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpBitwiseOr(ctx.U32[1], a, b);
} }
void EmitBitwiseXor32(EmitContext&) { Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpBitwiseXor(ctx.U32[1], a, b);
} }
void EmitBitFieldInsert(EmitContext&) { void EmitBitFieldInsert(EmitContext&) {
@ -77,36 +106,36 @@ Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs) {
return ctx.OpSLessThan(ctx.U1, lhs, rhs); return ctx.OpSLessThan(ctx.U1, lhs, rhs);
} }
void EmitULessThan(EmitContext&) { Id EmitULessThan(EmitContext& ctx, Id lhs, Id rhs) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpULessThan(ctx.U1, lhs, rhs);
} }
void EmitIEqual(EmitContext&) { Id EmitIEqual(EmitContext& ctx, Id lhs, Id rhs) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpIEqual(ctx.U1, lhs, rhs);
} }
void EmitSLessThanEqual(EmitContext&) { Id EmitSLessThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpSLessThanEqual(ctx.U1, lhs, rhs);
} }
void EmitULessThanEqual(EmitContext&) { Id EmitULessThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpULessThanEqual(ctx.U1, lhs, rhs);
} }
Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs) { Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs) {
return ctx.OpSGreaterThan(ctx.U1, lhs, rhs); return ctx.OpSGreaterThan(ctx.U1, lhs, rhs);
} }
void EmitUGreaterThan(EmitContext&) { Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpUGreaterThan(ctx.U1, lhs, rhs);
} }
void EmitINotEqual(EmitContext&) { Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpINotEqual(ctx.U1, lhs, rhs);
} }
void EmitSGreaterThanEqual(EmitContext&) { Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpSGreaterThanEqual(ctx.U1, lhs, rhs);
} }
Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) { Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) {

View file

@ -14,8 +14,8 @@ void EmitSelect16(EmitContext&) {
throw NotImplementedException("SPIR-V Instruction"); throw NotImplementedException("SPIR-V Instruction");
} }
void EmitSelect32(EmitContext&) { Id EmitSelect32(EmitContext& ctx, Id cond, Id true_value, Id false_value) {
throw NotImplementedException("SPIR-V Instruction"); return ctx.OpSelect(ctx.U32[1], cond, true_value, false_value);
} }
void EmitSelect64(EmitContext&) { void EmitSelect64(EmitContext&) {

View file

@ -468,11 +468,11 @@ F16F32F64 IREmitter::FPFma(const F16F32F64& a, const F16F32F64& b, const F16F32F
F16F32F64 IREmitter::FPAbs(const F16F32F64& value) { F16F32F64 IREmitter::FPAbs(const F16F32F64& value) {
switch (value.Type()) { switch (value.Type()) {
case Type::U16: case Type::F16:
return Inst<F16>(Opcode::FPAbs16, value); return Inst<F16>(Opcode::FPAbs16, value);
case Type::U32: case Type::F32:
return Inst<F32>(Opcode::FPAbs32, value); return Inst<F32>(Opcode::FPAbs32, value);
case Type::U64: case Type::F64:
return Inst<F64>(Opcode::FPAbs64, value); return Inst<F64>(Opcode::FPAbs64, value);
default: default:
ThrowInvalidType(value.Type()); ThrowInvalidType(value.Type());
@ -481,11 +481,11 @@ F16F32F64 IREmitter::FPAbs(const F16F32F64& value) {
F16F32F64 IREmitter::FPNeg(const F16F32F64& value) { F16F32F64 IREmitter::FPNeg(const F16F32F64& value) {
switch (value.Type()) { switch (value.Type()) {
case Type::U16: case Type::F16:
return Inst<F16>(Opcode::FPNeg16, value); return Inst<F16>(Opcode::FPNeg16, value);
case Type::U32: case Type::F32:
return Inst<F32>(Opcode::FPNeg32, value); return Inst<F32>(Opcode::FPNeg32, value);
case Type::U64: case Type::F64:
return Inst<F64>(Opcode::FPNeg64, value); return Inst<F64>(Opcode::FPNeg64, value);
default: default:
ThrowInvalidType(value.Type()); ThrowInvalidType(value.Type());
@ -495,10 +495,10 @@ F16F32F64 IREmitter::FPNeg(const F16F32F64& value) {
F16F32F64 IREmitter::FPAbsNeg(const F16F32F64& value, bool abs, bool neg) { F16F32F64 IREmitter::FPAbsNeg(const F16F32F64& value, bool abs, bool neg) {
F16F32F64 result{value}; F16F32F64 result{value};
if (abs) { if (abs) {
result = FPAbs(value); result = FPAbs(result);
} }
if (neg) { if (neg) {
result = FPNeg(value); result = FPNeg(result);
} }
return result; return result;
} }

View file

@ -19,8 +19,8 @@ enum class Pred : u64 {
PT, PT,
}; };
constexpr size_t NUM_USER_PREDS = 6; constexpr size_t NUM_USER_PREDS = 7;
constexpr size_t NUM_PREDS = 7; constexpr size_t NUM_PREDS = 8;
[[nodiscard]] constexpr size_t PredIndex(Pred pred) noexcept { [[nodiscard]] constexpr size_t PredIndex(Pred pred) noexcept {
return static_cast<size_t>(pred); return static_cast<size_t>(pred);

View file

@ -56,12 +56,12 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
.post_order_blocks{}, .post_order_blocks{},
}); });
} }
fmt::print(stdout, "{}\n", IR::DumpProgram(program));
Optimization::LowerFp16ToFp32(program); Optimization::LowerFp16ToFp32(program);
for (IR::Function& function : functions) { for (IR::Function& function : functions) {
function.post_order_blocks = PostOrder(function.blocks); function.post_order_blocks = PostOrder(function.blocks);
Optimization::SsaRewritePass(function.post_order_blocks); Optimization::SsaRewritePass(function.post_order_blocks);
} }
fmt::print(stdout, "{}\n", IR::DumpProgram(program));
Optimization::GlobalMemoryToStorageBufferPass(program); Optimization::GlobalMemoryToStorageBufferPass(program);
for (IR::Function& function : functions) { for (IR::Function& function : functions) {
Optimization::PostOrderInvoke(Optimization::ConstantPropagationPass, function); Optimization::PostOrderInvoke(Optimization::ConstantPropagationPass, function);

View file

@ -9,7 +9,6 @@
namespace Shader::Maxwell { namespace Shader::Maxwell {
namespace { namespace {
void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRounding fp_rounding, void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRounding fp_rounding,
const IR::F32& src_b, bool abs_a, bool neg_a, bool abs_b, bool neg_b) { const IR::F32& src_b, bool abs_a, bool neg_a, bool abs_b, bool neg_b) {
union { union {
@ -18,9 +17,6 @@ void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRoundin
BitField<8, 8, IR::Reg> src_a; BitField<8, 8, IR::Reg> src_a;
} const fadd{insn}; } const fadd{insn};
if (sat) {
throw NotImplementedException("FADD SAT");
}
if (cc) { if (cc) {
throw NotImplementedException("FADD CC"); throw NotImplementedException("FADD CC");
} }
@ -31,7 +27,11 @@ void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRoundin
.rounding{CastFpRounding(fp_rounding)}, .rounding{CastFpRounding(fp_rounding)},
.fmz_mode{ftz ? IR::FmzMode::FTZ : IR::FmzMode::None}, .fmz_mode{ftz ? IR::FmzMode::FTZ : IR::FmzMode::None},
}; };
v.F(fadd.dest_reg, v.ir.FPAdd(op_a, op_b, control)); IR::F32 value{v.ir.FPAdd(op_a, op_b, control)};
if (sat) {
value = v.ir.FPSaturate(value);
}
v.F(fadd.dest_reg, value);
} }
void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) { void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) {
@ -53,15 +53,15 @@ void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) {
} // Anonymous namespace } // Anonymous namespace
void TranslatorVisitor::FADD_reg(u64 insn) { void TranslatorVisitor::FADD_reg(u64 insn) {
FADD(*this, insn, GetReg20F(insn)); FADD(*this, insn, GetRegFloat20(insn));
} }
void TranslatorVisitor::FADD_cbuf(u64) { void TranslatorVisitor::FADD_cbuf(u64 insn) {
throw NotImplementedException("FADD (cbuf)"); FADD(*this, insn, GetFloatCbuf(insn));
} }
void TranslatorVisitor::FADD_imm(u64) { void TranslatorVisitor::FADD_imm(u64 insn) {
throw NotImplementedException("FADD (imm)"); FADD(*this, insn, GetFloatImm20(insn));
} }
void TranslatorVisitor::FADD32I(u64) { void TranslatorVisitor::FADD32I(u64) {

View file

@ -158,7 +158,7 @@ void TranslatorVisitor::F2I_cbuf(u64 insn) {
case SrcFormat::F16: case SrcFormat::F16:
return IR::F16{ir.CompositeExtract(ir.UnpackFloat2x16(GetCbuf(insn)), f2i.half)}; return IR::F16{ir.CompositeExtract(ir.UnpackFloat2x16(GetCbuf(insn)), f2i.half)};
case SrcFormat::F32: case SrcFormat::F32:
return GetCbufF(insn); return GetFloatCbuf(insn);
case SrcFormat::F64: { case SrcFormat::F64: {
return UnpackCbuf(*this, insn); return UnpackCbuf(*this, insn);
} }

View file

@ -51,7 +51,7 @@ void FFMA(TranslatorVisitor& v, u64 insn, const IR::F32& src_b, const IR::F32& s
} // Anonymous namespace } // Anonymous namespace
void TranslatorVisitor::FFMA_reg(u64 insn) { void TranslatorVisitor::FFMA_reg(u64 insn) {
FFMA(*this, insn, GetReg20F(insn), GetReg39F(insn)); FFMA(*this, insn, GetRegFloat20(insn), GetRegFloat39(insn));
} }
void TranslatorVisitor::FFMA_rc(u64) { void TranslatorVisitor::FFMA_rc(u64) {
@ -59,7 +59,7 @@ void TranslatorVisitor::FFMA_rc(u64) {
} }
void TranslatorVisitor::FFMA_cr(u64 insn) { void TranslatorVisitor::FFMA_cr(u64 insn) {
FFMA(*this, insn, GetCbufF(insn), GetReg39F(insn)); FFMA(*this, insn, GetFloatCbuf(insn), GetRegFloat39(insn));
} }
void TranslatorVisitor::FFMA_imm(u64) { void TranslatorVisitor::FFMA_imm(u64) {

View file

@ -91,7 +91,7 @@ void FMUL(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) {
} // Anonymous namespace } // Anonymous namespace
void TranslatorVisitor::FMUL_reg(u64 insn) { void TranslatorVisitor::FMUL_reg(u64 insn) {
return FMUL(*this, insn, GetReg20F(insn)); return FMUL(*this, insn, GetRegFloat20(insn));
} }
void TranslatorVisitor::FMUL_cbuf(u64) { void TranslatorVisitor::FMUL_cbuf(u64) {

View file

@ -48,11 +48,11 @@ IR::U32 TranslatorVisitor::GetReg39(u64 insn) {
return X(reg.index); return X(reg.index);
} }
IR::F32 TranslatorVisitor::GetReg20F(u64 insn) { IR::F32 TranslatorVisitor::GetRegFloat20(u64 insn) {
return ir.BitCast<IR::F32>(GetReg20(insn)); return ir.BitCast<IR::F32>(GetReg20(insn));
} }
IR::F32 TranslatorVisitor::GetReg39F(u64 insn) { IR::F32 TranslatorVisitor::GetRegFloat39(u64 insn) {
return ir.BitCast<IR::F32>(GetReg39(insn)); return ir.BitCast<IR::F32>(GetReg39(insn));
} }
@ -73,7 +73,7 @@ IR::U32 TranslatorVisitor::GetCbuf(u64 insn) {
return ir.GetCbuf(binding, byte_offset); return ir.GetCbuf(binding, byte_offset);
} }
IR::F32 TranslatorVisitor::GetCbufF(u64 insn) { IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) {
return ir.BitCast<IR::F32>(GetCbuf(insn)); return ir.BitCast<IR::F32>(GetCbuf(insn));
} }
@ -88,6 +88,17 @@ IR::U32 TranslatorVisitor::GetImm20(u64 insn) {
return ir.Imm32(value); return ir.Imm32(value);
} }
IR::F32 TranslatorVisitor::GetFloatImm20(u64 insn) {
union {
u64 raw;
BitField<20, 19, u64> value;
BitField<56, 1, u64> is_negative;
} const imm{insn};
const f32 positive_value{Common::BitCast<f32>(static_cast<u32>(imm.value) << 12)};
const f32 value{imm.is_negative != 0 ? -positive_value : positive_value};
return ir.Imm32(value);
}
IR::U32 TranslatorVisitor::GetImm32(u64 insn) { IR::U32 TranslatorVisitor::GetImm32(u64 insn) {
union { union {
u64 raw; u64 raw;

View file

@ -304,13 +304,14 @@ public:
[[nodiscard]] IR::U32 GetReg8(u64 insn); [[nodiscard]] IR::U32 GetReg8(u64 insn);
[[nodiscard]] IR::U32 GetReg20(u64 insn); [[nodiscard]] IR::U32 GetReg20(u64 insn);
[[nodiscard]] IR::U32 GetReg39(u64 insn); [[nodiscard]] IR::U32 GetReg39(u64 insn);
[[nodiscard]] IR::F32 GetReg20F(u64 insn); [[nodiscard]] IR::F32 GetRegFloat20(u64 insn);
[[nodiscard]] IR::F32 GetReg39F(u64 insn); [[nodiscard]] IR::F32 GetRegFloat39(u64 insn);
[[nodiscard]] IR::U32 GetCbuf(u64 insn); [[nodiscard]] IR::U32 GetCbuf(u64 insn);
[[nodiscard]] IR::F32 GetCbufF(u64 insn); [[nodiscard]] IR::F32 GetFloatCbuf(u64 insn);
[[nodiscard]] IR::U32 GetImm20(u64 insn); [[nodiscard]] IR::U32 GetImm20(u64 insn);
[[nodiscard]] IR::F32 GetFloatImm20(u64 insn);
[[nodiscard]] IR::U32 GetImm32(u64 insn); [[nodiscard]] IR::U32 GetImm32(u64 insn);

View file

@ -84,8 +84,8 @@ void TranslatorVisitor::IADD_cbuf(u64 insn) {
IADD(*this, insn, GetCbuf(insn)); IADD(*this, insn, GetCbuf(insn));
} }
void TranslatorVisitor::IADD_imm(u64) { void TranslatorVisitor::IADD_imm(u64 insn) {
throw NotImplementedException("IADD (imm)"); IADD(*this, insn, GetImm20(insn));
} }
void TranslatorVisitor::IADD32I(u64 insn) { void TranslatorVisitor::IADD32I(u64 insn) {

View file

@ -0,0 +1,66 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/bit_field.h"
#include "shader_recompiler/exception.h"
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
namespace Shader::Maxwell {
namespace {
enum class Mode : u64 {
PR,
CC,
};
} // Anonymous namespace
void TranslatorVisitor::P2R_reg(u64) {
throw NotImplementedException("P2R (reg)");
}
void TranslatorVisitor::P2R_cbuf(u64) {
throw NotImplementedException("P2R (cbuf)");
}
void TranslatorVisitor::P2R_imm(u64 insn) {
union {
u64 raw;
BitField<0, 8, IR::Reg> dest_reg;
BitField<8, 8, IR::Reg> src;
BitField<40, 1, Mode> mode;
BitField<41, 2, u64> byte_selector;
} const p2r{insn};
const u32 mask{GetImm20(insn).U32()};
const bool pr_mode{p2r.mode == Mode::PR};
const u32 num_items{pr_mode ? 7U : 4U};
const u32 offset{static_cast<u32>(p2r.byte_selector) * 8};
IR::U32 insert{ir.Imm32(0)};
for (u32 index = 0; index < num_items; ++index) {
if (((mask >> index) & 1) == 0) {
continue;
}
const IR::U1 cond{[this, index, pr_mode] {
if (pr_mode) {
return ir.GetPred(IR::Pred{index});
}
switch (index) {
case 0:
return ir.GetZFlag();
case 1:
return ir.GetSFlag();
case 2:
return ir.GetCFlag();
case 3:
return ir.GetOFlag();
}
throw LogicError("Unreachable P2R index");
}()};
const IR::U32 bit{ir.Select(cond, ir.Imm32(1U << (index + offset)), ir.Imm32(0))};
insert = ir.BitwiseOr(insert, bit);
}
const IR::U32 masked_out{ir.BitwiseAnd(X(p2r.src), ir.Imm32(~(mask << offset)))};
X(p2r.dest_reg, ir.BitwiseOr(masked_out, insert));
}
} // namespace Shader::Maxwell

View file

@ -633,18 +633,6 @@ void TranslatorVisitor::OUT_imm(u64) {
ThrowNotImplemented(Opcode::OUT_imm); ThrowNotImplemented(Opcode::OUT_imm);
} }
void TranslatorVisitor::P2R_reg(u64) {
ThrowNotImplemented(Opcode::P2R_reg);
}
void TranslatorVisitor::P2R_cbuf(u64) {
ThrowNotImplemented(Opcode::P2R_cbuf);
}
void TranslatorVisitor::P2R_imm(u64) {
ThrowNotImplemented(Opcode::P2R_imm);
}
void TranslatorVisitor::PBK() { void TranslatorVisitor::PBK() {
// PBK is a no-op // PBK is a no-op
} }

View file

@ -191,12 +191,12 @@ ComputePipeline PipelineCache::CreateComputePipeline(ShaderInfo* shader_info) {
.support_fp32_denorm_flush = float_control.shaderDenormFlushToZeroFloat32 != VK_FALSE, .support_fp32_denorm_flush = float_control.shaderDenormFlushToZeroFloat32 != VK_FALSE,
}; };
const auto [info, code]{Shader::RecompileSPIRV(profile, env, qmd.program_start)}; const auto [info, code]{Shader::RecompileSPIRV(profile, env, qmd.program_start)};
/*
FILE* file = fopen("D:\\shader.spv", "wb"); FILE* file = fopen("D:\\shader.spv", "wb");
fwrite(code.data(), 4, code.size(), file); fwrite(code.data(), 4, code.size(), file);
fclose(file); fclose(file);
std::system("spirv-dis D:\\shader.spv"); std::system("spirv-dis D:\\shader.spv");
*/
shader_info->unique_hash = env.ComputeHash(); shader_info->unique_hash = env.ComputeHash();
shader_info->size_bytes = env.ShaderSize(); shader_info->size_bytes = env.ShaderSize();
return ComputePipeline{device, descriptor_pool, update_descriptor_queue, info, return ComputePipeline{device, descriptor_pool, update_descriptor_queue, info,