Skip to content

Commit

Permalink
Use std430 for all storage buffers
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
hyazinthh committed Dec 19, 2023
1 parent e678b6d commit 829af98
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 10 deletions.
28 changes: 19 additions & 9 deletions src/Libs/FShade.GLSL/Assembler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1438,8 +1438,13 @@ module Assembler =
| Some fmt -> fmt
| _ -> t.Name

let private uniformLayout (isUniformBuffer : bool) (decorations : list<UniformDecoration>) (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<UniformDecoration>) (set : int) (binding : int) =
let decorations =
decorations |> List.choose (fun d ->
match d with
Expand All @@ -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
| [] -> ""
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 ->
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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

()

Expand Down
33 changes: 32 additions & 1 deletion src/Tests/FShade.GLSL.Tests/SimpleTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1234,4 +1234,35 @@ let ``Uniform alias with mismatching scope``() =
e.Shaders |> ignore
)

Assert.That(exn.Message, Does.Contain "has conflicting values")
Assert.That(exn.Message, Does.Contain "has conflicting values")

[<Test>]
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 ]

0 comments on commit 829af98

Please sign in to comment.