1     object Pipeline =
2         def create (vertex_shader : VertexShader
3                     fragment_shader : FragmentShader
4                     pipeline_layout : PipelineLayout
5                     render_pass : RenderPass
6                     vertex_format : VertexFormat
7                     rasterization : Rasterization
8                     multisample : Multisample
9                     depth_stencil : DepthStencil
10                    blend : ColorBlend
11                    subpass : u32) =
12            let instance : Instance @auto
13    
14            assert subpass < render_pass.format.subpasses.size
15            let subpass_format = render_pass.format.subpasses[subpass]
16            let output_mask = subpass_format.color_attachments
17                              |> filter { _ <> Vulkan.attachment_unused }
18                              |> with_index
19                              |> fold 0 { acc (i, _) -> acc | 1 << i }
20    
21            assert fragment_shader.output_mask == output_mask
22    
23            let pipeline_vertex_input_state_create_info = if
24                vertex_format <> null
25            then
26                let input_mask = vertex_format.attribute_descriptions
27                                 |> fold 0 { acc x -> acc | 1 << x.location }
28                assert vertex_shader.input_mask & input_mask == vertex_shader.input_mask
29    
30                PipelineVertexInputStateCreateInfo
31                    type = StructureType/PipelineVertexInputStateCreateInfo
32                    next = null
33                    flags = PipelineVertexInputStateCreateFlags@zero
34                    vertex_binding_description_count =
35                        vertex_format.binding_descriptions.size
36    
37                    vertex_binding_descriptions =
38                        vertex_format.binding_descriptions.ptr
39    
40                    vertex_attribute_description_count =
41                        vertex_format.attribute_descriptions.size
42    
43                    vertex_attribute_descriptions =
44                        vertex_format.attribute_descriptions.ptr
45            else
46                assert vertex_shader.input_mask == 0
47                PipelineVertexInputStateCreateInfo
48                    type = StructureType/PipelineVertexInputStateCreateInfo
49                    next = null
50                    flags = PipelineVertexInputStateCreateFlags@zero
51                    vertex_binding_description_count = 0
52                    vertex_binding_descriptions = null
53                    vertex_attribute_description_count = 0
54                    vertex_attribute_descriptions = null
55    
56            let input_assembly_create_info = PipelineInputAssemblyStateCreateInfo
57                type = StructureType/PipelineInputAssemblyStateCreateInfo
58                next = null
59                flags = PipelineInputAssemblyStateCreateFlags@zero
60                topology = PrimitiveTopology/TriangleList
61                primitive_restart_enable = 0
62    
63            let viewport_state_create_info = PipelineViewportStateCreateInfo
64                type = StructureType/PipelineViewportStateCreateInfo
65                next = null
66                flags = PipelineViewportStateCreateFlags@zero
67                viewport_count = 1
68                viewports = null
69                scissor_count = 1
70                scissors = null
71    
72            let rasterization_state_create_info = PipelineRasterizationStateCreateInfo
73                type = StructureType/PipelineRasterizationStateCreateInfo
74                next = null
75                flags = PipelineRasterizationStateCreateFlags@zero
76                depth_clamp_enable = if rasterization.enable_depth_clamp then 1 else 0
77                rasterizer_discard_enable = if rasterization.discard_primitives
78                                            then 1
79                                            else 0
80    
81                polygon_mode = if rasterization.wireframe
82                               then PolygonMode/Line
83                               else PolygonMode/Fill
84    
85                cull_mode = rasterization.cull_mode
86                front_face = rasterization.front_face
87                depth_bias_enable = if rasterization.depth_bias_enable then 1 else 0
88                depth_bias_constant_factor = rasterization.depth_bias_constant_factor
89                depth_bias_clamp = rasterization.depth_bias_clamp
90                depth_bias_slope_factor = rasterization.depth_bias_slope_factor
91                line_width = rasterization.line_width
92    
93            let multisample_state_create_info = PipelineMultisampleStateCreateInfo
94                type = StructureType/PipelineMultisampleStateCreateInfo
95                next = null
96                flags = PipelineMultisampleStateCreateFlags@zero
97                rasterization_samples = multisample.samples
98                sample_shading_enable = if multisample.enable_sample_shading
99                                        then 1
100                                       else 0
101   
102               min_sample_shading = multisample.min_sample_shading
103               sample_mask = null
104               alpha_to_coverage_enable = if multisample.enable_alpha_to_coverage
105                                          then 1
106                                          else 0
107   
108               alpha_to_one_enable = if multisample.enable_alpha_to_one then 1 else 0
109   
110           let depth_stencil_state_create_info = PipelineDepthStencilStateCreateInfo
111               type = StructureType/PipelineDepthStencilStateCreateInfo
112               next = null
113               flags = PipelineDepthStencilStateCreateFlags@zero
114               depth_test_enable = if depth_stencil.enable_depth_test then 1 else 0
115               depth_write_enable = if depth_stencil.enable_depth_write then 1 else 0
116               depth_compare_op = depth_stencil.depth_compare_operator
117               depth_bounds_test_enable = if depth_stencil.enable_depth_range
118                                          then 1
119                                          else 0
120   
121               stencil_test_enable = if depth_stencil.enable_stencil then 1 else 0
122               front = StencilOpState
123                   fail_op = depth_stencil.front_op.fail_op
124                   pass_op = depth_stencil.front_op.pass_op
125                   depth_fail_op = depth_stencil.front_op.depth_fail_op
126                   compare_op = depth_stencil.front_op.compare_op
127                   compare_mask = depth_stencil.front_op.compare_mask
128                   write_mask = depth_stencil.front_op.write_mask
129                   reference = depth_stencil.front_op.reference
130   
131               back = StencilOpState
132                   fail_op = depth_stencil.back_op.fail_op
133                   pass_op = depth_stencil.back_op.pass_op
134                   depth_fail_op = depth_stencil.back_op.depth_fail_op
135                   compare_op = depth_stencil.back_op.compare_op
136                   compare_mask = depth_stencil.back_op.compare_mask
137                   write_mask = depth_stencil.back_op.write_mask
138                   reference = depth_stencil.back_op.reference
139   
140               min_depth_bounds = depth_stencil.depth_range_min
141               max_depth_bounds = depth_stencil.depth_range_max
142   
143           let attachment_states = subpass_format.color_attachments
144               |> filter { _ <> Vulkan.attachment_unused }
145               |> with_index
146               |> map { i, _ ->
147                   let attachment = blend.attachments[i]
148                   let mut color_write_mask = ColorComponentFlags@zero
149                   if attachment.write_r then
150                       color_write_mask |= ColorComponentFlags/R
151   
152                   if attachment.write_g then
153                       color_write_mask |= ColorComponentFlags/G
154   
155                   if attachment.write_b then
156                       color_write_mask |= ColorComponentFlags/B
157   
158                   if attachment.write_a then
159                       color_write_mask |= ColorComponentFlags/A
160   
161                   PipelineColorBlendAttachmentState
162                       blend_enable = if attachment.enable_blend then 1 else 0
163                       src_color_blend_factor = attachment.src_color_blend_factor
164                       dst_color_blend_factor = attachment.dst_color_blend_factor
165                       color_blend_op = attachment.color_blend_op
166                       src_alpha_blend_factor = attachment.src_alpha_blend_factor
167                       dst_alpha_blend_factor = attachment.dst_alpha_blend_factor
168                       alpha_blend_op = attachment.alpha_blend_op
169                       =color_write_mask }
170   
171           assert attachment_states.size == blend.attachments.size
172   
173           let color_blend_state_create_info = PipelineColorBlendStateCreateInfo
174               type = StructureType/PipelineColorBlendStateCreateInfo
175               next = null
176               flags = PipelineColorBlendStateCreateFlags@zero
177               logic_op_enable = if blend.enable_logic_op then 1 else 0
178               logic_op = blend.logic_op
179               attachment_count = attachment_states.size
180               attachments = attachment_states.as_ptr
181               blend_constants = [blend.blend_constant.x
182                                  blend.blend_constant.y
183                                  blend.blend_constant.z
184                                  blend.blend_constant.w]
185   
186           let dynamic_states = [DynamicState/Viewport, DynamicState/Scissor]
187           let dynamic_state_create_info = PipelineDynamicStateCreateInfo
188               type = StructureType/PipelineDynamicStateCreateInfo
189               next = null
190               flags = PipelineDynamicStateCreateFlags@zero
191               dynamic_state_count = dynamic_states.size
192               dynamic_states = dynamic_states.as_ptr
193   
194           let pipeline_stages = [vertex_shader.create_info, fragment_shader.create_info]
195           let graphics_pipeline_create_info = GraphicsPipelineCreateInfo
196               type = StructureType/GraphicsPipelineCreateInfo
197               next = null
198               flags = PipelineCreateFlags@zero
199               stage_count = pipeline_stages.size
200               stages = pipeline_stages.as_ptr
201               vertex_input_state = pipeline_vertex_input_state_create_info@ptr
202               input_assembly_state = input_assembly_create_info@ptr
203               tessellation_state = null
204               viewport_state = viewport_state_create_info@ptr
205               rasterization_state = rasterization_state_create_info@ptr
206               multisample_state = multisample_state_create_info@ptr
207               depth_stencil_state = depth_stencil_state_create_info@ptr
208               color_blend_state = color_blend_state_create_info@ptr
209               dynamic_state = dynamic_state_create_info@ptr
210               layout = pipeline_layout.object
211               render_pass = render_pass.object
212               =subpass
213               base_pipeline_handle = VkPipeline@zero
214               base_pipeline_index = 0
215   
216           let mut pipeline = null
217           vk/create_graphics_pipelines instance.device VkPipelineCache@zero 1
218                                        graphics_pipeline_create_info@ptr null
219                                        pipeline@mut_ptr
220           |> assert_success
221   
222           Pipeline =vertex_shader
223                    =fragment_shader
224                    pipeline_layout = pipeline_layout.object
225                    object = pipeline
226                    push_constant_size = pipeline_layout.push_constant_size
227                    push_constant_stages = pipeline_layout.push_constant_stages
228