[ShaderCompiler] Widen host-evaluable scalar operations for descriptors

A resource descriptor the host materializes is built by replaying the shader's
scalar operations on the host. The validator that decides whether a value can
be replayed listed only part of what the scalar evaluator implements, so a
descriptor computed through any of the others was rejected even though the
host can compute it exactly.

The list now covers every pure scalar function the evaluator supports: the
remaining integer maximum, absolute value and high multiplies, the signed and
unsigned comparisons, 64-bit equality, the bit-counting and bit-scanning
operations, the quad mask, the integer/float conversions, and the float
arithmetic and comparisons. Anything with side effects or a lane-varying
result is still rejected.
This commit is contained in:
kuba 2026-09-29 23:19:26 +02:00
parent ed08311ce4
commit 7c50c31988
2 changed files with 44 additions and 0 deletions

View File

@ -49,6 +49,15 @@ public sealed class RuntimeValueValidator
ScalarOperation.LogicalOr or ScalarOperation.LogicalAnd or ScalarOperation.LogicalXor or ScalarOperation.LogicalNot or
ScalarOperation.FLessThanEqual or ScalarOperation.FGreaterThanEqual or ScalarOperation.FIsNan or
ScalarOperation.FMul or ScalarOperation.FTrunc => true,
// Every other pure scalar function ScalarOperationSemantics evaluates is as uniform as the
// ones above; a descriptor built through them was rejected although the host can compute it.
ScalarOperation.UMax32 or ScalarOperation.IAbs32 or ScalarOperation.SMulHi32 or ScalarOperation.UMulHi32 or
ScalarOperation.SLessThan32 or ScalarOperation.SLessThanEqual32 or ScalarOperation.SGreaterThan32 or ScalarOperation.SGreaterThanEqual32 or
ScalarOperation.ULessThanEqual32 or ScalarOperation.UGreaterThanEqual32 or ScalarOperation.IEqual64 or ScalarOperation.INotEqual64 or
ScalarOperation.BitCount32 or ScalarOperation.BitReverse32 or ScalarOperation.FindLowestBit32 or ScalarOperation.FindHighestBit32 or
ScalarOperation.QuadMask32 or ScalarOperation.ConvertF32S32 or ScalarOperation.ConvertS32F32 or
ScalarOperation.FAdd or ScalarOperation.FSub or ScalarOperation.FMin or ScalarOperation.FMax or
ScalarOperation.FEqual or ScalarOperation.FNotEqual or ScalarOperation.FLessThan or ScalarOperation.FGreaterThan => true,
_ => false,
};

View File

@ -0,0 +1,35 @@
// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.ShaderCompiler.Resources;
using Xunit;
namespace SharpEmu.ShaderCompiler.Tests;
public sealed class RuntimeValueValidatorTests
{
// The host evaluates runtime descriptor values with ScalarOperationSemantics, so the validator must
// not reject an operation the evaluator can compute (Silent Hill's compute plans failed that way).
[Fact]
public void EveryEvaluableOperationIsAcceptedAsUniform()
{
ulong[] operands = [1, 2, 3, 4];
foreach (var operation in Enum.GetValues<ScalarOperation>())
{
bool evaluable;
try
{
evaluable = ScalarOperationSemantics.TryEvaluate(operation, operands, out _);
}
catch (Exception)
{
evaluable = false;
}
if (evaluable)
{
Assert.True(RuntimeValueValidator.IsUniformOperation(operation), $"{operation} is evaluable but not uniform.");
}
}
}
}