From 0fed9bbc7ffb7e33a4219db7cf56e3e3816fab62 Mon Sep 17 00:00:00 2001 From: Rua Date: Sat, 7 Oct 2023 16:46:03 +0200 Subject: [PATCH] Make dynamic state future-proof and more Vulkan-y (#2348) * Make dynamic state future-proof and more Vulkan-y * Additional fixes * Extra docs * Oops * Derp! * Review fixes --- examples/src/bin/async-update.rs | 19 +- examples/src/bin/buffer-allocator.rs | 12 +- .../deferred/frame/ambient_lighting_system.rs | 23 +- .../frame/directional_lighting_system.rs | 23 +- .../deferred/frame/point_lighting_system.rs | 23 +- .../src/bin/deferred/triangle_draw_system.rs | 19 +- examples/src/bin/gl-interop.rs | 24 +- examples/src/bin/image-self-copy-blit/main.rs | 24 +- examples/src/bin/image/main.rs | 24 +- examples/src/bin/immutable-sampler/main.rs | 24 +- examples/src/bin/indirect.rs | 14 +- examples/src/bin/instancing.rs | 12 +- .../pixels_draw_pipeline.rs | 12 +- examples/src/bin/msaa-renderpass.rs | 12 +- examples/src/bin/multi-window.rs | 12 +- .../multi_window_game_of_life/pixels_draw.rs | 12 +- examples/src/bin/multiview.rs | 18 +- examples/src/bin/occlusion-query.rs | 19 +- examples/src/bin/push-descriptors/main.rs | 24 +- examples/src/bin/runtime-shader/main.rs | 22 +- examples/src/bin/runtime_array/main.rs | 17 +- examples/src/bin/simple-particles.rs | 32 +- examples/src/bin/teapot/main.rs | 25 +- examples/src/bin/tessellation.rs | 40 +- examples/src/bin/texture_array/main.rs | 24 +- examples/src/bin/triangle-v1_3.rs | 13 +- examples/src/bin/triangle.rs | 15 +- vulkano/autogen/extensions.rs | 4 +- vulkano/autogen/features.rs | 4 +- vulkano/src/command_buffer/auto/builder.rs | 84 +- .../src/command_buffer/commands/bind_push.rs | 8 +- .../command_buffer/commands/dynamic_state.rs | 8 +- .../src/command_buffer/commands/pipeline.rs | 405 ++++--- vulkano/src/format.rs | 2 +- vulkano/src/macros.rs | 4 +- vulkano/src/pipeline/graphics/color_blend.rs | 187 +-- .../src/pipeline/graphics/depth_stencil.rs | 450 ++----- .../pipeline/graphics/discard_rectangle.rs | 56 +- .../src/pipeline/graphics/input_assembly.rs | 355 +++--- vulkano/src/pipeline/graphics/mod.rs | 1066 +++++------------ vulkano/src/pipeline/graphics/multisample.rs | 34 +- .../src/pipeline/graphics/rasterization.rs | 302 ++--- vulkano/src/pipeline/graphics/tessellation.rs | 100 +- .../pipeline/graphics/vertex_input/buffers.rs | 2 +- .../graphics/vertex_input/impl_vertex.rs | 2 +- vulkano/src/pipeline/graphics/viewport.rs | 323 ++--- vulkano/src/pipeline/mod.rs | 346 ++++-- 47 files changed, 1848 insertions(+), 2432 deletions(-) diff --git a/examples/src/bin/async-update.rs b/examples/src/bin/async-update.rs index dc9182983f..1df714b943 100644 --- a/examples/src/bin/async-update.rs +++ b/examples/src/bin/async-update.rs @@ -71,7 +71,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::RasterizationState, @@ -80,7 +80,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, @@ -456,13 +456,18 @@ fn main() { GraphicsPipelineCreateInfo { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some( - InputAssemblyState::new().topology(PrimitiveTopology::TriangleStrip), - ), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + input_assembly_state: Some(InputAssemblyState { + topology: PrimitiveTopology::TriangleStrip, + ..Default::default() + }), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/buffer-allocator.rs b/examples/src/bin/buffer-allocator.rs index fa7088e843..c9a708b1f5 100644 --- a/examples/src/bin/buffer-allocator.rs +++ b/examples/src/bin/buffer-allocator.rs @@ -31,7 +31,7 @@ use vulkano::{ memory::allocator::{MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -40,7 +40,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, swapchain::{ @@ -253,10 +253,14 @@ fn main() { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/deferred/frame/ambient_lighting_system.rs b/examples/src/bin/deferred/frame/ambient_lighting_system.rs index 53536cfd56..443a4547be 100644 --- a/examples/src/bin/deferred/frame/ambient_lighting_system.rs +++ b/examples/src/bin/deferred/frame/ambient_lighting_system.rs @@ -22,7 +22,9 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::{AttachmentBlend, BlendFactor, BlendOp, ColorBlendState}, + color_blend::{ + AttachmentBlend, BlendFactor, BlendOp, ColorBlendAttachmentState, ColorBlendState, + }, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -31,7 +33,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::Subpass, @@ -118,21 +120,24 @@ impl AmbientLightingSystem { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend( - AttachmentBlend { + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend { color_blend_op: BlendOp::Add, src_color_blend_factor: BlendFactor::One, dst_color_blend_factor: BlendFactor::One, alpha_blend_op: BlendOp::Max, src_alpha_blend_factor: BlendFactor::One, dst_alpha_blend_factor: BlendFactor::One, - }, - ), - ), + }), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.clone().into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/deferred/frame/directional_lighting_system.rs b/examples/src/bin/deferred/frame/directional_lighting_system.rs index 802fd559fc..67b1fa6df6 100644 --- a/examples/src/bin/deferred/frame/directional_lighting_system.rs +++ b/examples/src/bin/deferred/frame/directional_lighting_system.rs @@ -23,7 +23,9 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::{AttachmentBlend, BlendFactor, BlendOp, ColorBlendState}, + color_blend::{ + AttachmentBlend, BlendFactor, BlendOp, ColorBlendAttachmentState, ColorBlendState, + }, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -32,7 +34,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::Subpass, @@ -119,21 +121,24 @@ impl DirectionalLightingSystem { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend( - AttachmentBlend { + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend { color_blend_op: BlendOp::Add, src_color_blend_factor: BlendFactor::One, dst_color_blend_factor: BlendFactor::One, alpha_blend_op: BlendOp::Max, src_alpha_blend_factor: BlendFactor::One, dst_alpha_blend_factor: BlendFactor::One, - }, - ), - ), + }), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.clone().into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/deferred/frame/point_lighting_system.rs b/examples/src/bin/deferred/frame/point_lighting_system.rs index 3e9b0b2733..b8e89fdb1d 100644 --- a/examples/src/bin/deferred/frame/point_lighting_system.rs +++ b/examples/src/bin/deferred/frame/point_lighting_system.rs @@ -23,7 +23,9 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::{AttachmentBlend, BlendFactor, BlendOp, ColorBlendState}, + color_blend::{ + AttachmentBlend, BlendFactor, BlendOp, ColorBlendAttachmentState, ColorBlendState, + }, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -32,7 +34,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::Subpass, @@ -118,21 +120,24 @@ impl PointLightingSystem { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend( - AttachmentBlend { + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend { color_blend_op: BlendOp::Add, src_color_blend_factor: BlendFactor::One, dst_color_blend_factor: BlendFactor::One, alpha_blend_op: BlendOp::Max, src_alpha_blend_factor: BlendFactor::One, dst_alpha_blend_factor: BlendFactor::One, - }, - ), - ), + }), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.clone().into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/deferred/triangle_draw_system.rs b/examples/src/bin/deferred/triangle_draw_system.rs index 9a47416d1c..083c68f2ff 100644 --- a/examples/src/bin/deferred/triangle_draw_system.rs +++ b/examples/src/bin/deferred/triangle_draw_system.rs @@ -18,8 +18,8 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, - depth_stencil::DepthStencilState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, + depth_stencil::{DepthState, DepthStencilState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -28,7 +28,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::Subpass, }; @@ -107,11 +107,18 @@ impl TriangleDrawSystem { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), - depth_stencil_state: Some(DepthStencilState::simple_depth_test()), + depth_stencil_state: Some(DepthStencilState { + depth: Some(DepthState::simple()), + ..Default::default() + }), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.clone().into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/gl-interop.rs b/examples/src/bin/gl-interop.rs index 8bc1faaead..45d88b1db2 100644 --- a/examples/src/bin/gl-interop.rs +++ b/examples/src/bin/gl-interop.rs @@ -48,7 +48,7 @@ mod linux { }, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::RasterizationState, @@ -57,7 +57,7 @@ mod linux { GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, @@ -688,15 +688,21 @@ mod linux { GraphicsPipelineCreateInfo { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some( - InputAssemblyState::new().topology(PrimitiveTopology::TriangleStrip), - ), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + input_assembly_state: Some(InputAssemblyState { + topology: PrimitiveTopology::TriangleStrip, + ..Default::default() + }), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend_alpha(), - ), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend::alpha()), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/image-self-copy-blit/main.rs b/examples/src/bin/image-self-copy-blit/main.rs index a33c31b3bb..2dbff95efe 100644 --- a/examples/src/bin/image-self-copy-blit/main.rs +++ b/examples/src/bin/image-self-copy-blit/main.rs @@ -32,7 +32,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::RasterizationState, @@ -41,7 +41,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, @@ -363,15 +363,21 @@ fn main() { GraphicsPipelineCreateInfo { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some( - InputAssemblyState::new().topology(PrimitiveTopology::TriangleStrip), - ), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + input_assembly_state: Some(InputAssemblyState { + topology: PrimitiveTopology::TriangleStrip, + ..Default::default() + }), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend_alpha(), - ), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend::alpha()), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/image/main.rs b/examples/src/bin/image/main.rs index 485e3977d8..10d3fba7ca 100644 --- a/examples/src/bin/image/main.rs +++ b/examples/src/bin/image/main.rs @@ -31,7 +31,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::RasterizationState, @@ -40,7 +40,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, @@ -311,15 +311,21 @@ fn main() { GraphicsPipelineCreateInfo { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some( - InputAssemblyState::new().topology(PrimitiveTopology::TriangleStrip), - ), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + input_assembly_state: Some(InputAssemblyState { + topology: PrimitiveTopology::TriangleStrip, + ..Default::default() + }), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend_alpha(), - ), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend::alpha()), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/immutable-sampler/main.rs b/examples/src/bin/immutable-sampler/main.rs index 3153ae08b1..3ea590d81f 100644 --- a/examples/src/bin/immutable-sampler/main.rs +++ b/examples/src/bin/immutable-sampler/main.rs @@ -40,7 +40,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::RasterizationState, @@ -49,7 +49,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, @@ -329,15 +329,21 @@ fn main() { GraphicsPipelineCreateInfo { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some( - InputAssemblyState::new().topology(PrimitiveTopology::TriangleStrip), - ), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + input_assembly_state: Some(InputAssemblyState { + topology: PrimitiveTopology::TriangleStrip, + ..Default::default() + }), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend_alpha(), - ), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend::alpha()), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/indirect.rs b/examples/src/bin/indirect.rs index e434db9a06..bde6c9d942 100644 --- a/examples/src/bin/indirect.rs +++ b/examples/src/bin/indirect.rs @@ -46,7 +46,7 @@ use vulkano::{ pipeline::{ compute::ComputePipelineCreateInfo, graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -55,8 +55,8 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - ComputePipeline, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, - PipelineShaderStageCreateInfo, + ComputePipeline, DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, + PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, single_pass_renderpass, @@ -346,10 +346,14 @@ fn main() { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/instancing.rs b/examples/src/bin/instancing.rs index 0e48d03fcb..6cd95f5261 100644 --- a/examples/src/bin/instancing.rs +++ b/examples/src/bin/instancing.rs @@ -28,7 +28,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -37,7 +37,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, single_pass_renderpass, @@ -323,10 +323,14 @@ fn main() { // types are expected to be used. vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/interactive_fractal/pixels_draw_pipeline.rs b/examples/src/bin/interactive_fractal/pixels_draw_pipeline.rs index 9a24aea597..4fdc5595fc 100644 --- a/examples/src/bin/interactive_fractal/pixels_draw_pipeline.rs +++ b/examples/src/bin/interactive_fractal/pixels_draw_pipeline.rs @@ -25,7 +25,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -34,7 +34,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::Subpass, @@ -155,10 +155,14 @@ impl PixelsDrawPipeline { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.clone().into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/msaa-renderpass.rs b/examples/src/bin/msaa-renderpass.rs index 9515b0bc35..d83026eaf5 100644 --- a/examples/src/bin/msaa-renderpass.rs +++ b/examples/src/bin/msaa-renderpass.rs @@ -79,7 +79,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -88,7 +88,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, Subpass}, sync::GpuFuture, @@ -345,13 +345,17 @@ fn main() { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState { rasterization_samples: subpass.num_samples().unwrap(), ..Default::default() }), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/multi-window.rs b/examples/src/bin/multi-window.rs index 9506f58171..c210fa807b 100644 --- a/examples/src/bin/multi-window.rs +++ b/examples/src/bin/multi-window.rs @@ -32,7 +32,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -41,7 +41,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, swapchain::{ @@ -291,10 +291,14 @@ fn main() { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/multi_window_game_of_life/pixels_draw.rs b/examples/src/bin/multi_window_game_of_life/pixels_draw.rs index 85d4e8fbc7..08280b1837 100644 --- a/examples/src/bin/multi_window_game_of_life/pixels_draw.rs +++ b/examples/src/bin/multi_window_game_of_life/pixels_draw.rs @@ -26,7 +26,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -35,7 +35,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::Subpass, @@ -151,10 +151,14 @@ impl PixelsDrawPipeline { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.clone().into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/multiview.rs b/examples/src/bin/multiview.rs index 19e61e9fc0..5e73c2f526 100644 --- a/examples/src/bin/multiview.rs +++ b/examples/src/bin/multiview.rs @@ -32,7 +32,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -291,16 +291,22 @@ fn main() { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_fixed_scissor_irrelevant([ - Viewport { + viewport_state: Some(ViewportState { + viewports: [Viewport { offset: [0.0, 0.0], extent: [image.extent()[0] as f32, image.extent()[1] as f32], depth_range: 0.0..=1.0, - }, - ])), + }] + .into_iter() + .collect(), + ..Default::default() + }), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/occlusion-query.rs b/examples/src/bin/occlusion-query.rs index 8d85df8307..cde850e0cb 100644 --- a/examples/src/bin/occlusion-query.rs +++ b/examples/src/bin/occlusion-query.rs @@ -28,8 +28,8 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, - depth_stencil::DepthStencilState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, + depth_stencil::{DepthState, DepthStencilState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -38,7 +38,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, query::{QueryControlFlags, QueryPool, QueryPoolCreateInfo, QueryResultFlags, QueryType}, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, @@ -332,14 +332,21 @@ fn main() { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), // Enable depth testing, which is needed for occlusion queries to make sense at all. If you // disable depth testing, every pixel is considered to pass the depth test, so every query // will return a nonzero result. - depth_stencil_state: Some(DepthStencilState::simple_depth_test()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + depth_stencil_state: Some(DepthStencilState { + depth: Some(DepthState::simple()), + ..Default::default() + }), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/push-descriptors/main.rs b/examples/src/bin/push-descriptors/main.rs index b0d4f3868b..331420674e 100644 --- a/examples/src/bin/push-descriptors/main.rs +++ b/examples/src/bin/push-descriptors/main.rs @@ -29,7 +29,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::RasterizationState, @@ -38,7 +38,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, @@ -314,15 +314,21 @@ fn main() { GraphicsPipelineCreateInfo { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some( - InputAssemblyState::new().topology(PrimitiveTopology::TriangleStrip), - ), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + input_assembly_state: Some(InputAssemblyState { + topology: PrimitiveTopology::TriangleStrip, + ..Default::default() + }), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend_alpha(), - ), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend::alpha()), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/runtime-shader/main.rs b/examples/src/bin/runtime-shader/main.rs index 7333e5d0f3..07c23acb6b 100644 --- a/examples/src/bin/runtime-shader/main.rs +++ b/examples/src/bin/runtime-shader/main.rs @@ -37,7 +37,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::{CullMode, FrontFace, RasterizationState}, @@ -46,7 +46,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, shader::{ShaderModule, ShaderModuleCreateInfo}, @@ -219,14 +219,18 @@ fn main() { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), - rasterization_state: Some( - RasterizationState::new() - .cull_mode(CullMode::Front) - .front_face(FrontFace::CounterClockwise), - ), + viewport_state: Some(ViewportState::default()), + rasterization_state: Some(RasterizationState { + cull_mode: CullMode::Front, + front_face: FrontFace::CounterClockwise, + ..Default::default() + }), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/runtime_array/main.rs b/examples/src/bin/runtime_array/main.rs index 37c26aada2..45743f6323 100644 --- a/examples/src/bin/runtime_array/main.rs +++ b/examples/src/bin/runtime_array/main.rs @@ -32,7 +32,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -41,7 +41,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, @@ -435,12 +435,17 @@ fn main() { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend_alpha(), - ), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend::alpha()), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/simple-particles.rs b/examples/src/bin/simple-particles.rs index 810d3b50d1..55ffd7fc4b 100644 --- a/examples/src/bin/simple-particles.rs +++ b/examples/src/bin/simple-particles.rs @@ -32,7 +32,7 @@ use vulkano::{ pipeline::{ compute::ComputePipelineCreateInfo, graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::RasterizationState, @@ -455,13 +455,6 @@ fn main() { ) .unwrap(); - // Fixed viewport. - let viewport = Viewport { - offset: [0.0, 0.0], - extent: [WINDOW_WIDTH as f32, WINDOW_HEIGHT as f32], - depth_range: 0.0..=1.0, - }; - // Create a basic graphics pipeline for rendering particles. let graphics_pipeline = { let vs = vs::load(device.clone()) @@ -494,13 +487,26 @@ fn main() { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), // Vertices will be rendered as a list of points. - input_assembly_state: Some( - InputAssemblyState::new().topology(PrimitiveTopology::PointList), - ), - viewport_state: Some(ViewportState::viewport_fixed_scissor_irrelevant([viewport])), + input_assembly_state: Some(InputAssemblyState { + topology: PrimitiveTopology::PointList, + ..Default::default() + }), + viewport_state: Some(ViewportState { + viewports: [Viewport { + offset: [0.0, 0.0], + extent: [WINDOW_WIDTH as f32, WINDOW_HEIGHT as f32], + depth_range: 0.0..=1.0, + }] + .into_iter() + .collect(), + ..Default::default() + }), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/teapot/main.rs b/examples/src/bin/teapot/main.rs index 8223d41237..7f133f16f3 100644 --- a/examples/src/bin/teapot/main.rs +++ b/examples/src/bin/teapot/main.rs @@ -32,8 +32,8 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, - depth_stencil::DepthStencilState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, + depth_stencil::{DepthState, DepthStencilState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -504,17 +504,26 @@ fn window_size_dependent_setup( stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::viewport_fixed_scissor_irrelevant([ - Viewport { + viewport_state: Some(ViewportState { + viewports: [Viewport { offset: [0.0, 0.0], extent: [extent[0] as f32, extent[1] as f32], depth_range: 0.0..=1.0, - }, - ])), + }] + .into_iter() + .collect(), + ..Default::default() + }), rasterization_state: Some(RasterizationState::default()), - depth_stencil_state: Some(DepthStencilState::simple_depth_test()), + depth_stencil_state: Some(DepthStencilState { + depth: Some(DepthState::simple()), + ..Default::default() + }), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/tessellation.rs b/examples/src/bin/tessellation.rs index a53295ae6a..eff10e9b62 100644 --- a/examples/src/bin/tessellation.rs +++ b/examples/src/bin/tessellation.rs @@ -37,7 +37,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::{PolygonMode, RasterizationState}, @@ -47,7 +47,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, swapchain::{ @@ -373,22 +373,28 @@ fn main() { GraphicsPipelineCreateInfo { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some( - InputAssemblyState::new().topology(PrimitiveTopology::PatchList), - ), - tessellation_state: Some( - TessellationState::new() - // Use a patch_control_points of 3, because we want to convert one *triangle* - // into lots of little ones. - // A value of 4 would convert a *rectangle* into lots of little triangles. - .patch_control_points(3), - ), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), - rasterization_state: Some( - RasterizationState::new().polygon_mode(PolygonMode::Line), - ), + input_assembly_state: Some(InputAssemblyState { + topology: PrimitiveTopology::PatchList, + ..Default::default() + }), + tessellation_state: Some(TessellationState { + // Use a patch_control_points of 3, because we want to convert one *triangle* + // into lots of little ones. + // A value of 4 would convert a *rectangle* into lots of little triangles. + patch_control_points: 3, + ..Default::default() + }), + viewport_state: Some(ViewportState::default()), + rasterization_state: Some(RasterizationState { + polygon_mode: PolygonMode::Line, + ..Default::default() + }), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/texture_array/main.rs b/examples/src/bin/texture_array/main.rs index 2ceda9a59b..9f836f084b 100644 --- a/examples/src/bin/texture_array/main.rs +++ b/examples/src/bin/texture_array/main.rs @@ -31,7 +31,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState}, input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::RasterizationState, @@ -40,7 +40,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, @@ -322,15 +322,21 @@ fn main() { GraphicsPipelineCreateInfo { stages: stages.into_iter().collect(), vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some( - InputAssemblyState::new().topology(PrimitiveTopology::TriangleStrip), - ), - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + input_assembly_state: Some(InputAssemblyState { + topology: PrimitiveTopology::TriangleStrip, + ..Default::default() + }), + viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - color_blend_state: Some( - ColorBlendState::new(subpass.num_color_attachments()).blend_alpha(), - ), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState { + blend: Some(AttachmentBlend::alpha()), + ..Default::default() + }, + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/triangle-v1_3.rs b/examples/src/bin/triangle-v1_3.rs index cd550e036d..9a3e3464c3 100644 --- a/examples/src/bin/triangle-v1_3.rs +++ b/examples/src/bin/triangle-v1_3.rs @@ -37,7 +37,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -47,7 +47,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{AttachmentLoadOp, AttachmentStoreOp}, swapchain::{ @@ -449,7 +449,7 @@ fn main() { input_assembly_state: Some(InputAssemblyState::default()), // How primitives are transformed and clipped to fit the framebuffer. // We use a resizable viewport, set to draw over the entire window. - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), // How polygons are culled and converted into a raster of pixels. // The default value does not perform any culling. rasterization_state: Some(RasterizationState::default()), @@ -458,9 +458,14 @@ fn main() { multisample_state: Some(MultisampleState::default()), // How pixel values are combined with the values already present in the framebuffer. // The default value overwrites the old value with the new one, without any blending. - color_blend_state: Some(ColorBlendState::new( + color_blend_state: Some(ColorBlendState::with_attachment_states( subpass.color_attachment_formats.len() as u32, + ColorBlendAttachmentState::default(), )), + // Dynamic states allows us to specify parts of the pipeline settings when + // recording the command buffer, before we perform drawing. + // Here, we specify that the viewport should be dynamic. + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/examples/src/bin/triangle.rs b/examples/src/bin/triangle.rs index b3912843a8..872af91d0f 100644 --- a/examples/src/bin/triangle.rs +++ b/examples/src/bin/triangle.rs @@ -32,7 +32,7 @@ use vulkano::{ memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, pipeline::{ graphics::{ - color_blend::ColorBlendState, + color_blend::{ColorBlendAttachmentState, ColorBlendState}, input_assembly::InputAssemblyState, multisample::MultisampleState, rasterization::RasterizationState, @@ -41,7 +41,7 @@ use vulkano::{ GraphicsPipelineCreateInfo, }, layout::PipelineDescriptorSetLayoutCreateInfo, - GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, + DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo, }, render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}, swapchain::{ @@ -446,7 +446,7 @@ fn main() { input_assembly_state: Some(InputAssemblyState::default()), // How primitives are transformed and clipped to fit the framebuffer. // We use a resizable viewport, set to draw over the entire window. - viewport_state: Some(ViewportState::viewport_dynamic_scissor_irrelevant()), + viewport_state: Some(ViewportState::default()), // How polygons are culled and converted into a raster of pixels. // The default value does not perform any culling. rasterization_state: Some(RasterizationState::default()), @@ -455,7 +455,14 @@ fn main() { multisample_state: Some(MultisampleState::default()), // How pixel values are combined with the values already present in the framebuffer. // The default value overwrites the old value with the new one, without any blending. - color_blend_state: Some(ColorBlendState::new(subpass.num_color_attachments())), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.num_color_attachments(), + ColorBlendAttachmentState::default(), + )), + // Dynamic states allows us to specify parts of the pipeline settings when + // recording the command buffer, before we perform drawing. + // Here, we specify that the viewport should be dynamic. + dynamic_state: [DynamicState::Viewport].into_iter().collect(), subpass: Some(subpass.into()), ..GraphicsPipelineCreateInfo::layout(layout) }, diff --git a/vulkano/autogen/extensions.rs b/vulkano/autogen/extensions.rs index 8df8fac057..8c46ac7339 100644 --- a/vulkano/autogen/extensions.rs +++ b/vulkano/autogen/extensions.rs @@ -575,7 +575,7 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } /// Returns an `Extensions` object with none of the members set. - #[deprecated(since = "0.31.0", note = "Use `empty` instead.")] + #[deprecated(since = "0.31.0", note = "use `empty` instead")] #[inline] pub const fn none() -> Self { Self::empty() @@ -594,7 +594,7 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } /// Returns whether all members in `other` are set in `self`. - #[deprecated(since = "0.31.0", note = "Use `contains` instead.")] + #[deprecated(since = "0.31.0", note = "use `contains` instead")] #[inline] pub const fn is_superset_of(&self, other: &Self) -> bool { self.contains(other) diff --git a/vulkano/autogen/features.rs b/vulkano/autogen/features.rs index 59f2352342..70a35ae21e 100644 --- a/vulkano/autogen/features.rs +++ b/vulkano/autogen/features.rs @@ -306,7 +306,7 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { } /// Returns an `Features` object with none of the members set. - #[deprecated(since = "0.31.0", note = "Use `empty` instead.")] + #[deprecated(since = "0.31.0", note = "use `empty` instead")] #[inline] pub const fn none() -> Self { Self::empty() @@ -334,7 +334,7 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { } /// Returns whether all members in `other` are set in `self`. - #[deprecated(since = "0.31.0", note = "Use `contains` instead.")] + #[deprecated(since = "0.31.0", note = "use `contains` instead")] #[inline] pub const fn is_superset_of(&self, other: &Self) -> bool { self.contains(other) diff --git a/vulkano/src/command_buffer/auto/builder.rs b/vulkano/src/command_buffer/auto/builder.rs index 19492cd961..854ed72771 100644 --- a/vulkano/src/command_buffer/auto/builder.rs +++ b/vulkano/src/command_buffer/auto/builder.rs @@ -31,7 +31,7 @@ use crate::{ color_blend::LogicOp, depth_stencil::{CompareOp, StencilOps}, input_assembly::PrimitiveTopology, - rasterization::{CullMode, DepthBias, FrontFace, LineStipple}, + rasterization::{CullMode, DepthBiasState, FrontFace, LineStipple}, subpass::PipelineRenderingCreateInfo, viewport::{Scissor, Viewport}, }, @@ -1337,7 +1337,7 @@ pub(in crate::command_buffer) struct CommandBufferBuilderState { pub(in crate::command_buffer) blend_constants: Option<[f32; 4]>, pub(in crate::command_buffer) color_write_enable: Option>, pub(in crate::command_buffer) cull_mode: Option, - pub(in crate::command_buffer) depth_bias: Option, + pub(in crate::command_buffer) depth_bias: Option, pub(in crate::command_buffer) depth_bias_enable: Option, pub(in crate::command_buffer) depth_bounds: Option>, pub(in crate::command_buffer) depth_bounds_test_enable: Option, @@ -1392,8 +1392,8 @@ impl CommandBufferBuilderState { DynamicState::DepthTestEnable => self.depth_test_enable = None, DynamicState::DepthWriteEnable => self.depth_write_enable = None, DynamicState::DiscardRectangle => self.discard_rectangle.clear(), - DynamicState::ExclusiveScissor => (), // TODO; - DynamicState::FragmentShadingRate => (), // TODO: + // DynamicState::ExclusiveScissor => todo!(), + // DynamicState::FragmentShadingRate => todo!(), DynamicState::FrontFace => self.front_face = None, DynamicState::LineStipple => self.line_stipple = None, DynamicState::LineWidth => self.line_width = None, @@ -1402,8 +1402,8 @@ impl CommandBufferBuilderState { DynamicState::PrimitiveRestartEnable => self.primitive_restart_enable = None, DynamicState::PrimitiveTopology => self.primitive_topology = None, DynamicState::RasterizerDiscardEnable => self.rasterizer_discard_enable = None, - DynamicState::RayTracingPipelineStackSize => (), // TODO: - DynamicState::SampleLocations => (), // TODO: + // DynamicState::RayTracingPipelineStackSize => todo!(), + // DynamicState::SampleLocations => todo!(), DynamicState::Scissor => self.scissor.clear(), DynamicState::ScissorWithCount => self.scissor_with_count = None, DynamicState::StencilCompareMask => self.stencil_compare_mask = Default::default(), @@ -1411,44 +1411,44 @@ impl CommandBufferBuilderState { DynamicState::StencilReference => self.stencil_reference = Default::default(), DynamicState::StencilTestEnable => self.stencil_test_enable = None, DynamicState::StencilWriteMask => self.stencil_write_mask = Default::default(), - DynamicState::VertexInput => (), // TODO: - DynamicState::VertexInputBindingStride => (), // TODO: + // DynamicState::VertexInput => todo!(), + // DynamicState::VertexInputBindingStride => todo!(), DynamicState::Viewport => self.viewport.clear(), - DynamicState::ViewportCoarseSampleOrder => (), // TODO: - DynamicState::ViewportShadingRatePalette => (), // TODO: - DynamicState::ViewportWScaling => (), // TODO: + // DynamicState::ViewportCoarseSampleOrder => todo!(), + // DynamicState::ViewportShadingRatePalette => todo!(), + // DynamicState::ViewportWScaling => todo!(), DynamicState::ViewportWithCount => self.viewport_with_count = None, - DynamicState::TessellationDomainOrigin => (), // TODO: - DynamicState::DepthClampEnable => (), // TODO: - DynamicState::PolygonMode => (), // TODO: - DynamicState::RasterizationSamples => (), // TODO: - DynamicState::SampleMask => (), // TODO: - DynamicState::AlphaToCoverageEnable => (), // TODO: - DynamicState::AlphaToOneEnable => (), // TODO: - DynamicState::LogicOpEnable => (), // TODO: - DynamicState::ColorBlendEnable => (), // TODO: - DynamicState::ColorBlendEquation => (), // TODO: - DynamicState::ColorWriteMask => (), // TODO: - DynamicState::RasterizationStream => (), // TODO: - DynamicState::ConservativeRasterizationMode => (), // TODO: - DynamicState::ExtraPrimitiveOverestimationSize => (), // TODO: - DynamicState::DepthClipEnable => (), // TODO: - DynamicState::SampleLocationsEnable => (), // TODO: - DynamicState::ColorBlendAdvanced => (), // TODO: - DynamicState::ProvokingVertexMode => (), // TODO: - DynamicState::LineRasterizationMode => (), // TODO: - DynamicState::LineStippleEnable => (), // TODO: - DynamicState::DepthClipNegativeOneToOne => (), // TODO: - DynamicState::ViewportWScalingEnable => (), // TODO: - DynamicState::ViewportSwizzle => (), // TODO: - DynamicState::CoverageToColorEnable => (), // TODO: - DynamicState::CoverageToColorLocation => (), // TODO: - DynamicState::CoverageModulationMode => (), // TODO: - DynamicState::CoverageModulationTableEnable => (), // TODO: - DynamicState::CoverageModulationTable => (), // TODO: - DynamicState::ShadingRateImageEnable => (), // TODO: - DynamicState::RepresentativeFragmentTestEnable => (), // TODO: - DynamicState::CoverageReductionMode => (), // TODO: + // DynamicState::TessellationDomainOrigin => todo!(), + // DynamicState::DepthClampEnable => todo!(), + // DynamicState::PolygonMode => todo!(), + // DynamicState::RasterizationSamples => todo!(), + // DynamicState::SampleMask => todo!(), + // DynamicState::AlphaToCoverageEnable => todo!(), + // DynamicState::AlphaToOneEnable => todo!(), + // DynamicState::LogicOpEnable => todo!(), + // DynamicState::ColorBlendEnable => todo!(), + // DynamicState::ColorBlendEquation => todo!(), + // DynamicState::ColorWriteMask => todo!(), + // DynamicState::RasterizationStream => todo!(), + // DynamicState::ConservativeRasterizationMode => todo!(), + // DynamicState::ExtraPrimitiveOverestimationSize => todo!(), + // DynamicState::DepthClipEnable => todo!(), + // DynamicState::SampleLocationsEnable => todo!(), + // DynamicState::ColorBlendAdvanced => todo!(), + // DynamicState::ProvokingVertexMode => todo!(), + // DynamicState::LineRasterizationMode => todo!(), + // DynamicState::LineStippleEnable => todo!(), + // DynamicState::DepthClipNegativeOneToOne => todo!(), + // DynamicState::ViewportWScalingEnable => todo!(), + // DynamicState::ViewportSwizzle => todo!(), + // DynamicState::CoverageToColorEnable => todo!(), + // DynamicState::CoverageToColorLocation => todo!(), + // DynamicState::CoverageModulationMode => todo!(), + // DynamicState::CoverageModulationTableEnable => todo!(), + // DynamicState::CoverageModulationTable => todo!(), + // DynamicState::ShadingRateImageEnable => todo!(), + // DynamicState::RepresentativeFragmentTestEnable => todo!(), + // DynamicState::CoverageReductionMode => todo!(), } } } diff --git a/vulkano/src/command_buffer/commands/bind_push.rs b/vulkano/src/command_buffer/commands/bind_push.rs index 8e6a9e3b36..cdcda8c430 100644 --- a/vulkano/src/command_buffer/commands/bind_push.rs +++ b/vulkano/src/command_buffer/commands/bind_push.rs @@ -226,12 +226,8 @@ where ) -> &mut Self { // Reset any states that are fixed in the new pipeline. The pipeline bind command will // overwrite these states. - self.builder_state.reset_dynamic_states( - pipeline - .dynamic_states() - .filter(|(_, d)| !d) // not dynamic - .map(|(s, _)| s), - ); + self.builder_state + .reset_dynamic_states(pipeline.fixed_state().iter().copied()); self.builder_state.pipeline_graphics = Some(pipeline.clone()); self.add_command( "bind_pipeline_graphics", diff --git a/vulkano/src/command_buffer/commands/dynamic_state.rs b/vulkano/src/command_buffer/commands/dynamic_state.rs index 6b267a9256..43286de851 100644 --- a/vulkano/src/command_buffer/commands/dynamic_state.rs +++ b/vulkano/src/command_buffer/commands/dynamic_state.rs @@ -18,7 +18,7 @@ use crate::{ color_blend::LogicOp, depth_stencil::{CompareOp, StencilFaces, StencilOp, StencilOps}, input_assembly::PrimitiveTopology, - rasterization::{CullMode, DepthBias, FrontFace, LineStipple}, + rasterization::{CullMode, DepthBiasState, FrontFace, LineStipple}, viewport::{Scissor, Viewport}, }, DynamicState, @@ -44,9 +44,7 @@ where .builder_state .pipeline_graphics .as_ref() - .map_or(false, |pipeline| { - matches!(pipeline.dynamic_state(state), Some(false)) - }) + .map_or(false, |pipeline| pipeline.fixed_state().contains(&state)) { return Err(Box::new(ValidationError { problem: "the state for this value in the currently bound graphics pipeline \ @@ -217,7 +215,7 @@ where clamp: f32, slope_factor: f32, ) -> &mut Self { - self.builder_state.depth_bias = Some(DepthBias { + self.builder_state.depth_bias = Some(DepthBiasState { constant_factor, clamp, slope_factor, diff --git a/vulkano/src/command_buffer/commands/pipeline.rs b/vulkano/src/command_buffer/commands/pipeline.rs index 18bfd750a2..d5d8aaeb39 100644 --- a/vulkano/src/command_buffer/commands/pipeline.rs +++ b/vulkano/src/command_buffer/commands/pipeline.rs @@ -29,7 +29,7 @@ use crate::{ input_assembly::PrimitiveTopology, subpass::PipelineSubpassType, vertex_input::VertexInputRate, }, - DynamicState, GraphicsPipeline, PartialStateMode, Pipeline, PipelineLayout, + DynamicState, GraphicsPipeline, Pipeline, PipelineLayout, }, shader::{DescriptorBindingRequirements, DescriptorIdentifier, ShaderStage, ShaderStages}, sync::{PipelineStageAccess, PipelineStageAccessFlags}, @@ -1519,11 +1519,7 @@ where ) -> Result<(), Box> { let device = pipeline.device(); - for dynamic_state in pipeline - .dynamic_states() - .filter(|(_, d)| *d) - .map(|(s, _)| s) - { + for dynamic_state in pipeline.dynamic_state().iter().copied() { match dynamic_state { DynamicState::BlendConstants => { if self.builder_state.blend_constants.is_none() { @@ -1534,7 +1530,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07835"), ..Default::default() })); @@ -1551,7 +1548,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07749"), ..Default::default() })); @@ -1579,7 +1577,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07840"), ..Default::default() })); @@ -1594,7 +1593,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07834"), ..Default::default() })); @@ -1609,7 +1609,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-04877"), ..Default::default() })); @@ -1624,7 +1625,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07836"), ..Default::default() })); @@ -1639,7 +1641,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07846"), ..Default::default() })); @@ -1654,7 +1657,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07845"), ..Default::default() })); @@ -1669,7 +1673,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07843"), ..Default::default() })); @@ -1684,20 +1689,17 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07844"), ..Default::default() })); } } DynamicState::DiscardRectangle => { - let discard_rectangle_count = - match pipeline.discard_rectangle_state().unwrap().rectangles { - PartialStateMode::Dynamic(count) => count, - _ => unreachable!(), - }; - - for num in 0..discard_rectangle_count { + for num in + 0..pipeline.discard_rectangle_state().unwrap().rectangles.len() as u32 + { if !self.builder_state.discard_rectangle.contains_key(&num) { return Err(Box::new(ValidationError { problem: format!( @@ -1707,15 +1709,16 @@ where it was overwritten by a more recent \ `bind_pipeline_graphics` command", dynamic_state, num, - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07751"), ..Default::default() })); } } } - DynamicState::ExclusiveScissor => todo!(), - DynamicState::FragmentShadingRate => todo!(), + // DynamicState::ExclusiveScissor => todo!(), + // DynamicState::FragmentShadingRate => todo!(), DynamicState::FrontFace => { if self.builder_state.front_face.is_none() { return Err(Box::new(ValidationError { @@ -1725,7 +1728,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-0784"), ..Default::default() })); @@ -1740,7 +1744,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07849"), ..Default::default() })); @@ -1755,7 +1760,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07833"), ..Default::default() })); @@ -1770,7 +1776,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "logicOp-04878"), ..Default::default() })); @@ -1785,7 +1792,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-04875"), ..Default::default() })); @@ -1803,31 +1811,34 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-04879"), ..Default::default() })); }; if primitive_restart_enable { - let topology = match pipeline.input_assembly_state().topology { - PartialStateMode::Fixed(topology) => topology, - PartialStateMode::Dynamic(_) => { - if let Some(topology) = self.builder_state.primitive_topology { - topology - } else { - return Err(Box::new(ValidationError { - problem: "the currently bound graphics pipeline requires \ - the `DynamicState::PrimitiveTopology` dynamic state, \ - but this state was either not set, or it was \ - overwritten by a more recent `bind_pipeline_graphics` \ - command" - .into(), - vuids: vuids!(vuid_type, "None-07842"), - ..Default::default() - })); - } + let topology = if pipeline + .dynamic_state() + .contains(&DynamicState::PrimitiveTopology) + { + if let Some(topology) = self.builder_state.primitive_topology { + topology + } else { + return Err(Box::new(ValidationError { + problem: "the currently bound graphics pipeline requires \ + the `DynamicState::PrimitiveTopology` dynamic state, \ + but this state was either not set, or it was \ + overwritten by a more recent `bind_pipeline_graphics` \ + command" + .into(), + vuids: vuids!(vuid_type, "None-07842"), + ..Default::default() + })); } + } else { + pipeline.input_assembly_state().topology }; match topology { @@ -1843,7 +1854,9 @@ where dynamic primitive topology is \ `PrimitiveTopology::*List`" .into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature("primitive_topology_list_restart")])]), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ + Requires::Feature("primitive_topology_list_restart"), + ])]), // vuids? ..Default::default() })); @@ -1860,7 +1873,11 @@ where dynamic primitive topology is \ `PrimitiveTopology::PatchList`" .into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature("primitive_topology_patch_list_restart")])]), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ + Requires::Feature( + "primitive_topology_patch_list_restart", + ), + ])]), // vuids? ..Default::default() })); @@ -1881,7 +1898,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07842"), ..Default::default() })); @@ -1896,7 +1914,8 @@ where includes tessellation shader stages, but the dynamic \ primitive topology is not `PrimitiveTopology::PatchList`", dynamic_state - ).into(), + ) + .into(), // vuids? ..Default::default() })); @@ -1910,7 +1929,8 @@ where does not include tessellation shader stages, but the dynamic \ primitive topology is `PrimitiveTopology::PatchList`", dynamic_state - ).into(), + ) + .into(), // vuids? ..Default::default() })); @@ -1919,13 +1939,39 @@ where let properties = device.physical_device().properties(); - if !properties.dynamic_primitive_topology_unrestricted.unwrap_or(false) { - let required_topology_class = match pipeline.input_assembly_state().topology { - PartialStateMode::Dynamic(topology_class) => topology_class, - _ => unreachable!(), - }; + if !properties + .dynamic_primitive_topology_unrestricted + .unwrap_or(false) + { + let is_same_topology_class = matches!( + (topology, pipeline.input_assembly_state().topology), + (PrimitiveTopology::PointList, PrimitiveTopology::PointList) + | ( + PrimitiveTopology::LineList + | PrimitiveTopology::LineStrip + | PrimitiveTopology::LineListWithAdjacency + | PrimitiveTopology::LineStripWithAdjacency, + PrimitiveTopology::LineList + | PrimitiveTopology::LineStrip + | PrimitiveTopology::LineListWithAdjacency + | PrimitiveTopology::LineStripWithAdjacency, + ) + | ( + PrimitiveTopology::TriangleList + | PrimitiveTopology::TriangleStrip + | PrimitiveTopology::TriangleFan + | PrimitiveTopology::TriangleListWithAdjacency + | PrimitiveTopology::TriangleStripWithAdjacency, + PrimitiveTopology::TriangleList + | PrimitiveTopology::TriangleStrip + | PrimitiveTopology::TriangleFan + | PrimitiveTopology::TriangleListWithAdjacency + | PrimitiveTopology::TriangleStripWithAdjacency, + ) + | (PrimitiveTopology::PatchList, PrimitiveTopology::PatchList) + ); - if topology.class() != required_topology_class { + if !is_same_topology_class { return Err(Box::new(ValidationError { problem: format!( "the currently bound graphics pipeline requires the \ @@ -1935,8 +1981,12 @@ where to the same topology class as the topology that the \ graphics pipeline was created with", dynamic_state - ).into(), - vuids: vuids!(vuid_type, "dynamicPrimitiveTopologyUnrestricted-07500"), + ) + .into(), + vuids: vuids!( + vuid_type, + "dynamicPrimitiveTopologyUnrestricted-07500" + ), ..Default::default() })); } @@ -1953,41 +2003,48 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-04876"), ..Default::default() })); } } - DynamicState::RayTracingPipelineStackSize => unreachable!( - "RayTracingPipelineStackSize dynamic state should not occur on a graphics pipeline" - ), - DynamicState::SampleLocations => todo!(), + // DynamicState::RayTracingPipelineStackSize => unreachable!( + // "RayTracingPipelineStackSize dynamic state should not occur on a graphics pipeline" + // ), + // DynamicState::SampleLocations => todo!(), DynamicState::Scissor => { - for num in 0..pipeline.viewport_state().unwrap().count().unwrap() { + let viewport_state = pipeline.viewport_state().unwrap(); + + for num in 0..viewport_state.scissors.len() as u32 { if !self.builder_state.scissor.contains_key(&num) { return Err(Box::new(ValidationError { - problem: format!( - "the currently bound graphics pipeline requires the \ - `DynamicState::{:?}` dynamic state, but \ - this state was either not set, or it was overwritten by a \ - more recent `bind_pipeline_graphics` command", - dynamic_state - ).into(), - vuids: vuids!(vuid_type, "None-07832"), - ..Default::default() - })); + problem: format!( + "the currently bound graphics pipeline requires the \ + `DynamicState::{:?}` dynamic state, but \ + this state was either not set, or it was overwritten by a \ + more recent `bind_pipeline_graphics` command", + dynamic_state + ) + .into(), + vuids: vuids!(vuid_type, "None-07832"), + ..Default::default() + })); } } } DynamicState::ScissorWithCount => { if let Some(scissors) = &self.builder_state.scissor_with_count { - if let Some(viewport_count) = pipeline.viewport_state().unwrap().count() { + let viewport_state = pipeline.viewport_state().unwrap(); + let viewport_count = viewport_state.viewports.len() as u32; + let scissor_count = scissors.len() as u32; + + if viewport_count != 0 { // Check if the counts match, but only if the viewport count is fixed. // If the viewport count is also dynamic, then the // DynamicState::ViewportWithCount match arm will handle it. - - if viewport_count != scissors.len() as u32 { + if viewport_count != scissor_count { return Err(Box::new(ValidationError { problem: "the currently bound graphics pipeline requires the \ `DynamicState::ScissorWithCount` dynamic state, and \ @@ -2008,7 +2065,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "scissorCount-03418", "viewportCount-03419"), ..Default::default() })); @@ -2025,9 +2083,10 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07837"), - ..Default::default() + ..Default::default() // })); } } @@ -2042,7 +2101,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07848"), ..Default::default() })); @@ -2059,7 +2119,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07839"), ..Default::default() })); @@ -2074,7 +2135,8 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07847"), ..Default::default() })); @@ -2091,36 +2153,90 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "None-07838"), ..Default::default() })); } } - DynamicState::VertexInput => todo!(), - DynamicState::VertexInputBindingStride => todo!(), + // DynamicState::VertexInput => todo!(), + // DynamicState::VertexInputBindingStride => todo!(), DynamicState::Viewport => { - for num in 0..pipeline.viewport_state().unwrap().count().unwrap() { + let viewport_state = pipeline.viewport_state().unwrap(); + + for num in 0..viewport_state.viewports.len() as u32 { if !self.builder_state.viewport.contains_key(&num) { return Err(Box::new(ValidationError { - problem: format!( - "the currently bound graphics pipeline requires the \ - `DynamicState::{:?}` dynamic state, but \ - this state was either not set, or it was overwritten by a \ - more recent `bind_pipeline_graphics` command", - dynamic_state - ).into(), - vuids: vuids!(vuid_type, "None-07831"), - ..Default::default() - })); + problem: format!( + "the currently bound graphics pipeline requires the \ + `DynamicState::{:?}` dynamic state, but \ + this state was either not set, or it was overwritten by a \ + more recent `bind_pipeline_graphics` command", + dynamic_state + ) + .into(), + vuids: vuids!(vuid_type, "None-07831"), + ..Default::default() + })); } } } - DynamicState::ViewportCoarseSampleOrder => todo!(), - DynamicState::ViewportShadingRatePalette => todo!(), + // DynamicState::ViewportCoarseSampleOrder => todo!(), + // DynamicState::ViewportShadingRatePalette => todo!(), DynamicState::ViewportWithCount => { - let viewport_count = if let Some(viewports) = &self.builder_state.viewport_with_count { - viewports.len() as u32 + if let Some(viewports) = &self.builder_state.viewport_with_count { + let viewport_state = pipeline.viewport_state().unwrap(); + let scissor_count = viewport_state.scissors.len() as u32; + let viewport_count = viewports.len() as u32; + + if scissor_count != 0 { + if viewport_count != scissor_count { + return Err(Box::new(ValidationError { + problem: "the currently bound graphics pipeline requires the \ + `DynamicState::ViewportWithCount` dynamic state, and \ + not the `DynamicState::ScissorWithCount` dynamic state, \ + but the dynamic scissor count is not equal to the scissor \ + count specified when creating the pipeline" + .into(), + vuids: vuids!(vuid_type, "viewportCount-03417"), + ..Default::default() + })); + } + } else { + if let Some(scissors) = &self.builder_state.scissor_with_count { + if viewport_count != scissors.len() as u32 { + return Err(Box::new(ValidationError { + problem: + "the currently bound graphics pipeline requires both \ + the `DynamicState::ViewportWithCount` and the \ + `DynamicState::ScissorWithCount` dynamic states, but \ + the dynamic scissor count is not equal to the \ + dynamic scissor count " + .into(), + vuids: vuids!(vuid_type, "viewportCount-03419"), + ..Default::default() + })); + } + } else { + return Err(Box::new(ValidationError { + problem: format!( + "the currently bound graphics pipeline requires the \ + `DynamicState::{:?}` dynamic state, but \ + this state was either not set, or it was overwritten by a \ + more recent `bind_pipeline_graphics` command", + dynamic_state + ) + .into(), + vuids: vuids!( + vuid_type, + "scissorCount-03418", + "viewportCount-03419" + ), + ..Default::default() + })); + } + } } else { return Err(Box::new(ValidationError { problem: format!( @@ -2129,54 +2245,11 @@ where this state was either not set, or it was overwritten by a \ more recent `bind_pipeline_graphics` command", dynamic_state - ).into(), + ) + .into(), vuids: vuids!(vuid_type, "viewportCount-03417", "viewportCount-03419"), ..Default::default() })); - }; - - if let Some(scissor_count) = - pipeline.viewport_state().unwrap().count() - { - if viewport_count != scissor_count { - return Err(Box::new(ValidationError { - problem: "the currently bound graphics pipeline requires the \ - `DynamicState::ViewportWithCount` dynamic state, and \ - not the `DynamicState::ScissorWithCount` dynamic state, but \ - the dynamic scissor count is not equal to the scissor count \ - specified when creating the pipeline" - .into(), - vuids: vuids!(vuid_type, "viewportCount-03417"), - ..Default::default() - })); - } - } else { - if let Some(scissors) = &self.builder_state.scissor_with_count { - if viewport_count != scissors.len() as u32 { - return Err(Box::new(ValidationError { - problem: "the currently bound graphics pipeline requires both \ - the `DynamicState::ViewportWithCount` and the \ - `DynamicState::ScissorWithCount` dynamic states, but \ - the dynamic scissor count is not equal to the \ - dynamic scissor count " - .into(), - vuids: vuids!(vuid_type, "viewportCount-03419"), - ..Default::default() - })); - } - } else { - return Err(Box::new(ValidationError { - problem: format!( - "the currently bound graphics pipeline requires the \ - `DynamicState::{:?}` dynamic state, but \ - this state was either not set, or it was overwritten by a \ - more recent `bind_pipeline_graphics` command", - dynamic_state - ).into(), - vuids: vuids!(vuid_type, "scissorCount-03418", "viewportCount-03419"), - ..Default::default() - })); - } } // TODO: VUID-vkCmdDrawIndexed-primitiveFragmentShadingRateWithMultipleViewports-04552 @@ -2188,38 +2261,6 @@ where // command buffer prior to this drawing command, and the viewportCount parameter of // vkCmdSetViewportWithCountEXT must be 1 } - DynamicState::ViewportWScaling => todo!(), - DynamicState::TessellationDomainOrigin => todo!(), - DynamicState::DepthClampEnable => todo!(), - DynamicState::PolygonMode => todo!(), - DynamicState::RasterizationSamples => todo!(), - DynamicState::SampleMask => todo!(), - DynamicState::AlphaToCoverageEnable => todo!(), - DynamicState::AlphaToOneEnable => todo!(), - DynamicState::LogicOpEnable => todo!(), - DynamicState::ColorBlendEnable => todo!(), - DynamicState::ColorBlendEquation => todo!(), - DynamicState::ColorWriteMask => todo!(), - DynamicState::RasterizationStream => todo!(), - DynamicState::ConservativeRasterizationMode => todo!(), - DynamicState::ExtraPrimitiveOverestimationSize => todo!(), - DynamicState::DepthClipEnable => todo!(), - DynamicState::SampleLocationsEnable => todo!(), - DynamicState::ColorBlendAdvanced => todo!(), - DynamicState::ProvokingVertexMode => todo!(), - DynamicState::LineRasterizationMode => todo!(), - DynamicState::LineStippleEnable => todo!(), - DynamicState::DepthClipNegativeOneToOne => todo!(), - DynamicState::ViewportWScalingEnable => todo!(), - DynamicState::ViewportSwizzle => todo!(), - DynamicState::CoverageToColorEnable => todo!(), - DynamicState::CoverageToColorLocation => todo!(), - DynamicState::CoverageModulationMode => todo!(), - DynamicState::CoverageModulationTableEnable => todo!(), - DynamicState::CoverageModulationTable => todo!(), - DynamicState::ShadingRateImageEnable => todo!(), - DynamicState::RepresentativeFragmentTestEnable => todo!(), - DynamicState::CoverageReductionMode => todo!(), } } diff --git a/vulkano/src/format.rs b/vulkano/src/format.rs index db63512a02..64d9c10eaa 100644 --- a/vulkano/src/format.rs +++ b/vulkano/src/format.rs @@ -108,7 +108,7 @@ impl Format { /// Retrieves the properties of a format when used by a certain device. #[deprecated( since = "0.28.0", - note = "Use PhysicalDevice::format_properties instead" + note = "use PhysicalDevice::format_properties instead" )] #[inline] pub fn properties(self, physical_device: PhysicalDevice) -> FormatProperties { diff --git a/vulkano/src/macros.rs b/vulkano/src/macros.rs index 4b6dacdca2..ac511cc9ba 100644 --- a/vulkano/src/macros.rs +++ b/vulkano/src/macros.rs @@ -35,7 +35,7 @@ macro_rules! vulkan_bitflags { Self(0) } - #[deprecated(since = "0.31.0", note = "Use `empty` instead.")] + #[deprecated(since = "0.31.0", note = "use `empty` instead")] #[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")] #[inline] pub const fn none() -> Self { @@ -263,7 +263,7 @@ macro_rules! vulkan_bitflags { Self(0) } - #[deprecated(since = "0.31.0", note = "Use `empty` instead.")] + #[deprecated(since = "0.31.0", note = "use `empty` instead")] #[doc = concat!("Returns a `", stringify!($ty), "` with none of the flags set.")] #[inline] pub const fn none() -> Self { diff --git a/vulkano/src/pipeline/graphics/color_blend.rs b/vulkano/src/pipeline/graphics/color_blend.rs index 7357932652..1120e0b09a 100644 --- a/vulkano/src/pipeline/graphics/color_blend.rs +++ b/vulkano/src/pipeline/graphics/color_blend.rs @@ -24,9 +24,9 @@ use crate::{ device::Device, macros::{vulkan_bitflags, vulkan_enum}, - pipeline::StateMode, Requires, RequiresAllOf, RequiresOneOf, ValidationError, }; +use std::iter; /// Describes how the color output of the fragment shader is written to the attachment. See the /// documentation of the `blend` module for more info. @@ -41,62 +41,84 @@ pub struct ColorBlendState { /// fragment in the framebuffer attachment. /// /// If set to `Some`, the [`logic_op`](crate::device::Features::logic_op) feature must be - /// enabled on the device. If set to `Some(Dynamic)`, then the - /// [`extended_dynamic_state2_logic_op`](crate::device::Features::extended_dynamic_state2_logic_op) - /// feature must also be enabled on the device. - pub logic_op: Option>, + /// enabled on the device. + /// + /// The default value is `None`. + pub logic_op: Option, /// Sets the blend and output state for each color attachment. The number of elements must match - /// the number of color attachments in the framebuffer. + /// the number of color attachments in the subpass. /// /// If there are multiple elements, and the `blend` and `color_write_mask` members of each /// element differ, then the [`independent_blend`](crate::device::Features::independent_blend) /// feature must be enabled on the device. + /// + /// The default value is empty, + /// which must be overridden if the subpass has color attachments. pub attachments: Vec, /// The constant color to use for some of the `BlendFactor` variants. - pub blend_constants: StateMode<[f32; 4]>, + /// + /// The default value is `[0.0; 4]`. + pub blend_constants: [f32; 4], pub _ne: crate::NonExhaustive, } +impl Default for ColorBlendState { + /// Returns [`ColorBlendState::new(1)`]. + #[inline] + fn default() -> Self { + Self { + flags: ColorBlendStateFlags::empty(), + logic_op: None, + attachments: Vec::new(), + blend_constants: [0.0; 4], + _ne: crate::NonExhaustive(()), + } + } +} + impl ColorBlendState { + /// Returns a default `ColorBlendState` with `count` duplicates of `attachment_state`. + #[inline] + pub fn with_attachment_states(count: u32, attachment_state: ColorBlendAttachmentState) -> Self { + Self { + attachments: iter::repeat(attachment_state) + .take(count as usize) + .collect(), + ..Default::default() + } + } + /// Creates a `ColorBlendState` with logical operations disabled, blend constants set to zero, /// and `num` attachment entries that have blending disabled, and color write and all color /// components enabled. #[inline] + #[deprecated(since = "0.34.0")] pub fn new(num: u32) -> Self { Self { flags: ColorBlendStateFlags::empty(), logic_op: None, attachments: (0..num) - .map(|_| ColorBlendAttachmentState { - blend: None, - color_write_mask: ColorComponents::all(), - color_write_enable: StateMode::Fixed(true), - }) + .map(|_| ColorBlendAttachmentState::default()) .collect(), - blend_constants: StateMode::Fixed([0.0, 0.0, 0.0, 0.0]), + blend_constants: [0.0; 4], _ne: crate::NonExhaustive(()), } } /// Enables logical operations with the given logical operation. #[inline] + #[deprecated(since = "0.34.0")] pub fn logic_op(mut self, logic_op: LogicOp) -> Self { - self.logic_op = Some(StateMode::Fixed(logic_op)); - self - } - - /// Enables logical operations with a dynamic logical operation. - #[inline] - pub fn logic_op_dynamic(mut self) -> Self { - self.logic_op = Some(StateMode::Dynamic); + self.logic_op = Some(logic_op); self } /// Enables blending for all attachments, with the given parameters. #[inline] + #[deprecated(since = "0.34.0")] pub fn blend(mut self, blend: AttachmentBlend) -> Self { self.attachments .iter_mut() @@ -106,6 +128,7 @@ impl ColorBlendState { /// Enables blending for all attachments, with alpha blending. #[inline] + #[deprecated(since = "0.34.0")] pub fn blend_alpha(mut self) -> Self { self.attachments .iter_mut() @@ -115,6 +138,7 @@ impl ColorBlendState { /// Enables blending for all attachments, with additive blending. #[inline] + #[deprecated(since = "0.34.0")] pub fn blend_additive(mut self) -> Self { self.attachments.iter_mut().for_each(|attachment_state| { attachment_state.blend = Some(AttachmentBlend::additive()) @@ -124,6 +148,7 @@ impl ColorBlendState { /// Sets the color write mask for all attachments. #[inline] + #[deprecated(since = "0.34.0")] pub fn color_write_mask(mut self, color_write_mask: ColorComponents) -> Self { self.attachments .iter_mut() @@ -133,15 +158,9 @@ impl ColorBlendState { /// Sets the blend constants. #[inline] + #[deprecated(since = "0.34.0")] pub fn blend_constants(mut self, constants: [f32; 4]) -> Self { - self.blend_constants = StateMode::Fixed(constants); - self - } - - /// Sets the blend constants as dynamic. - #[inline] - pub fn blend_constants_dynamic(mut self) -> Self { - self.blend_constants = StateMode::Dynamic; + self.blend_constants = constants; self } @@ -171,25 +190,10 @@ impl ColorBlendState { })); } - match logic_op { - StateMode::Fixed(logic_op) => logic_op.validate_device(device).map_err(|err| { - err.add_context("logic_op").set_vuids(&[ - "VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00607", - ]) - })?, - StateMode::Dynamic => { - if !device.enabled_features().extended_dynamic_state2_logic_op { - return Err(Box::new(ValidationError { - context: "logic_op".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( - "extended_dynamic_state2_logic_op", - )])]), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869"], - })); - } - } - } + logic_op.validate_device(device).map_err(|err| { + err.add_context("logic_op") + .set_vuids(&["VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00607"]) + })?; } if device.enabled_features().independent_blend { @@ -225,14 +229,6 @@ impl ColorBlendState { } } -impl Default for ColorBlendState { - /// Returns [`ColorBlendState::new(1)`]. - #[inline] - fn default() -> Self { - Self::new(1) - } -} - vulkan_bitflags! { #[non_exhaustive] @@ -323,9 +319,13 @@ pub struct ColorBlendAttachmentState { /// The blend parameters for the attachment. /// /// If set to `None`, blending is disabled, and all incoming pixels will be used directly. + /// + /// The default value is `None`. pub blend: Option, /// Sets which components of the final pixel value are written to the attachment. + /// + /// The default value is `ColorComponents::all()`. pub color_write_mask: ColorComponents, /// Sets whether anything at all is written to the attachment. If enabled, the pixel data @@ -335,7 +335,20 @@ pub struct ColorBlendAttachmentState { /// If set to anything other than `Fixed(true)`, the /// [`color_write_enable`](crate::device::Features::color_write_enable) feature must be enabled /// on the device. - pub color_write_enable: StateMode, + /// + /// The default value is `true`. + pub color_write_enable: bool, +} + +impl Default for ColorBlendAttachmentState { + #[inline] + fn default() -> Self { + Self { + blend: None, + color_write_mask: ColorComponents::all(), + color_write_enable: true, + } + } } impl ColorBlendAttachmentState { @@ -352,31 +365,15 @@ impl ColorBlendAttachmentState { .map_err(|err| err.add_context("blend"))?; } - match color_write_enable { - StateMode::Fixed(enable) => { - if !enable && !device.enabled_features().color_write_enable { - return Err(Box::new(ValidationError { - context: "color_write_enable".into(), - problem: "is `false`".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( - "color_write_enable", - )])]), - vuids: &["VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801"], - })); - } - } - StateMode::Dynamic => { - if !device.enabled_features().color_write_enable { - return Err(Box::new(ValidationError { - context: "color_write_enable".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( - "color_write_enable", - )])]), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800"], - })); - } - } + if !color_write_enable && !device.enabled_features().color_write_enable { + return Err(Box::new(ValidationError { + context: "color_write_enable".into(), + problem: "is `false`".into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( + "color_write_enable", + )])]), + vuids: &["VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801"], + })); } Ok(()) @@ -387,26 +384,52 @@ impl ColorBlendAttachmentState { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct AttachmentBlend { /// The operation to apply to the source color component before applying `color_op`. + /// + /// The default value is [`BlendFactor::SrcColor`]. pub src_color_blend_factor: BlendFactor, /// The operation to apply to the destination color component before applying `color_op`. + /// + /// The default value is [`BlendFactor::Zero`]. pub dst_color_blend_factor: BlendFactor, /// The operation to apply between the color components of the source and destination pixels, /// to produce the final pixel value. + /// + /// The default value is [`BlendOp::Add`]. pub color_blend_op: BlendOp, /// The operation to apply to the source alpha component before applying `alpha_op`. + /// + /// The default value is [`BlendFactor::SrcColor`]. pub src_alpha_blend_factor: BlendFactor, /// The operation to apply to the destination alpha component before applying `alpha_op`. + /// + /// The default value is [`BlendFactor::Zero`]. pub dst_alpha_blend_factor: BlendFactor, /// The operation to apply between the alpha component of the source and destination pixels, /// to produce the final pixel value. + /// + /// The default value is [`BlendOp::Add`]. pub alpha_blend_op: BlendOp, } +impl Default for AttachmentBlend { + #[inline] + fn default() -> Self { + Self { + src_color_blend_factor: BlendFactor::SrcColor, + dst_color_blend_factor: BlendFactor::Zero, + color_blend_op: BlendOp::Add, + src_alpha_blend_factor: BlendFactor::SrcColor, + dst_alpha_blend_factor: BlendFactor::Zero, + alpha_blend_op: BlendOp::Add, + } + } +} + impl AttachmentBlend { /// Builds an `AttachmentBlend` where the output of the fragment shader is ignored and the /// destination is untouched. diff --git a/vulkano/src/pipeline/graphics/depth_stencil.rs b/vulkano/src/pipeline/graphics/depth_stencil.rs index 8cba6d9563..9c5f8b9c81 100644 --- a/vulkano/src/pipeline/graphics/depth_stencil.rs +++ b/vulkano/src/pipeline/graphics/depth_stencil.rs @@ -23,8 +23,7 @@ use crate::{ device::Device, macros::{vulkan_bitflags, vulkan_enum}, - pipeline::StateMode, - Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, + Requires, RequiresAllOf, RequiresOneOf, ValidationError, }; use std::ops::RangeInclusive; @@ -41,26 +40,32 @@ pub struct DepthStencilState { /// /// If set to `None`, the depth test is disabled, all fragments will pass and no depth writes /// are performed. + /// + /// The default value is `None`. pub depth: Option, - /// The state of the depth bounds test. + /// The minimum and maximum depth values to use for the depth bounds test. + /// Fragments with values outside this range are discarded. /// /// If set to `None`, the depth bounds test is disabled, all fragments will pass. - pub depth_bounds: Option, + /// + /// The default value is `None`. + pub depth_bounds: Option>, /// The state of the stencil test. /// /// If set to `None`, the stencil test is disabled, all fragments will pass and no stencil /// writes are performed. + /// + /// The default value is `None`. pub stencil: Option, pub _ne: crate::NonExhaustive, } -impl DepthStencilState { - /// Creates a `DepthStencilState` where all tests are disabled and have no effect. +impl Default for DepthStencilState { #[inline] - pub fn disabled() -> Self { + fn default() -> Self { Self { flags: DepthStencilStateFlags::empty(), depth: Default::default(), @@ -69,18 +74,24 @@ impl DepthStencilState { _ne: crate::NonExhaustive(()), } } +} + +impl DepthStencilState { + /// Creates a `DepthStencilState` where all tests are disabled and have no effect. + #[inline] + #[deprecated(since = "0.34.0", note = "use `DepthStencilState::default` instead")] + pub fn disabled() -> Self { + Self::default() + } /// Creates a `DepthStencilState` with a `Less` depth test, `depth_write` set to true, and other /// tests disabled. #[inline] + #[deprecated(since = "0.34.0", note = "use `DepthState::simple` instead")] pub fn simple_depth_test() -> Self { Self { flags: DepthStencilStateFlags::empty(), - depth: Some(DepthState { - enable_dynamic: false, - compare_op: StateMode::Fixed(CompareOp::Less), - write_enable: StateMode::Fixed(true), - }), + depth: Some(DepthState::simple()), depth_bounds: Default::default(), stencil: Default::default(), _ne: crate::NonExhaustive(()), @@ -107,7 +118,7 @@ impl DepthStencilState { .map_err(|err| err.add_context("depth"))?; } - if let Some(depth_bounds_state) = depth_bounds { + if let Some(depth_bounds) = depth_bounds { if !device.enabled_features().depth_bounds { return Err(Box::new(ValidationError { context: "depth_bounds".into(), @@ -121,9 +132,29 @@ impl DepthStencilState { })); } - depth_bounds_state - .validate(device) - .map_err(|err| err.add_context("depth_bounds"))?; + if !device.enabled_extensions().ext_depth_range_unrestricted { + if !(0.0..1.0).contains(depth_bounds.start()) { + return Err(Box::new(ValidationError { + context: "depth_bounds.start".into(), + problem: "is not between 0.0 and 1.0 inclusive".into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ + Requires::DeviceExtension("ext_depth_range_unrestricted"), + ])]), + vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-02510"], + })); + } + + if !(0.0..1.0).contains(depth_bounds.end()) { + return Err(Box::new(ValidationError { + context: "depth_bounds.end".into(), + problem: "is not between 0.0 and 1.0 inclusive".into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ + Requires::DeviceExtension("ext_depth_range_unrestricted"), + ])]), + vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-02510"], + })); + } + } } if let Some(stencil_state) = stencil { @@ -136,14 +167,6 @@ impl DepthStencilState { } } -impl Default for DepthStencilState { - /// Returns [`DepthStencilState::disabled()`]. - #[inline] - fn default() -> Self { - DepthStencilState::disabled() - } -} - vulkan_bitflags! { #[non_exhaustive] @@ -170,322 +193,93 @@ vulkan_bitflags! { /// The state in a graphics pipeline describing how the depth test should behave when enabled. #[derive(Clone, Copy, Debug)] pub struct DepthState { - /// Sets whether depth testing should be enabled and disabled dynamically. If set to `false`, - /// depth testing is always enabled. - /// - /// If set to `true`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub enable_dynamic: bool, - /// Sets whether the value in the depth buffer will be updated when the depth test succeeds. /// - /// If set to `Dynamic`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub write_enable: StateMode, + /// The default value is `false`. + pub write_enable: bool, /// Comparison operation to use between the depth value of each incoming fragment and the depth /// value currently in the depth buffer. /// - /// If set to `Dynamic`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub compare_op: StateMode, -} - -impl DepthState { - pub(crate) fn validate(self, device: &Device) -> Result<(), Box> { - let Self { - enable_dynamic, - write_enable, - compare_op, - } = self; - - if enable_dynamic - && !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state) - { - return Err(Box::new(ValidationError { - context: "enable_dynamic".into(), - problem: "is `true`".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); - } - - match write_enable { - StateMode::Fixed(_) => (), - StateMode::Dynamic => { - if !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state) - { - return Err(Box::new(ValidationError { - context: "write_enable".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); - } - } - } - - match compare_op { - StateMode::Fixed(compare_op) => { - compare_op.validate_device(device).map_err(|err| { - err.add_context("compare_op").set_vuids(&[ - "VUID-VkPipelineDepthStencilStateCreateInfo-depthCompareOp-parameter", - ]) - })?; - } - StateMode::Dynamic => { - if !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state) - { - return Err(Box::new(ValidationError { - context: "compare_op".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); - } - } - } - - Ok(()) - } + /// The default value is [`CompareOp::Always`]. + pub compare_op: CompareOp, } impl Default for DepthState { - /// Creates a `DepthState` with no dynamic state, depth writes disabled and `compare_op` set - /// to always pass. #[inline] fn default() -> Self { Self { - enable_dynamic: false, - write_enable: StateMode::Fixed(false), - compare_op: StateMode::Fixed(CompareOp::Always), + write_enable: false, + compare_op: CompareOp::Always, } } } -/// The state in a graphics pipeline describing how the depth bounds test should behave when -/// enabled. -#[derive(Clone, Debug)] -pub struct DepthBoundsState { - /// Sets whether depth bounds testing should be enabled and disabled dynamically. If set to - /// `false`, depth bounds testing is always enabled. - /// - /// If set to `true`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub enable_dynamic: bool, - - /// The minimum and maximum depth values to use for the test. Fragments with values outside this - /// range are discarded. - /// - /// If set to `Dynamic`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub bounds: StateMode>, -} - -impl DepthBoundsState { - pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { - let &Self { - enable_dynamic, - ref bounds, - } = self; - - if enable_dynamic - && !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state) - { - return Err(Box::new(ValidationError { - context: "enable_dynamic".into(), - problem: "is `true`".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); +impl DepthState { + /// Returns a `DepthState` with a `Less` depth test and depth writes enabled. + #[inline] + pub fn simple() -> Self { + Self { + compare_op: CompareOp::Less, + write_enable: true, } + } - if let StateMode::Fixed(bounds) = bounds { - if !device.enabled_extensions().ext_depth_range_unrestricted { - if !(0.0..1.0).contains(bounds.start()) { - return Err(Box::new(ValidationError { - context: "bounds.start".into(), - problem: "is not between 0.0 and 1.0 inclusive".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ - Requires::DeviceExtension("ext_depth_range_unrestricted"), - ])]), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-02510"], - })); - } + pub(crate) fn validate(self, device: &Device) -> Result<(), Box> { + let Self { + write_enable: _, + compare_op, + } = self; - if !(0.0..1.0).contains(bounds.end()) { - return Err(Box::new(ValidationError { - context: "bounds.end".into(), - problem: "is not between 0.0 and 1.0 inclusive".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ - Requires::DeviceExtension("ext_depth_range_unrestricted"), - ])]), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-02510"], - })); - } - } - } + compare_op.validate_device(device).map_err(|err| { + err.add_context("compare_op") + .set_vuids(&["VUID-VkPipelineDepthStencilStateCreateInfo-depthCompareOp-parameter"]) + })?; Ok(()) } } -impl Default for DepthBoundsState { - /// Creates a `DepthBoundsState` with no dynamic state and the bounds set to `0.0..=1.0`. - #[inline] - fn default() -> Self { - Self { - enable_dynamic: false, - bounds: StateMode::Fixed(0.0..=1.0), - } - } -} - /// The state in a graphics pipeline describing how the stencil test should behave when enabled. -/// -/// Dynamic state can only be enabled or disabled for both faces at once. Therefore, the dynamic -/// state values in `StencilOpState`, must match: the values for `front` and `back` must either both -/// be `Fixed` or both be `Dynamic`. #[derive(Clone, Debug)] pub struct StencilState { - /// Sets whether stencil testing should be enabled and disabled dynamically. If set to - /// `false`, stencil testing is always enabled. - /// - /// If set to `true`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub enable_dynamic: bool, - /// The stencil operation state to use for points and lines, and for triangles whose front is /// facing the user. + /// + /// The default value is `StencilOpState::default()`. pub front: StencilOpState, /// The stencil operation state to use for triangles whose back is facing the user. + /// + /// The default value is `StencilOpState::default()`. pub back: StencilOpState, } +impl Default for StencilState { + #[inline] + fn default() -> Self { + Self { + front: Default::default(), + back: Default::default(), + } + } +} + impl StencilState { pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let &StencilState { - enable_dynamic, ref front, ref back, } = self; - if enable_dynamic - && !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state) - { - return Err(Box::new(ValidationError { - context: "enable_dynamic".into(), - problem: "is `true`".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); - } + front + .ops + .validate(device) + .map_err(|err| err.add_context("front.ops"))?; - match (front.ops, back.ops) { - (StateMode::Fixed(front_ops), StateMode::Fixed(back_ops)) => { - front_ops - .validate(device) - .map_err(|err| err.add_context("front.ops"))?; - back_ops - .validate(device) - .map_err(|err| err.add_context("back.ops"))?; - } - (StateMode::Dynamic, StateMode::Dynamic) => { - if !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state) - { - return Err(Box::new(ValidationError { - problem: "`front.ops` and `back.ops` are dynamic".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); - } - } - _ => { - return Err(Box::new(ValidationError { - problem: "`front.ops` and `back.ops` are \ - not both fixed or both dynamic" - .into(), - // vuids? - ..Default::default() - })); - } - } - - if !matches!( - (front.compare_mask, back.compare_mask), - (StateMode::Fixed(_), StateMode::Fixed(_)) | (StateMode::Dynamic, StateMode::Dynamic) - ) { - return Err(Box::new(ValidationError { - problem: "`front.compare_mask` and `back.compare_mask` are \ - not both fixed or both dynamic" - .into(), - // vuids? - ..Default::default() - })); - } - - if !matches!( - (front.write_mask, back.write_mask), - (StateMode::Fixed(_), StateMode::Fixed(_)) | (StateMode::Dynamic, StateMode::Dynamic) - ) { - return Err(Box::new(ValidationError { - problem: "`front.write_mask` and `back.write_mask` are \ - not both fixed or both dynamic" - .into(), - // vuids? - ..Default::default() - })); - } - - if !matches!( - (front.reference, back.reference), - (StateMode::Fixed(_), StateMode::Fixed(_)) | (StateMode::Dynamic, StateMode::Dynamic) - ) { - return Err(Box::new(ValidationError { - problem: "`front.reference` and `back.reference` are \ - not both fixed or both dynamic" - .into(), - // vuids? - ..Default::default() - })); - } + back.ops + .validate(device) + .map_err(|err| err.add_context("back.ops"))?; Ok(()) } @@ -496,19 +290,21 @@ impl StencilState { pub struct StencilOpState { /// The stencil operations to perform. /// - /// If set to `Dynamic`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub ops: StateMode, + /// The default value is `StencilOps::default()`. + pub ops: StencilOps, /// A bitmask that selects the bits of the unsigned integer stencil values participating in the /// stencil test. Ignored if `compare_op` is `Never` or `Always`. - pub compare_mask: StateMode, + /// + /// The default value is [`u32::MAX`]. + pub compare_mask: u32, /// A bitmask that selects the bits of the unsigned integer stencil values updated by the /// stencil test in the stencil framebuffer attachment. Ignored if the relevant operation is /// `Keep`. - pub write_mask: StateMode, + /// + /// The default value is [`u32::MAX`]. + pub write_mask: u32, /// Reference value that is used in the unsigned stencil comparison. The stencil test is /// considered to pass if the `compare_op` between the stencil buffer value and this reference @@ -519,19 +315,19 @@ pub struct StencilOpState { /// are not equal, then the /// [`separate_stencil_mask_ref`](crate::device::Features::separate_stencil_mask_ref) /// feature must be enabled on the device. - pub reference: StateMode, + /// + /// The default value is [`u32::MAX`]. + pub reference: u32, } impl Default for StencilOpState { - /// Creates a `StencilOpState` with no dynamic state, `compare_op` set to `Never`, the stencil - /// operations set to `Keep`, and the masks and reference values set to `u32::MAX`. #[inline] fn default() -> StencilOpState { StencilOpState { - ops: StateMode::Fixed(Default::default()), - compare_mask: StateMode::Fixed(u32::MAX), - write_mask: StateMode::Fixed(u32::MAX), - reference: StateMode::Fixed(u32::MAX), + ops: Default::default(), + compare_mask: u32::MAX, + write_mask: u32::MAX, + reference: u32::MAX, } } } @@ -539,19 +335,39 @@ impl Default for StencilOpState { #[derive(Clone, Copy, Debug)] pub struct StencilOps { /// The operation to perform when the stencil test failed. + /// + /// The default value is [`StencilOp::Keep`]. pub fail_op: StencilOp, /// The operation to perform when both the depth test and the stencil test passed. + /// + /// The default value is [`StencilOp::Keep`]. pub pass_op: StencilOp, /// The operation to perform when the stencil test passed but the depth test failed. + /// + /// The default value is [`StencilOp::Keep`]. pub depth_fail_op: StencilOp, /// The comparison to perform between the existing stencil value in the stencil buffer, and /// the reference value (given by `reference`). + /// + /// The default value is [`CompareOp::Never`]. pub compare_op: CompareOp, } +impl Default for StencilOps { + #[inline] + fn default() -> Self { + Self { + pass_op: StencilOp::Keep, + fail_op: StencilOp::Keep, + depth_fail_op: StencilOp::Keep, + compare_op: CompareOp::Never, + } + } +} + impl StencilOps { pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let &Self { @@ -585,20 +401,6 @@ impl StencilOps { } } -impl Default for StencilOps { - /// Creates a `StencilOps` with no dynamic state, `compare_op` set to `Never` and the stencil - /// operations set to `Keep`. - #[inline] - fn default() -> Self { - Self { - pass_op: StencilOp::Keep, - fail_op: StencilOp::Keep, - depth_fail_op: StencilOp::Keep, - compare_op: CompareOp::Never, - } - } -} - vulkan_enum! { #[non_exhaustive] diff --git a/vulkano/src/pipeline/graphics/discard_rectangle.rs b/vulkano/src/pipeline/graphics/discard_rectangle.rs index 99fb4b3a92..2bfd248939 100644 --- a/vulkano/src/pipeline/graphics/discard_rectangle.rs +++ b/vulkano/src/pipeline/graphics/discard_rectangle.rs @@ -12,39 +12,56 @@ //! The discard rectangle test is similar to, but separate from the scissor test. use crate::{ - device::Device, - macros::vulkan_enum, - pipeline::{graphics::viewport::Scissor, PartialStateMode}, - ValidationError, + device::Device, macros::vulkan_enum, pipeline::graphics::viewport::Scissor, ValidationError, }; /// The state in a graphics pipeline describing how the discard rectangle test should behave. #[derive(Clone, Debug)] pub struct DiscardRectangleState { /// Sets whether the discard rectangle test operates inclusively or exclusively. + /// + /// The default value is [`DiscardRectangleMode::Exclusive`]. pub mode: DiscardRectangleMode, - /// Specifies the discard rectangles. If set to `Dynamic`, it specifies only the number of - /// rectangles used from the dynamic state. + /// Specifies the discard rectangles. + /// + /// When [`DynamicState::DiscardRectangle`] is used, the values of each rectangle are ignored + /// and must be set dynamically, but the number of discard rectangles is fixed and + /// must be matched when setting the dynamic value. /// - /// If set to `Dynamic` or to `Fixed` with a non-empty list, the + /// If this not not empty, then the /// [`ext_discard_rectangles`](crate::device::DeviceExtensions::ext_discard_rectangles) /// extension must be enabled on the device. - pub rectangles: PartialStateMode, u32>, + /// + /// The default value is empty. + /// + /// [`DynamicState::DiscardRectangle`]: crate::pipeline::DynamicState::DiscardRectangle + pub rectangles: Vec, pub _ne: crate::NonExhaustive, } -impl DiscardRectangleState { - /// Creates a `DiscardRectangleState` in exclusive mode with zero rectangles. +impl Default for DiscardRectangleState { #[inline] - pub fn new() -> Self { + fn default() -> Self { Self { mode: DiscardRectangleMode::Exclusive, - rectangles: PartialStateMode::Fixed(Vec::new()), + rectangles: Vec::new(), _ne: crate::NonExhaustive(()), } } +} + +impl DiscardRectangleState { + /// Creates a `DiscardRectangleState` in exclusive mode with zero rectangles. + #[inline] + #[deprecated( + since = "0.34.0", + note = "use `DiscardRectangleState::default` instead" + )] + pub fn new() -> Self { + Self::default() + } pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let &Self { @@ -61,12 +78,7 @@ impl DiscardRectangleState { ]) })?; - let discard_rectangle_count = match rectangles { - PartialStateMode::Dynamic(count) => *count, - PartialStateMode::Fixed(rectangles) => rectangles.len() as u32, - }; - - if discard_rectangle_count > properties.max_discard_rectangles.unwrap() { + if rectangles.len() as u32 > properties.max_discard_rectangles.unwrap() { return Err(Box::new(ValidationError { context: "rectangles".into(), problem: "the length exceeds the `max_discard_rectangles` limit".into(), @@ -81,14 +93,6 @@ impl DiscardRectangleState { } } -impl Default for DiscardRectangleState { - /// Returns [`DiscardRectangleState::new`]. - #[inline] - fn default() -> Self { - Self::new() - } -} - vulkan_enum! { #[non_exhaustive] diff --git a/vulkano/src/pipeline/graphics/input_assembly.rs b/vulkano/src/pipeline/graphics/input_assembly.rs index c82b4c927e..0965e0c331 100644 --- a/vulkano/src/pipeline/graphics/input_assembly.rs +++ b/vulkano/src/pipeline/graphics/input_assembly.rs @@ -10,10 +10,7 @@ //! Configures how input vertices are assembled into primitives. use crate::{ - device::Device, - macros::vulkan_enum, - pipeline::{PartialStateMode, StateMode}, - Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, + device::Device, macros::vulkan_enum, Requires, RequiresAllOf, RequiresOneOf, ValidationError, }; /// The state in a graphics pipeline describing how the input assembly stage should behave. @@ -21,12 +18,17 @@ use crate::{ pub struct InputAssemblyState { /// The type of primitives. /// - /// Note that some topologies require a feature to be enabled on the device. + /// When [`DynamicState::PrimitiveTopology`] is used, if the + /// [`dynamic_primitive_topology_unrestricted`] device property is `false`, then + /// the dynamically set primitive topology must belong to the same *topology class* as + /// `topology`. + /// In practice, this is simply the first word in the name of the topology. /// - /// If set to `Dynamic`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub topology: PartialStateMode, + /// The default value is [`PrimitiveTopology::TriangleList`]. + /// + /// [`DynamicState::PrimitiveTopology`]: crate::pipeline::DynamicState::PrimitiveTopology + /// [`dynamic_primitive_topology_unrestricted`]: crate::device::Properties::dynamic_primitive_topology_unrestricted + pub topology: PrimitiveTopology, /// If true, then when drawing with an index buffer, the special index value consisting of the /// maximum unsigned value (`0xff`, `0xffff` or `0xffffffff`) will tell the GPU that it is the @@ -36,54 +38,54 @@ pub struct InputAssemblyState { /// topologies require a feature to be enabled on the device when combined with primitive /// restart. /// - /// If set to `Dynamic`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature must - /// be enabled on the device. - pub primitive_restart_enable: StateMode, + /// The default value is `false`. + pub primitive_restart_enable: bool, pub _ne: crate::NonExhaustive, } +impl Default for InputAssemblyState { + /// Returns [`InputAssemblyState::new()`]. + #[inline] + fn default() -> Self { + Self { + topology: PrimitiveTopology::TriangleList, + primitive_restart_enable: false, + _ne: crate::NonExhaustive(()), + } + } +} + impl InputAssemblyState { /// Creates an `InputAssemblyState` with the `TriangleList` topology and primitive restart /// disabled. #[inline] + #[deprecated(since = "0.34.0", note = "use `InputAssemblyState::default` instead")] pub fn new() -> Self { Self { - topology: PartialStateMode::Fixed(PrimitiveTopology::TriangleList), - primitive_restart_enable: StateMode::Fixed(false), + topology: PrimitiveTopology::TriangleList, + primitive_restart_enable: false, _ne: crate::NonExhaustive(()), } } /// Sets the primitive topology. #[inline] + #[deprecated(since = "0.34.0")] pub fn topology(mut self, topology: PrimitiveTopology) -> Self { - self.topology = PartialStateMode::Fixed(topology); - self - } - - /// Sets the primitive topology to dynamic. - #[inline] - pub fn topology_dynamic(mut self, topology_class: PrimitiveTopologyClass) -> Self { - self.topology = PartialStateMode::Dynamic(topology_class); + self.topology = topology; self } /// Enables primitive restart. #[inline] + #[deprecated(since = "0.34.0")] pub fn primitive_restart_enable(mut self) -> Self { - self.primitive_restart_enable = StateMode::Fixed(true); - self - } - - /// Sets primitive restart enable to dynmamic. - #[inline] - pub fn primitive_restart_enable_dynamic(mut self) -> Self { - self.primitive_restart_enable = StateMode::Dynamic; + self.primitive_restart_enable = true; self } + #[allow(clippy::trivially_copy_pass_by_ref)] pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let &Self { topology, @@ -91,152 +93,96 @@ impl InputAssemblyState { _ne: _, } = self; - match topology { - PartialStateMode::Fixed(topology) => { - topology.validate_device(device).map_err(|err| { - err.add_context("topology").set_vuids(&[ - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-parameter", - ]) - })?; + topology.validate_device(device).map_err(|err| { + err.add_context("topology") + .set_vuids(&["VUID-VkPipelineInputAssemblyStateCreateInfo-topology-parameter"]) + })?; - match topology { - PrimitiveTopology::TriangleFan => { - if device.enabled_extensions().khr_portability_subset - && !device.enabled_features().triangle_fans - { - return Err(Box::new(ValidationError { - problem: "this device is a portability subset device, and \ - `topology` is `PrimitiveTopology::TriangleFan`" - .into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ - Requires::Feature("triangle_fans"), - ])]), - vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-triangleFans-04452"], - ..Default::default() - })); - } - } - PrimitiveTopology::LineListWithAdjacency - | PrimitiveTopology::LineStripWithAdjacency - | PrimitiveTopology::TriangleListWithAdjacency - | PrimitiveTopology::TriangleStripWithAdjacency => { - if !device.enabled_features().geometry_shader { - return Err(Box::new(ValidationError { - context: "topology".into(), - problem: "is `PrimitiveTopology::*WithAdjacency`".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ - Requires::Feature("geometry_shader"), - ])]), - vuids: &[ - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429", - ], - })); - } - } - PrimitiveTopology::PatchList => { - if !device.enabled_features().tessellation_shader { - return Err(Box::new(ValidationError { - context: "topology".into(), - problem: "is `PrimitiveTopology::PatchList`".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ - Requires::Feature("tessellation_shader"), - ])]), - vuids: &[ - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430", - ], - })); - } - } - _ => (), + match topology { + PrimitiveTopology::TriangleFan => { + if device.enabled_extensions().khr_portability_subset + && !device.enabled_features().triangle_fans + { + return Err(Box::new(ValidationError { + problem: "this device is a portability subset device, and \ + `topology` is `PrimitiveTopology::TriangleFan`" + .into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( + "triangle_fans", + )])]), + vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-triangleFans-04452"], + ..Default::default() + })); } } - PartialStateMode::Dynamic(topology_class) => { - topology_class - .example() - .validate_device(device) - .map_err(|err| { - err.add_context("topology").set_vuids(&[ - "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-parameter", - ]) - })?; - - if !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state) - { + PrimitiveTopology::LineListWithAdjacency + | PrimitiveTopology::LineStripWithAdjacency + | PrimitiveTopology::TriangleListWithAdjacency + | PrimitiveTopology::TriangleStripWithAdjacency => { + if !device.enabled_features().geometry_shader { return Err(Box::new(ValidationError { context: "topology".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() + problem: "is `PrimitiveTopology::*WithAdjacency`".into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( + "geometry_shader", + )])]), + vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429"], + })); + } + } + PrimitiveTopology::PatchList => { + if !device.enabled_features().tessellation_shader { + return Err(Box::new(ValidationError { + context: "topology".into(), + problem: "is `PrimitiveTopology::PatchList`".into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( + "tessellation_shader", + )])]), + vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430"], })); } } + _ => (), } - match primitive_restart_enable { - StateMode::Fixed(primitive_restart_enable) => { - if primitive_restart_enable { - match topology { - PartialStateMode::Fixed( - PrimitiveTopology::PointList - | PrimitiveTopology::LineList - | PrimitiveTopology::TriangleList - | PrimitiveTopology::LineListWithAdjacency - | PrimitiveTopology::TriangleListWithAdjacency, - ) => { - if !device.enabled_features().primitive_topology_list_restart { - return Err(Box::new(ValidationError { - problem: "`topology` is `PrimitiveTopology::*List`, and \ - `primitive_restart_enable` is `true`" - .into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ - Requires::Feature("primitive_topology_list_restart"), - ])]), - vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252"], - ..Default::default() - })); - } - } - PartialStateMode::Fixed(PrimitiveTopology::PatchList) => { - if !device - .enabled_features() - .primitive_topology_patch_list_restart - { - return Err(Box::new(ValidationError { - problem: "`topology` is `PrimitiveTopology::PatchList`, and \ - `primitive_restart_enable` is `true`" - .into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[ - Requires::Feature("primitive_topology_patch_list_restart"), - ])]), - vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06253"], - ..Default::default() - })); - } - } - _ => (), + if primitive_restart_enable { + match topology { + PrimitiveTopology::PointList + | PrimitiveTopology::LineList + | PrimitiveTopology::TriangleList + | PrimitiveTopology::LineListWithAdjacency + | PrimitiveTopology::TriangleListWithAdjacency => { + if !device.enabled_features().primitive_topology_list_restart { + return Err(Box::new(ValidationError { + problem: "`topology` is `PrimitiveTopology::*List`, and \ + `primitive_restart_enable` is `true`" + .into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( + "primitive_topology_list_restart", + )])]), + vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252"], + ..Default::default() + })); } } - } - StateMode::Dynamic => { - if !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state2) - { - return Err(Box::new(ValidationError { - context: "primitive_restart_enable".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); + PrimitiveTopology::PatchList => { + if !device + .enabled_features() + .primitive_topology_patch_list_restart + { + return Err(Box::new(ValidationError { + problem: "`topology` is `PrimitiveTopology::PatchList`, and \ + `primitive_restart_enable` is `true`" + .into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( + "primitive_topology_patch_list_restart", + )])]), + vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06253"], + ..Default::default() + })); + } } + _ => (), } } @@ -244,19 +190,17 @@ impl InputAssemblyState { } } -impl Default for InputAssemblyState { - /// Returns [`InputAssemblyState::new()`]. - #[inline] - fn default() -> Self { - Self::new() - } -} - vulkan_enum! { #[non_exhaustive] /// Describes how vertices must be grouped together to form primitives. /// + /// When [`DynamicState::PrimitiveTopology`] is used, if the + /// [`dynamic_primitive_topology_unrestricted`] device property is `false`, then + /// the dynamically set primitive topology must belong to the same *topology class* as what + /// was set during pipeline creation. + /// In practice, this is simply the first word in the name of the topology. + /// /// When enabling primitive restart, "list" topologies require a feature to be enabled on the /// device: /// - The `PatchList` topology requires the @@ -265,40 +209,34 @@ vulkan_enum! { /// - All other "list" topologies require the /// [`primitive_topology_list_restart`](crate::device::Features::primitive_topology_list_restart) /// feature. - PrimitiveTopology impl { - /// Returns the topology class of this topology. - #[inline] - pub fn class(self) -> PrimitiveTopologyClass { - match self { - Self::PointList => PrimitiveTopologyClass::Point, - Self::LineList - | Self::LineStrip - | Self::LineListWithAdjacency - | Self::LineStripWithAdjacency => PrimitiveTopologyClass::Line, - Self::TriangleList - | Self::TriangleStrip - | Self::TriangleFan - | Self::TriangleListWithAdjacency - | Self::TriangleStripWithAdjacency => PrimitiveTopologyClass::Triangle, - Self::PatchList => PrimitiveTopologyClass::Patch, - } - } - } - = PrimitiveTopology(i32); + /// + /// [`DynamicState::PrimitiveTopology`]: crate::pipeline::DynamicState::PrimitiveTopology + /// [`dynamic_primitive_topology_unrestricted`]: crate::device::Properties::dynamic_primitive_topology_unrestricted + PrimitiveTopology = PrimitiveTopology(i32); /// A series of separate point primitives. + /// + /// Topology class: Point PointList = POINT_LIST, /// A series of separate line primitives. + /// + /// Topology class: Line LineList = LINE_LIST, /// A series of consecutive line primitives, with consecutive lines sharing a vertex. + /// + /// Topology class: Line LineStrip = LINE_STRIP, /// A series of separate triangle primitives. + /// + /// Topology class: Triangle TriangleList = TRIANGLE_LIST, /// A series of consecutive triangle primitives, with consecutive triangles sharing an edge (two vertices). + /// + /// Topology class: Triangle TriangleStrip = TRIANGLE_STRIP, /// A series of consecutive triangle primitives, with all triangles sharing a common vertex (the first). @@ -306,26 +244,38 @@ vulkan_enum! { /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag) /// devices, the [`triangle_fans`](crate::device::Features::triangle_fans) /// feature must be enabled on the device. + /// + /// Topology class: Triangle TriangleFan = TRIANGLE_FAN, /// As `LineList, but with adjacency, used in combination with geometry shaders. Requires the /// [`geometry_shader`](crate::device::Features::geometry_shader) feature. + /// + /// Topology class: Line LineListWithAdjacency = LINE_LIST_WITH_ADJACENCY, /// As `LineStrip`, but with adjacency, used in combination with geometry shaders. Requires the /// [`geometry_shader`](crate::device::Features::geometry_shader) feature. + /// + /// Topology class: Line LineStripWithAdjacency = LINE_STRIP_WITH_ADJACENCY, /// As `TriangleList`, but with adjacency, used in combination with geometry shaders. Requires /// the [`geometry_shader`](crate::device::Features::geometry_shader) feature. + /// + /// Topology class: Triangle TriangleListWithAdjacency = TRIANGLE_LIST_WITH_ADJACENCY, /// As `TriangleStrip`, but with adjacency, used in combination with geometry shaders. Requires /// the [`geometry_shader`](crate::device::Features::geometry_shader) feature. + /// + /// Topology class: Triangle TriangleStripWithAdjacency = TRIANGLE_STRIP_WITH_ADJACENCY, /// Separate patch primitives, used in combination with tessellation shaders. Requires the /// [`tessellation_shader`](crate::device::Features::tessellation_shader) feature. + /// + /// Topology class: Patch PatchList = PATCH_LIST, } @@ -338,24 +288,3 @@ impl Default for PrimitiveTopology { PrimitiveTopology::TriangleList } } - -/// Describes the shape of a primitive topology. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum PrimitiveTopologyClass { - Point, - Line, - Triangle, - Patch, -} - -impl PrimitiveTopologyClass { - /// Returns a representative example of this topology class. - pub(crate) fn example(self) -> PrimitiveTopology { - match self { - Self::Point => PrimitiveTopology::PointList, - Self::Line => PrimitiveTopology::LineList, - Self::Triangle => PrimitiveTopology::TriangleList, - Self::Patch => PrimitiveTopology::PatchList, - } - } -} diff --git a/vulkano/src/pipeline/graphics/mod.rs b/vulkano/src/pipeline/graphics/mod.rs index 91989fc0c8..ced82d4aeb 100644 --- a/vulkano/src/pipeline/graphics/mod.rs +++ b/vulkano/src/pipeline/graphics/mod.rs @@ -58,9 +58,9 @@ use self::{ color_blend::ColorBlendState, - depth_stencil::{DepthBoundsState, DepthState, DepthStencilState}, + depth_stencil::{DepthState, DepthStencilState}, discard_rectangle::DiscardRectangleState, - input_assembly::{InputAssemblyState, PrimitiveTopology, PrimitiveTopologyClass}, + input_assembly::{InputAssemblyState, PrimitiveTopology}, multisample::MultisampleState, rasterization::RasterizationState, subpass::PipelineSubpassType, @@ -70,7 +70,7 @@ use self::{ }; use super::{ cache::PipelineCache, DynamicState, Pipeline, PipelineBindPoint, PipelineCreateFlags, - PipelineLayout, PipelineShaderStageCreateInfo, StateMode, + PipelineLayout, PipelineShaderStageCreateInfo, }; use crate::{ device::{Device, DeviceOwned, DeviceOwnedDebugWrapper}, @@ -78,16 +78,13 @@ use crate::{ image::{ImageAspect, ImageAspects}, instance::InstanceOwnedDebugWrapper, macros::impl_id_counter, - pipeline::{ - graphics::{ - color_blend::ColorBlendAttachmentState, - depth_stencil::{StencilOpState, StencilState}, - rasterization::{CullMode, FrontFace}, - subpass::PipelineRenderingCreateInfo, - tessellation::TessellationDomainOrigin, - vertex_input::VertexInputRate, - }, - PartialStateMode, + pipeline::graphics::{ + color_blend::ColorBlendAttachmentState, + depth_stencil::{StencilOpState, StencilState}, + rasterization::{CullMode, DepthBiasState}, + subpass::PipelineRenderingCreateInfo, + tessellation::TessellationDomainOrigin, + vertex_input::VertexInputRate, }, shader::{ spirv::{ExecutionMode, ExecutionModel, Instruction}, @@ -95,7 +92,7 @@ use crate::{ }, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject, }; -use ahash::HashMap; +use ahash::{HashMap, HashSet}; use smallvec::SmallVec; use std::{ collections::hash_map::Entry, ffi::CString, fmt::Debug, mem::MaybeUninit, num::NonZeroU64, ptr, @@ -140,11 +137,13 @@ pub struct GraphicsPipeline { multisample_state: Option, depth_stencil_state: Option, color_blend_state: Option, + dynamic_state: HashSet, layout: DeviceOwnedDebugWrapper>, subpass: PipelineSubpassType, - dynamic_state: HashMap, discard_rectangle_state: Option, + + fixed_state: HashSet, } impl GraphicsPipeline { @@ -189,6 +188,7 @@ impl GraphicsPipeline { ref multisample_state, ref depth_stencil_state, ref color_blend_state, + ref dynamic_state, ref layout, ref subpass, @@ -198,8 +198,6 @@ impl GraphicsPipeline { _ne: _, } = &create_info; - let mut dynamic_state: HashMap = HashMap::default(); - struct PerPipelineShaderStageCreateInfo { name_vk: CString, specialization_info_vk: ash::vk::SpecializationInfo, @@ -309,8 +307,6 @@ impl GraphicsPipeline { let mut vertex_binding_divisor_descriptions_vk: SmallVec<[_; 8]> = SmallVec::new(); if let Some(vertex_input_state) = vertex_input_state { - dynamic_state.insert(DynamicState::VertexInput, false); - let VertexInputState { bindings, attributes, @@ -385,32 +381,10 @@ impl GraphicsPipeline { _ne: _, } = input_assembly_state; - let topology = match topology { - PartialStateMode::Fixed(topology) => { - dynamic_state.insert(DynamicState::PrimitiveTopology, false); - topology.into() - } - PartialStateMode::Dynamic(topology_class) => { - dynamic_state.insert(DynamicState::PrimitiveTopology, true); - topology_class.example().into() - } - }; - - let primitive_restart_enable = match primitive_restart_enable { - StateMode::Fixed(primitive_restart_enable) => { - dynamic_state.insert(DynamicState::PrimitiveRestartEnable, false); - primitive_restart_enable as ash::vk::Bool32 - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::PrimitiveRestartEnable, true); - Default::default() - } - }; - let _ = input_assembly_state_vk.insert(ash::vk::PipelineInputAssemblyStateCreateInfo { flags: ash::vk::PipelineInputAssemblyStateCreateFlags::empty(), - topology, - primitive_restart_enable, + topology: topology.into(), + primitive_restart_enable: primitive_restart_enable as ash::vk::Bool32, ..Default::default() }); } @@ -425,17 +399,6 @@ impl GraphicsPipeline { _ne: _, } = tessellation_state; - let patch_control_points = match patch_control_points { - StateMode::Fixed(patch_control_points) => { - dynamic_state.insert(DynamicState::PatchControlPoints, false); - patch_control_points - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::PatchControlPoints, true); - Default::default() - } - }; - let tessellation_state_vk = tessellation_state_vk.insert(ash::vk::PipelineTessellationStateCreateInfo { flags: ash::vk::PipelineTessellationStateCreateFlags::empty(), @@ -467,53 +430,18 @@ impl GraphicsPipeline { _ne: _, } = viewport_state; - let viewport_count = match viewports { - PartialStateMode::Fixed(viewports) => { - dynamic_state.insert(DynamicState::Viewport, false); - dynamic_state.insert(DynamicState::ViewportWithCount, false); - viewports_vk.extend(viewports.iter().map(Into::into)); - viewports.len() as u32 - } - PartialStateMode::Dynamic(StateMode::Fixed(count)) => { - dynamic_state.insert(DynamicState::Viewport, true); - dynamic_state.insert(DynamicState::ViewportWithCount, false); - *count - } - PartialStateMode::Dynamic(StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::Viewport, true); - dynamic_state.insert(DynamicState::ViewportWithCount, true); - 0 - } - }; - - let scissor_count = match scissors { - PartialStateMode::Fixed(scissors) => { - dynamic_state.insert(DynamicState::Scissor, false); - dynamic_state.insert(DynamicState::ScissorWithCount, false); - scissors_vk.extend(scissors.iter().map(Into::into)); - scissors.len() as u32 - } - PartialStateMode::Dynamic(StateMode::Fixed(count)) => { - dynamic_state.insert(DynamicState::Scissor, true); - dynamic_state.insert(DynamicState::ScissorWithCount, false); - *count - } - PartialStateMode::Dynamic(StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::Scissor, true); - dynamic_state.insert(DynamicState::ScissorWithCount, true); - 0 - } - }; + viewports_vk.extend(viewports.iter().map(Into::into)); + scissors_vk.extend(scissors.iter().map(Into::into)); let _ = viewport_state_vk.insert(ash::vk::PipelineViewportStateCreateInfo { flags: ash::vk::PipelineViewportStateCreateFlags::empty(), - viewport_count, + viewport_count: viewports_vk.len() as u32, p_viewports: if viewports_vk.is_empty() { ptr::null() } else { viewports_vk.as_ptr() }, - scissor_count, + scissor_count: scissors_vk.len() as u32, p_scissors: if scissors_vk.is_empty() { ptr::null() } else { @@ -533,93 +461,38 @@ impl GraphicsPipeline { polygon_mode, cull_mode, front_face, - depth_bias, + ref depth_bias, line_width, line_rasterization_mode, line_stipple, _ne: _, } = rasterization_state; - let rasterizer_discard_enable = match rasterizer_discard_enable { - StateMode::Fixed(rasterizer_discard_enable) => { - dynamic_state.insert(DynamicState::RasterizerDiscardEnable, false); - rasterizer_discard_enable as ash::vk::Bool32 - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::RasterizerDiscardEnable, true); - ash::vk::FALSE - } - }; - - let cull_mode = match cull_mode { - StateMode::Fixed(cull_mode) => { - dynamic_state.insert(DynamicState::CullMode, false); - cull_mode.into() - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::CullMode, true); - CullMode::default().into() - } - }; - - let front_face = match front_face { - StateMode::Fixed(front_face) => { - dynamic_state.insert(DynamicState::FrontFace, false); - front_face.into() - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::FrontFace, true); - FrontFace::default().into() - } - }; - let ( depth_bias_enable, depth_bias_constant_factor, depth_bias_clamp, depth_bias_slope_factor, ) = if let Some(depth_bias_state) = depth_bias { - if depth_bias_state.enable_dynamic { - dynamic_state.insert(DynamicState::DepthBiasEnable, true); - } else { - dynamic_state.insert(DynamicState::DepthBiasEnable, false); - } - - let (constant_factor, clamp, slope_factor) = match depth_bias_state.bias { - StateMode::Fixed(bias) => { - dynamic_state.insert(DynamicState::DepthBias, false); - (bias.constant_factor, bias.clamp, bias.slope_factor) - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::DepthBias, true); - (0.0, 0.0, 0.0) - } - }; + let &DepthBiasState { + constant_factor, + clamp, + slope_factor, + } = depth_bias_state; (ash::vk::TRUE, constant_factor, clamp, slope_factor) } else { (ash::vk::FALSE, 0.0, 0.0, 0.0) }; - let line_width = match line_width { - StateMode::Fixed(line_width) => { - dynamic_state.insert(DynamicState::LineWidth, false); - line_width - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::LineWidth, true); - 1.0 - } - }; - let rasterization_state = rasterization_state_vk.insert(ash::vk::PipelineRasterizationStateCreateInfo { flags: ash::vk::PipelineRasterizationStateCreateFlags::empty(), depth_clamp_enable: depth_clamp_enable as ash::vk::Bool32, - rasterizer_discard_enable, + rasterizer_discard_enable: rasterizer_discard_enable as ash::vk::Bool32, polygon_mode: polygon_mode.into(), - cull_mode, - front_face, + cull_mode: cull_mode.into(), + front_face: front_face.into(), depth_bias_enable, depth_bias_constant_factor, depth_bias_clamp, @@ -631,18 +504,7 @@ impl GraphicsPipeline { if device.enabled_extensions().ext_line_rasterization { let (stippled_line_enable, line_stipple_factor, line_stipple_pattern) = if let Some(line_stipple) = line_stipple { - let (factor, pattern) = match line_stipple { - StateMode::Fixed(line_stipple) => { - dynamic_state.insert(DynamicState::LineStipple, false); - (line_stipple.factor, line_stipple.pattern) - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::LineStipple, true); - (1, 0) - } - }; - - (ash::vk::TRUE, factor, pattern) + (ash::vk::TRUE, line_stipple.factor, line_stipple.pattern) } else { (ash::vk::FALSE, 1, 0) }; @@ -704,125 +566,28 @@ impl GraphicsPipeline { let (depth_test_enable, depth_write_enable, depth_compare_op) = if let Some(depth_state) = depth { let &DepthState { - enable_dynamic, write_enable, compare_op, } = depth_state; - if enable_dynamic { - dynamic_state.insert(DynamicState::DepthTestEnable, true); - } else { - dynamic_state.insert(DynamicState::DepthTestEnable, false); - } - - let write_enable = match write_enable { - StateMode::Fixed(write_enable) => { - dynamic_state.insert(DynamicState::DepthWriteEnable, false); - write_enable as ash::vk::Bool32 - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::DepthWriteEnable, true); - ash::vk::TRUE - } - }; - - let compare_op = match compare_op { - StateMode::Fixed(compare_op) => { - dynamic_state.insert(DynamicState::DepthCompareOp, false); - compare_op.into() - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::DepthCompareOp, true); - ash::vk::CompareOp::ALWAYS - } - }; - - (ash::vk::TRUE, write_enable, compare_op) + ( + ash::vk::TRUE, + write_enable as ash::vk::Bool32, + compare_op.into(), + ) } else { (ash::vk::FALSE, ash::vk::FALSE, ash::vk::CompareOp::ALWAYS) }; let (depth_bounds_test_enable, min_depth_bounds, max_depth_bounds) = - if let Some(depth_bounds_state) = depth_bounds { - let depth_stencil::DepthBoundsState { - enable_dynamic, - bounds, - } = depth_bounds_state; - - if *enable_dynamic { - dynamic_state.insert(DynamicState::DepthBoundsTestEnable, true); - } else { - dynamic_state.insert(DynamicState::DepthBoundsTestEnable, false); - } - - let (min_bounds, max_bounds) = match bounds.clone() { - StateMode::Fixed(bounds) => { - dynamic_state.insert(DynamicState::DepthBounds, false); - bounds.into_inner() - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::DepthBounds, true); - (0.0, 1.0) - } - }; - - (ash::vk::TRUE, min_bounds, max_bounds) + if let Some(depth_bounds) = depth_bounds { + (ash::vk::TRUE, *depth_bounds.start(), *depth_bounds.end()) } else { (ash::vk::FALSE, 0.0, 1.0) }; let (stencil_test_enable, front, back) = if let Some(stencil_state) = stencil { - let StencilState { - enable_dynamic, - front, - back, - } = stencil_state; - - if *enable_dynamic { - dynamic_state.insert(DynamicState::StencilTestEnable, true); - } else { - dynamic_state.insert(DynamicState::StencilTestEnable, false); - } - - match (front.ops, back.ops) { - (StateMode::Fixed(_), StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::StencilOp, false); - } - (StateMode::Dynamic, StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::StencilOp, true); - } - _ => unreachable!(), - }; - - match (front.compare_mask, back.compare_mask) { - (StateMode::Fixed(_), StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::StencilCompareMask, false); - } - (StateMode::Dynamic, StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::StencilCompareMask, true); - } - _ => unreachable!(), - }; - - match (front.write_mask, back.write_mask) { - (StateMode::Fixed(_), StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::StencilWriteMask, false); - } - (StateMode::Dynamic, StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::StencilWriteMask, true); - } - _ => unreachable!(), - }; - - match (front.reference, back.reference) { - (StateMode::Fixed(_), StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::StencilReference, false); - } - (StateMode::Dynamic, StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::StencilReference, true); - } - _ => unreachable!(), - }; + let StencilState { front, back } = stencil_state; let [front, back] = [front, back].map(|stencil_op_state| { let &StencilOpState { @@ -832,23 +597,6 @@ impl GraphicsPipeline { reference, } = stencil_op_state; - let ops = match ops { - StateMode::Fixed(x) => x, - StateMode::Dynamic => Default::default(), - }; - let compare_mask = match compare_mask { - StateMode::Fixed(x) => x, - StateMode::Dynamic => Default::default(), - }; - let write_mask = match write_mask { - StateMode::Fixed(x) => x, - StateMode::Dynamic => Default::default(), - }; - let reference = match reference { - StateMode::Fixed(x) => x, - StateMode::Dynamic => Default::default(), - }; - ash::vk::StencilOpState { fail_op: ops.fail_op.into(), pass_op: ops.pass_op.into(), @@ -916,33 +664,11 @@ impl GraphicsPipeline { )); let (logic_op_enable, logic_op) = if let Some(logic_op) = logic_op { - let logic_op = match logic_op { - StateMode::Fixed(logic_op) => { - dynamic_state.insert(DynamicState::LogicOp, false); - logic_op.into() - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::LogicOp, true); - Default::default() - } - }; - - (ash::vk::TRUE, logic_op) + (ash::vk::TRUE, logic_op.into()) } else { (ash::vk::FALSE, Default::default()) }; - let blend_constants = match blend_constants { - StateMode::Fixed(blend_constants) => { - dynamic_state.insert(DynamicState::BlendConstants, false); - blend_constants - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::BlendConstants, true); - Default::default() - } - }; - let color_blend_state_vk = color_blend_state_vk.insert(ash::vk::PipelineColorBlendStateCreateInfo { flags: flags.into(), @@ -963,16 +689,7 @@ impl GraphicsPipeline { color_write_enable, } = color_blend_attachment_state; - match color_write_enable { - StateMode::Fixed(enable) => { - dynamic_state.insert(DynamicState::ColorWriteEnable, false); - enable as ash::vk::Bool32 - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::ColorWriteEnable, true); - ash::vk::TRUE - } - } + color_write_enable as ash::vk::Bool32 }, )); @@ -985,26 +702,15 @@ impl GraphicsPipeline { } } - let mut dynamic_state_list: SmallVec<[_; 4]> = SmallVec::new(); - let mut dynamic_state_vk = None; - - { - dynamic_state_list.extend( - dynamic_state - .iter() - .filter(|(_, d)| **d) - .map(|(&state, _)| state.into()), - ); - - if !dynamic_state_list.is_empty() { - let _ = dynamic_state_vk.insert(ash::vk::PipelineDynamicStateCreateInfo { - flags: ash::vk::PipelineDynamicStateCreateFlags::empty(), - dynamic_state_count: dynamic_state_list.len() as u32, - p_dynamic_states: dynamic_state_list.as_ptr(), - ..Default::default() - }); - } - } + let dynamic_state_list_vk: SmallVec<[_; 4]> = + dynamic_state.iter().copied().map(Into::into).collect(); + let dynamic_state_vk = + (!dynamic_state_list_vk.is_empty()).then(|| ash::vk::PipelineDynamicStateCreateInfo { + flags: ash::vk::PipelineDynamicStateCreateFlags::empty(), + dynamic_state_count: dynamic_state_list_vk.len() as u32, + p_dynamic_states: dynamic_state_list_vk.as_ptr(), + ..Default::default() + }); let render_pass = subpass.as_ref().unwrap(); let mut render_pass_vk = ash::vk::RenderPass::null(); @@ -1046,7 +752,7 @@ impl GraphicsPipeline { } let mut discard_rectangle_state_vk = None; - let mut discard_rectangles: SmallVec<[_; 2]> = SmallVec::new(); + let mut discard_rectangles_vk: SmallVec<[_; 2]> = SmallVec::new(); if let Some(discard_rectangle_state) = discard_rectangle_state { let DiscardRectangleState { @@ -1055,26 +761,14 @@ impl GraphicsPipeline { _ne: _, } = discard_rectangle_state; - let discard_rectangle_count = match rectangles { - PartialStateMode::Fixed(rectangles) => { - dynamic_state.insert(DynamicState::DiscardRectangle, false); - discard_rectangles.extend(rectangles.iter().map(|rect| rect.into())); - - discard_rectangles.len() as u32 - } - PartialStateMode::Dynamic(count) => { - dynamic_state.insert(DynamicState::DiscardRectangle, true); - - *count - } - }; + discard_rectangles_vk.extend(rectangles.iter().map(|rect| rect.into())); let _ = discard_rectangle_state_vk.insert( ash::vk::PipelineDiscardRectangleStateCreateInfoEXT { flags: ash::vk::PipelineDiscardRectangleStateCreateFlagsEXT::empty(), discard_rectangle_mode: (*mode).into(), - discard_rectangle_count, - p_discard_rectangles: discard_rectangles.as_ptr(), + discard_rectangle_count: discard_rectangles_vk.len() as u32, + p_discard_rectangles: discard_rectangles_vk.as_ptr(), ..Default::default() }, ); @@ -1200,6 +894,7 @@ impl GraphicsPipeline { multisample_state, depth_stencil_state, color_blend_state, + dynamic_state, layout, subpass, @@ -1266,350 +961,68 @@ impl GraphicsPipeline { .map(|x| x + 1) .unwrap_or(0); - let mut dynamic_state: HashMap = HashMap::default(); + let mut fixed_state: HashSet = Default::default(); - if vertex_input_state.is_some() { - dynamic_state.insert(DynamicState::VertexInput, false); + if input_assembly_state.is_some() { + fixed_state.extend([ + DynamicState::PrimitiveTopology, + DynamicState::PrimitiveRestartEnable, + ]); } - if let Some(input_assembly_state) = &input_assembly_state { - let &InputAssemblyState { - topology, - primitive_restart_enable, - _ne: _, - } = input_assembly_state; - - match topology { - PartialStateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::PrimitiveTopology, false); - } - PartialStateMode::Dynamic(_) => { - dynamic_state.insert(DynamicState::PrimitiveTopology, true); - } - } - - match primitive_restart_enable { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::PrimitiveRestartEnable, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::PrimitiveRestartEnable, true); - } - } + if tessellation_state.is_some() { + fixed_state.extend([DynamicState::PatchControlPoints]); } - if let Some(tessellation_state) = &tessellation_state { - let &TessellationState { - patch_control_points, - domain_origin: _, - _ne: _, - } = tessellation_state; - - match patch_control_points { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::PatchControlPoints, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::PatchControlPoints, true); - } - } + if viewport_state.is_some() { + fixed_state.extend([ + DynamicState::Viewport, + DynamicState::ViewportWithCount, + DynamicState::Scissor, + DynamicState::ScissorWithCount, + ]); } - if let Some(viewport_state) = &viewport_state { - let ViewportState { - viewports, - scissors, - _ne: _, - } = viewport_state; - - match viewports { - PartialStateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::Viewport, false); - dynamic_state.insert(DynamicState::ViewportWithCount, false); - } - PartialStateMode::Dynamic(StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::Viewport, true); - dynamic_state.insert(DynamicState::ViewportWithCount, false); - } - PartialStateMode::Dynamic(StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::Viewport, true); - dynamic_state.insert(DynamicState::ViewportWithCount, true); - } - } - - match scissors { - PartialStateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::Scissor, false); - dynamic_state.insert(DynamicState::ScissorWithCount, false); - } - PartialStateMode::Dynamic(StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::Scissor, true); - dynamic_state.insert(DynamicState::ScissorWithCount, false); - } - PartialStateMode::Dynamic(StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::Scissor, true); - dynamic_state.insert(DynamicState::ScissorWithCount, true); - } - } + if rasterization_state.is_some() { + fixed_state.extend([ + DynamicState::RasterizerDiscardEnable, + DynamicState::CullMode, + DynamicState::FrontFace, + DynamicState::DepthBiasEnable, + DynamicState::DepthBias, + DynamicState::LineWidth, + DynamicState::LineStipple, + ]); } - if let Some(rasterization_state) = &rasterization_state { - let &RasterizationState { - rasterizer_discard_enable, - cull_mode, - front_face, - depth_bias, - line_width, - line_stipple, - .. - } = rasterization_state; - - match rasterizer_discard_enable { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::RasterizerDiscardEnable, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::RasterizerDiscardEnable, true); - } - } - - match cull_mode { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::CullMode, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::CullMode, true); - } - } - - match front_face { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::FrontFace, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::FrontFace, true); - } - } - - if let Some(depth_bias_state) = depth_bias { - if depth_bias_state.enable_dynamic { - dynamic_state.insert(DynamicState::DepthBiasEnable, true); - } else { - dynamic_state.insert(DynamicState::DepthBiasEnable, false); - } - - match depth_bias_state.bias { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::DepthBias, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::DepthBias, true); - } - } - } - - match line_width { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::LineWidth, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::LineWidth, true); - } - } - - if device.enabled_extensions().ext_line_rasterization { - if let Some(line_stipple) = line_stipple { - match line_stipple { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::LineStipple, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::LineStipple, true); - } - } - } - } + if depth_stencil_state.is_some() { + fixed_state.extend([ + DynamicState::DepthTestEnable, + DynamicState::DepthWriteEnable, + DynamicState::DepthCompareOp, + DynamicState::DepthBoundsTestEnable, + DynamicState::DepthBounds, + DynamicState::StencilTestEnable, + DynamicState::StencilOp, + DynamicState::StencilCompareMask, + DynamicState::StencilWriteMask, + DynamicState::StencilReference, + ]); } - if let Some(depth_stencil_state) = &depth_stencil_state { - let DepthStencilState { - flags: _, - depth, - depth_bounds, - stencil, - _ne: _, - } = depth_stencil_state; - - if let Some(depth_state) = depth { - let &DepthState { - enable_dynamic, - write_enable, - compare_op, - } = depth_state; - - if enable_dynamic { - dynamic_state.insert(DynamicState::DepthTestEnable, true); - } else { - dynamic_state.insert(DynamicState::DepthTestEnable, false); - } - - match write_enable { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::DepthWriteEnable, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::DepthWriteEnable, true); - } - } - - match compare_op { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::DepthCompareOp, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::DepthCompareOp, true); - } - } - } - - if let Some(depth_bounds_state) = depth_bounds { - let DepthBoundsState { - enable_dynamic, - bounds, - } = depth_bounds_state; - - if *enable_dynamic { - dynamic_state.insert(DynamicState::DepthBoundsTestEnable, true); - } else { - dynamic_state.insert(DynamicState::DepthBoundsTestEnable, false); - } - - match bounds.clone() { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::DepthBounds, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::DepthBounds, true); - } - } - } - - if let Some(stencil_state) = stencil { - let StencilState { - enable_dynamic, - front, - back, - } = stencil_state; - - if *enable_dynamic { - dynamic_state.insert(DynamicState::StencilTestEnable, true); - } else { - dynamic_state.insert(DynamicState::StencilTestEnable, false); - } - - match (front.ops, back.ops) { - (StateMode::Fixed(_), StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::StencilOp, false); - } - (StateMode::Dynamic, StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::StencilOp, true); - } - _ => unreachable!(), - } - - match (front.compare_mask, back.compare_mask) { - (StateMode::Fixed(_), StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::StencilCompareMask, false); - } - (StateMode::Dynamic, StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::StencilCompareMask, true); - } - _ => unreachable!(), - } - - match (front.write_mask, back.write_mask) { - (StateMode::Fixed(_), StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::StencilWriteMask, false); - } - (StateMode::Dynamic, StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::StencilWriteMask, true); - } - _ => unreachable!(), - } - - match (front.reference, back.reference) { - (StateMode::Fixed(_), StateMode::Fixed(_)) => { - dynamic_state.insert(DynamicState::StencilReference, false); - } - (StateMode::Dynamic, StateMode::Dynamic) => { - dynamic_state.insert(DynamicState::StencilReference, true); - } - _ => unreachable!(), - } - } + if color_blend_state.is_some() { + fixed_state.extend([ + DynamicState::LogicOp, + DynamicState::BlendConstants, + DynamicState::ColorWriteEnable, + ]); } - if let Some(color_blend_state) = &color_blend_state { - let &ColorBlendState { - flags: _, - logic_op, - ref attachments, - blend_constants, - _ne: _, - } = color_blend_state; - - if let Some(logic_op) = logic_op { - match logic_op { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::LogicOp, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::LogicOp, true); - } - } - } - - match blend_constants { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::BlendConstants, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::BlendConstants, true); - } - } - - if device.enabled_extensions().ext_color_write_enable { - for color_blend_attachment_state in attachments { - let &ColorBlendAttachmentState { - blend: _, - color_write_mask: _, - color_write_enable, - } = color_blend_attachment_state; - - match color_write_enable { - StateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::ColorWriteEnable, false); - } - StateMode::Dynamic => { - dynamic_state.insert(DynamicState::ColorWriteEnable, true); - } - } - } - } + if discard_rectangle_state.is_some() { + fixed_state.extend([DynamicState::DiscardRectangle]); } - if let Some(discard_rectangle_state) = &discard_rectangle_state { - let DiscardRectangleState { rectangles, .. } = discard_rectangle_state; - - match rectangles { - PartialStateMode::Fixed(_) => { - dynamic_state.insert(DynamicState::DiscardRectangle, false); - } - PartialStateMode::Dynamic(_) => { - dynamic_state.insert(DynamicState::DiscardRectangle, true); - } - } - } + fixed_state.retain(|state| !dynamic_state.contains(state)); Arc::new(Self { handle, @@ -1630,11 +1043,13 @@ impl GraphicsPipeline { multisample_state, depth_stencil_state, color_blend_state, + dynamic_state, layout: DeviceOwnedDebugWrapper(layout), subpass: subpass.unwrap(), - dynamic_state, discard_rectangle_state, + + fixed_state, }) } @@ -1716,19 +1131,10 @@ impl GraphicsPipeline { &self.subpass } - /// Returns whether a particular state is must be dynamically set. - /// - /// `None` is returned if the pipeline does not contain this state. Previously set dynamic - /// state is not disturbed when binding it. + /// Returns the dynamic states of the pipeline. #[inline] - pub fn dynamic_state(&self, state: DynamicState) -> Option { - self.dynamic_state.get(&state).copied() - } - - /// Returns all potentially dynamic states in the pipeline, and whether they are dynamic or not. - #[inline] - pub fn dynamic_states(&self) -> impl ExactSizeIterator + '_ { - self.dynamic_state.iter().map(|(k, v)| (*k, *v)) + pub fn dynamic_state(&self) -> &HashSet { + &self.dynamic_state } /// Returns the discard rectangle state used to create this pipeline. @@ -1742,6 +1148,12 @@ impl GraphicsPipeline { pub fn fragment_tests_stages(&self) -> Option { self.fragment_tests_stages } + + /// Returns the dynamic states that are not dynamic in this pipeline. + #[inline] + pub(crate) fn fixed_state(&self) -> &HashSet { + &self.fixed_state + } } impl Pipeline for GraphicsPipeline { @@ -1877,6 +1289,11 @@ pub struct GraphicsPipelineCreateInfo { /// [rasterizer discarding]: RasterizationState::rasterizer_discard_enable pub color_blend_state: Option, + /// The state(s) that will be set dynamically when recording a command buffer. + /// + /// The default value is empty. + pub dynamic_state: HashSet, + /// The pipeline layout to use for the pipeline. /// /// There is no default value. @@ -1915,6 +1332,7 @@ impl GraphicsPipelineCreateInfo { Self { flags: PipelineCreateFlags::empty(), stages: SmallVec::new(), + vertex_input_state: None, input_assembly_state: None, tessellation_state: None, @@ -1923,9 +1341,12 @@ impl GraphicsPipelineCreateInfo { multisample_state: None, depth_stencil_state: None, color_blend_state: None, + dynamic_state: Default::default(), + layout, subpass: None, base_pipeline: None, + discard_rectangle_state: None, _ne: crate::NonExhaustive(()), } @@ -1944,6 +1365,7 @@ impl GraphicsPipelineCreateInfo { ref multisample_state, ref depth_stencil_state, ref color_blend_state, + ref dynamic_state, ref layout, ref subpass, @@ -2101,17 +1523,17 @@ impl GraphicsPipelineCreateInfo { ) }); let need_fragment_shader_state = need_pre_rasterization_shader_state - && rasterization_state + && (!rasterization_state .as_ref() .unwrap() .rasterizer_discard_enable - != StateMode::Fixed(true); + || dynamic_state.contains(&DynamicState::RasterizerDiscardEnable)); let need_fragment_output_state = need_pre_rasterization_shader_state - && rasterization_state + && (!rasterization_state .as_ref() .unwrap() .rasterizer_discard_enable - != StateMode::Fixed(true); + || dynamic_state.contains(&DynamicState::RasterizerDiscardEnable)); match (vertex_stage.is_some(), need_pre_rasterization_shader_state) { (true, false) => { @@ -2310,11 +1732,11 @@ impl GraphicsPipelineCreateInfo { match ( viewport_state.is_some(), need_pre_rasterization_shader_state - && rasterization_state + && (!rasterization_state .as_ref() .unwrap() .rasterizer_discard_enable - != StateMode::Fixed(true), + || dynamic_state.contains(&DynamicState::RasterizerDiscardEnable)), ) { (true, false) => { return Err(Box::new(ValidationError { @@ -2598,6 +2020,75 @@ impl GraphicsPipelineCreateInfo { .validate(device) .map_err(|err| err.add_context("viewport_state"))?; + let ViewportState { + ref viewports, + ref scissors, + _ne: _, + } = viewport_state; + + if dynamic_state.contains(&DynamicState::ViewportWithCount) { + if !viewports.is_empty() { + return Err(Box::new(ValidationError { + problem: "`dynamic_state` contains \ + `DynamicState::ViewportWithCount`, but \ + `viewport_state.viewports` is not empty" + .into(), + vuids: &["VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135"], + ..Default::default() + })); + } + } else { + if viewports.is_empty() { + return Err(Box::new(ValidationError { + problem: "`dynamic_state` does not contain \ + `DynamicState::ViewportWithCount`, but \ + `viewport_state.viewports` is empty" + .into(), + vuids: &["VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135"], + ..Default::default() + })); + } + } + + if dynamic_state.contains(&DynamicState::ScissorWithCount) { + if !scissors.is_empty() { + return Err(Box::new(ValidationError { + problem: "`dynamic_state` contains \ + `DynamicState::ScissorWithCount`, but \ + `viewport_state.scissors` is not empty" + .into(), + vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"], + ..Default::default() + })); + } + } else { + if scissors.is_empty() { + return Err(Box::new(ValidationError { + problem: "`dynamic_state` does not contain \ + `DynamicState::ScissorWithCount`, but \ + `viewport_state.scissors` is empty" + .into(), + vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"], + ..Default::default() + })); + } + } + + if !dynamic_state.contains(&DynamicState::ViewportWithCount) + && !dynamic_state.contains(&DynamicState::ScissorWithCount) + && viewports.len() != scissors.len() + { + return Err(Box::new(ValidationError { + problem: "`dynamic_state` does not contain both \ + `DynamicState::ViewportWithCount` and `DynamicState::ScissorWithCount`, \ + and the lengths of `viewport_state.viewports` and \ + `viewport_state.scissors` are not equal" + .into(), + vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"], + ..Default::default() + })); + } + // TODO: // VUID-VkGraphicsPipelineCreateInfo-primitiveFragmentShadingRateWithMultipleViewports-04503 // VUID-VkGraphicsPipelineCreateInfo-primitiveFragmentShadingRateWithMultipleViewports-04504 @@ -2608,6 +2099,75 @@ impl GraphicsPipelineCreateInfo { .validate(device) .map_err(|err| err.add_context("rasterization_state"))?; + let &RasterizationState { + depth_clamp_enable: _, + rasterizer_discard_enable: _, + polygon_mode: _, + cull_mode: _, + front_face: _, + ref depth_bias, + line_width, + line_rasterization_mode: _, + line_stipple, + _ne: _, + } = rasterization_state; + + if !dynamic_state.contains(&DynamicState::LineWidth) + && line_width != 1.0 + && !device.enabled_features().wide_lines + { + return Err(Box::new(ValidationError { + context: "rasterization_state.line_width".into(), + problem: "is not 1.0".into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( + "wide_lines", + )])]), + vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00749"], + })); + } + + if let Some(depth_bias_state) = depth_bias { + let &DepthBiasState { + constant_factor: _, + clamp, + slope_factor: _, + } = depth_bias_state; + + if !dynamic_state.contains(&DynamicState::DepthBias) + && clamp != 0.0 + && !device.enabled_features().depth_bias_clamp + { + return Err(Box::new(ValidationError { + context: "rasterization_state.depth_bias.clamp".into(), + problem: "is not 0.0".into(), + requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( + "depth_bias_clamp", + )])]), + vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00754"], + })); + } + } else if dynamic_state.contains(&DynamicState::DepthBiasEnable) { + return Err(Box::new(ValidationError { + problem: "`dynamic_state` contains `DynamicState::DepthBiasEnable`, but \ + `rasterization_state.depth_bias` is `None`" + .into(), + ..Default::default() + })); + } + + if let Some(line_stipple) = line_stipple { + if !dynamic_state.contains(&DynamicState::LineStipple) + && !(1..=256).contains(&line_stipple.factor) + { + return Err(Box::new(ValidationError { + context: "rasterization_state.line_stipple.factor".into(), + problem: "is not between 1 and 256 inclusive".into(), + vuids: &["VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767"], + ..Default::default() + })); + } + } + // TODO: // VUID-VkGraphicsPipelineCreateInfo-pStages-00740 // VUID-VkGraphicsPipelineCreateInfo-renderPass-06049 @@ -2629,6 +2189,43 @@ impl GraphicsPipelineCreateInfo { .validate(device) .map_err(|err| err.add_context("depth_stencil_state"))?; + let &DepthStencilState { + flags: _, + ref depth, + ref depth_bounds, + ref stencil, + _ne: _, + } = depth_stencil_state; + + if dynamic_state.contains(&DynamicState::DepthTestEnable) && depth.is_none() { + return Err(Box::new(ValidationError { + problem: "`dynamic_state` contains `DynamicState::DepthTestEnable`, but \ + `depth_stencil_state.depth` is `None`" + .into(), + ..Default::default() + })); + } + + if dynamic_state.contains(&DynamicState::DepthBoundsTestEnable) + && depth_bounds.is_none() + { + return Err(Box::new(ValidationError { + problem: "`dynamic_state` contains `DynamicState::DepthBoundsTestEnable`, but \ + `depth_stencil_state.depth_bounds` is `None`" + .into(), + ..Default::default() + })); + } + + if dynamic_state.contains(&DynamicState::StencilTestEnable) && stencil.is_none() { + return Err(Box::new(ValidationError { + problem: "`dynamic_state` contains `DynamicState::StencilTestEnable`, but \ + `depth_stencil_state.stencil` is `None`" + .into(), + ..Default::default() + })); + } + // TODO: // VUID-VkGraphicsPipelineCreateInfo-renderPass-06040 } @@ -2757,6 +2354,13 @@ impl GraphicsPipelineCreateInfo { .map_err(|err| err.add_context("discard_rectangle_state"))?; } + for dynamic_state in dynamic_state.iter().copied() { + dynamic_state.validate_device(device).map_err(|err| { + err.add_context("dynamic_state") + .set_vuids(&["VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-parameter"]) + })?; + } + /* Checks that rely on multiple pieces of state */ @@ -2857,16 +2461,14 @@ impl GraphicsPipelineCreateInfo { }) .unwrap(); - if let PartialStateMode::Fixed(topology) = input_assembly_state.topology { - if !input.is_compatible_with(topology) { - return Err(Box::new(ValidationError { - problem: "`input_assembly_state.topology` is not compatible with the \ - input topology of the geometry shader" - .into(), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-00738"], - ..Default::default() - })); - } + if !input.is_compatible_with(input_assembly_state.topology) { + return Err(Box::new(ValidationError { + problem: "`input_assembly_state.topology` is not compatible with the \ + input topology of the geometry shader" + .into(), + vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-00738"], + ..Default::default() + })); } } @@ -2898,11 +2500,7 @@ impl GraphicsPipelineCreateInfo { } if let (Some(input_assembly_state), Some(_)) = (input_assembly_state, tessellation_state) { - if !matches!( - input_assembly_state.topology, - PartialStateMode::Dynamic(PrimitiveTopologyClass::Patch) - | PartialStateMode::Fixed(PrimitiveTopology::PatchList) - ) { + if input_assembly_state.topology != PrimitiveTopology::PatchList { return Err(Box::new(ValidationError { problem: "`stages` contains tessellation shaders, but \ `input_assembly_state.topology` is not `PrimitiveTopology::PatchList`" @@ -2917,18 +2515,13 @@ impl GraphicsPipelineCreateInfo { (rasterization_state, depth_stencil_state) { if let Some(stencil_state) = &depth_stencil_state.stencil { - if let (StateMode::Fixed(front_reference), StateMode::Fixed(back_reference)) = - (stencil_state.front.reference, stencil_state.back.reference) + if device.enabled_extensions().khr_portability_subset + && !device.enabled_features().separate_stencil_mask_ref + && rasterization_state.cull_mode == CullMode::None + && !dynamic_state.contains(&DynamicState::StencilReference) + && stencil_state.front.reference != stencil_state.back.reference { - if device.enabled_extensions().khr_portability_subset - && !device.enabled_features().separate_stencil_mask_ref - && matches!( - rasterization_state.cull_mode, - StateMode::Fixed(CullMode::None) - ) - && front_reference != back_reference - { - return Err(Box::new(ValidationError { + return Err(Box::new(ValidationError { problem: "this device is a portability subset device, \ `rasterization_state.cull_mode` is `CullMode::None`, and \ `depth_stencil_state.stencil.front.reference` does not equal \ @@ -2939,7 +2532,6 @@ impl GraphicsPipelineCreateInfo { vuids: &["VUID-VkPipelineDepthStencilStateCreateInfo-separateStencilMaskRef-04453"], ..Default::default() })); - } } } } @@ -3002,7 +2594,9 @@ impl GraphicsPipelineCreateInfo { })); } - if let StateMode::Fixed(true) = depth_state.write_enable { + if !dynamic_state.contains(&DynamicState::DepthWriteEnable) + && depth_state.write_enable + { match subpass { PipelineSubpassType::BeginRenderPass(subpass) => { if !subpass diff --git a/vulkano/src/pipeline/graphics/multisample.rs b/vulkano/src/pipeline/graphics/multisample.rs index 6fb1a651bb..d6889953df 100644 --- a/vulkano/src/pipeline/graphics/multisample.rs +++ b/vulkano/src/pipeline/graphics/multisample.rs @@ -36,12 +36,14 @@ pub struct MultisampleState { /// /// If set to `Some`, the [`sample_rate_shading`](crate::device::Features::sample_rate_shading) /// feature must be enabled on the device. + /// + /// The default value is `None`. pub sample_shading: Option, /// A mask of bits that is ANDed with the coverage mask of each set of `rasterization_samples` /// samples. Only the first `rasterization_samples / 32` bits are used, the rest is ignored. /// - /// The default value is `[0xFFFFFFFF; 2]`. + /// The default value is `[u32::MAX; 2]`. pub sample_mask: [u32; 2], // 64 bits for needed for 64 SampleCount /// Controls whether the alpha value of the fragment will be used in an implementation-defined @@ -49,6 +51,8 @@ pub struct MultisampleState { /// then about half of the samples will be discarded. If you render to a multisample image, this /// means that the color will end up being mixed with whatever color was underneath, which gives /// the same effect as alpha blending. + /// + /// The default value is `false`. pub alpha_to_coverage_enable: bool, /// Controls whether the alpha value of all the samples will be forced to 1.0 (or the @@ -56,24 +60,34 @@ pub struct MultisampleState { /// /// If set to `true`, the [`alpha_to_one`](crate::device::Features::alpha_to_one) /// feature must be enabled on the device. + /// + /// The default value is `false`. pub alpha_to_one_enable: bool, pub _ne: crate::NonExhaustive, } -impl MultisampleState { - /// Creates a `MultisampleState` with multisampling disabled. +impl Default for MultisampleState { #[inline] - pub fn new() -> MultisampleState { - MultisampleState { + fn default() -> Self { + Self { rasterization_samples: SampleCount::Sample1, sample_shading: None, - sample_mask: [0xFFFFFFFF; 2], + sample_mask: [u32::MAX; 2], alpha_to_coverage_enable: false, alpha_to_one_enable: false, _ne: crate::NonExhaustive(()), } } +} + +impl MultisampleState { + /// Creates a `MultisampleState` with multisampling disabled. + #[inline] + #[deprecated(since = "0.34.0", note = "use `MultisampleState::default` instead")] + pub fn new() -> MultisampleState { + Self::default() + } pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let &Self { @@ -129,11 +143,3 @@ impl MultisampleState { Ok(()) } } - -impl Default for MultisampleState { - /// Returns [`MultisampleState::new()`]. - #[inline] - fn default() -> Self { - Self::new() - } -} diff --git a/vulkano/src/pipeline/graphics/rasterization.rs b/vulkano/src/pipeline/graphics/rasterization.rs index a3a6a8ee57..e0167e2538 100644 --- a/vulkano/src/pipeline/graphics/rasterization.rs +++ b/vulkano/src/pipeline/graphics/rasterization.rs @@ -10,8 +10,7 @@ //! Configures how primitives should be converted into collections of fragments. use crate::{ - device::Device, macros::vulkan_enum, pipeline::StateMode, Requires, RequiresAllOf, - RequiresOneOf, ValidationError, Version, + device::Device, macros::vulkan_enum, Requires, RequiresAllOf, RequiresOneOf, ValidationError, }; /// The state in a graphics pipeline describing how the rasterization stage should behave. @@ -22,16 +21,16 @@ pub struct RasterizationState { /// /// If enabled, the [`depth_clamp`](crate::device::Features::depth_clamp) feature must be /// enabled on the device. + /// + /// The default value is `false`. pub depth_clamp_enable: bool, /// If true, all the fragments will be discarded, and the fragment shader will not be run. This /// is usually used when your vertex shader has some side effects and you don't need to run the /// fragment shader. /// - /// If set to `Dynamic`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature must - /// be enabled on the device. - pub rasterizer_discard_enable: StateMode, + /// The default value is `false`. + pub rasterizer_discard_enable: bool, /// This setting can ask the rasterizer to downgrade triangles into lines or points, or lines /// into points. @@ -39,26 +38,26 @@ pub struct RasterizationState { /// If set to a value other than `Fill`, the /// [`fill_mode_non_solid`](crate::device::Features::fill_mode_non_solid) feature must be /// enabled on the device. + /// + /// The default value is [`PolygonMode::Fill`]. pub polygon_mode: PolygonMode, /// Specifies whether front faces or back faces should be discarded, or none, or both. /// - /// If set to `Dynamic`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub cull_mode: StateMode, + /// The default value is [`CullMode::None`]. + pub cull_mode: CullMode, /// Specifies which triangle orientation is considered to be the front of the triangle. /// - /// If set to `Dynamic`, the device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be - /// enabled on the device. - pub front_face: StateMode, + /// The default value is [`FrontFace::CounterClockwise`]. + pub front_face: FrontFace, /// Sets how to modify depth values in the rasterization stage. /// /// If set to `None`, depth biasing is disabled, the depth values will pass to the fragment /// shader unmodified. + /// + /// The default value is `None`. pub depth_bias: Option, /// Width, in pixels, of lines when drawing lines. @@ -66,13 +65,17 @@ pub struct RasterizationState { /// Setting this to a value other than 1.0 requires the /// [`wide_lines`](crate::device::Features::wide_lines) feature to be enabled on /// the device. - pub line_width: StateMode, + /// + /// The default value is `1.0`. + pub line_width: f32, /// The rasterization mode for lines. /// /// If this is not set to `Default`, the /// [`ext_line_rasterization`](crate::device::DeviceExtensions::ext_line_rasterization) /// extension and an additional feature must be enabled on the device. + /// + /// The default value is [`LineRasterizationMode::Default`]. pub line_rasterization_mode: LineRasterizationMode, /// Enables and sets the parameters for line stippling. @@ -80,33 +83,44 @@ pub struct RasterizationState { /// If this is set to `Some`, the /// [`ext_line_rasterization`](crate::device::DeviceExtensions::ext_line_rasterization) /// extension and an additional feature must be enabled on the device. - pub line_stipple: Option>, + /// + /// The default value is `None`. + pub line_stipple: Option, pub _ne: crate::NonExhaustive, } -impl RasterizationState { - /// Creates a `RasterizationState` with depth clamping, discard, depth biasing and line - /// stippling disabled, filled polygons, no culling, counterclockwise front face, and the - /// default line width and line rasterization mode. +impl Default for RasterizationState { #[inline] - pub fn new() -> Self { + fn default() -> Self { Self { depth_clamp_enable: false, - rasterizer_discard_enable: StateMode::Fixed(false), + rasterizer_discard_enable: false, polygon_mode: Default::default(), - cull_mode: StateMode::Fixed(Default::default()), - front_face: StateMode::Fixed(Default::default()), + cull_mode: Default::default(), + front_face: Default::default(), depth_bias: None, - line_width: StateMode::Fixed(1.0), + line_width: 1.0, line_rasterization_mode: Default::default(), line_stipple: None, _ne: crate::NonExhaustive(()), } } +} + +impl RasterizationState { + /// Creates a `RasterizationState` with depth clamping, discard, depth biasing and line + /// stippling disabled, filled polygons, no culling, counterclockwise front face, and the + /// default line width and line rasterization mode. + #[inline] + #[deprecated(since = "0.34.0", note = "use `RasterizationState::default` instead")] + pub fn new() -> Self { + Self::default() + } /// Sets the polygon mode. #[inline] + #[deprecated(since = "0.34.0")] pub fn polygon_mode(mut self, polygon_mode: PolygonMode) -> Self { self.polygon_mode = polygon_mode; self @@ -114,29 +128,17 @@ impl RasterizationState { /// Sets the cull mode. #[inline] + #[deprecated(since = "0.34.0")] pub fn cull_mode(mut self, cull_mode: CullMode) -> Self { - self.cull_mode = StateMode::Fixed(cull_mode); - self - } - - /// Sets the cull mode to dynamic. - #[inline] - pub fn cull_mode_dynamic(mut self) -> Self { - self.cull_mode = StateMode::Dynamic; + self.cull_mode = cull_mode; self } /// Sets the front face. #[inline] + #[deprecated(since = "0.34.0")] pub fn front_face(mut self, front_face: FrontFace) -> Self { - self.front_face = StateMode::Fixed(front_face); - self - } - - /// Sets the front face to dynamic. - #[inline] - pub fn front_face_dynamic(mut self) -> Self { - self.front_face = StateMode::Dynamic; + self.front_face = front_face; self } @@ -147,8 +149,8 @@ impl RasterizationState { polygon_mode, cull_mode, front_face, - ref depth_bias, - line_width, + depth_bias: _, + line_width: _, line_rasterization_mode, ref line_stipple, _ne: _, @@ -187,145 +189,34 @@ impl RasterizationState { })); } - match rasterizer_discard_enable { - StateMode::Fixed(false) => { - if device.enabled_extensions().khr_portability_subset - && !device.enabled_features().point_polygons - && polygon_mode == PolygonMode::Point - { - return Err(Box::new(ValidationError { - problem: "this device is a portability subset device, \ - `rasterizer_discard_enable` is `false`, and \ - `polygon_mode` is `PolygonMode::Point`" - .into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( - "point_polygons", - )])]), - vuids: &["VUID-VkPipelineRasterizationStateCreateInfo-pointPolygons-04458"], - ..Default::default() - })); - } - } - StateMode::Dynamic => { - if !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state2) - { - return Err(Box::new(ValidationError { - context: "rasterizer_discard_enable".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); - } - } - _ => (), - } - - match cull_mode { - StateMode::Fixed(cull_mode) => { - cull_mode.validate_device(device).map_err(|err| { - err.add_context("cull_mode").set_vuids(&[ - "VUID-VkPipelineRasterizationStateCreateInfo-cullMode-parameter", - ]) - })?; - } - StateMode::Dynamic => { - if !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state) - { - return Err(Box::new(ValidationError { - context: "cull_mode".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); - } - } - } - - match front_face { - StateMode::Fixed(front_face) => { - front_face.validate_device(device).map_err(|err| { - err.add_context("front_face").set_vuids(&[ - "VUID-VkPipelineRasterizationStateCreateInfo-frontFace-parameter", - ]) - })?; - } - StateMode::Dynamic => { - if !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state) - { - return Err(Box::new(ValidationError { - context: "front_face".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state")]), - ]), - // vuids? - ..Default::default() - })); - } - } - } - - if let Some(depth_bias_state) = depth_bias { - let &DepthBiasState { - enable_dynamic, - bias, - } = depth_bias_state; - - if enable_dynamic - && !(device.api_version() >= Version::V1_3 - || device.enabled_features().extended_dynamic_state2) - { - return Err(Box::new(ValidationError { - context: "depth_bias.enable_dynamic".into(), - problem: "is `true`".into(), - requires_one_of: RequiresOneOf(&[ - RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]), - RequiresAllOf(&[Requires::Feature("extended_dynamic_state2")]), - ]), - // vuids? - ..Default::default() - })); - } - - if matches!(bias, StateMode::Fixed(bias) if bias.clamp != 0.0) - && !device.enabled_features().depth_bias_clamp - { - return Err(Box::new(ValidationError { - context: "depth_bias.bias.clamp".into(), - problem: "is not 0.0".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( - "depth_bias_clamp", - )])]), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00754"], - })); - } - } - - if matches!(line_width, StateMode::Fixed(line_width) if line_width != 1.0) - && !device.enabled_features().wide_lines + if device.enabled_extensions().khr_portability_subset + && !device.enabled_features().point_polygons + && !rasterizer_discard_enable + && polygon_mode == PolygonMode::Point { return Err(Box::new(ValidationError { - context: "line_width".into(), - problem: "is not 1.0".into(), + problem: "this device is a portability subset device, \ + `rasterizer_discard_enable` is `false`, and \ + `polygon_mode` is `PolygonMode::Point`" + .into(), requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( - "wide_lines", + "point_polygons", )])]), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00749"], + vuids: &["VUID-VkPipelineRasterizationStateCreateInfo-pointPolygons-04458"], + ..Default::default() })); } + cull_mode.validate_device(device).map_err(|err| { + err.add_context("cull_mode") + .set_vuids(&["VUID-VkPipelineRasterizationStateCreateInfo-cullMode-parameter"]) + })?; + + front_face.validate_device(device).map_err(|err| { + err.add_context("front_face") + .set_vuids(&["VUID-VkPipelineRasterizationStateCreateInfo-frontFace-parameter"]) + })?; + if line_rasterization_mode != LineRasterizationMode::Default { if !device.enabled_extensions().ext_line_rasterization { return Err(Box::new(ValidationError { @@ -379,7 +270,7 @@ impl RasterizationState { } } - if let Some(line_stipple) = line_stipple { + if line_stipple.is_some() { if !device.enabled_extensions().ext_line_rasterization { return Err(Box::new(ValidationError { context: "line_stipple".into(), @@ -391,19 +282,6 @@ impl RasterizationState { })); } - if let StateMode::Fixed(line_stipple) = line_stipple { - let &LineStipple { factor, pattern: _ } = line_stipple; - - if !(1..=256).contains(&factor) { - return Err(Box::new(ValidationError { - context: "line_stipple.factor".into(), - problem: "is not between 1 and 256 inclusive".into(), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767"], - ..Default::default() - })); - } - } - match line_rasterization_mode { LineRasterizationMode::Default => { if !device.enabled_features().stippled_rectangular_lines { @@ -479,33 +357,12 @@ impl RasterizationState { } } -impl Default for RasterizationState { - /// Returns [`RasterizationState::new()`]. - #[inline] - fn default() -> Self { - Self::new() - } -} - -/// The state in a graphics pipeline describing how depth biasing should behave when enabled. +/// The values to use for depth biasing. #[derive(Clone, Copy, Debug)] pub struct DepthBiasState { - /// Sets whether depth biasing should be enabled and disabled dynamically. If set to `false`, - /// depth biasing is always enabled. + /// Specifies a constant factor to be multiplied to every depth value. /// - /// If set to `true`, the - /// [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature must - /// be enabled on the device. - pub enable_dynamic: bool, - - /// The values to use when depth biasing is enabled. - pub bias: StateMode, -} - -/// The values to use for depth biasing. -#[derive(Clone, Copy, Debug)] -pub struct DepthBias { - /// Specifies a constant factor to be added to every depth value. + /// The default value is `1.0`. pub constant_factor: f32, /// The maximum (or minimum) depth bias of a fragment. @@ -513,12 +370,27 @@ pub struct DepthBias { /// Setting this to a value other than 0.0 requires the /// [`depth_bias_clamp`](crate::device::Features::depth_bias_clamp) feature to be enabled on /// the device. + /// + /// The default value is `0.0`. pub clamp: f32, - /// A scalar factor applied to a fragment's slope in depth bias calculations. + /// A scalar factor to multiply with a fragment's slope in depth bias calculations. + /// + /// The default value is `1.0`. pub slope_factor: f32, } +impl Default for DepthBiasState { + #[inline] + fn default() -> Self { + Self { + constant_factor: 1.0, + clamp: 0.0, + slope_factor: 1.0, + } + } +} + vulkan_enum! { #[non_exhaustive] @@ -560,7 +432,6 @@ vulkan_enum! { /// as facing their front. Otherwise they will be considered as facing their back. CounterClockwise = COUNTER_CLOCKWISE, - /// Triangles whose vertices are oriented clockwise on the screen will be considered /// as facing their front. Otherwise they will be considered as facing their back. Clockwise = CLOCKWISE, @@ -660,6 +531,7 @@ impl Default for LineRasterizationMode { pub struct LineStipple { /// The repeat factor used in stippled line rasterization. Must be between 1 and 256 inclusive. pub factor: u32, + /// The bit pattern used in stippled line rasterization. pub pattern: u16, } diff --git a/vulkano/src/pipeline/graphics/tessellation.rs b/vulkano/src/pipeline/graphics/tessellation.rs index ac2363acb4..f33d987607 100644 --- a/vulkano/src/pipeline/graphics/tessellation.rs +++ b/vulkano/src/pipeline/graphics/tessellation.rs @@ -10,8 +10,8 @@ //! Subdivides primitives into smaller primitives. use crate::{ - device::Device, macros::vulkan_enum, pipeline::StateMode, Requires, RequiresAllOf, - RequiresOneOf, ValidationError, Version, + device::Device, macros::vulkan_enum, Requires, RequiresAllOf, RequiresOneOf, ValidationError, + Version, }; /// The state in a graphics pipeline describing the tessellation shader execution of a graphics @@ -20,10 +20,8 @@ use crate::{ pub struct TessellationState { /// The number of patch control points to use. /// - /// If set to `Dynamic`, the - /// [`extended_dynamic_state2_patch_control_points`](crate::device::Features::extended_dynamic_state2_patch_control_points) - /// feature must be enabled on the device. - pub patch_control_points: StateMode, + /// The default value is 3. + pub patch_control_points: u32, /// The origin to use for the tessellation domain. /// @@ -37,31 +35,34 @@ pub struct TessellationState { pub _ne: crate::NonExhaustive, } -impl TessellationState { - /// Creates a new `TessellationState` with 3 patch control points. +impl Default for TessellationState { #[inline] - pub fn new() -> Self { + fn default() -> Self { Self { - patch_control_points: StateMode::Fixed(3), + patch_control_points: 3, domain_origin: TessellationDomainOrigin::default(), _ne: crate::NonExhaustive(()), } } +} - /// Sets the number of patch control points. +impl TessellationState { + /// Creates a new `TessellationState` with 3 patch control points. #[inline] - pub fn patch_control_points(mut self, num: u32) -> Self { - self.patch_control_points = StateMode::Fixed(num); - self + #[deprecated(since = "0.34.0", note = "use `TessellationState::default` instead")] + pub fn new() -> Self { + Self::default() } - /// Sets the number of patch control points to dynamic. + /// Sets the number of patch control points. #[inline] - pub fn patch_control_points_dynamic(mut self) -> Self { - self.patch_control_points = StateMode::Dynamic; + #[deprecated(since = "0.34.0")] + pub fn patch_control_points(mut self, num: u32) -> Self { + self.patch_control_points = num; self } + #[allow(clippy::trivially_copy_pass_by_ref)] pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let &Self { patch_control_points, @@ -71,46 +72,23 @@ impl TessellationState { let properties = device.physical_device().properties(); - match patch_control_points { - StateMode::Fixed(patch_control_points) => { - if patch_control_points == 0 { - return Err(Box::new(ValidationError { - context: "patch_control_points".into(), - problem: "is zero".into(), - vuids: &[ - "VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214", - ], - ..Default::default() - })); - } - - if patch_control_points > properties.max_tessellation_patch_size { - return Err(Box::new(ValidationError { - context: "patch_control_points".into(), - problem: "exceeds the `max_tessellation_patch_size` limit".into(), - vuids: &[ - "VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214", - ], - ..Default::default() - })); - } - } - StateMode::Dynamic => { - if !device - .enabled_features() - .extended_dynamic_state2_patch_control_points - { - return Err(Box::new(ValidationError { - context: "patch_control_points".into(), - problem: "is dynamic".into(), - requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature( - "extended_dynamic_state2_patch_control_points", - )])]), - vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04870"], - })); - } - } - }; + if patch_control_points == 0 { + return Err(Box::new(ValidationError { + context: "patch_control_points".into(), + problem: "is zero".into(), + vuids: &["VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214"], + ..Default::default() + })); + } + + if patch_control_points > properties.max_tessellation_patch_size { + return Err(Box::new(ValidationError { + context: "patch_control_points".into(), + problem: "exceeds the `max_tessellation_patch_size` limit".into(), + vuids: &["VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214"], + ..Default::default() + })); + } domain_origin.validate_device(device).map_err(|err| { err.add_context("domain_origin").set_vuids(&[ @@ -137,14 +115,6 @@ impl TessellationState { } } -impl Default for TessellationState { - /// Returns [`TessellationState::new()`]. - #[inline] - fn default() -> Self { - Self::new() - } -} - vulkan_enum! { #[non_exhaustive] diff --git a/vulkano/src/pipeline/graphics/vertex_input/buffers.rs b/vulkano/src/pipeline/graphics/vertex_input/buffers.rs index 734e88a78a..a13ee613ba 100644 --- a/vulkano/src/pipeline/graphics/vertex_input/buffers.rs +++ b/vulkano/src/pipeline/graphics/vertex_input/buffers.rs @@ -17,7 +17,7 @@ use crate::{ /// A vertex definition for any number of vertex and instance buffers. #[deprecated( since = "0.33.0", - note = "Use `VertexBufferDescription` directly instead as returned by `Vertex::per_vertex` or `Vertex::per_instance`" + note = "use `VertexBufferDescription` directly instead as returned by `Vertex::per_vertex` or `Vertex::per_instance`" )] #[derive(Clone, Debug, Default)] pub struct BuffersDefinition(Vec); diff --git a/vulkano/src/pipeline/graphics/vertex_input/impl_vertex.rs b/vulkano/src/pipeline/graphics/vertex_input/impl_vertex.rs index 2f5a319b0d..431c843f85 100644 --- a/vulkano/src/pipeline/graphics/vertex_input/impl_vertex.rs +++ b/vulkano/src/pipeline/graphics/vertex_input/impl_vertex.rs @@ -97,7 +97,7 @@ macro_rules! impl_vertex { /// Trait for data types that can be used as vertex members. Used by the `impl_vertex!` macro. #[deprecated( since = "0.33.0", - note = "Derive `Vertex` instead and use field-level attributes to specify format" + note = "derive `Vertex` instead and use field-level attributes to specify format" )] pub unsafe trait VertexMember { /// Returns the format and array size of the member. diff --git a/vulkano/src/pipeline/graphics/viewport.rs b/vulkano/src/pipeline/graphics/viewport.rs index c26f4ae499..ae2ba71226 100644 --- a/vulkano/src/pipeline/graphics/viewport.rs +++ b/vulkano/src/pipeline/graphics/viewport.rs @@ -48,11 +48,7 @@ //! In all cases the number of viewports and scissor boxes must be the same. //! -use crate::{ - device::Device, - pipeline::{PartialStateMode, StateMode}, - Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, -}; +use crate::{device::Device, Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version}; use smallvec::{smallvec, SmallVec}; use std::ops::RangeInclusive; @@ -63,125 +59,90 @@ use std::ops::RangeInclusive; pub struct ViewportState { /// Specifies the viewport transforms. /// - /// If the value is `PartialStateMode::Dynamic`, then the viewports are set dynamically, but - /// the number of viewports is still fixed. - /// - /// If the value is `PartialStateMode::Dynamic(StateMode::Dynamic)`, then the number of - /// viewports is also dynamic. The device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must - /// be enabled on the device. + /// When [`DynamicState::Viewport`] is used, the values of each viewport are ignored + /// and must be set dynamically, but the number of viewports is fixed and + /// must be matched when setting the dynamic value. + /// When [`DynamicState::ViewportWithCount`] is used, the number of viewports is also dynamic, + /// and `viewports` must be empty. /// /// If neither the number of viewports nor the number of scissors is dynamic, then the /// number of both must be identical. /// - /// The default value is `PartialStateMode::Fixed` with no viewports. - pub viewports: PartialStateMode, StateMode>, + /// The default value is a single element of `Viewport::default()`. + /// + /// [`DynamicState::Viewport`]: crate::pipeline::DynamicState::Viewport + /// [`DynamicState::ViewportWithCount`]: crate::pipeline::DynamicState::ViewportWithCount + pub viewports: SmallVec<[Viewport; 1]>, /// Specifies the scissor rectangles. /// - /// If the value is `PartialStateMode::Dynamic`, then the scissors are set dynamically, but - /// the number of scissors is still fixed. - /// - /// If the value is `PartialStateMode::Dynamic(StateMode::Dynamic)`, then the number of - /// scissors is also dynamic. The device API version must be at least 1.3, or the - /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must - /// be enabled on the device. + /// When [`DynamicState::Scissor`] is used, the values of each scissor are ignored + /// and must be set dynamically, but the number of scissors is fixed and + /// must be matched when setting the dynamic value. + /// When [`DynamicState::ScissorWithCount`] is used, the number of scissors is also dynamic, + /// and `scissors` must be empty. /// /// If neither the number of viewports nor the number of scissors is dynamic, then the /// number of both must be identical. /// - /// The default value is `PartialStateMode::Fixed` with no scissors. - pub scissors: PartialStateMode, StateMode>, + /// The default value is a single element of `Scissor::default()`. + /// + /// [`DynamicState::Scissor`]: crate::pipeline::DynamicState::Scissor + /// [`DynamicState::ScissorWithCount`]: crate::pipeline::DynamicState::ScissorWithCount + pub scissors: SmallVec<[Scissor; 1]>, pub _ne: crate::NonExhaustive, } +impl Default for ViewportState { + #[inline] + fn default() -> Self { + Self { + viewports: smallvec![Viewport::default()], + scissors: smallvec![Scissor::default()], + _ne: crate::NonExhaustive(()), + } + } +} + impl ViewportState { /// Creates a `ViewportState` with fixed state and no viewports or scissors. + #[deprecated(since = "0.34.0")] #[inline] pub fn new() -> Self { Self { - viewports: PartialStateMode::Fixed(SmallVec::new()), - scissors: PartialStateMode::Fixed(SmallVec::new()), + viewports: SmallVec::new(), + scissors: SmallVec::new(), _ne: crate::NonExhaustive(()), } } /// Creates a `ViewportState` with fixed state from the given viewports and scissors. + #[deprecated(since = "0.34.0")] pub fn viewport_fixed_scissor_fixed( data: impl IntoIterator, ) -> Self { let (viewports, scissors) = data.into_iter().unzip(); Self { - viewports: PartialStateMode::Fixed(viewports), - scissors: PartialStateMode::Fixed(scissors), + viewports, + scissors, _ne: crate::NonExhaustive(()), } } /// Creates a `ViewportState` with fixed state from the given viewports, and matching scissors /// that cover the whole viewport. + #[deprecated(since = "0.34.0")] pub fn viewport_fixed_scissor_irrelevant(data: impl IntoIterator) -> Self { let viewports: SmallVec<_> = data.into_iter().collect(); - let scissors = smallvec![Scissor::irrelevant(); viewports.len()]; - Self { - viewports: PartialStateMode::Fixed(viewports), - scissors: PartialStateMode::Fixed(scissors), - _ne: crate::NonExhaustive(()), - } - } - - /// Creates a `ViewportState` with dynamic viewport, and a single scissor that always covers - /// the whole viewport. - #[inline] - pub fn viewport_dynamic_scissor_irrelevant() -> Self { - Self { - viewports: PartialStateMode::Dynamic(StateMode::Fixed(1)), - scissors: PartialStateMode::Fixed(smallvec![Scissor::irrelevant(); 1]), - _ne: crate::NonExhaustive(()), - } - } - - /// Creates a `ViewportState` with dynamic viewports and scissors, but a fixed count. - #[inline] - pub fn viewport_dynamic_scissor_dynamic(count: u32) -> Self { - Self { - viewports: PartialStateMode::Dynamic(StateMode::Fixed(count)), - scissors: PartialStateMode::Dynamic(StateMode::Fixed(count)), - _ne: crate::NonExhaustive(()), - } - } - - /// Creates a `ViewportState` with dynamic viewport count and scissor count. - #[inline] - pub fn viewport_count_dynamic_scissor_count_dynamic() -> Self { + let scissors = smallvec![Scissor::default(); viewports.len()]; Self { - viewports: PartialStateMode::Dynamic(StateMode::Dynamic), - scissors: PartialStateMode::Dynamic(StateMode::Dynamic), + viewports, + scissors, _ne: crate::NonExhaustive(()), } } - /// Returns the number of viewports and scissors. - /// - /// `None` is returned if both counts are dynamic. - #[inline] - pub(crate) fn count(&self) -> Option { - match &self.viewports { - PartialStateMode::Fixed(viewports) => return Some(viewports.len() as u32), - PartialStateMode::Dynamic(StateMode::Fixed(count)) => return Some(*count), - PartialStateMode::Dynamic(StateMode::Dynamic) => (), - } - - match &self.scissors { - PartialStateMode::Fixed(scissors) => return Some(scissors.len() as u32), - PartialStateMode::Dynamic(StateMode::Fixed(count)) => return Some(*count), - PartialStateMode::Dynamic(StateMode::Dynamic) => (), - } - - None - } - pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let Self { viewports, @@ -191,117 +152,46 @@ impl ViewportState { let properties = device.physical_device().properties(); - let viewport_count = match viewports { - PartialStateMode::Fixed(viewports) => { - if viewports.is_empty() { - return Err(Box::new(ValidationError { - context: "viewports".into(), - problem: "is empty".into(), - vuids: &["VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135"], - ..Default::default() - })); - } - - for (index, viewport) in viewports.iter().enumerate() { - viewport - .validate(device) - .map_err(|err| err.add_context(format!("viewports[{}].0", index)))?; - } - - viewports.len() as u32 - } - PartialStateMode::Dynamic(StateMode::Fixed(count)) => { - if *count == 0 { - return Err(Box::new(ValidationError { - context: "viewports".into(), - problem: "is empty".into(), - vuids: &["VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135"], - ..Default::default() - })); - } - - *count - } - PartialStateMode::Dynamic(StateMode::Dynamic) => { - // VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135 - 0 - } - }; - - let scissor_count = match scissors { - PartialStateMode::Fixed(scissors) => { - if scissors.is_empty() { - return Err(Box::new(ValidationError { - context: "scissors".into(), - problem: "is empty".into(), - vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"], - ..Default::default() - })); - } - - for (index, scissor) in scissors.iter().enumerate() { - let &Scissor { offset, extent } = scissor; - - // VUID-VkPipelineViewportStateCreateInfo-x-02821 - // Ensured by the use of an unsigned integer. - - if (i32::try_from(offset[0]).ok()) - .zip(i32::try_from(extent[0]).ok()) - .and_then(|(o, e)| o.checked_add(e)) - .is_none() - { - return Err(Box::new(ValidationError { - context: format!("scissors[{}]", index).into(), - problem: "`offset[0] + extent[0]` is greater than `i32::MAX`".into(), - vuids: &["VUID-VkPipelineViewportStateCreateInfo-offset-02822"], - ..Default::default() - })); - } - - if (i32::try_from(offset[1]).ok()) - .zip(i32::try_from(extent[1]).ok()) - .and_then(|(o, e)| o.checked_add(e)) - .is_none() - { - return Err(Box::new(ValidationError { - context: format!("scissors[{}]", index).into(), - problem: "`offset[1] + extent[1]` is greater than `i32::MAX`".into(), - vuids: &["VUID-VkPipelineViewportStateCreateInfo-offset-02823"], - ..Default::default() - })); - } - } - - scissors.len() as u32 - } - PartialStateMode::Dynamic(StateMode::Fixed(count)) => { - if *count == 0 { - return Err(Box::new(ValidationError { - context: "scissors".into(), - problem: "is empty".into(), - vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"], - ..Default::default() - })); - } - - *count - } - PartialStateMode::Dynamic(StateMode::Dynamic) => { - // VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136 - 0 + for (index, viewport) in viewports.iter().enumerate() { + viewport + .validate(device) + .map_err(|err| err.add_context(format!("viewports[{}].0", index)))?; + } + + for (index, scissor) in scissors.iter().enumerate() { + let &Scissor { offset, extent } = scissor; + + // VUID-VkPipelineViewportStateCreateInfo-x-02821 + // Ensured by the use of an unsigned integer. + + if (i32::try_from(offset[0]).ok()) + .zip(i32::try_from(extent[0]).ok()) + .and_then(|(o, e)| o.checked_add(e)) + .is_none() + { + return Err(Box::new(ValidationError { + context: format!("scissors[{}]", index).into(), + problem: "`offset[0] + extent[0]` is greater than `i32::MAX`".into(), + vuids: &["VUID-VkPipelineViewportStateCreateInfo-offset-02822"], + ..Default::default() + })); } - }; - if viewport_count != 0 && scissor_count != 0 && viewport_count != scissor_count { - return Err(Box::new(ValidationError { - problem: "the length of `viewports` and the length of `scissors` are not equal" - .into(), - vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"], - ..Default::default() - })); + if (i32::try_from(offset[1]).ok()) + .zip(i32::try_from(extent[1]).ok()) + .and_then(|(o, e)| o.checked_add(e)) + .is_none() + { + return Err(Box::new(ValidationError { + context: format!("scissors[{}]", index).into(), + problem: "`offset[1] + extent[1]` is greater than `i32::MAX`".into(), + vuids: &["VUID-VkPipelineViewportStateCreateInfo-offset-02823"], + ..Default::default() + })); + } } - if viewport_count > 1 && !device.enabled_features().multi_viewport { + if viewports.len() > 1 && !device.enabled_features().multi_viewport { return Err(Box::new(ValidationError { context: "viewports".into(), problem: "the length is greater than 1".into(), @@ -312,7 +202,7 @@ impl ViewportState { })); } - if scissor_count > 1 && !device.enabled_features().multi_viewport { + if scissors.len() > 1 && !device.enabled_features().multi_viewport { return Err(Box::new(ValidationError { context: "scissors".into(), problem: "the length is greater than 1".into(), @@ -323,7 +213,7 @@ impl ViewportState { })); } - if viewport_count > properties.max_viewports { + if viewports.len() > properties.max_viewports as usize { return Err(Box::new(ValidationError { context: "viewports".into(), problem: "the length exceeds the `max_viewports` limit".into(), @@ -332,7 +222,7 @@ impl ViewportState { })); } - if scissor_count > properties.max_viewports { + if scissors.len() > properties.max_viewports as usize { return Err(Box::new(ValidationError { context: "scissors".into(), problem: "the length exceeds the `max_viewports` limit".into(), @@ -345,21 +235,18 @@ impl ViewportState { } } -impl Default for ViewportState { - /// Returns [`ViewportState::new()`]. - #[inline] - fn default() -> Self { - Self::new() - } -} - /// State of a single viewport. #[derive(Debug, Clone, PartialEq)] pub struct Viewport { /// Coordinates in pixels of the top-left hand corner of the viewport. + /// + /// The default value is `[0.0; 2]`. pub offset: [f32; 2], /// Dimensions in pixels of the viewport. + /// + /// The default value is `[1.0; 2]`, which you probably want to override if you are not + /// using dynamic state. pub extent: [f32; 2], /// Minimum and maximum values of the depth. @@ -369,9 +256,22 @@ pub struct Viewport { /// /// This is equivalents to `glDepthRange` in OpenGL, except that OpenGL uses the Z coordinate /// range from `-1.0` to `1.0` instead. + /// + /// The default value is `0.0..=1.0`. pub depth_range: RangeInclusive, } +impl Default for Viewport { + #[inline] + fn default() -> Self { + Self { + offset: [0.0; 2], + extent: [1.0; 2], + depth_range: 0.0..=1.0, + } + } +} + impl Viewport { pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { let &Self { @@ -525,28 +425,33 @@ impl From<&Viewport> for ash::vk::Viewport { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Scissor { /// Coordinates of the top-left hand corner of the box. + /// + /// The default value is `[0; 2]`. pub offset: [u32; 2], /// Dimensions of the box. + /// + /// The default value is `[i32::MAX; 2]`. pub extent: [u32; 2], } -impl Scissor { - /// Returns a scissor that, when used, will instruct the pipeline to draw to the entire - /// framebuffer no matter its size. +impl Default for Scissor { #[inline] - pub fn irrelevant() -> Scissor { - Scissor { - offset: [0, 0], - extent: [0x7fffffff, 0x7fffffff], + fn default() -> Scissor { + Self { + offset: [0; 2], + extent: [i32::MAX as u32; 2], } } } -impl Default for Scissor { +impl Scissor { + /// Returns a scissor that, when used, will instruct the pipeline to draw to the entire + /// framebuffer no matter its size. + #[deprecated(since = "0.34.0", note = "use `Scissor::default` instead")] #[inline] - fn default() -> Scissor { - Scissor::irrelevant() + pub fn irrelevant() -> Scissor { + Self::default() } } diff --git a/vulkano/src/pipeline/mod.rs b/vulkano/src/pipeline/mod.rs index 1ed1a7c3aa..9c40b85dd0 100644 --- a/vulkano/src/pipeline/mod.rs +++ b/vulkano/src/pipeline/mod.rs @@ -945,441 +945,571 @@ vulkan_bitflags! { vulkan_enum! { #[non_exhaustive] - /// A particular state value within a graphics pipeline that can be dynamically set by a command - /// buffer. + /// A particular state value within a pipeline that can be dynamically set by a command buffer. + /// + /// Whenever a particular state is set to be dynamic while creating the pipeline, + /// the corresponding predefined value in the pipeline's create info is ignored, unless + /// specified otherwise here. + /// + /// If the dynamic state is used to enable/disable a certain functionality, + /// and the value in the create info is an `Option` + /// (for example, [`DynamicState::DepthTestEnable`] and [`DepthStencilState::depth`]), + /// then that `Option` must be `Some` when creating the pipeline, + /// in order to provide settings to use when the functionality is enabled. + /// + /// [`DepthStencilState::depth`]: (crate::pipeline::graphics::depth_stencil::DepthStencilState::depth) DynamicState = DynamicState(i32); - // TODO: document + /// The elements, but not the count, of + /// [`ViewportState::viewports`](crate::pipeline::graphics::viewport::ViewportState::viewports). + /// + /// Set with + /// [`set_viewport`](crate::command_buffer::AutoCommandBufferBuilder::set_viewport). Viewport = VIEWPORT, - // TODO: document + /// The elements, but not the count, of + /// [`ViewportState::scissors`](crate::pipeline::graphics::viewport::ViewportState::scissors). + /// + /// Set with + /// [`set_scissor`](crate::command_buffer::AutoCommandBufferBuilder::set_scissor). Scissor = SCISSOR, - // TODO: document + /// The value of + /// [`RasterizationState::line_width`](crate::pipeline::graphics::rasterization::RasterizationState::line_width). + /// + /// Set with + /// [`set_line_width`](crate::command_buffer::AutoCommandBufferBuilder::set_line_width). LineWidth = LINE_WIDTH, - // TODO: document + /// The value of + /// [`RasterizationState::depth_bias`](crate::pipeline::graphics::rasterization::RasterizationState::depth_bias). + /// + /// Set with + /// [`set_depth_bias`](crate::command_buffer::AutoCommandBufferBuilder::set_depth_bias). DepthBias = DEPTH_BIAS, - // TODO: document + /// The value of + /// [`ColorBlendState::blend_constants`](crate::pipeline::graphics::color_blend::ColorBlendState::blend_constants). + /// + /// Set with + /// [`set_blend_constants`](crate::command_buffer::AutoCommandBufferBuilder::set_blend_constants). BlendConstants = BLEND_CONSTANTS, - // TODO: document + /// The value, but not the `Option` variant, of + /// [`DepthStencilState::depth_bounds`](crate::pipeline::graphics::depth_stencil::DepthStencilState::depth_bounds). + /// + /// Set with + /// [`set_depth_bounds`](crate::command_buffer::AutoCommandBufferBuilder::set_depth_bounds). DepthBounds = DEPTH_BOUNDS, - // TODO: document + /// The value of + /// [`StencilOpState::compare_mask`](crate::pipeline::graphics::depth_stencil::StencilOpState::compare_mask) + /// for both the front and back face. + /// + /// Set with + /// [`set_stencil_compare_mask`](crate::command_buffer::AutoCommandBufferBuilder::set_stencil_compare_mask). StencilCompareMask = STENCIL_COMPARE_MASK, - // TODO: document + /// The value of + /// [`StencilOpState::write_mask`](crate::pipeline::graphics::depth_stencil::StencilOpState::write_mask) + /// for both the front and back face. + /// + /// Set with + /// [`set_stencil_write_mask`](crate::command_buffer::AutoCommandBufferBuilder::set_stencil_write_mask). StencilWriteMask = STENCIL_WRITE_MASK, - // TODO: document + /// The value of + /// [`StencilOpState::reference`](crate::pipeline::graphics::depth_stencil::StencilOpState::reference) + /// for both the front and back face. + /// + /// Set with + /// [`set_stencil_reference`](crate::command_buffer::AutoCommandBufferBuilder::set_stencil_reference). StencilReference = STENCIL_REFERENCE, - // TODO: document + /// The value of + /// [`RasterizationState::cull_mode`](crate::pipeline::graphics::rasterization::RasterizationState::cull_mode). + /// + /// Set with + /// [`set_cull_mode`](crate::command_buffer::AutoCommandBufferBuilder::set_cull_mode). CullMode = CULL_MODE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// The value of + /// [`RasterizationState::front_face`](crate::pipeline::graphics::rasterization::RasterizationState::front_face). + /// + /// Set with + /// [`set_front_face`](crate::command_buffer::AutoCommandBufferBuilder::set_front_face). FrontFace = FRONT_FACE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// The value of + /// [`InputAssemblyState::topology`](crate::pipeline::graphics::input_assembly::InputAssemblyState::topology). + /// + /// Set with + /// [`set_primitive_topology`](crate::command_buffer::AutoCommandBufferBuilder::set_primitive_topology). PrimitiveTopology = PRIMITIVE_TOPOLOGY RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// Both the elements and the count of + /// [`ViewportState::viewports`](crate::pipeline::graphics::viewport::ViewportState::viewports). + /// + /// Set with + /// [`set_viewport_with_count`](crate::command_buffer::AutoCommandBufferBuilder::set_viewport_with_count). ViewportWithCount = VIEWPORT_WITH_COUNT RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// Both the elements and the count of + /// [`ViewportState::scissors`](crate::pipeline::graphics::viewport::ViewportState::scissors). + /// + /// Set with + /// [`set_scissor_with_count`](crate::command_buffer::AutoCommandBufferBuilder::set_scissor_with_count). ScissorWithCount = SCISSOR_WITH_COUNT RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), + /* TODO: enable // TODO: document VertexInputBindingStride = VERTEX_INPUT_BINDING_STRIDE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), - ]), + ]),*/ - // TODO: document + /// The `Option` variant of + /// [`DepthStencilState::depth`](crate::pipeline::graphics::depth_stencil::DepthStencilState::depth). + /// + /// Set with + /// [`set_depth_test_enable`](crate::command_buffer::AutoCommandBufferBuilder::set_depth_test_enable). DepthTestEnable = DEPTH_TEST_ENABLE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// The value of + /// [`DepthState::write_enable`](crate::pipeline::graphics::depth_stencil::DepthState::write_enable). + /// + /// Set with + /// [`set_depth_write_enable`](crate::command_buffer::AutoCommandBufferBuilder::set_depth_write_enable). DepthWriteEnable = DEPTH_WRITE_ENABLE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// The value of + /// [`DepthState::compare_op`](crate::pipeline::graphics::depth_stencil::DepthState::compare_op). + /// + /// Set with + /// [`set_depth_compare_op`](crate::command_buffer::AutoCommandBufferBuilder::set_depth_compare_op). DepthCompareOp = DEPTH_COMPARE_OP RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// The `Option` variant of + /// [`DepthStencilState::depth_bounds`](crate::pipeline::graphics::depth_stencil::DepthStencilState::depth_bounds). + /// + /// Set with + /// [`set_depth_bounds_test_enable`](crate::command_buffer::AutoCommandBufferBuilder::set_depth_bounds_test_enable). DepthBoundsTestEnable = DEPTH_BOUNDS_TEST_ENABLE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// The `Option` variant of + /// [`DepthStencilState::stencil`](crate::pipeline::graphics::depth_stencil::DepthStencilState::stencil). + /// + /// Set with + /// [`set_stencil_test_enable`](crate::command_buffer::AutoCommandBufferBuilder::set_stencil_test_enable). StencilTestEnable = STENCIL_TEST_ENABLE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// The value of + /// [`StencilOpState::ops`](crate::pipeline::graphics::depth_stencil::StencilOpState::ops) + /// for both the front and back face. + /// + /// Set with + /// [`set_stencil_op`](crate::command_buffer::AutoCommandBufferBuilder::set_stencil_op). StencilOp = STENCIL_OP RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state)]), ]), - // TODO: document + /// The value of + /// [`RasterizationState::rasterizer_discard_enable`](crate::pipeline::graphics::rasterization::RasterizationState::rasterizer_discard_enable). + /// + /// Set with + /// [`set_rasterizer_discard_enable`](crate::command_buffer::AutoCommandBufferBuilder::set_rasterizer_discard_enable). RasterizerDiscardEnable = RASTERIZER_DISCARD_ENABLE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state2)]), ]), - // TODO: document + /// The `Option` variant of + /// [`RasterizationState::depth_bias`](crate::pipeline::graphics::rasterization::RasterizationState::depth_bias). + /// + /// Set with + /// [`set_depth_bias_enable`](crate::command_buffer::AutoCommandBufferBuilder::set_depth_bias_enable). DepthBiasEnable = DEPTH_BIAS_ENABLE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state2)]), ]), - // TODO: document + /// The value of + /// [`InputAssemblyState::primitive_restart_enable`](crate::pipeline::graphics::input_assembly::InputAssemblyState::primitive_restart_enable). + /// + /// Set with + /// [`set_primitive_restart_enable`](crate::command_buffer::AutoCommandBufferBuilder::set_primitive_restart_enable). PrimitiveRestartEnable = PRIMITIVE_RESTART_ENABLE RequiresOneOf([ RequiresAllOf([APIVersion(V1_3)]), RequiresAllOf([DeviceExtension(ext_extended_dynamic_state2)]), ]), + /* TODO: enable // TODO: document ViewportWScaling = VIEWPORT_W_SCALING_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(nv_clip_space_w_scaling)]), - ]), + ]), */ - // TODO: document + /// The elements, but not count, of + /// [`DiscardRectangleState::rectangles`](crate::pipeline::graphics::discard_rectangle::DiscardRectangleState::rectangles). + /// + /// Set with + /// [`set_discard_rectangle`](crate::command_buffer::AutoCommandBufferBuilder::set_discard_rectangle). DiscardRectangle = DISCARD_RECTANGLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_discard_rectangles)]), ]), + /* TODO: enable // TODO: document SampleLocations = SAMPLE_LOCATIONS_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_sample_locations)]), - ]), + ]), */ + /* TODO: enable // TODO: document RayTracingPipelineStackSize = RAY_TRACING_PIPELINE_STACK_SIZE_KHR RequiresOneOf([ RequiresAllOf([DeviceExtension(khr_ray_tracing_pipeline)]), - ]), + ]), */ + /* TODO: enable // TODO: document ViewportShadingRatePalette = VIEWPORT_SHADING_RATE_PALETTE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(nv_shading_rate_image)]), - ]), + ]), */ + /* TODO: enable // TODO: document ViewportCoarseSampleOrder = VIEWPORT_COARSE_SAMPLE_ORDER_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(nv_shading_rate_image)]), - ]), + ]), */ + /* TODO: enable // TODO: document ExclusiveScissor = EXCLUSIVE_SCISSOR_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(nv_scissor_exclusive)]), - ]), + ]), */ + /* TODO: enable // TODO: document FragmentShadingRate = FRAGMENT_SHADING_RATE_KHR RequiresOneOf([ RequiresAllOf([DeviceExtension(khr_fragment_shading_rate)]), - ]), + ]), */ - // TODO: document + /// The value of + /// [`RasterizationState::line_stipple`](crate::pipeline::graphics::rasterization::RasterizationState::line_stipple). + /// + /// Set with + /// [`set_line_stipple`](crate::command_buffer::AutoCommandBufferBuilder::set_line_stipple). LineStipple = LINE_STIPPLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_line_rasterization)]), ]), + /* TODO: enable // TODO: document VertexInput = VERTEX_INPUT_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_vertex_input_dynamic_state)]), - ]), + ]), */ - // TODO: document + /// The value of + /// [`TessellationState::patch_control_points`](crate::pipeline::graphics::tessellation::TessellationState::patch_control_points). + /// + /// Set with + /// [`set_patch_control_points`](crate::command_buffer::AutoCommandBufferBuilder::set_patch_control_points). PatchControlPoints = PATCH_CONTROL_POINTS_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state2)]), ]), - // TODO: document + /// The value of + /// [`ColorBlendState::logic_op`](crate::pipeline::graphics::color_blend::ColorBlendState::logic_op). + /// + /// Set with + /// [`set_logic_op`](crate::command_buffer::AutoCommandBufferBuilder::set_logic_op). LogicOp = LOGIC_OP_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state2)]), ]), - // TODO: document + /// The value of + /// [`ColorBlendAttachmentState::color_write_enable`](crate::pipeline::graphics::color_blend::ColorBlendAttachmentState::color_write_enable) + /// for every attachment. + /// + /// Set with + /// [`set_color_write_enable`](crate::command_buffer::AutoCommandBufferBuilder::set_color_write_enable). ColorWriteEnable = COLOR_WRITE_ENABLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_color_write_enable)]), ]), + /* TODO: enable // TODO: document TessellationDomainOrigin = TESSELLATION_DOMAIN_ORIGIN_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document DepthClampEnable = DEPTH_CLAMP_ENABLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document PolygonMode = POLYGON_MODE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document RasterizationSamples = RASTERIZATION_SAMPLES_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document SampleMask = SAMPLE_MASK_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document AlphaToCoverageEnable = ALPHA_TO_COVERAGE_ENABLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document AlphaToOneEnable = ALPHA_TO_ONE_ENABLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document LogicOpEnable = LOGIC_OP_ENABLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ColorBlendEnable = COLOR_BLEND_ENABLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ColorBlendEquation = COLOR_BLEND_EQUATION_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ColorWriteMask = COLOR_WRITE_MASK_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document RasterizationStream = RASTERIZATION_STREAM_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ConservativeRasterizationMode = CONSERVATIVE_RASTERIZATION_MODE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ExtraPrimitiveOverestimationSize = EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document DepthClipEnable = DEPTH_CLIP_ENABLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document SampleLocationsEnable = SAMPLE_LOCATIONS_ENABLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ColorBlendAdvanced = COLOR_BLEND_ADVANCED_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ProvokingVertexMode = PROVOKING_VERTEX_MODE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document LineRasterizationMode = LINE_RASTERIZATION_MODE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document LineStippleEnable = LINE_STIPPLE_ENABLE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document DepthClipNegativeOneToOne = DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ViewportWScalingEnable = VIEWPORT_W_SCALING_ENABLE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ViewportSwizzle = VIEWPORT_SWIZZLE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document CoverageToColorEnable = COVERAGE_TO_COLOR_ENABLE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document CoverageToColorLocation = COVERAGE_TO_COLOR_LOCATION_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document CoverageModulationMode = COVERAGE_MODULATION_MODE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document CoverageModulationTableEnable = COVERAGE_MODULATION_TABLE_ENABLE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document CoverageModulationTable = COVERAGE_MODULATION_TABLE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document ShadingRateImageEnable = SHADING_RATE_IMAGE_ENABLE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document RepresentativeFragmentTestEnable = REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), + ]), */ + /* TODO: enable // TODO: document CoverageReductionMode = COVERAGE_REDUCTION_MODE_NV RequiresOneOf([ RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]), - ]), -} - -/// Specifies how a dynamic state is handled by a graphics pipeline. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum StateMode { - /// The pipeline has a fixed value for this state. Previously set dynamic state will be lost - /// when binding it, and will have to be re-set after binding a pipeline that uses it. - Fixed(F), - - /// The pipeline expects a dynamic value to be set by a command buffer. Previously set dynamic - /// state is not disturbed when binding it. - Dynamic, -} - -impl From> for StateMode { - fn from(val: Option) -> Self { - match val { - Some(x) => StateMode::Fixed(x), - None => StateMode::Dynamic, - } - } -} - -impl From> for Option { - fn from(val: StateMode) -> Self { - match val { - StateMode::Fixed(x) => Some(x), - StateMode::Dynamic => None, - } - } -} - -/// A variant of `StateMode` that is used for cases where some value is still needed when the state -/// is dynamic. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum PartialStateMode { - Fixed(F), - Dynamic(D), + ]), */ }