shader-slang / slang

Making it easier to work with shaders
http://shader-slang.com
MIT License
2.13k stars 180 forks source link

InterlockedAddF64? #5253

Open torkeldanielsson opened 1 week ago

torkeldanielsson commented 1 week ago

The VK_EXT_shader_atomic_float adds support for atomic float operations: https://registry.khronos.org/VulkanSC/specs/1.0-extensions/man/html/VK_EXT_shader_atomic_float.html

There are different float width versions specified for spirv: float32 and float64. I wanted to use the float64 version: https://registry.khronos.org/VulkanSC/specs/1.0-extensions/html/vkspec.html#features-shaderBufferFloat64AtomicAdd

When I compile code with slang, I only see the float32 version available (as an operation on a RWByteAddressBuffer). I am curious why this is - is it intentional or just an omission where a simple PR could add it?

I can enable float64 atomics without validation layer errors so it seems like my gpu (nvidia) supports it:

        VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_floats = {};
        atomic_floats.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT;
        atomic_floats.shaderBufferFloat32Atomics = 1;
        atomic_floats.shaderBufferFloat32AtomicAdd = 1;
        atomic_floats.shaderBufferFloat64Atomics = 1;
        atomic_floats.shaderBufferFloat64AtomicAdd = 1;
csyonghe commented 1 week ago

Yes, this is just an oversight that can be easily added.

In the meanwhile, Atomic<double> works just fine:

RWStructuredBuffer<Atomic<double>> buf;

[numthreads(1, 1, 1)]
void CSMain(uint3 DTid : SV_DispatchThreadID)
{
    buf[0] += 1.0;
}
> slangc example.slang -target spirv

produces:

OpCapability Float64
OpCapability AtomicFloat64AddEXT
OpCapability Shader
OpExtension "SPV_KHR_storage_buffer_storage_class"
OpExtension "SPV_EXT_shader_atomic_float_add"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %CSMain "main" %buf
OpExecutionMode %CSMain LocalSize 1 1 1

; Debug Information
OpSource Slang 1
OpName %RWStructuredBuffer "RWStructuredBuffer"     ; id %10
OpName %buf "buf"                                   ; id %13
OpName %CSMain "CSMain"                             ; id %2

; Annotations
OpDecorate %_runtimearr_double ArrayStride 8
OpDecorate %RWStructuredBuffer Block
OpMemberDecorate %RWStructuredBuffer 0 Offset 0
OpDecorate %buf Binding 0
OpDecorate %buf DescriptorSet 0

; Types, variables and constants
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%double = OpTypeFloat 64
%_ptr_StorageBuffer_double = OpTypePointer StorageBuffer %double
%_runtimearr_double = OpTypeRuntimeArray %double    ; ArrayStride 8
%RWStructuredBuffer = OpTypeStruct %_runtimearr_double  ; Block
%_ptr_StorageBuffer_RWStructuredBuffer = OpTypePointer StorageBuffer %RWStructuredBuffer
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%uint_0 = OpConstant %uint 0
%double_1 = OpConstant %double 1
%buf = OpVariable %_ptr_StorageBuffer_RWStructuredBuffer StorageBuffer  ; Binding 0, DescriptorSet 0

; Function CSMain
%CSMain = OpFunction %void None %3
%4 = OpLabel
%9 = OpAccessChain %_ptr_StorageBuffer_double %buf %int_0 %int_0
%17 = OpAtomicFAddEXT %double %9 %uint_1 %uint_0 %double_1
OpReturn
OpFunctionEnd
csyonghe commented 1 week ago

See https://shader-slang.com/stdlib-reference/types/Atomic/add

torkeldanielsson commented 1 week ago

Thank you for a very good answer! RWStructuredBuffer<Atomic> solved it for me :)