• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017 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 pub use self::builder::GraphicsPipelineBuilder;
11 pub use self::creation_error::GraphicsPipelineCreationError;
12 use crate::buffer::BufferAccess;
13 use crate::device::Device;
14 use crate::device::DeviceOwned;
15 use crate::pipeline::layout::PipelineLayout;
16 use crate::pipeline::shader::ShaderInterface;
17 use crate::pipeline::vertex::BufferlessDefinition;
18 use crate::pipeline::vertex::IncompatibleVertexDefinitionError;
19 use crate::pipeline::vertex::VertexDefinition;
20 use crate::pipeline::vertex::VertexInput;
21 use crate::pipeline::vertex::VertexSource;
22 use crate::render_pass::RenderPass;
23 use crate::render_pass::Subpass;
24 use crate::SafeDeref;
25 use crate::VulkanObject;
26 use std::fmt;
27 use std::hash::Hash;
28 use std::hash::Hasher;
29 use std::marker::PhantomData;
30 use std::ptr;
31 use std::sync::Arc;
32 use std::u32;
33 
34 mod builder;
35 mod creation_error;
36 // FIXME: restore
37 //mod tests;
38 
39 /// Defines how the implementation should perform a draw operation.
40 ///
41 /// This object contains the shaders and the various fixed states that describe how the
42 /// implementation should perform the various operations needed by a draw command.
43 pub struct GraphicsPipeline<VertexDefinition> {
44     inner: Inner,
45     layout: Arc<PipelineLayout>,
46     subpass: Subpass,
47     vertex_definition: VertexDefinition,
48     vertex_input: VertexInput,
49 
50     dynamic_line_width: bool,
51     dynamic_viewport: bool,
52     dynamic_scissor: bool,
53     dynamic_depth_bias: bool,
54     dynamic_depth_bounds: bool,
55     dynamic_stencil_compare_mask: bool,
56     dynamic_stencil_write_mask: bool,
57     dynamic_stencil_reference: bool,
58     dynamic_blend_constants: bool,
59 
60     num_viewports: u32,
61 }
62 
63 #[derive(PartialEq, Eq, Hash)]
64 struct Inner {
65     pipeline: ash::vk::Pipeline,
66     device: Arc<Device>,
67 }
68 
69 impl GraphicsPipeline<()> {
70     /// Starts the building process of a graphics pipeline. Returns a builder object that you can
71     /// fill with the various parameters.
start<'a>() -> GraphicsPipelineBuilder< 'static, 'static, 'static, 'static, 'static, BufferlessDefinition, (), (), (), (), (), >72     pub fn start<'a>() -> GraphicsPipelineBuilder<
73         'static,
74         'static,
75         'static,
76         'static,
77         'static,
78         BufferlessDefinition,
79         (),
80         (),
81         (),
82         (),
83         (),
84     > {
85         GraphicsPipelineBuilder::new()
86     }
87 }
88 
89 impl<Mv> GraphicsPipeline<Mv> {
90     /// Returns the vertex definition used in the constructor.
91     #[inline]
vertex_definition(&self) -> &Mv92     pub fn vertex_definition(&self) -> &Mv {
93         &self.vertex_definition
94     }
95 
96     /// Returns the device used to create this pipeline.
97     #[inline]
device(&self) -> &Arc<Device>98     pub fn device(&self) -> &Arc<Device> {
99         &self.inner.device
100     }
101 
102     /// Returns the pass used in the constructor.
103     #[inline]
subpass(&self) -> Subpass104     pub fn subpass(&self) -> Subpass {
105         self.subpass.clone()
106     }
107 
108     /// Returns the render pass used in the constructor.
109     #[inline]
render_pass(&self) -> &Arc<RenderPass>110     pub fn render_pass(&self) -> &Arc<RenderPass> {
111         self.subpass.render_pass()
112     }
113 
114     /// Returns true if the line width used by this pipeline is dynamic.
115     #[inline]
has_dynamic_line_width(&self) -> bool116     pub fn has_dynamic_line_width(&self) -> bool {
117         self.dynamic_line_width
118     }
119 
120     /// Returns the number of viewports and scissors of this pipeline.
121     #[inline]
num_viewports(&self) -> u32122     pub fn num_viewports(&self) -> u32 {
123         self.num_viewports
124     }
125 
126     /// Returns true if the viewports used by this pipeline are dynamic.
127     #[inline]
has_dynamic_viewports(&self) -> bool128     pub fn has_dynamic_viewports(&self) -> bool {
129         self.dynamic_viewport
130     }
131 
132     /// Returns true if the scissors used by this pipeline are dynamic.
133     #[inline]
has_dynamic_scissors(&self) -> bool134     pub fn has_dynamic_scissors(&self) -> bool {
135         self.dynamic_scissor
136     }
137 
138     /// Returns true if the depth bounds used by this pipeline are dynamic.
139     #[inline]
has_dynamic_depth_bounds(&self) -> bool140     pub fn has_dynamic_depth_bounds(&self) -> bool {
141         self.dynamic_depth_bounds
142     }
143 
144     /// Returns true if the stencil compare masks used by this pipeline are dynamic.
145     #[inline]
has_dynamic_stencil_compare_mask(&self) -> bool146     pub fn has_dynamic_stencil_compare_mask(&self) -> bool {
147         self.dynamic_stencil_compare_mask
148     }
149 
150     /// Returns true if the stencil write masks used by this pipeline are dynamic.
151     #[inline]
has_dynamic_stencil_write_mask(&self) -> bool152     pub fn has_dynamic_stencil_write_mask(&self) -> bool {
153         self.dynamic_stencil_write_mask
154     }
155 
156     /// Returns true if the stencil references used by this pipeline are dynamic.
157     #[inline]
has_dynamic_stencil_reference(&self) -> bool158     pub fn has_dynamic_stencil_reference(&self) -> bool {
159         self.dynamic_stencil_reference
160     }
161 }
162 
163 unsafe impl<Mv> DeviceOwned for GraphicsPipeline<Mv> {
164     #[inline]
device(&self) -> &Arc<Device>165     fn device(&self) -> &Arc<Device> {
166         &self.inner.device
167     }
168 }
169 
170 impl<Mv> fmt::Debug for GraphicsPipeline<Mv> {
171     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>172     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
173         write!(fmt, "<Vulkan graphics pipeline {:?}>", self.inner.pipeline)
174     }
175 }
176 
177 unsafe impl<Mv> VulkanObject for GraphicsPipeline<Mv> {
178     type Object = ash::vk::Pipeline;
179 
180     #[inline]
internal_object(&self) -> ash::vk::Pipeline181     fn internal_object(&self) -> ash::vk::Pipeline {
182         self.inner.pipeline
183     }
184 }
185 
186 impl Drop for Inner {
187     #[inline]
drop(&mut self)188     fn drop(&mut self) {
189         unsafe {
190             let fns = self.device.fns();
191             fns.v1_0
192                 .destroy_pipeline(self.device.internal_object(), self.pipeline, ptr::null());
193         }
194     }
195 }
196 
197 /// Trait implemented on objects that reference a graphics pipeline. Can be made into a trait
198 /// object.
199 /// When using this trait `AutoCommandBufferBuilder::draw*` calls will need the buffers to be
200 /// wrapped in a `vec!()`.
201 pub unsafe trait GraphicsPipelineAbstract:
202     VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>> + DeviceOwned
203 {
204     /// Returns an opaque object that represents the inside of the graphics pipeline.
inner(&self) -> GraphicsPipelineSys205     fn inner(&self) -> GraphicsPipelineSys;
206 
207     /// Returns the pipeline layout used in the constructor.
layout(&self) -> &Arc<PipelineLayout>208     fn layout(&self) -> &Arc<PipelineLayout>;
209 
210     /// Returns the subpass this graphics pipeline is rendering to.
subpass(&self) -> &Subpass211     fn subpass(&self) -> &Subpass;
212 
213     /// Returns the vertex input description of the graphics pipeline.
vertex_input(&self) -> &VertexInput214     fn vertex_input(&self) -> &VertexInput;
215 
216     /// Returns true if the line width used by this pipeline is dynamic.
has_dynamic_line_width(&self) -> bool217     fn has_dynamic_line_width(&self) -> bool;
218 
219     /// Returns the number of viewports and scissors of this pipeline.
num_viewports(&self) -> u32220     fn num_viewports(&self) -> u32;
221 
222     /// Returns true if the viewports used by this pipeline are dynamic.
has_dynamic_viewports(&self) -> bool223     fn has_dynamic_viewports(&self) -> bool;
224 
225     /// Returns true if the scissors used by this pipeline are dynamic.
has_dynamic_scissors(&self) -> bool226     fn has_dynamic_scissors(&self) -> bool;
227 
228     /// Returns true if the depth bounds used by this pipeline are dynamic.
has_dynamic_depth_bounds(&self) -> bool229     fn has_dynamic_depth_bounds(&self) -> bool;
230 
231     /// Returns true if the stencil compare masks used by this pipeline are dynamic.
has_dynamic_stencil_compare_mask(&self) -> bool232     fn has_dynamic_stencil_compare_mask(&self) -> bool;
233 
234     /// Returns true if the stencil write masks used by this pipeline are dynamic.
has_dynamic_stencil_write_mask(&self) -> bool235     fn has_dynamic_stencil_write_mask(&self) -> bool;
236 
237     /// Returns true if the stencil references used by this pipeline are dynamic.
has_dynamic_stencil_reference(&self) -> bool238     fn has_dynamic_stencil_reference(&self) -> bool;
239 }
240 
241 unsafe impl<Mv> GraphicsPipelineAbstract for GraphicsPipeline<Mv>
242 where
243     Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>,
244 {
245     #[inline]
inner(&self) -> GraphicsPipelineSys246     fn inner(&self) -> GraphicsPipelineSys {
247         GraphicsPipelineSys(self.inner.pipeline, PhantomData)
248     }
249 
250     /// Returns the pipeline layout used in the constructor.
251     #[inline]
layout(&self) -> &Arc<PipelineLayout>252     fn layout(&self) -> &Arc<PipelineLayout> {
253         &self.layout
254     }
255 
256     #[inline]
subpass(&self) -> &Subpass257     fn subpass(&self) -> &Subpass {
258         &self.subpass
259     }
260 
261     #[inline]
vertex_input(&self) -> &VertexInput262     fn vertex_input(&self) -> &VertexInput {
263         &self.vertex_input
264     }
265 
266     #[inline]
has_dynamic_line_width(&self) -> bool267     fn has_dynamic_line_width(&self) -> bool {
268         self.dynamic_line_width
269     }
270 
271     #[inline]
num_viewports(&self) -> u32272     fn num_viewports(&self) -> u32 {
273         self.num_viewports
274     }
275 
276     #[inline]
has_dynamic_viewports(&self) -> bool277     fn has_dynamic_viewports(&self) -> bool {
278         self.dynamic_viewport
279     }
280 
281     #[inline]
has_dynamic_scissors(&self) -> bool282     fn has_dynamic_scissors(&self) -> bool {
283         self.dynamic_scissor
284     }
285 
286     #[inline]
has_dynamic_depth_bounds(&self) -> bool287     fn has_dynamic_depth_bounds(&self) -> bool {
288         self.dynamic_depth_bounds
289     }
290 
291     #[inline]
has_dynamic_stencil_compare_mask(&self) -> bool292     fn has_dynamic_stencil_compare_mask(&self) -> bool {
293         self.dynamic_stencil_compare_mask
294     }
295 
296     #[inline]
has_dynamic_stencil_write_mask(&self) -> bool297     fn has_dynamic_stencil_write_mask(&self) -> bool {
298         self.dynamic_stencil_write_mask
299     }
300 
301     #[inline]
has_dynamic_stencil_reference(&self) -> bool302     fn has_dynamic_stencil_reference(&self) -> bool {
303         self.dynamic_stencil_reference
304     }
305 }
306 
307 unsafe impl<T> GraphicsPipelineAbstract for T
308 where
309     T: SafeDeref,
310     T::Target: GraphicsPipelineAbstract,
311 {
312     #[inline]
inner(&self) -> GraphicsPipelineSys313     fn inner(&self) -> GraphicsPipelineSys {
314         GraphicsPipelineAbstract::inner(&**self)
315     }
316 
317     #[inline]
layout(&self) -> &Arc<PipelineLayout>318     fn layout(&self) -> &Arc<PipelineLayout> {
319         (**self).layout()
320     }
321 
322     #[inline]
subpass(&self) -> &Subpass323     fn subpass(&self) -> &Subpass {
324         (**self).subpass()
325     }
326 
327     #[inline]
vertex_input(&self) -> &VertexInput328     fn vertex_input(&self) -> &VertexInput {
329         (**self).vertex_input()
330     }
331 
332     #[inline]
has_dynamic_line_width(&self) -> bool333     fn has_dynamic_line_width(&self) -> bool {
334         (**self).has_dynamic_line_width()
335     }
336 
337     #[inline]
num_viewports(&self) -> u32338     fn num_viewports(&self) -> u32 {
339         (**self).num_viewports()
340     }
341 
342     #[inline]
has_dynamic_viewports(&self) -> bool343     fn has_dynamic_viewports(&self) -> bool {
344         (**self).has_dynamic_viewports()
345     }
346 
347     #[inline]
has_dynamic_scissors(&self) -> bool348     fn has_dynamic_scissors(&self) -> bool {
349         (**self).has_dynamic_scissors()
350     }
351 
352     #[inline]
has_dynamic_depth_bounds(&self) -> bool353     fn has_dynamic_depth_bounds(&self) -> bool {
354         (**self).has_dynamic_depth_bounds()
355     }
356 
357     #[inline]
has_dynamic_stencil_compare_mask(&self) -> bool358     fn has_dynamic_stencil_compare_mask(&self) -> bool {
359         (**self).has_dynamic_stencil_compare_mask()
360     }
361 
362     #[inline]
has_dynamic_stencil_write_mask(&self) -> bool363     fn has_dynamic_stencil_write_mask(&self) -> bool {
364         (**self).has_dynamic_stencil_write_mask()
365     }
366 
367     #[inline]
has_dynamic_stencil_reference(&self) -> bool368     fn has_dynamic_stencil_reference(&self) -> bool {
369         (**self).has_dynamic_stencil_reference()
370     }
371 }
372 
373 impl<Mv> PartialEq for GraphicsPipeline<Mv>
374 where
375     Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>,
376 {
377     #[inline]
eq(&self, other: &Self) -> bool378     fn eq(&self, other: &Self) -> bool {
379         self.inner == other.inner
380     }
381 }
382 
383 impl<Mv> Eq for GraphicsPipeline<Mv> where Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>
384 {}
385 
386 impl<Mv> Hash for GraphicsPipeline<Mv>
387 where
388     Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>,
389 {
390     #[inline]
hash<H: Hasher>(&self, state: &mut H)391     fn hash<H: Hasher>(&self, state: &mut H) {
392         self.inner.hash(state);
393     }
394 }
395 
396 impl PartialEq for dyn GraphicsPipelineAbstract + Send + Sync {
397     #[inline]
eq(&self, other: &Self) -> bool398     fn eq(&self, other: &Self) -> bool {
399         GraphicsPipelineAbstract::inner(self).0 == GraphicsPipelineAbstract::inner(other).0
400             && DeviceOwned::device(self) == DeviceOwned::device(other)
401     }
402 }
403 
404 impl Eq for dyn GraphicsPipelineAbstract + Send + Sync {}
405 
406 impl Hash for dyn GraphicsPipelineAbstract + Send + Sync {
407     #[inline]
hash<H: Hasher>(&self, state: &mut H)408     fn hash<H: Hasher>(&self, state: &mut H) {
409         GraphicsPipelineAbstract::inner(self).0.hash(state);
410         DeviceOwned::device(self).hash(state);
411     }
412 }
413 
414 /// Opaque object that represents the inside of the graphics pipeline.
415 #[derive(Debug, Copy, Clone)]
416 pub struct GraphicsPipelineSys<'a>(ash::vk::Pipeline, PhantomData<&'a ()>);
417 
418 unsafe impl<'a> VulkanObject for GraphicsPipelineSys<'a> {
419     type Object = ash::vk::Pipeline;
420 
421     #[inline]
internal_object(&self) -> ash::vk::Pipeline422     fn internal_object(&self) -> ash::vk::Pipeline {
423         self.0
424     }
425 }
426 
427 unsafe impl<Mv> VertexDefinition for GraphicsPipeline<Mv>
428 where
429     Mv: VertexDefinition,
430 {
431     #[inline]
definition( &self, interface: &ShaderInterface, ) -> Result<VertexInput, IncompatibleVertexDefinitionError>432     fn definition(
433         &self,
434         interface: &ShaderInterface,
435     ) -> Result<VertexInput, IncompatibleVertexDefinitionError> {
436         self.vertex_definition.definition(interface)
437     }
438 }
439 
440 unsafe impl<Mv, S> VertexSource<S> for GraphicsPipeline<Mv>
441 where
442     Mv: VertexSource<S>,
443 {
444     #[inline]
decode(&self, s: S) -> (Vec<Box<dyn BufferAccess + Send + Sync>>, usize, usize)445     fn decode(&self, s: S) -> (Vec<Box<dyn BufferAccess + Send + Sync>>, usize, usize) {
446         self.vertex_definition.decode(s)
447     }
448 }
449