From 829af9818dc5759810afe31b0bf37bb25c193c4e Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 19 Dec 2023 18:04:45 +0100 Subject: [PATCH] Use std430 for all storage buffers This commit changes the used layout for storage buffers to std430. Previously, only storage buffers defined as function inputs of compute shaders would use this layout. Storage buffers defined via UniformScope would not use any layout and thus lead to implementation dependent behavior. --- src/Libs/FShade.GLSL/Assembler.fs | 28 ++++++++++++------ src/Tests/FShade.GLSL.Tests/SimpleTests.fs | 33 +++++++++++++++++++++- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/Libs/FShade.GLSL/Assembler.fs b/src/Libs/FShade.GLSL/Assembler.fs index fceee20..8b0a285 100644 --- a/src/Libs/FShade.GLSL/Assembler.fs +++ b/src/Libs/FShade.GLSL/Assembler.fs @@ -1438,8 +1438,13 @@ module Assembler = | Some fmt -> fmt | _ -> t.Name - let private uniformLayout (isUniformBuffer : bool) (decorations : list) (set : int) (binding : int) = + // For some reason we use std430 for storage buffers but std140 for uniform buffers + type private Layout = + | None = 0 + | Std140 = 1 + | Std430 = 2 + let private uniformLayout (layout : Layout) (decorations : list) (set : int) (binding : int) = let decorations = decorations |> List.choose (fun d -> match d with @@ -1458,8 +1463,13 @@ module Assembler = else decorations let decorations = - if isUniformBuffer then "std140" :: decorations - else decorations + let layout = + match layout with + | Layout.Std430 -> ["std430"] + | Layout.Std140 -> ["std140"] + | _ -> [] + + layout @ decorations match decorations with | [] -> "" @@ -1529,7 +1539,7 @@ module Assembler = fields |> List.mapS (fun field -> state { let! binding = getBinding InputKind.StorageBuffer 1 [field] - let prefix = uniformLayout false [] set binding + let prefix = uniformLayout Layout.Std430 [] set binding let name = checkName field.cUniformName match field.cUniformType with @@ -1559,7 +1569,7 @@ module Assembler = | Some bufferName when config.createUniformBuffers -> let bufferName = checkName bufferName let! binding = getBinding InputKind.UniformBuffer 1 fields - let prefix = uniformLayout true [] set binding + let prefix = uniformLayout Layout.Std140 [] set binding let fieldStr = fields |> List.map (fun u -> @@ -1588,7 +1598,7 @@ module Assembler = match t with | GLSLTextureType.GLSLSampler samplerType -> let! binding = getBinding InputKind.Sampler cnt [u] - prefix <- uniformLayout false u.cUniformDecorations set binding + prefix <- uniformLayout Layout.None u.cUniformDecorations set binding do! Interface.addSampler { samplerSet = set @@ -1601,7 +1611,7 @@ module Assembler = | GLSLTextureType.GLSLImage imageType -> let! binding = getBinding InputKind.Image cnt [u] - prefix <- uniformLayout false u.cUniformDecorations set binding + prefix <- uniformLayout Layout.None u.cUniformDecorations set binding do! Interface.addImage { imageSet = set @@ -1612,7 +1622,7 @@ module Assembler = | CAccelerationStructure -> let! binding = getBinding InputKind.AccelerationStructure 1 [u] - prefix <- uniformLayout false u.cUniformDecorations set binding + prefix <- uniformLayout Layout.None u.cUniformDecorations set binding do! Interface.addAccelerationStructure { accelSet = set @@ -1622,7 +1632,7 @@ module Assembler = | _ -> let! binding = getBinding InputKind.UniformBuffer 1 [u] - prefix <- uniformLayout false u.cUniformDecorations set binding + prefix <- uniformLayout Layout.None u.cUniformDecorations set binding () diff --git a/src/Tests/FShade.GLSL.Tests/SimpleTests.fs b/src/Tests/FShade.GLSL.Tests/SimpleTests.fs index 2d76be0..0f3cf10 100644 --- a/src/Tests/FShade.GLSL.Tests/SimpleTests.fs +++ b/src/Tests/FShade.GLSL.Tests/SimpleTests.fs @@ -1234,4 +1234,35 @@ let ``Uniform alias with mismatching scope``() = e.Shaders |> ignore ) - Assert.That(exn.Message, Does.Contain "has conflicting values") \ No newline at end of file + Assert.That(exn.Message, Does.Contain "has conflicting values") + +[] +let ``Uniform and storage buffers use std140 and std430 layout``() = + Setup.Run() + + let fs (v : Vertex) = + fragment { + return uniform.RegionBuffer.[0] + } + + let fsu (v : Vertex) = + fragment { + return uniform.SomeUniformArr.[0] + } + + let cs (mybuffer : int[]) = + compute { + let id = getGlobalId().XY + mybuffer.[id.X] <- id.Y + } + + GLSL.shouldCompileAndContainRegex [ Effect.ofFunction fs ] [ "std430" ] + GLSL.shouldCompileAndContainRegex [ Effect.ofFunction fsu ] [ "std140" ] + + let glsl = + cs + |> ComputeShader.ofFunction (V3i(128,128,128)) + |> ComputeShader.toModule + |> ModuleCompiler.compileGLSL430 + + GLSL.shouldContainRegex glsl [ "std430", None ] \ No newline at end of file