1     type BarrierFlags = flags
2         | Raster
3         | Compute
4         | Transfer
5     
6         def has_transfer = contains Transfer
7         def has_raster = contains Raster
8         def has_compute = contains Compute
9     
10    let get_flags (buffer : Buffer
11                   post_barrier : BarrierFlags) : (PipelineStageFlags, AccessFlags) =
12        let mut stage_mask = PipelineStageFlags@zero
13        let mut access_mask = AccessFlags@zero
14        if post_barrier.has_transfer then
15            stage_mask = PipelineStageFlags/Transfer
16            access_mask = AccessFlags/TransferWrite
17    
18        case buffer.type of
19            BufferType/Vertex ->
20                stage_mask |= PipelineStageFlags/VertexInput
21                access_mask |= AccessFlags/VertexAttributeRead
22                if buffer.usage.contains BufferUsageFlags/StorageBuffer then
23                    if post_barrier.has_raster then
24                        access_mask |= AccessFlags/ShaderRead | AccessFlags/ShaderWrite
25                        stage_mask |= PipelineStageFlags/VertexShader
26                                      | PipelineStageFlags/FragmentShader
27    
28                    if post_barrier.has_compute then
29                        access_mask |= AccessFlags/ShaderRead | AccessFlags/ShaderWrite
30                        stage_mask |= PipelineStageFlags/ComputeShader
31    
32            BufferType/Index ->
33                stage_mask |= PipelineStageFlags/VertexInput
34                access_mask |= AccessFlags/IndexRead
35    
36            BufferType/Uniform ->
37                if post_barrier.has_raster then
38                    stage_mask |= PipelineStageFlags/VertexShader
39                                  | PipelineStageFlags/FragmentShader
40    
41                if post_barrier.has_compute then
42                    stage_mask |= PipelineStageFlags/ComputeShader
43    
44                access_mask |= AccessFlags/UniformRead
45    
46            BufferType/Image ->
47                if post_barrier.has_raster then
48                    stage_mask |= PipelineStageFlags/VertexShader
49                                  | PipelineStageFlags/FragmentShader
50    
51                    access_mask |= AccessFlags/ShaderRead
52    
53                if post_barrier.has_compute then
54                    stage_mask |= PipelineStageFlags/ComputeShader
55                    access_mask |= AccessFlags/ShaderRead
56    
57            BufferType/Storage ->
58                if post_barrier.has_raster then
59                    stage_mask |= PipelineStageFlags/VertexShader
60                                  | PipelineStageFlags/FragmentShader
61    
62                    access_mask |= AccessFlags/ShaderRead | AccessFlags/ShaderWrite
63    
64                if post_barrier.has_compute then
65                    stage_mask |= PipelineStageFlags/ComputeShader
66                    access_mask |= AccessFlags/ShaderRead | AccessFlags/ShaderWrite
67    
68                if buffer.usage.contains BufferUsageFlags/IndirectBuffer then
69                    stage_mask |= PipelineStageFlags/DrawIndirect
70                    access_mask |= AccessFlags/IndirectCommandRead
71    
72        if stage_mask == PipelineStageFlags@zero then
73            stage_mask = PipelineStageFlags/BottomOfPipe
74    
75        (stage_mask, access_mask)
76    
77    type Buffer
78        def update<T> self (data : Slice<T>) (post_barrier : BarrierFlags) =
79            let command_buffer : CommandBuffer @auto
80    
81            let size = sizeof T * data.size
82            assert size <= self.size
83    
84            let target = Target/Buffer self.object
85            buffer/write target data.ptr size 32
86    
87            let (stage_mask, access_flags) = get_flags self post_barrier
88    
89            let barrier = BufferMemoryBarrier
90                type = StructureType/BufferMemoryBarrier
91                next = null
92                src_access_mask = AccessFlags/TransferWrite
93                dst_access_mask = access_flags
94                src_queue_family_index = Vk.queue_family_ignored
95                dst_queue_family_index = Vk.queue_family_ignored
96                buffer = self.object
97                offset = 0
98                size = data.size as u64
99    
100           vk/cmd_pipeline_barrier command_buffer.object PipelineStageFlags/Transfer
101                                   stage_mask DependencyFlags@zero 0 null 1
102                                   barrier@ptr 0 null
103   
104       def update_single<T> (data : ptr T) (post_barrier : BarrierFlags) =
105           let slice = Slice<T> data 1
106           update slice post_barrier
107