shader: drop the large-input select before sin and cos since fract already returns zero

This commit is contained in:
nmzik
2026-10-22 00:44:43 +02:00
parent 09a9654458
commit 11465a5e3c
2 changed files with 29 additions and 39 deletions
@@ -162,34 +162,19 @@ uint32_t EmitFlushF32DenormToSignedZero(EmitterState& state, uint32_t value) {
} }
uint32_t EmitTrigCycleF32(EmitterState& state, uint32_t src, bool preserve_signed_zero) { uint32_t EmitTrigCycleF32(EmitterState& state, uint32_t src, bool preserve_signed_zero) {
const auto fract = state.builder.AllocateId(); // Finite values of magnitude 2^23 and above are integers, so fract already gives them +0.
const auto bits = state.builder.AllocateId(); const auto fract = state.builder.AllocateId();
const auto abs_bits = state.builder.AllocateId();
const auto large = state.builder.AllocateId();
const auto finite = state.builder.AllocateId();
const auto large_finite = state.builder.AllocateId();
const auto reduced = state.builder.AllocateId();
state.builder.AddFunction(spv::OpExtInst, TypeF32(state), fract, GlslStd450(state), state.builder.AddFunction(spv::OpExtInst, TypeF32(state), fract, GlslStd450(state),
GLSLstd450Fract, src); GLSLstd450Fract, src);
state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, src);
state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), abs_bits, bits,
ConstantU32(state, 0x7fffffffu));
state.builder.AddFunction(spv::OpUGreaterThanEqual, TypeBool(state), large, abs_bits,
ConstantU32(state, 0x4b000000u));
state.builder.AddFunction(spv::OpULessThan, TypeBool(state), finite, abs_bits,
ConstantU32(state, 0x7f800000u));
state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), large_finite, large, finite);
state.builder.AddFunction(spv::OpSelect, TypeF32(state), reduced, large_finite,
ConstantF32(state, 0), fract);
if (!preserve_signed_zero) { if (!preserve_signed_zero) {
return reduced; return fract;
} }
const auto zero = state.builder.AllocateId(); const auto abs_bits = Binary(state, spv::OpBitwiseAnd, TypeU32(state),
const auto ret = state.builder.AllocateId(); Unary(state, spv::OpBitcast, TypeU32(state), src),
state.builder.AddFunction(spv::OpIEqual, TypeBool(state), zero, abs_bits, ConstantU32(state, 0x7fffffffu));
ConstantU32(state, 0)); return Select(state, TypeF32(state),
state.builder.AddFunction(spv::OpSelect, TypeF32(state), ret, zero, src, reduced); Binary(state, spv::OpIEqual, TypeBool(state), abs_bits, ConstantU32(state, 0)),
return ret; src, fract);
} }
uint32_t EmitF16BitsToF32(EmitterState& state, uint32_t bits) { uint32_t EmitF16BitsToF32(EmitterState& state, uint32_t bits) {
+20 -15
View File
@@ -29230,23 +29230,28 @@ TestCase VectorRcpIflagF32IntegerReciprocal() {
return test; return test;
} }
// Runtime inputs keep the driver from folding; finite values from 2^23 up are whole periods.
TestCase VectorSinCosMaxFiniteSpecialCases() { TestCase VectorSinCosMaxFiniteSpecialCases() {
using O = ShaderOpcode; using O = ShaderOpcode;
constexpr u32 inputs[] = {0xff7fffffu, 0x7f7fffffu, 0x4b000001u, 0xcb800000u};
std::vector<u32> code; TestCase test;
AppendVMovLiteral(&code, 0, 0xff7fffffu); test.name = "VectorSinCosMaxFiniteSpecialCases";
code.push_back(EncodeVop1(0x35, 1, Vgpr(0))); test.initial.assign(std::begin(inputs), std::end(inputs));
code.push_back(EncodeVop1(0x36, 2, Vgpr(0))); test.expected = test.initial;
AppendStoreVgpr(&code, 1, 0); for (u32 i = 0; i < std::size(inputs); i++) {
AppendStoreVgpr(&code, 2, 1); AppendVMovU32(&test.code, 30, i * 4u);
AppendEnd(&code); AppendBufferLoadDword(&test.code, 0, 30);
test.code.push_back(EncodeVop1(0x35, 1, Vgpr(0)));
return {"VectorSinCosMaxFiniteSpecialCases", test.code.push_back(EncodeVop1(0x36, 2, Vgpr(0)));
code, AppendStoreVgpr(&test.code, 1, u32(test.expected.size()));
{}, AppendStoreVgpr(&test.code, 2, u32(test.expected.size() + 1));
{0x00000000u, 0x3f800000u}, test.expected.insert(test.expected.end(), {0x00000000u, 0x3f800000u});
{O::V_MOV_B32, O::V_SIN_F32, O::V_COS_F32, O::BUFFER_STORE_DWORD, }
O::S_ENDPGM}}; AppendEnd(&test.code);
test.initial.resize(test.expected.size());
test.opcodes = {O::V_MOV_B32, O::BUFFER_LOAD_DWORD, O::V_SIN_F32, O::V_COS_F32,
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
return test;
} }
TestCase VectorCompareF32ExposureGuard() { TestCase VectorCompareF32ExposureGuard() {