1     object Renderer =
2         val max_uniform_sets : u32 = 16
3     
4     type DescriptorSetLayout =
5         val bindings : List<Binding>
6         val object : VkDescriptorSetLayout
7     
8     type PipelineLayout =
9         val object : VkPipelineLayout
10        val push_constant_size : u32
11        val push_constant_stages : ShaderStageFlags
12        val descriptor_set_layouts : List<DescriptorSetLayout>
13    
14        fun get (index : u32) = descriptor_set_layouts[index]
15    
16    object VkPipelineLayout =
17        def create (layouts : List<VkDescriptorSetLayout>
18                    push_constant_size : u32
19                    push_constant_stages : ShaderStageFlags) =
20            let instance : Instance @auto
21    
22            let push_constant_ranges = if push_constant_size <> 0 then
23                [PushConstantRange
24                     stage_flags = push_constant_stages
25                     offset = 0
26                     size = push_constant_size].as_slice
27            else
28                Slice<PushConstantRange>.empty
29    
30            let pipeline_layout_create_info = PipelineLayoutCreateInfo
31                type = StructureType/PipelineLayoutCreateInfo
32                next = null
33                flags = PipelineLayoutCreateFlags@zero
34                set_layout_count = layouts.size
35                set_layouts = layouts.as_ptr
36                push_constant_range_count = push_constant_ranges.size
37                push_constant_ranges = push_constant_ranges.ptr
38    
39            let mut pipeline_layout = null
40            vk/create_pipeline_layout instance.device pipeline_layout_create_info@ptr
41                                      null pipeline_layout@mut_ptr
42            |> assert_success
43    
44            pipeline_layout
45    
46    let get_push_constant (vertex_shader : VertexShader
47                           fragment_shader : FragmentShader) : (u32, ShaderStageFlags) =
48        let mut push_constant_size = 0
49        let mut push_constant_stages = ShaderStageFlags@zero
50    
51        let f (size : u32) (stages : ShaderStageFlags) =
52            if push_constant_stages == ShaderStageFlags@zero then
53                push_constant_stages = stages
54                push_constant_size = size
55            else
56                assert stages == ShaderStageFlags@zero || push_constant_size == size
57                push_constant_stages |= stages
58    
59        f vertex_shader.push_constant_size vertex_shader.push_constant_stages
60        f fragment_shader.push_constant_size fragment_shader.push_constant_stages
61    
62        (push_constant_size, push_constant_stages)
63    
64    object PipelineLayout =
65        def create (bindings : Slice<Binding>
66                    push_constant_size : u32
67                    push_constant_stages : ShaderStageFlags) =
68            let instance : Instance @auto
69    
70            let set_bindings = List<mut List<Binding>>.new
71            let set_vk_bindings = List<mut List<DescriptorSetLayoutBinding>>.new
72    
73            for binding in bindings do
74                while set_vk_bindings.size <= binding.set do
75                    set_vk_bindings.add List.new
76                    set_bindings.add List.new
77    
78                DescriptorSetLayoutBinding
79                    binding = binding.binding
80                    descriptor_type = binding.descriptor_type
81                    descriptor_count = binding.descriptor_count
82                    stage_flags = binding.stage_flags
83                    immutable_samplers = null
84                |> set_vk_bindings[binding.set].add
85    
86                set_bindings[binding.set].add binding
87    
88            assert set_vk_bindings.size < Renderer.max_uniform_sets
89            assert set_vk_bindings.size < instance.limits.max_bound_descriptor_sets
90    
91            let descriptor_set_layouts = List<DescriptorSetLayout>.new
92            for i = 0 until set_vk_bindings.size do
93                if set_vk_bindings[i].size == 0 then
94                    continue
95    
96                let descriptor_set_layout_create_info = DescriptorSetLayoutCreateInfo
97                    type = StructureType/DescriptorSetLayoutCreateInfo
98                    next = null
99                    flags = DescriptorSetLayoutCreateFlags@zero
100                   binding_count = set_vk_bindings[i].size
101                   bindings = set_vk_bindings[i].as_ptr
102   
103               let mut layout = null
104               vk/create_descriptor_set_layout instance.device
105                                               descriptor_set_layout_create_info@ptr
106                                               null layout@mut_ptr
107               |> assert_success
108   
109               set_bindings[i].sort
110               let descriptor_set_layout = DescriptorSetLayout
111                   bindings = set_bindings[i]
112                   object = layout
113   
114               descriptor_set_layouts.add descriptor_set_layout
115   
116           let pipeline_layout =
117               let layouts = descriptor_set_layouts.map { _.object }
118               VkPipelineLayout.create layouts push_constant_size
119                                       push_constant_stages
120   
121           PipelineLayout object = pipeline_layout
122                          =push_constant_size
123                          =push_constant_stages
124                          =descriptor_set_layouts
125   
126       def compute (shader : ComputeShader) =
127           create shader.metadata.bindings.as_slice
128                  shader.push_constant_size
129                  shader.push_constant_stages
130   
131       def raster (vertex_shader : VertexShader) (fragment_shader : FragmentShader) =
132           let map = Map<(u32, u32), Binding>.new
133           for bindings in [vertex_shader.metadata.bindings
134                            fragment_shader.metadata.bindings] do
135               for binding in bindings do
136                   if map.try_get (binding.set, binding.binding) ? Some item then
137                       item.stage_flags |= binding.stage_flags
138                   else
139                       map.add (binding.set, binding.binding) binding
140   
141           let bindings = map.map { _, v -> v }
142           bindings.sort_by_key { _.binding }
143   
144           let (push_constant_size, push_constant_stages) =
145               get_push_constant vertex_shader fragment_shader
146   
147           create bindings.as_slice
148                  push_constant_size
149                  push_constant_stages
150