@@ -13,12 +13,42 @@ module internal ComputeTaskInternals =
1313 {
1414 Shader : IComputeShader
1515 DescriptorSets : INativeResourceLocation < DescriptorSetBinding >
16- PushConstants : IConstantResourceLocation < PushConstants > voption
1716 }
1817
1918 interface IComputeInputBinding with
2019 member x.Shader = x.Shader
2120
21+ type PushConstant ( shader : IComputeShader , name : Symbol , inputType : Type ) =
22+ let layout =
23+ shader.PipelineLayout.PushConstants
24+ |> ValueOption.defaultWith ( fun _ -> failf " Compute shader does not use any push constants." )
25+
26+ let field =
27+ layout.Buffer.ubFields
28+ |> List.tryFindV ( fun f -> f.ufName = string name)
29+ |> ValueOption.defaultWith ( fun _ -> failf $" Compute shader does not use push constant '{name}'." )
30+
31+ let writer =
32+ match UniformWriters.tryGetWriter 0 field.ufType inputType with
33+ | Result.Ok writer -> writer
34+ | Result.Error msg -> failf $" Cannot get writer for compute constant '{name}': {msg}"
35+
36+ let size = GLSLType.sizeof field.ufType
37+
38+ member _.Size = size
39+
40+ member _.Write ( stream : VKVM.CommandStream , value : obj , buffer : nativeint ) =
41+ writer.WriteUnsafeValue( value, buffer)
42+ stream.PushConstants( shader.PipelineLayout.Handle, layout.StageFlags, uint32 field.ufOffset, uint32 size, buffer) |> ignore
43+
44+ interface IComputeConstant with
45+ member _.Shader = shader
46+ member _.Name = name
47+
48+ type PushConstant < 'T >( shader : IComputeShader , name : Symbol ) =
49+ inherit PushConstant( shader, name, typeof< 'T>)
50+ interface IComputeConstant< 'T>
51+
2252 type ResourceManager with
2353
2454 member x.CreateComputeInputBinding ( shader : IComputeShader , inputs : IUniformProvider ) =
@@ -28,15 +58,8 @@ module internal ComputeTaskInternals =
2858 let sets = x.CreateDescriptorSets( shader.PipelineLayout, provider)
2959 x.CreateDescriptorSetBinding( VkPipelineBindPoint.Compute, shader.PipelineLayout, sets)
3060
31- let pushConstants =
32- shader.PipelineLayout.PushConstants |> ValueOption.map ( fun pc ->
33- x.CreatePushConstants( pc, provider)
34- )
35-
3661 { Shader = shader
37- DescriptorSets = descriptorSets
38- PushConstants = pushConstants }
39-
62+ DescriptorSets = descriptorSets }
4063
4164 [<RequireQualifiedAccess>]
4265 type private HostCommand =
@@ -59,11 +82,16 @@ module internal ComputeTaskInternals =
5982
6083 type private CompilerState =
6184 {
62- Commands : CompiledCommand list
63- UsedImages : HashSet < Image >
64- ImageLayouts : HashMap < Image , VkImageLayout >
85+ Commands : CompiledCommand list
86+ UsedImages : HashSet < Image >
87+ ImageLayouts : HashMap < Image , VkImageLayout >
88+ ConstantBuffers : nativeptr < uint8 > list
6589 }
6690
91+ member this.Free () =
92+ for cmd in this.Commands do cmd.Dispose()
93+ for buf in this.ConstantBuffers do NativePtr.free buf
94+
6795 type private ICompiledTask =
6896 abstract member State : CompilerState
6997
@@ -93,9 +121,10 @@ module internal ComputeTaskInternals =
93121 module private CompilerState =
94122
95123 let empty =
96- { Commands = []
97- UsedImages = HashSet.empty
98- ImageLayouts = HashMap.empty }
124+ { Commands = []
125+ UsedImages = HashSet.empty
126+ ImageLayouts = HashMap.empty
127+ ConstantBuffers = [] }
99128
100129 let stream =
101130 State.custom ( fun s ->
@@ -127,7 +156,7 @@ module internal ComputeTaskInternals =
127156 State.modify ( fun s -> { s with UsedImages = s.UsedImages |> HashSet.add image })
128157
129158 let usedImages =
130- State.get |> State.map ( fun s -> s .UsedImages)
159+ State.get |> State.map _ . UsedImages
131160
132161 let inline layout ( image : Image ) =
133162 State.get |> State.map ( fun s ->
@@ -150,6 +179,12 @@ module internal ComputeTaskInternals =
150179 return oldLayout
151180 }
152181
182+ let inline constantBuffer ( constant : PushConstant ) =
183+ State.custom ( fun s ->
184+ let buffer = NativePtr.alloc constant.Size
185+ { s with ConstantBuffers = buffer :: s.ConstantBuffers }, buffer
186+ )
187+
153188 [<AutoOpen>]
154189 module private CommandStreamExtensions =
155190
@@ -262,14 +297,22 @@ module internal ComputeTaskInternals =
262297 let input = unbox< ComputeInputBinding> input
263298 let! stream = CompilerState.stream
264299 stream.IndirectBindDescriptorSets( input.DescriptorSets.Pointer) |> ignore
265- match input.PushConstants with
266- | ValueSome pc -> stream.PushConstants( input.Shader.PipelineLayout.Handle, pc.Handle) |> ignore
267- | _ -> ()
300+
301+ | ComputeCommand.SetConstantCmd ( constant, value) ->
302+ let constant = unbox< PushConstant> constant
303+ let! stream = CompilerState.stream
304+ let! buffer = CompilerState.constantBuffer constant
305+ constant.Write( stream, value, buffer.Address)
268306
269307 | ComputeCommand.DispatchCmd groups ->
270308 let! stream = CompilerState.stream
271309 stream.Dispatch( uint32 groups.X, uint32 groups.Y, uint32 groups.Z) |> ignore
272310
311+ | ComputeCommand.DispatchIndirectCmd ( indirectBuffer, offset) ->
312+ let! stream = CompilerState.stream
313+ let indirectBuffer = indirectBuffer |> unbox< Buffer>
314+ stream.DispatchIndirect( indirectBuffer.Handle, offset) |> ignore
315+
273316 | ComputeCommand.ExecuteCmd other ->
274317 let compiled = unbox< ICompiledTask> other
275318 do ! restoreLayouts compiled.State.UsedImages
@@ -415,7 +458,6 @@ module internal ComputeTaskInternals =
415458 failf " unknown input binding type %A " ( input.GetType())
416459
417460 resources.Add input.DescriptorSets
418- input.PushConstants |> ValueOption.iter resources.Add
419461 inputs.[ index] <- input
420462
421463 ComputeCommand.SetInputCmd input
@@ -469,7 +511,6 @@ module internal ComputeTaskInternals =
469511 // This way nothing will be released if the input just moved in the command list
470512 for input in removedInputs do
471513 resources.Remove input.DescriptorSets
472- input.PushConstants |> ValueOption.iter resources.Remove
473514
474515 // Update all hooked compute programs
475516 let mutable changed = deltas.Count > 0
@@ -479,7 +520,7 @@ module internal ComputeTaskInternals =
479520
480521 // Compile updated command list
481522 if changed then
482- for c in compiled.Commands do c.Dispose ()
523+ compiled.Free ()
483524 compiled <- ComputeCommand.compile queueFlags commands
484525 true
485526 else
@@ -488,7 +529,6 @@ module internal ComputeTaskInternals =
488529 member x.Dispose () =
489530 for KeyValue(_, input) in inputs do
490531 resources.Remove input.DescriptorSets
491- input.PushConstants |> ValueOption.iter resources.Remove
492532 inputs.Clear()
493533
494534 for KeyValue(_, task) in nested do
@@ -497,7 +537,7 @@ module internal ComputeTaskInternals =
497537
498538 hooked.Clear()
499539 commands <- IndexList.empty
500- for c in compiled.Commands do c.Dispose ()
540+ compiled.Free ()
501541 compiled <- CompilerState.empty
502542
503543 interface IDisposable with
0 commit comments