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