[SpirvTranslator] Preserve F32 signed zero, infinity and NaN when supported
Co-authored-by: Sekai <140012992+SekaixX@users.noreply.github.com>
This commit is contained in:
parent
dc3b1d305d
commit
7b30868b03
|
|
@ -41,6 +41,7 @@ internal interface IShaderPipelineHost
|
|||
// The device supports shaderSharedInt64Atomics, so LDS 64-bit atomics can be
|
||||
// emitted as real 64-bit atomics instead of a non-atomic 32-bit pair.
|
||||
bool SharedInt64AtomicsEnabled { get; }
|
||||
bool ShaderSignedZeroInfNanPreserveFloat32Supported => false;
|
||||
bool ExecGuardElisionEnabled => true;
|
||||
ShaderPrewarmList? ShaderPrewarm => null;
|
||||
bool PerVertexPixelInputsSupported => true;
|
||||
|
|
|
|||
|
|
@ -593,6 +593,7 @@ internal sealed class ShaderProgramCache
|
|||
{
|
||||
var enableGraphicsSubgroups = _host.GraphicsSubgroupOperationsEnabled;
|
||||
var sharedInt64Atomics = _host.SharedInt64AtomicsEnabled;
|
||||
var signedZeroInfNanPreserve = _host.ShaderSignedZeroInfNanPreserveFloat32Supported;
|
||||
switch (source.Stage)
|
||||
{
|
||||
case ShaderStage.Vertex:
|
||||
|
|
@ -605,6 +606,7 @@ internal sealed class ShaderProgramCache
|
|||
ScratchDwords = info.ScratchDwords,
|
||||
EnableGraphicsSubgroupOperations = enableGraphicsSubgroups,
|
||||
SupportsSharedInt64Atomics = sharedInt64Atomics,
|
||||
ShaderSignedZeroInfNanPreserveFloat32Supported = signedZeroInfNanPreserve,
|
||||
RequiredVertexOutputCount = options.RequiredVertexOutputCount,
|
||||
VertexInputs = entry.VertexInputs,
|
||||
PositionExportControl = info.PositionExportControl,
|
||||
|
|
@ -632,6 +634,7 @@ internal sealed class ShaderProgramCache
|
|||
ScratchDwords = info.ScratchDwords,
|
||||
EnableGraphicsSubgroupOperations = enableGraphicsSubgroups,
|
||||
SupportsSharedInt64Atomics = sharedInt64Atomics,
|
||||
ShaderSignedZeroInfNanPreserveFloat32Supported = signedZeroInfNanPreserve,
|
||||
PixelOutputs = options.PixelOutputs,
|
||||
PixelInputEnable = options.PixelInputEnable,
|
||||
PixelCustomInterpolationMask = info.CustomInterpolationMask,
|
||||
|
|
@ -643,7 +646,7 @@ internal sealed class ShaderProgramCache
|
|||
|
||||
default:
|
||||
return BuildComputeRequest(entry.Plan, resources, layout, options.ComputeInfo!, options.ComputeSystemRegisters,
|
||||
sharedInt64Atomics, _host.ExecGuardElisionEnabled);
|
||||
sharedInt64Atomics, _host.ExecGuardElisionEnabled, signedZeroInfNanPreserve);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -659,7 +662,8 @@ internal sealed class ShaderProgramCache
|
|||
usesDispatchThreadLimits: usesDispatchThreadLimits);
|
||||
|
||||
private static ShaderCompileRequest BuildComputeRequest(ShaderResourcePlan plan, SpecializedResourceInfo resources, BindingLayout layout,
|
||||
ComputeInputInfo info, Gen5ComputeSystemRegisters? systemRegisters, bool sharedInt64Atomics, bool execGuardElision) =>
|
||||
ComputeInputInfo info, Gen5ComputeSystemRegisters? systemRegisters, bool sharedInt64Atomics, bool execGuardElision,
|
||||
bool signedZeroInfNanPreserve) =>
|
||||
new(plan, resources, layout)
|
||||
{
|
||||
WaveSize = info.WaveSize,
|
||||
|
|
@ -667,6 +671,7 @@ internal sealed class ShaderProgramCache
|
|||
TraceDeviceAddressFaults = SharpEmu.HLE.GpuMemory.GuestGpuMemoryHook.TraceEnabled,
|
||||
ScratchDwords = info.ScratchDwords,
|
||||
SupportsSharedInt64Atomics = sharedInt64Atomics,
|
||||
ShaderSignedZeroInfNanPreserveFloat32Supported = signedZeroInfNanPreserve,
|
||||
ComputeSystemRegisters = systemRegisters,
|
||||
LocalDataShareDwords = info.LocalDataShareDwords,
|
||||
LocalSizeX = Math.Max(info.ThreadsX, 1),
|
||||
|
|
@ -675,7 +680,8 @@ internal sealed class ShaderProgramCache
|
|||
};
|
||||
|
||||
internal static bool TryCompilePrewarm(ComputePrewarmRecord record, ShaderCodeCapture code, IGuestGpuBackend compiler,
|
||||
bool sharedInt64Atomics, bool execGuardElision, out IGuestCompiledShader? compiled, out BindingLayout? layout, out string error)
|
||||
bool sharedInt64Atomics, bool execGuardElision, bool signedZeroInfNanPreserve, out IGuestCompiledShader? compiled,
|
||||
out BindingLayout? layout, out string error)
|
||||
{
|
||||
compiled = null;
|
||||
layout = null;
|
||||
|
|
@ -692,7 +698,7 @@ internal sealed class ShaderProgramCache
|
|||
layout = AllocateLayout(program, plan, resources, record.UserDataBase, record.UserDataCount, record.PushDataCursor,
|
||||
record.Info.DispatchThreadDimensions);
|
||||
var request = BuildComputeRequest(plan, resources, layout, record.Info, record.SystemRegisters,
|
||||
sharedInt64Atomics, execGuardElision);
|
||||
sharedInt64Atomics, execGuardElision, signedZeroInfNanPreserve);
|
||||
return compiler.TryCompileProgram(request, out compiled, out error) && compiled is not null;
|
||||
}
|
||||
catch (Exception exception)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
private ulong _minStorageBufferOffsetAlignment = 1;
|
||||
private bool _supportsIndependentBlend;
|
||||
private bool _supportsDepthBiasClamp;
|
||||
private bool _supportsShaderSignedZeroInfNanPreserveFloat32;
|
||||
private uint _maxColorAttachments;
|
||||
private Device _device;
|
||||
private PipelineCache _pipelineCache;
|
||||
|
|
@ -583,10 +584,15 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
{
|
||||
SType = StructureType.PhysicalDevicePushDescriptorPropertiesKhr,
|
||||
};
|
||||
var floatControls = new PhysicalDeviceFloatControlsProperties
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceFloatControlsProperties,
|
||||
PNext = &pushDescriptorProperties,
|
||||
};
|
||||
var subgroupSizeControl = new PhysicalDeviceSubgroupSizeControlProperties
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceSubgroupSizeControlProperties,
|
||||
PNext = &pushDescriptorProperties,
|
||||
PNext = &floatControls,
|
||||
};
|
||||
var subgroup = new PhysicalDeviceSubgroupProperties
|
||||
{
|
||||
|
|
@ -599,6 +605,8 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
PNext = &subgroup,
|
||||
};
|
||||
_vk.GetPhysicalDeviceProperties2(_physicalDevice, &properties2);
|
||||
_supportsShaderSignedZeroInfNanPreserveFloat32 =
|
||||
floatControls.ShaderSignedZeroInfNanPreserveFloat32;
|
||||
SetNativeSubgroupCapabilities(subgroup.SubgroupSize, subgroup.SupportedStages);
|
||||
_canRequireComputeSubgroup32 =
|
||||
subgroup.SubgroupSize != RdnaSubgroupSize &&
|
||||
|
|
@ -657,6 +665,9 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
_ when GraphicsSubgroupOperationsEnabled => "auto-native-wave32",
|
||||
_ => "auto-fallback",
|
||||
};
|
||||
Console.Error.WriteLine(
|
||||
$"[LOADER][INFO] Vulkan shaderSignedZeroInfNanPreserveFloat32 " +
|
||||
$"enabled={_supportsShaderSignedZeroInfNanPreserveFloat32}");
|
||||
Console.Error.WriteLine(
|
||||
$"[LOADER][INFO] Vulkan graphics subgroup operations " +
|
||||
$"enabled={GraphicsSubgroupOperationsEnabled} " +
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
bool IShaderPipelineHost.GraphicsSubgroupOperationsEnabled => GraphicsSubgroupOperationsEnabled;
|
||||
|
||||
bool IShaderPipelineHost.SharedInt64AtomicsEnabled => SharedInt64AtomicsEnabled;
|
||||
bool IShaderPipelineHost.ShaderSignedZeroInfNanPreserveFloat32Supported =>
|
||||
_supportsShaderSignedZeroInfNanPreserveFloat32;
|
||||
// NVIDIA's compiler rejects the elided-EXEC wave64 compute module with NVVM error 3.
|
||||
bool IShaderPipelineHost.ExecGuardElisionEnabled => _physicalDeviceVendorId != NvidiaVendorId;
|
||||
bool IShaderPipelineHost.PerVertexPixelInputsSupported => _supportsPerVertexPixelInputs;
|
||||
|
|
|
|||
|
|
@ -162,7 +162,8 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
bool execGuardElision)
|
||||
{
|
||||
if (!ShaderProgramCache.TryCompilePrewarm(
|
||||
record, code, compiler, sharedInt64Atomics, execGuardElision, out var compiled, out var layout, out var error))
|
||||
record, code, compiler, sharedInt64Atomics, execGuardElision,
|
||||
_supportsShaderSignedZeroInfNanPreserveFloat32, out var compiled, out var layout, out var error))
|
||||
{
|
||||
NoteShaderPrewarmFailure(record, error);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -518,6 +518,13 @@ public static partial class Gen5SpirvTranslator
|
|||
_ => SpirvExecutionModel.GLCompute,
|
||||
};
|
||||
_module.AddEntryPoint(model, main, "main", _interfaces);
|
||||
if (_request.ShaderSignedZeroInfNanPreserveFloat32Supported)
|
||||
{
|
||||
_module.AddExecutionMode(
|
||||
main,
|
||||
SpirvExecutionMode.SignedZeroInfNanPreserve,
|
||||
32);
|
||||
}
|
||||
if (_stage == Gen5SpirvStage.Pixel)
|
||||
{
|
||||
_module.AddExecutionMode(main, SpirvExecutionMode.OriginUpperLeft);
|
||||
|
|
@ -555,6 +562,11 @@ public static partial class Gen5SpirvTranslator
|
|||
private void DeclareModule()
|
||||
{
|
||||
_module.AddCapability(SpirvCapability.Shader);
|
||||
if (_request.ShaderSignedZeroInfNanPreserveFloat32Supported)
|
||||
{
|
||||
_module.AddExtension("SPV_KHR_float_controls");
|
||||
_module.AddCapability(SpirvCapability.SignedZeroInfNanPreserve);
|
||||
}
|
||||
_module.AddCapability(SpirvCapability.Int64);
|
||||
_module.AddCapability(SpirvCapability.ImageQuery);
|
||||
if (UsesSubgroupOperations())
|
||||
|
|
|
|||
|
|
@ -213,6 +213,7 @@ public enum SpirvCapability : uint
|
|||
ShaderViewportIndexLayerExt = 5254,
|
||||
RuntimeDescriptorArray = 5302,
|
||||
PhysicalStorageBufferAddresses = 5347,
|
||||
SignedZeroInfNanPreserve = 4466,
|
||||
}
|
||||
|
||||
public enum SpirvStorageClass : uint
|
||||
|
|
@ -242,6 +243,7 @@ public enum SpirvExecutionMode : uint
|
|||
OriginUpperLeft = 7,
|
||||
DepthReplacing = 12,
|
||||
LocalSize = 17,
|
||||
SignedZeroInfNanPreserve = 4461,
|
||||
}
|
||||
|
||||
public enum SpirvDecoration : uint
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ public sealed class ShaderCompileRequest
|
|||
// 64-bit atomics are emitted as real 64-bit atomics instead of a pair of
|
||||
// 32-bit ones, which is not atomic as a pair.
|
||||
public bool SupportsSharedInt64Atomics { get; init; }
|
||||
public bool ShaderSignedZeroInfNanPreserveFloat32Supported { get; init; }
|
||||
public Gen5ComputeSystemRegisters? ComputeSystemRegisters { get; init; }
|
||||
|
||||
public IReadOnlyList<Gen5PixelOutputBinding> PixelOutputs { get; init; } = [];
|
||||
|
|
|
|||
Loading…
Reference in New Issue