1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 //! Describes a processing operation that will execute on the Vulkan device.
11 //!
12 //! In Vulkan, before you can add a draw or a compute command to a command buffer you have to
13 //! create a *pipeline object* that describes this command.
14 //!
15 //! When you create a pipeline object, the implementation will usually generate some GPU machine
16 //! code that will execute the operation (similar to a compiler that generates an executable for
17 //! the CPU). Consequently it is a CPU-intensive operation that should be performed at
18 //! initialization or during a loading screen.
19 
20 pub use self::{compute::ComputePipeline, graphics::GraphicsPipeline, layout::PipelineLayout};
21 use crate::{device::DeviceOwned, macros::vulkan_enum, shader::DescriptorBindingRequirements};
22 use ahash::HashMap;
23 use std::sync::Arc;
24 
25 pub mod cache;
26 pub mod compute;
27 pub mod graphics;
28 pub mod layout;
29 
30 /// A trait for operations shared between pipeline types.
31 pub trait Pipeline: DeviceOwned {
32     /// Returns the bind point of this pipeline.
bind_point(&self) -> PipelineBindPoint33     fn bind_point(&self) -> PipelineBindPoint;
34 
35     /// Returns the pipeline layout used in this pipeline.
layout(&self) -> &Arc<PipelineLayout>36     fn layout(&self) -> &Arc<PipelineLayout>;
37 
38     /// Returns the number of descriptor sets actually accessed by this pipeline. This may be less
39     /// than the number of sets in the pipeline layout.
num_used_descriptor_sets(&self) -> u3240     fn num_used_descriptor_sets(&self) -> u32;
41 
42     /// Returns a reference to the descriptor binding requirements for this pipeline.
descriptor_binding_requirements( &self, ) -> &HashMap<(u32, u32), DescriptorBindingRequirements>43     fn descriptor_binding_requirements(
44         &self,
45     ) -> &HashMap<(u32, u32), DescriptorBindingRequirements>;
46 }
47 
48 vulkan_enum! {
49     #[non_exhaustive]
50 
51     /// The type of a pipeline.
52     ///
53     /// When binding a pipeline or descriptor sets in a command buffer, the state for each bind point
54     /// is independent from the others. This means that it is possible, for example, to bind a graphics
55     /// pipeline without disturbing any bound compute pipeline. Likewise, binding descriptor sets for
56     /// the `Compute` bind point does not affect sets that were bound to the `Graphics` bind point.
57     PipelineBindPoint = PipelineBindPoint(i32);
58 
59     // TODO: document
60     Compute = COMPUTE,
61 
62     // TODO: document
63     Graphics = GRAPHICS,
64 
65     /* TODO: enable
66     // TODO: document
67     RayTracing = RAY_TRACING_KHR {
68         device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing],
69     },*/
70 
71     /* TODO: enable
72     // TODO: document
73     SubpassShading = SUBPASS_SHADING_HUAWEI {
74         device_extensions: [huawei_subpass_shading],
75     },*/
76 }
77 
78 vulkan_enum! {
79     #[non_exhaustive]
80 
81     /// A particular state value within a graphics pipeline that can be dynamically set by a command
82     /// buffer.
83     DynamicState = DynamicState(i32);
84 
85     // TODO: document
86     Viewport = VIEWPORT,
87 
88     // TODO: document
89     Scissor = SCISSOR,
90 
91     // TODO: document
92     LineWidth = LINE_WIDTH,
93 
94     // TODO: document
95     DepthBias = DEPTH_BIAS,
96 
97     // TODO: document
98     BlendConstants = BLEND_CONSTANTS,
99 
100     // TODO: document
101     DepthBounds = DEPTH_BOUNDS,
102 
103     // TODO: document
104     StencilCompareMask = STENCIL_COMPARE_MASK,
105 
106     // TODO: document
107     StencilWriteMask = STENCIL_WRITE_MASK,
108 
109     // TODO: document
110     StencilReference = STENCIL_REFERENCE,
111 
112     // TODO: document
113     CullMode = CULL_MODE {
114         api_version: V1_3,
115         device_extensions: [ext_extended_dynamic_state],
116     },
117 
118     // TODO: document
119     FrontFace = FRONT_FACE {
120         api_version: V1_3,
121         device_extensions: [ext_extended_dynamic_state],
122     },
123 
124     // TODO: document
125     PrimitiveTopology = PRIMITIVE_TOPOLOGY {
126         api_version: V1_3,
127         device_extensions: [ext_extended_dynamic_state],
128     },
129 
130     // TODO: document
131     ViewportWithCount = VIEWPORT_WITH_COUNT {
132         api_version: V1_3,
133         device_extensions: [ext_extended_dynamic_state],
134     },
135 
136     // TODO: document
137     ScissorWithCount = SCISSOR_WITH_COUNT {
138         api_version: V1_3,
139         device_extensions: [ext_extended_dynamic_state],
140     },
141 
142     // TODO: document
143     VertexInputBindingStride = VERTEX_INPUT_BINDING_STRIDE {
144         api_version: V1_3,
145         device_extensions: [ext_extended_dynamic_state],
146     },
147 
148     // TODO: document
149     DepthTestEnable = DEPTH_TEST_ENABLE {
150         api_version: V1_3,
151         device_extensions: [ext_extended_dynamic_state],
152     },
153 
154     // TODO: document
155     DepthWriteEnable = DEPTH_WRITE_ENABLE {
156         api_version: V1_3,
157         device_extensions: [ext_extended_dynamic_state],
158     },
159 
160     // TODO: document
161     DepthCompareOp = DEPTH_COMPARE_OP {
162         api_version: V1_3,
163         device_extensions: [ext_extended_dynamic_state],
164     },
165 
166     // TODO: document
167     DepthBoundsTestEnable = DEPTH_BOUNDS_TEST_ENABLE {
168         api_version: V1_3,
169         device_extensions: [ext_extended_dynamic_state],
170     },
171 
172     // TODO: document
173     StencilTestEnable = STENCIL_TEST_ENABLE {
174         api_version: V1_3,
175         device_extensions: [ext_extended_dynamic_state],
176     },
177 
178     // TODO: document
179     StencilOp = STENCIL_OP {
180         api_version: V1_3,
181         device_extensions: [ext_extended_dynamic_state],
182     },
183 
184     // TODO: document
185     RasterizerDiscardEnable = RASTERIZER_DISCARD_ENABLE {
186         api_version: V1_3,
187         device_extensions: [ext_extended_dynamic_state2],
188     },
189 
190     // TODO: document
191     DepthBiasEnable = DEPTH_BIAS_ENABLE {
192         api_version: V1_3,
193         device_extensions: [ext_extended_dynamic_state2],
194     },
195 
196     // TODO: document
197     PrimitiveRestartEnable = PRIMITIVE_RESTART_ENABLE {
198         api_version: V1_3,
199         device_extensions: [ext_extended_dynamic_state2],
200     },
201 
202     // TODO: document
203     ViewportWScaling = VIEWPORT_W_SCALING_NV {
204         device_extensions: [nv_clip_space_w_scaling],
205     },
206 
207     // TODO: document
208     DiscardRectangle = DISCARD_RECTANGLE_EXT {
209         device_extensions: [ext_discard_rectangles],
210     },
211 
212     // TODO: document
213     SampleLocations = SAMPLE_LOCATIONS_EXT {
214         device_extensions: [ext_sample_locations],
215     },
216 
217     // TODO: document
218     RayTracingPipelineStackSize = RAY_TRACING_PIPELINE_STACK_SIZE_KHR {
219         device_extensions: [khr_ray_tracing_pipeline],
220     },
221 
222     // TODO: document
223     ViewportShadingRatePalette = VIEWPORT_SHADING_RATE_PALETTE_NV {
224         device_extensions: [nv_shading_rate_image],
225     },
226 
227     // TODO: document
228     ViewportCoarseSampleOrder = VIEWPORT_COARSE_SAMPLE_ORDER_NV {
229         device_extensions: [nv_shading_rate_image],
230     },
231 
232     // TODO: document
233     ExclusiveScissor = EXCLUSIVE_SCISSOR_NV {
234         device_extensions: [nv_scissor_exclusive],
235     },
236 
237     // TODO: document
238     FragmentShadingRate = FRAGMENT_SHADING_RATE_KHR {
239         device_extensions: [khr_fragment_shading_rate],
240     },
241 
242     // TODO: document
243     LineStipple = LINE_STIPPLE_EXT {
244         device_extensions: [ext_line_rasterization],
245     },
246 
247     // TODO: document
248     VertexInput = VERTEX_INPUT_EXT {
249         device_extensions: [ext_vertex_input_dynamic_state],
250     },
251 
252     // TODO: document
253     PatchControlPoints = PATCH_CONTROL_POINTS_EXT {
254         device_extensions: [ext_extended_dynamic_state2],
255     },
256 
257     // TODO: document
258     LogicOp = LOGIC_OP_EXT {
259         device_extensions: [ext_extended_dynamic_state2],
260     },
261 
262     // TODO: document
263     ColorWriteEnable = COLOR_WRITE_ENABLE_EXT {
264         device_extensions: [ext_color_write_enable],
265     },
266 
267     // TODO: document
268     TessellationDomainOrigin = TESSELLATION_DOMAIN_ORIGIN_EXT {
269         device_extensions: [ext_extended_dynamic_state3],
270     },
271 
272     // TODO: document
273     DepthClampEnable = DEPTH_CLAMP_ENABLE_EXT {
274         device_extensions: [ext_extended_dynamic_state3],
275     },
276 
277     // TODO: document
278     PolygonMode = POLYGON_MODE_EXT {
279         device_extensions: [ext_extended_dynamic_state3],
280     },
281 
282     // TODO: document
283     RasterizationSamples = RASTERIZATION_SAMPLES_EXT {
284         device_extensions: [ext_extended_dynamic_state3],
285     },
286 
287     // TODO: document
288     SampleMask = SAMPLE_MASK_EXT {
289         device_extensions: [ext_extended_dynamic_state3],
290     },
291 
292     // TODO: document
293     AlphaToCoverageEnable = ALPHA_TO_COVERAGE_ENABLE_EXT {
294         device_extensions: [ext_extended_dynamic_state3],
295     },
296 
297     // TODO: document
298     AlphaToOneEnable = ALPHA_TO_ONE_ENABLE_EXT {
299         device_extensions: [ext_extended_dynamic_state3],
300     },
301 
302     // TODO: document
303     LogicOpEnable = LOGIC_OP_ENABLE_EXT {
304         device_extensions: [ext_extended_dynamic_state3],
305     },
306 
307     // TODO: document
308     ColorBlendEnable = COLOR_BLEND_ENABLE_EXT {
309         device_extensions: [ext_extended_dynamic_state3],
310     },
311 
312     // TODO: document
313     ColorBlendEquation = COLOR_BLEND_EQUATION_EXT {
314         device_extensions: [ext_extended_dynamic_state3],
315     },
316 
317     // TODO: document
318     ColorWriteMask = COLOR_WRITE_MASK_EXT {
319         device_extensions: [ext_extended_dynamic_state3],
320     },
321 
322     // TODO: document
323     RasterizationStream = RASTERIZATION_STREAM_EXT {
324         device_extensions: [ext_extended_dynamic_state3],
325     },
326 
327     // TODO: document
328     ConservativeRasterizationMode = CONSERVATIVE_RASTERIZATION_MODE_EXT {
329         device_extensions: [ext_extended_dynamic_state3],
330     },
331 
332     // TODO: document
333     ExtraPrimitiveOverestimationSize = EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT {
334         device_extensions: [ext_extended_dynamic_state3],
335     },
336 
337     // TODO: document
338     DepthClipEnable = DEPTH_CLIP_ENABLE_EXT {
339         device_extensions: [ext_extended_dynamic_state3],
340     },
341 
342     // TODO: document
343     SampleLocationsEnable = SAMPLE_LOCATIONS_ENABLE_EXT {
344         device_extensions: [ext_extended_dynamic_state3],
345     },
346 
347     // TODO: document
348     ColorBlendAdvanced = COLOR_BLEND_ADVANCED_EXT {
349         device_extensions: [ext_extended_dynamic_state3],
350     },
351 
352     // TODO: document
353     ProvokingVertexMode = PROVOKING_VERTEX_MODE_EXT {
354         device_extensions: [ext_extended_dynamic_state3],
355     },
356 
357     // TODO: document
358     LineRasterizationMode = LINE_RASTERIZATION_MODE_EXT {
359         device_extensions: [ext_extended_dynamic_state3],
360     },
361 
362     // TODO: document
363     LineStippleEnable = LINE_STIPPLE_ENABLE_EXT {
364         device_extensions: [ext_extended_dynamic_state3],
365     },
366 
367     // TODO: document
368     DepthClipNegativeOneToOne = DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT {
369         device_extensions: [ext_extended_dynamic_state3],
370     },
371 
372     // TODO: document
373     ViewportWScalingEnable = VIEWPORT_W_SCALING_ENABLE_NV {
374         device_extensions: [ext_extended_dynamic_state3],
375     },
376 
377     // TODO: document
378     ViewportSwizzle = VIEWPORT_SWIZZLE_NV {
379         device_extensions: [ext_extended_dynamic_state3],
380     },
381 
382     // TODO: document
383     CoverageToColorEnable = COVERAGE_TO_COLOR_ENABLE_NV {
384         device_extensions: [ext_extended_dynamic_state3],
385     },
386 
387     // TODO: document
388     CoverageToColorLocation = COVERAGE_TO_COLOR_LOCATION_NV {
389         device_extensions: [ext_extended_dynamic_state3],
390     },
391 
392     // TODO: document
393     CoverageModulationMode = COVERAGE_MODULATION_MODE_NV {
394         device_extensions: [ext_extended_dynamic_state3],
395     },
396 
397     // TODO: document
398     CoverageModulationTableEnable = COVERAGE_MODULATION_TABLE_ENABLE_NV {
399         device_extensions: [ext_extended_dynamic_state3],
400     },
401 
402     // TODO: document
403     CoverageModulationTable = COVERAGE_MODULATION_TABLE_NV {
404         device_extensions: [ext_extended_dynamic_state3],
405     },
406 
407     // TODO: document
408     ShadingRateImageEnable = SHADING_RATE_IMAGE_ENABLE_NV {
409         device_extensions: [ext_extended_dynamic_state3],
410     },
411 
412     // TODO: document
413     RepresentativeFragmentTestEnable = REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV {
414         device_extensions: [ext_extended_dynamic_state3],
415     },
416 
417     // TODO: document
418     CoverageReductionMode = COVERAGE_REDUCTION_MODE_NV {
419         device_extensions: [ext_extended_dynamic_state3],
420     },
421 }
422 
423 /// Specifies how a dynamic state is handled by a graphics pipeline.
424 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
425 pub enum StateMode<F> {
426     /// The pipeline has a fixed value for this state. Previously set dynamic state will be lost
427     /// when binding it, and will have to be re-set after binding a pipeline that uses it.
428     Fixed(F),
429 
430     /// The pipeline expects a dynamic value to be set by a command buffer. Previously set dynamic
431     /// state is not disturbed when binding it.
432     Dynamic,
433 }
434 
435 impl<T> From<Option<T>> for StateMode<T> {
from(val: Option<T>) -> Self436     fn from(val: Option<T>) -> Self {
437         match val {
438             Some(x) => StateMode::Fixed(x),
439             None => StateMode::Dynamic,
440         }
441     }
442 }
443 
444 impl<T> From<StateMode<T>> for Option<T> {
from(val: StateMode<T>) -> Self445     fn from(val: StateMode<T>) -> Self {
446         match val {
447             StateMode::Fixed(x) => Some(x),
448             StateMode::Dynamic => None,
449         }
450     }
451 }
452 
453 /// A variant of `StateMode` that is used for cases where some value is still needed when the state
454 /// is dynamic.
455 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
456 pub enum PartialStateMode<F, D> {
457     Fixed(F),
458     Dynamic(D),
459 }
460