mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 22:34:43 +00:00
Add synchronization tracking for render pass operations (#2101)
This commit is contained in:
parent
10d7349556
commit
79c39ecb06
@ -74,7 +74,18 @@ fn write_shader_execution(execution: &ShaderExecution) -> TokenStream {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ShaderExecution::Fragment => quote! { ::vulkano::shader::ShaderExecution::Fragment },
|
ShaderExecution::Fragment(::vulkano::shader::FragmentShaderExecution {
|
||||||
|
fragment_tests_stages,
|
||||||
|
}) => {
|
||||||
|
let fragment_tests_stages = format_ident!("{}", format!("{:?}", fragment_tests_stages));
|
||||||
|
quote! {
|
||||||
|
::vulkano::shader::ShaderExecution::Fragment(
|
||||||
|
::vulkano::shader::FragmentShaderExecution {
|
||||||
|
fragment_tests_stages: ::vulkano::shader::FragmentTestsStages::#fragment_tests_stages,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
ShaderExecution::Compute => quote! { ::vulkano::shader::ShaderExecution::Compute },
|
ShaderExecution::Compute => quote! { ::vulkano::shader::ShaderExecution::Compute },
|
||||||
ShaderExecution::RayGeneration => {
|
ShaderExecution::RayGeneration => {
|
||||||
quote! { ::vulkano::shader::ShaderExecution::RayGeneration }
|
quote! { ::vulkano::shader::ShaderExecution::RayGeneration }
|
||||||
|
@ -1419,7 +1419,6 @@ where
|
|||||||
DynamicState::ShadingRateImageEnable => todo!(),
|
DynamicState::ShadingRateImageEnable => todo!(),
|
||||||
DynamicState::RepresentativeFragmentTestEnable => todo!(),
|
DynamicState::RepresentativeFragmentTestEnable => todo!(),
|
||||||
DynamicState::CoverageReductionMode => todo!(),
|
DynamicState::CoverageReductionMode => todo!(),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1709,7 +1709,7 @@ impl SyncCommandBufferBuilder {
|
|||||||
ResourceUseRef {
|
ResourceUseRef {
|
||||||
command_index,
|
command_index,
|
||||||
command_name,
|
command_name,
|
||||||
resource_in_command: ResourceInCommand::DepthAttachment,
|
resource_in_command: ResourceInCommand::DepthStencilAttachment,
|
||||||
secondary_use_ref: None,
|
secondary_use_ref: None,
|
||||||
},
|
},
|
||||||
Resource::Image {
|
Resource::Image {
|
||||||
@ -1736,7 +1736,7 @@ impl SyncCommandBufferBuilder {
|
|||||||
ResourceUseRef {
|
ResourceUseRef {
|
||||||
command_index,
|
command_index,
|
||||||
command_name,
|
command_name,
|
||||||
resource_in_command: ResourceInCommand::DepthResolveAttachment,
|
resource_in_command: ResourceInCommand::DepthStencilResolveAttachment,
|
||||||
secondary_use_ref: None,
|
secondary_use_ref: None,
|
||||||
},
|
},
|
||||||
Resource::Image {
|
Resource::Image {
|
||||||
@ -1773,7 +1773,7 @@ impl SyncCommandBufferBuilder {
|
|||||||
ResourceUseRef {
|
ResourceUseRef {
|
||||||
command_index,
|
command_index,
|
||||||
command_name,
|
command_name,
|
||||||
resource_in_command: ResourceInCommand::StencilAttachment,
|
resource_in_command: ResourceInCommand::DepthStencilAttachment,
|
||||||
secondary_use_ref: None,
|
secondary_use_ref: None,
|
||||||
},
|
},
|
||||||
Resource::Image {
|
Resource::Image {
|
||||||
@ -1800,7 +1800,7 @@ impl SyncCommandBufferBuilder {
|
|||||||
ResourceUseRef {
|
ResourceUseRef {
|
||||||
command_index,
|
command_index,
|
||||||
command_name,
|
command_name,
|
||||||
resource_in_command: ResourceInCommand::StencilResolveAttachment,
|
resource_in_command: ResourceInCommand::DepthStencilResolveAttachment,
|
||||||
secondary_use_ref: None,
|
secondary_use_ref: None,
|
||||||
},
|
},
|
||||||
Resource::Image {
|
Resource::Image {
|
||||||
|
@ -592,8 +592,8 @@ impl From<ResourceUseRef> for SecondaryResourceUseRef {
|
|||||||
pub enum ResourceInCommand {
|
pub enum ResourceInCommand {
|
||||||
ColorAttachment { index: u32 },
|
ColorAttachment { index: u32 },
|
||||||
ColorResolveAttachment { index: u32 },
|
ColorResolveAttachment { index: u32 },
|
||||||
DepthAttachment,
|
DepthStencilAttachment,
|
||||||
DepthResolveAttachment,
|
DepthStencilResolveAttachment,
|
||||||
DescriptorSet { set: u32, binding: u32, index: u32 },
|
DescriptorSet { set: u32, binding: u32, index: u32 },
|
||||||
Destination,
|
Destination,
|
||||||
FramebufferAttachment { index: u32 },
|
FramebufferAttachment { index: u32 },
|
||||||
@ -602,8 +602,6 @@ pub enum ResourceInCommand {
|
|||||||
IndirectBuffer,
|
IndirectBuffer,
|
||||||
SecondaryCommandBuffer { index: u32 },
|
SecondaryCommandBuffer { index: u32 },
|
||||||
Source,
|
Source,
|
||||||
StencilAttachment,
|
|
||||||
StencilResolveAttachment,
|
|
||||||
VertexBuffer { binding: u32 },
|
VertexBuffer { binding: u32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,14 +34,15 @@ use crate::{
|
|||||||
},
|
},
|
||||||
descriptor_set::{DescriptorSetResources, DescriptorSetWithOffsets},
|
descriptor_set::{DescriptorSetResources, DescriptorSetWithOffsets},
|
||||||
device::{Device, DeviceOwned, QueueFamilyProperties, QueueFlags},
|
device::{Device, DeviceOwned, QueueFamilyProperties, QueueFlags},
|
||||||
format::{Format, FormatFeatures},
|
format::FormatFeatures,
|
||||||
image::{sys::Image, ImageAspects, ImageLayout, ImageSubresourceRange},
|
image::{sys::Image, ImageAspects, ImageLayout, ImageSubresourceRange, ImageViewAbstract},
|
||||||
pipeline::{
|
pipeline::{
|
||||||
graphics::{
|
graphics::{
|
||||||
color_blend::LogicOp,
|
color_blend::LogicOp,
|
||||||
depth_stencil::{CompareOp, StencilOps},
|
depth_stencil::{CompareOp, StencilOps},
|
||||||
input_assembly::{IndexType, PrimitiveTopology},
|
input_assembly::{IndexType, PrimitiveTopology},
|
||||||
rasterization::{CullMode, DepthBias, FrontFace, LineStipple},
|
rasterization::{CullMode, DepthBias, FrontFace, LineStipple},
|
||||||
|
render_pass::PipelineRenderingCreateInfo,
|
||||||
viewport::{Scissor, Viewport},
|
viewport::{Scissor, Viewport},
|
||||||
},
|
},
|
||||||
ComputePipeline, DynamicState, GraphicsPipeline, PipelineBindPoint, PipelineLayout,
|
ComputePipeline, DynamicState, GraphicsPipeline, PipelineBindPoint, PipelineLayout,
|
||||||
@ -49,7 +50,7 @@ use crate::{
|
|||||||
query::{QueryControlFlags, QueryType},
|
query::{QueryControlFlags, QueryType},
|
||||||
range_map::RangeMap,
|
range_map::RangeMap,
|
||||||
range_set::RangeSet,
|
range_set::RangeSet,
|
||||||
render_pass::{Framebuffer, Subpass},
|
render_pass::{Framebuffer, LoadOp, StoreOp, Subpass},
|
||||||
sync::{
|
sync::{
|
||||||
BufferMemoryBarrier, DependencyInfo, ImageMemoryBarrier, PipelineStage,
|
BufferMemoryBarrier, DependencyInfo, ImageMemoryBarrier, PipelineStage,
|
||||||
PipelineStageAccess, PipelineStageAccessSet, PipelineStages,
|
PipelineStageAccess, PipelineStageAccessSet, PipelineStages,
|
||||||
@ -847,49 +848,48 @@ struct RenderPassState {
|
|||||||
contents: SubpassContents,
|
contents: SubpassContents,
|
||||||
render_area_offset: [u32; 2],
|
render_area_offset: [u32; 2],
|
||||||
render_area_extent: [u32; 2],
|
render_area_extent: [u32; 2],
|
||||||
|
|
||||||
|
rendering_info: PipelineRenderingCreateInfo,
|
||||||
|
attachments: Option<RenderPassStateAttachments>,
|
||||||
|
|
||||||
render_pass: RenderPassStateType,
|
render_pass: RenderPassStateType,
|
||||||
view_mask: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderPassState {
|
impl RenderPassState {
|
||||||
fn from_inheritance(render_pass: &CommandBufferInheritanceRenderPassType) -> Self {
|
fn from_inheritance(render_pass: &CommandBufferInheritanceRenderPassType) -> Self {
|
||||||
// In a secondary command buffer, we don't know the render area yet, so use a
|
|
||||||
// dummy value.
|
|
||||||
let render_area_offset = [0, 0];
|
|
||||||
let mut render_area_extent = [u32::MAX, u32::MAX];
|
|
||||||
|
|
||||||
match render_pass {
|
match render_pass {
|
||||||
CommandBufferInheritanceRenderPassType::BeginRenderPass(info) => {
|
CommandBufferInheritanceRenderPassType::BeginRenderPass(info) => {
|
||||||
if let Some(framebuffer) = &info.framebuffer {
|
|
||||||
// Still not exact, but it's a better upper bound.
|
|
||||||
render_area_extent = framebuffer.extent();
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderPassState {
|
RenderPassState {
|
||||||
contents: SubpassContents::Inline,
|
contents: SubpassContents::Inline,
|
||||||
render_area_offset,
|
render_area_offset: [0, 0],
|
||||||
render_area_extent,
|
render_area_extent: (info.framebuffer.as_ref())
|
||||||
|
// Still not exact, but it's a better upper bound.
|
||||||
|
.map_or([u32::MAX, u32::MAX], |framebuffer| framebuffer.extent()),
|
||||||
|
|
||||||
|
rendering_info: PipelineRenderingCreateInfo::from_subpass(&info.subpass),
|
||||||
|
attachments: info.framebuffer.as_ref().map(|framebuffer| {
|
||||||
|
RenderPassStateAttachments::from_subpass(&info.subpass, framebuffer)
|
||||||
|
}),
|
||||||
|
|
||||||
render_pass: BeginRenderPassState {
|
render_pass: BeginRenderPassState {
|
||||||
subpass: info.subpass.clone(),
|
subpass: info.subpass.clone(),
|
||||||
framebuffer: info.framebuffer.clone(),
|
framebuffer: info.framebuffer.clone(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
view_mask: info.subpass.subpass_desc().view_mask,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CommandBufferInheritanceRenderPassType::BeginRendering(info) => RenderPassState {
|
CommandBufferInheritanceRenderPassType::BeginRendering(info) => RenderPassState {
|
||||||
contents: SubpassContents::Inline,
|
contents: SubpassContents::Inline,
|
||||||
render_area_offset,
|
render_area_offset: [0, 0],
|
||||||
render_area_extent,
|
render_area_extent: [u32::MAX, u32::MAX],
|
||||||
|
|
||||||
|
rendering_info: PipelineRenderingCreateInfo::from_inheritance_rendering_info(info),
|
||||||
|
attachments: None,
|
||||||
|
|
||||||
render_pass: BeginRenderingState {
|
render_pass: BeginRenderingState {
|
||||||
attachments: None,
|
|
||||||
color_attachment_formats: info.color_attachment_formats.clone(),
|
|
||||||
depth_attachment_format: info.depth_attachment_format,
|
|
||||||
stencil_attachment_format: info.stencil_attachment_format,
|
|
||||||
pipeline_used: false,
|
pipeline_used: false,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
view_mask: info.view_mask,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -920,17 +920,190 @@ struct BeginRenderPassState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct BeginRenderingState {
|
struct BeginRenderingState {
|
||||||
attachments: Option<BeginRenderingAttachments>,
|
|
||||||
color_attachment_formats: Vec<Option<Format>>,
|
|
||||||
depth_attachment_format: Option<Format>,
|
|
||||||
stencil_attachment_format: Option<Format>,
|
|
||||||
pipeline_used: bool,
|
pipeline_used: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BeginRenderingAttachments {
|
struct RenderPassStateAttachments {
|
||||||
color_attachments: Vec<Option<RenderingAttachmentInfo>>,
|
color_attachments: Vec<Option<RenderPassStateAttachmentInfo>>,
|
||||||
depth_attachment: Option<RenderingAttachmentInfo>,
|
depth_attachment: Option<RenderPassStateAttachmentInfo>,
|
||||||
stencil_attachment: Option<RenderingAttachmentInfo>,
|
stencil_attachment: Option<RenderPassStateAttachmentInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderPassStateAttachments {
|
||||||
|
fn from_subpass(subpass: &Subpass, framebuffer: &Framebuffer) -> Self {
|
||||||
|
let subpass_desc = subpass.subpass_desc();
|
||||||
|
let rp_attachments = subpass.render_pass().attachments();
|
||||||
|
let fb_attachments = framebuffer.attachments();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
color_attachments: (subpass_desc.color_attachments.iter().enumerate())
|
||||||
|
.map(|(index, atch_ref)| {
|
||||||
|
(atch_ref.as_ref()).map(|atch_ref| RenderPassStateAttachmentInfo {
|
||||||
|
image_view: fb_attachments[atch_ref.attachment as usize].clone(),
|
||||||
|
image_layout: atch_ref.layout,
|
||||||
|
load_access: subpass
|
||||||
|
.load_op(atch_ref.attachment)
|
||||||
|
.and_then(color_load_access),
|
||||||
|
store_access: subpass
|
||||||
|
.store_op(atch_ref.attachment)
|
||||||
|
.and_then(color_store_access),
|
||||||
|
resolve_info: (subpass_desc.resolve_attachments.get(index))
|
||||||
|
.and_then(|atch_ref| atch_ref.as_ref())
|
||||||
|
.map(|atch_ref| RenderPassStateAttachmentResolveInfo {
|
||||||
|
image_view: fb_attachments[atch_ref.attachment as usize].clone(),
|
||||||
|
image_layout: atch_ref.layout,
|
||||||
|
load_access: subpass
|
||||||
|
.load_op(atch_ref.attachment)
|
||||||
|
.and_then(color_load_access),
|
||||||
|
store_access: subpass
|
||||||
|
.store_op(atch_ref.attachment)
|
||||||
|
.and_then(color_store_access),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
depth_attachment: (subpass_desc.depth_stencil_attachment.as_ref())
|
||||||
|
.filter(|atch_ref| {
|
||||||
|
(rp_attachments[atch_ref.attachment as usize].format.unwrap())
|
||||||
|
.aspects()
|
||||||
|
.intersects(ImageAspects::DEPTH)
|
||||||
|
})
|
||||||
|
.map(|atch_ref| RenderPassStateAttachmentInfo {
|
||||||
|
image_view: fb_attachments[atch_ref.attachment as usize].clone(),
|
||||||
|
image_layout: atch_ref.layout,
|
||||||
|
load_access: subpass
|
||||||
|
.load_op(atch_ref.attachment)
|
||||||
|
.and_then(depth_stencil_load_access),
|
||||||
|
store_access: subpass
|
||||||
|
.store_op(atch_ref.attachment)
|
||||||
|
.and_then(depth_stencil_store_access),
|
||||||
|
resolve_info: None,
|
||||||
|
}),
|
||||||
|
stencil_attachment: (subpass_desc.depth_stencil_attachment.as_ref())
|
||||||
|
.filter(|atch_ref| {
|
||||||
|
(rp_attachments[atch_ref.attachment as usize].format.unwrap())
|
||||||
|
.aspects()
|
||||||
|
.intersects(ImageAspects::STENCIL)
|
||||||
|
})
|
||||||
|
.map(|atch_ref| RenderPassStateAttachmentInfo {
|
||||||
|
image_view: fb_attachments[atch_ref.attachment as usize].clone(),
|
||||||
|
image_layout: atch_ref.layout,
|
||||||
|
load_access: subpass
|
||||||
|
.stencil_load_op(atch_ref.attachment)
|
||||||
|
.and_then(depth_stencil_load_access),
|
||||||
|
store_access: subpass
|
||||||
|
.stencil_store_op(atch_ref.attachment)
|
||||||
|
.and_then(depth_stencil_store_access),
|
||||||
|
resolve_info: None,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_rendering_info(info: &RenderingInfo) -> Self {
|
||||||
|
Self {
|
||||||
|
color_attachments: (info.color_attachments.iter())
|
||||||
|
.map(|atch_info| {
|
||||||
|
(atch_info.as_ref()).map(|atch_info| RenderPassStateAttachmentInfo {
|
||||||
|
image_view: atch_info.image_view.clone(),
|
||||||
|
image_layout: atch_info.image_layout,
|
||||||
|
load_access: color_load_access(atch_info.load_op),
|
||||||
|
store_access: color_store_access(atch_info.store_op),
|
||||||
|
resolve_info: atch_info.resolve_info.as_ref().map(|resolve_atch_info| {
|
||||||
|
RenderPassStateAttachmentResolveInfo {
|
||||||
|
image_view: resolve_atch_info.image_view.clone(),
|
||||||
|
image_layout: resolve_atch_info.image_layout,
|
||||||
|
load_access: None,
|
||||||
|
store_access: None,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
depth_attachment: (info.depth_attachment.as_ref()).map(|atch_info| {
|
||||||
|
RenderPassStateAttachmentInfo {
|
||||||
|
image_view: atch_info.image_view.clone(),
|
||||||
|
image_layout: atch_info.image_layout,
|
||||||
|
load_access: depth_stencil_load_access(atch_info.load_op),
|
||||||
|
store_access: depth_stencil_store_access(atch_info.store_op),
|
||||||
|
resolve_info: atch_info.resolve_info.as_ref().map(|resolve_atch_info| {
|
||||||
|
RenderPassStateAttachmentResolveInfo {
|
||||||
|
image_view: resolve_atch_info.image_view.clone(),
|
||||||
|
image_layout: resolve_atch_info.image_layout,
|
||||||
|
load_access: None,
|
||||||
|
store_access: None,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stencil_attachment: (info.stencil_attachment.as_ref()).map(|atch_info| {
|
||||||
|
RenderPassStateAttachmentInfo {
|
||||||
|
image_view: atch_info.image_view.clone(),
|
||||||
|
image_layout: atch_info.image_layout,
|
||||||
|
load_access: depth_stencil_load_access(atch_info.load_op),
|
||||||
|
store_access: depth_stencil_store_access(atch_info.store_op),
|
||||||
|
resolve_info: atch_info.resolve_info.as_ref().map(|resolve_atch_info| {
|
||||||
|
RenderPassStateAttachmentResolveInfo {
|
||||||
|
image_view: resolve_atch_info.image_view.clone(),
|
||||||
|
image_layout: resolve_atch_info.image_layout,
|
||||||
|
load_access: None,
|
||||||
|
store_access: None,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn color_load_access(load_op: LoadOp) -> Option<PipelineStageAccess> {
|
||||||
|
match load_op {
|
||||||
|
LoadOp::Load => Some(PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentRead),
|
||||||
|
LoadOp::Clear => Some(PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentWrite),
|
||||||
|
LoadOp::DontCare => Some(PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentWrite),
|
||||||
|
//LoadOp::None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn depth_stencil_load_access(load_op: LoadOp) -> Option<PipelineStageAccess> {
|
||||||
|
match load_op {
|
||||||
|
LoadOp::Load => Some(PipelineStageAccess::EarlyFragmentTests_DepthStencilAttachmentRead),
|
||||||
|
LoadOp::Clear => Some(PipelineStageAccess::EarlyFragmentTests_DepthStencilAttachmentWrite),
|
||||||
|
LoadOp::DontCare => {
|
||||||
|
Some(PipelineStageAccess::EarlyFragmentTests_DepthStencilAttachmentWrite)
|
||||||
|
} //LoadOp::None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn color_store_access(store_op: StoreOp) -> Option<PipelineStageAccess> {
|
||||||
|
match store_op {
|
||||||
|
StoreOp::Store => Some(PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentWrite),
|
||||||
|
StoreOp::DontCare => Some(PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentWrite),
|
||||||
|
// StoreOp::None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn depth_stencil_store_access(store_op: StoreOp) -> Option<PipelineStageAccess> {
|
||||||
|
match store_op {
|
||||||
|
StoreOp::Store => Some(PipelineStageAccess::LateFragmentTests_DepthStencilAttachmentWrite),
|
||||||
|
StoreOp::DontCare => {
|
||||||
|
Some(PipelineStageAccess::LateFragmentTests_DepthStencilAttachmentWrite)
|
||||||
|
} // StoreOp::None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RenderPassStateAttachmentInfo {
|
||||||
|
image_view: Arc<dyn ImageViewAbstract>,
|
||||||
|
image_layout: ImageLayout,
|
||||||
|
load_access: Option<PipelineStageAccess>,
|
||||||
|
store_access: Option<PipelineStageAccess>,
|
||||||
|
resolve_info: Option<RenderPassStateAttachmentResolveInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RenderPassStateAttachmentResolveInfo {
|
||||||
|
image_view: Arc<dyn ImageViewAbstract>,
|
||||||
|
image_layout: ImageLayout,
|
||||||
|
load_access: Option<PipelineStageAccess>,
|
||||||
|
store_access: Option<PipelineStageAccess>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DescriptorSetState {
|
struct DescriptorSetState {
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
CommandBufferBuilder, DescriptorSetState, PipelineExecutionError, RenderPassState,
|
CommandBufferBuilder, CommandBufferBuilderState, DescriptorSetState, PipelineExecutionError,
|
||||||
RenderPassStateType, ResourcesState,
|
RenderPassState, RenderPassStateAttachmentInfo, RenderPassStateType, ResourcesState,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
buffer::{view::BufferViewAbstract, BufferAccess, BufferUsage, TypedBufferAccess},
|
buffer::{view::BufferViewAbstract, BufferAccess, BufferUsage, TypedBufferAccess},
|
||||||
@ -21,7 +21,7 @@ use crate::{
|
|||||||
descriptor_set::{layout::DescriptorType, DescriptorBindingResources},
|
descriptor_set::{layout::DescriptorType, DescriptorBindingResources},
|
||||||
device::{DeviceOwned, QueueFlags},
|
device::{DeviceOwned, QueueFlags},
|
||||||
format::FormatFeatures,
|
format::FormatFeatures,
|
||||||
image::{ImageAccess, ImageAspects, ImageViewAbstract, SampleCount},
|
image::{ImageAccess, ImageAspects, ImageSubresourceRange, ImageViewAbstract, SampleCount},
|
||||||
pipeline::{
|
pipeline::{
|
||||||
graphics::{
|
graphics::{
|
||||||
input_assembly::{IndexType, PrimitiveTopology},
|
input_assembly::{IndexType, PrimitiveTopology},
|
||||||
@ -32,7 +32,10 @@ use crate::{
|
|||||||
PipelineLayout,
|
PipelineLayout,
|
||||||
},
|
},
|
||||||
sampler::Sampler,
|
sampler::Sampler,
|
||||||
shader::{DescriptorBindingRequirements, ShaderScalarType, ShaderStage, ShaderStages},
|
shader::{
|
||||||
|
DescriptorBindingRequirements, FragmentTestsStages, ShaderScalarType, ShaderStage,
|
||||||
|
ShaderStages,
|
||||||
|
},
|
||||||
sync::PipelineStageAccess,
|
sync::PipelineStageAccess,
|
||||||
RequiresOneOf, VulkanObject,
|
RequiresOneOf, VulkanObject,
|
||||||
};
|
};
|
||||||
@ -353,6 +356,14 @@ where
|
|||||||
&self.builder_state.vertex_buffers,
|
&self.builder_state.vertex_buffers,
|
||||||
pipeline,
|
pipeline,
|
||||||
);
|
);
|
||||||
|
record_subpass_attachments_access(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
self.builder_state.render_pass.as_ref().unwrap(),
|
||||||
|
&self.builder_state,
|
||||||
|
pipeline,
|
||||||
|
);
|
||||||
|
|
||||||
if let RenderPassStateType::BeginRendering(state) =
|
if let RenderPassStateType::BeginRendering(state) =
|
||||||
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
||||||
@ -503,6 +514,14 @@ where
|
|||||||
command_name,
|
command_name,
|
||||||
&indirect_buffer,
|
&indirect_buffer,
|
||||||
);
|
);
|
||||||
|
record_subpass_attachments_access(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
self.builder_state.render_pass.as_ref().unwrap(),
|
||||||
|
&self.builder_state,
|
||||||
|
pipeline,
|
||||||
|
);
|
||||||
|
|
||||||
if let RenderPassStateType::BeginRendering(state) =
|
if let RenderPassStateType::BeginRendering(state) =
|
||||||
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
||||||
@ -658,6 +677,14 @@ where
|
|||||||
command_name,
|
command_name,
|
||||||
&self.builder_state.index_buffer,
|
&self.builder_state.index_buffer,
|
||||||
);
|
);
|
||||||
|
record_subpass_attachments_access(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
self.builder_state.render_pass.as_ref().unwrap(),
|
||||||
|
&self.builder_state,
|
||||||
|
pipeline,
|
||||||
|
);
|
||||||
|
|
||||||
if let RenderPassStateType::BeginRendering(state) =
|
if let RenderPassStateType::BeginRendering(state) =
|
||||||
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
||||||
@ -822,6 +849,14 @@ where
|
|||||||
command_name,
|
command_name,
|
||||||
&indirect_buffer,
|
&indirect_buffer,
|
||||||
);
|
);
|
||||||
|
record_subpass_attachments_access(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
self.builder_state.render_pass.as_ref().unwrap(),
|
||||||
|
&self.builder_state,
|
||||||
|
pipeline,
|
||||||
|
);
|
||||||
|
|
||||||
if let RenderPassStateType::BeginRendering(state) =
|
if let RenderPassStateType::BeginRendering(state) =
|
||||||
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
&mut self.builder_state.render_pass.as_mut().unwrap().render_pass
|
||||||
@ -1716,7 +1751,6 @@ where
|
|||||||
DynamicState::ShadingRateImageEnable => todo!(),
|
DynamicState::ShadingRateImageEnable => todo!(),
|
||||||
DynamicState::RepresentativeFragmentTestEnable => todo!(),
|
DynamicState::RepresentativeFragmentTestEnable => todo!(),
|
||||||
DynamicState::CoverageReductionMode => todo!(),
|
DynamicState::CoverageReductionMode => todo!(),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1757,43 +1791,48 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
RenderPassStateType::BeginRendering(current_rendering_info),
|
RenderPassStateType::BeginRendering(_),
|
||||||
PipelineRenderPassType::BeginRendering(pipeline_rendering_info),
|
PipelineRenderPassType::BeginRendering(pipeline_rendering_info),
|
||||||
) => {
|
) => {
|
||||||
// VUID-vkCmdDraw-viewMask-06178
|
// VUID-vkCmdDraw-viewMask-06178
|
||||||
if pipeline_rendering_info.view_mask != render_pass_state.view_mask {
|
if pipeline_rendering_info.view_mask != render_pass_state.rendering_info.view_mask {
|
||||||
return Err(PipelineExecutionError::PipelineViewMaskMismatch {
|
return Err(PipelineExecutionError::PipelineViewMaskMismatch {
|
||||||
pipeline_view_mask: pipeline_rendering_info.view_mask,
|
pipeline_view_mask: pipeline_rendering_info.view_mask,
|
||||||
required_view_mask: render_pass_state.view_mask,
|
required_view_mask: render_pass_state.rendering_info.view_mask,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdDraw-colorAttachmentCount-06179
|
// VUID-vkCmdDraw-colorAttachmentCount-06179
|
||||||
if pipeline_rendering_info.color_attachment_formats.len()
|
if pipeline_rendering_info.color_attachment_formats.len()
|
||||||
!= current_rendering_info.color_attachment_formats.len()
|
!= render_pass_state
|
||||||
|
.rendering_info
|
||||||
|
.color_attachment_formats
|
||||||
|
.len()
|
||||||
{
|
{
|
||||||
return Err(
|
return Err(
|
||||||
PipelineExecutionError::PipelineColorAttachmentCountMismatch {
|
PipelineExecutionError::PipelineColorAttachmentCountMismatch {
|
||||||
pipeline_count: pipeline_rendering_info.color_attachment_formats.len()
|
pipeline_count: pipeline_rendering_info.color_attachment_formats.len()
|
||||||
as u32,
|
as u32,
|
||||||
required_count: current_rendering_info.color_attachment_formats.len()
|
required_count: render_pass_state
|
||||||
as u32,
|
.rendering_info
|
||||||
|
.color_attachment_formats
|
||||||
|
.len() as u32,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (color_attachment_index, required_format, pipeline_format) in
|
for (color_attachment_index, required_format, pipeline_format) in render_pass_state
|
||||||
current_rendering_info
|
.rendering_info
|
||||||
.color_attachment_formats
|
.color_attachment_formats
|
||||||
.iter()
|
.iter()
|
||||||
.zip(
|
.zip(
|
||||||
pipeline_rendering_info
|
pipeline_rendering_info
|
||||||
.color_attachment_formats
|
.color_attachment_formats
|
||||||
.iter()
|
.iter()
|
||||||
.copied(),
|
.copied(),
|
||||||
)
|
)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, (r, p))| r.map(|r| (i as u32, r, p)))
|
.filter_map(|(i, (r, p))| r.map(|r| (i as u32, r, p)))
|
||||||
{
|
{
|
||||||
// VUID-vkCmdDraw-colorAttachmentCount-06180
|
// VUID-vkCmdDraw-colorAttachmentCount-06180
|
||||||
if Some(required_format) != pipeline_format {
|
if Some(required_format) != pipeline_format {
|
||||||
@ -1807,7 +1846,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((required_format, pipeline_format)) = current_rendering_info
|
if let Some((required_format, pipeline_format)) = render_pass_state
|
||||||
|
.rendering_info
|
||||||
.depth_attachment_format
|
.depth_attachment_format
|
||||||
.map(|r| (r, pipeline_rendering_info.depth_attachment_format))
|
.map(|r| (r, pipeline_rendering_info.depth_attachment_format))
|
||||||
{
|
{
|
||||||
@ -1822,7 +1862,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((required_format, pipeline_format)) = current_rendering_info
|
if let Some((required_format, pipeline_format)) = render_pass_state
|
||||||
|
.rendering_info
|
||||||
.stencil_attachment_format
|
.stencil_attachment_format
|
||||||
.map(|r| (r, pipeline_rendering_info.stencil_attachment_format))
|
.map(|r| (r, pipeline_rendering_info.stencil_attachment_format))
|
||||||
{
|
{
|
||||||
@ -2212,3 +2253,164 @@ fn record_indirect_buffer_access(
|
|||||||
PipelineStageAccess::DrawIndirect_IndirectCommandRead,
|
PipelineStageAccess::DrawIndirect_IndirectCommandRead,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn record_subpass_attachments_access(
|
||||||
|
resources_usage_state: &mut ResourcesState,
|
||||||
|
command_index: usize,
|
||||||
|
command_name: &'static str,
|
||||||
|
render_pass_state: &RenderPassState,
|
||||||
|
builder_state: &CommandBufferBuilderState,
|
||||||
|
pipeline: &GraphicsPipeline,
|
||||||
|
) {
|
||||||
|
if Option::from(pipeline.rasterization_state().rasterizer_discard_enable)
|
||||||
|
.or(builder_state.rasterizer_discard_enable)
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let attachments = match &render_pass_state.attachments {
|
||||||
|
Some(x) => x,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(attachment_info) = attachments.depth_attachment.as_ref() {
|
||||||
|
let &RenderPassStateAttachmentInfo {
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
..
|
||||||
|
} = attachment_info;
|
||||||
|
|
||||||
|
// TODO: check `pipeline.depth_stencil_state` for whether the attachment is going to be
|
||||||
|
// read and/or written.
|
||||||
|
let accesses: &'static [PipelineStageAccess] =
|
||||||
|
match pipeline.fragment_tests_stages().unwrap() {
|
||||||
|
FragmentTestsStages::Early => {
|
||||||
|
&[PipelineStageAccess::EarlyFragmentTests_DepthStencilAttachmentWrite]
|
||||||
|
}
|
||||||
|
FragmentTestsStages::Late => {
|
||||||
|
&[PipelineStageAccess::LateFragmentTests_DepthStencilAttachmentWrite]
|
||||||
|
}
|
||||||
|
FragmentTestsStages::EarlyAndLate => &[
|
||||||
|
PipelineStageAccess::EarlyFragmentTests_DepthStencilAttachmentWrite,
|
||||||
|
PipelineStageAccess::LateFragmentTests_DepthStencilAttachmentWrite,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
let image = image_view.image();
|
||||||
|
let image_inner = image.inner();
|
||||||
|
let mut subresource_range = ImageSubresourceRange {
|
||||||
|
aspects: ImageAspects::DEPTH,
|
||||||
|
..image_view.subresource_range().clone()
|
||||||
|
};
|
||||||
|
subresource_range.array_layers.start += image_inner.first_layer;
|
||||||
|
subresource_range.array_layers.end += image_inner.first_layer;
|
||||||
|
subresource_range.mip_levels.start += image_inner.first_mipmap_level;
|
||||||
|
subresource_range.mip_levels.end += image_inner.first_mipmap_level;
|
||||||
|
|
||||||
|
let use_ref = ResourceUseRef {
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
resource_in_command: ResourceInCommand::DepthStencilAttachment,
|
||||||
|
secondary_use_ref: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
for &access in accesses {
|
||||||
|
resources_usage_state.record_image_access(
|
||||||
|
&use_ref,
|
||||||
|
image_inner.image,
|
||||||
|
subresource_range.clone(),
|
||||||
|
access,
|
||||||
|
image_layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(attachment_info) = attachments.stencil_attachment.as_ref() {
|
||||||
|
let &RenderPassStateAttachmentInfo {
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
..
|
||||||
|
} = attachment_info;
|
||||||
|
|
||||||
|
// TODO: check `pipeline.depth_stencil_state` for whether the attachment is going to be
|
||||||
|
// read and/or written.
|
||||||
|
let accesses: &'static [PipelineStageAccess] =
|
||||||
|
match pipeline.fragment_tests_stages().unwrap() {
|
||||||
|
FragmentTestsStages::Early => {
|
||||||
|
&[PipelineStageAccess::EarlyFragmentTests_DepthStencilAttachmentWrite]
|
||||||
|
}
|
||||||
|
FragmentTestsStages::Late => {
|
||||||
|
&[PipelineStageAccess::LateFragmentTests_DepthStencilAttachmentWrite]
|
||||||
|
}
|
||||||
|
FragmentTestsStages::EarlyAndLate => &[
|
||||||
|
PipelineStageAccess::EarlyFragmentTests_DepthStencilAttachmentWrite,
|
||||||
|
PipelineStageAccess::LateFragmentTests_DepthStencilAttachmentWrite,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
let image = image_view.image();
|
||||||
|
let image_inner = image.inner();
|
||||||
|
let mut subresource_range = ImageSubresourceRange {
|
||||||
|
aspects: ImageAspects::STENCIL,
|
||||||
|
..image_view.subresource_range().clone()
|
||||||
|
};
|
||||||
|
subresource_range.array_layers.start += image_inner.first_layer;
|
||||||
|
subresource_range.array_layers.end += image_inner.first_layer;
|
||||||
|
subresource_range.mip_levels.start += image_inner.first_mipmap_level;
|
||||||
|
subresource_range.mip_levels.end += image_inner.first_mipmap_level;
|
||||||
|
|
||||||
|
let use_ref = ResourceUseRef {
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
resource_in_command: ResourceInCommand::DepthStencilAttachment,
|
||||||
|
secondary_use_ref: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
for &access in accesses {
|
||||||
|
resources_usage_state.record_image_access(
|
||||||
|
&use_ref,
|
||||||
|
image_inner.image,
|
||||||
|
subresource_range.clone(),
|
||||||
|
access,
|
||||||
|
image_layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, attachment_info) in (attachments.color_attachments.iter().enumerate())
|
||||||
|
.filter_map(|(i, a)| a.as_ref().map(|a| (i as u32, a)))
|
||||||
|
{
|
||||||
|
let &RenderPassStateAttachmentInfo {
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
..
|
||||||
|
} = attachment_info;
|
||||||
|
|
||||||
|
let image = image_view.image();
|
||||||
|
let image_inner = image.inner();
|
||||||
|
let mut subresource_range = image_view.subresource_range().clone();
|
||||||
|
subresource_range.array_layers.start += image_inner.first_layer;
|
||||||
|
subresource_range.array_layers.end += image_inner.first_layer;
|
||||||
|
subresource_range.mip_levels.start += image_inner.first_mipmap_level;
|
||||||
|
subresource_range.mip_levels.end += image_inner.first_mipmap_level;
|
||||||
|
|
||||||
|
let use_ref = ResourceUseRef {
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
resource_in_command: ResourceInCommand::ColorAttachment { index },
|
||||||
|
secondary_use_ref: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: process only the color attachment indices that the fragment shader actually
|
||||||
|
// writes to.
|
||||||
|
// TODO: is it possible to only read a color attachment but not write it?
|
||||||
|
resources_usage_state.record_image_access(
|
||||||
|
&use_ref,
|
||||||
|
image_inner.image,
|
||||||
|
subresource_range,
|
||||||
|
PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentWrite,
|
||||||
|
image_layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -131,7 +131,9 @@ where
|
|||||||
|
|
||||||
if let Some(render_pass_state) = &self.builder_state.render_pass {
|
if let Some(render_pass_state) = &self.builder_state.render_pass {
|
||||||
// VUID-vkCmdBeginQuery-query-00808
|
// VUID-vkCmdBeginQuery-query-00808
|
||||||
if query + render_pass_state.view_mask.count_ones() > query_pool.query_count() {
|
if query + render_pass_state.rendering_info.view_mask.count_ones()
|
||||||
|
> query_pool.query_count()
|
||||||
|
{
|
||||||
return Err(QueryError::OutOfRangeMultiview);
|
return Err(QueryError::OutOfRangeMultiview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,7 +218,9 @@ where
|
|||||||
|
|
||||||
if let Some(render_pass_state) = &self.builder_state.render_pass {
|
if let Some(render_pass_state) = &self.builder_state.render_pass {
|
||||||
// VUID-vkCmdEndQuery-query-00812
|
// VUID-vkCmdEndQuery-query-00812
|
||||||
if query + render_pass_state.view_mask.count_ones() > query_pool.query_count() {
|
if query + render_pass_state.rendering_info.view_mask.count_ones()
|
||||||
|
> query_pool.query_count()
|
||||||
|
{
|
||||||
return Err(QueryError::OutOfRangeMultiview);
|
return Err(QueryError::OutOfRangeMultiview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -448,7 +452,9 @@ where
|
|||||||
|
|
||||||
if let Some(render_pass_state) = &self.builder_state.render_pass {
|
if let Some(render_pass_state) = &self.builder_state.render_pass {
|
||||||
// VUID-vkCmdWriteTimestamp2-query-03865
|
// VUID-vkCmdWriteTimestamp2-query-03865
|
||||||
if query + render_pass_state.view_mask.count_ones() > query_pool.query_count() {
|
if query + render_pass_state.rendering_info.view_mask.count_ones()
|
||||||
|
> query_pool.query_count()
|
||||||
|
{
|
||||||
return Err(QueryError::OutOfRangeMultiview);
|
return Err(QueryError::OutOfRangeMultiview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,22 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
BeginRenderPassState, BeginRenderingAttachments, BeginRenderingState, ClearAttachment,
|
BeginRenderPassState, BeginRenderingState, ClearAttachment, ClearRect, CommandBufferBuilder,
|
||||||
ClearRect, CommandBufferBuilder, RenderPassBeginInfo, RenderPassError, RenderPassState,
|
RenderPassBeginInfo, RenderPassError, RenderPassState, RenderPassStateAttachmentInfo,
|
||||||
RenderPassStateType, RenderingAttachmentInfo, RenderingAttachmentResolveInfo, RenderingInfo,
|
RenderPassStateAttachmentResolveInfo, RenderPassStateAttachments, RenderPassStateType,
|
||||||
|
RenderingAttachmentInfo, RenderingAttachmentResolveInfo, RenderingInfo, ResourcesState,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
command_buffer::{allocator::CommandBufferAllocator, PrimaryCommandBuffer, SubpassContents},
|
command_buffer::{
|
||||||
|
allocator::CommandBufferAllocator, PrimaryCommandBuffer, ResourceInCommand, ResourceUseRef,
|
||||||
|
SubpassContents,
|
||||||
|
},
|
||||||
device::{DeviceOwned, QueueFlags},
|
device::{DeviceOwned, QueueFlags},
|
||||||
format::{ClearColorValue, ClearValue, NumericType},
|
format::{ClearColorValue, ClearValue, NumericType},
|
||||||
image::{ImageAspects, ImageLayout, ImageUsage, SampleCount},
|
image::{ImageAspects, ImageLayout, ImageUsage, SampleCount},
|
||||||
|
pipeline::graphics::render_pass::PipelineRenderingCreateInfo,
|
||||||
render_pass::{AttachmentDescription, LoadOp, ResolveMode, SubpassDescription},
|
render_pass::{AttachmentDescription, LoadOp, ResolveMode, SubpassDescription},
|
||||||
|
sync::PipelineStageAccess,
|
||||||
RequiresOneOf, Version, VulkanObject,
|
RequiresOneOf, Version, VulkanObject,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
@ -443,26 +449,47 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let subpass = render_pass.clone().first_subpass();
|
let command_index = self.next_command_index;
|
||||||
let view_mask = subpass.subpass_desc().view_mask;
|
let command_name = "begin_render_pass";
|
||||||
|
|
||||||
self.builder_state.render_pass = Some(RenderPassState {
|
// Advance to first subpass
|
||||||
contents,
|
{
|
||||||
render_area_offset,
|
let subpass = render_pass.clone().first_subpass();
|
||||||
render_area_extent,
|
self.builder_state.render_pass = Some(RenderPassState {
|
||||||
render_pass: BeginRenderPassState {
|
contents,
|
||||||
subpass,
|
render_area_offset,
|
||||||
framebuffer: Some(framebuffer.clone()),
|
render_area_extent,
|
||||||
}
|
|
||||||
.into(),
|
rendering_info: PipelineRenderingCreateInfo::from_subpass(&subpass),
|
||||||
view_mask,
|
attachments: Some(RenderPassStateAttachments::from_subpass(
|
||||||
});
|
&subpass,
|
||||||
|
&framebuffer,
|
||||||
|
)),
|
||||||
|
|
||||||
|
render_pass: BeginRenderPassState {
|
||||||
|
subpass,
|
||||||
|
framebuffer: Some(framebuffer.clone()),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start of first subpass
|
||||||
|
{
|
||||||
|
// TODO: Apply barriers and layout transitions
|
||||||
|
|
||||||
|
let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
|
||||||
|
record_subpass_attachments_load(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
render_pass_state,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
self.resources.push(Box::new(render_pass));
|
self.resources.push(Box::new(render_pass));
|
||||||
self.resources.push(Box::new(framebuffer));
|
self.resources.push(Box::new(framebuffer));
|
||||||
|
|
||||||
// TODO: sync state update
|
|
||||||
|
|
||||||
self.next_command_index += 1;
|
self.next_command_index += 1;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -562,23 +589,62 @@ where
|
|||||||
(fns.v1_0.cmd_next_subpass)(self.handle(), subpass_begin_info.contents);
|
(fns.v1_0.cmd_next_subpass)(self.handle(), subpass_begin_info.contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_pass_state = self.builder_state.render_pass.as_mut().unwrap();
|
let command_index = self.next_command_index;
|
||||||
let begin_render_pass_state = match &mut render_pass_state.render_pass {
|
let command_name = "next_subpass";
|
||||||
RenderPassStateType::BeginRenderPass(x) => x,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
begin_render_pass_state.subpass.next_subpass();
|
// End of previous subpass
|
||||||
render_pass_state.contents = contents;
|
{
|
||||||
render_pass_state.view_mask = begin_render_pass_state.subpass.subpass_desc().view_mask;
|
let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
|
||||||
|
record_subpass_attachments_resolve(
|
||||||
if render_pass_state.view_mask != 0 {
|
&mut self.resources_usage_state,
|
||||||
// When multiview is enabled, at the beginning of each subpass, all
|
command_index,
|
||||||
// non-render pass state is undefined.
|
command_name,
|
||||||
self.builder_state = Default::default();
|
render_pass_state,
|
||||||
|
);
|
||||||
|
record_subpass_attachments_store(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
render_pass_state,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: sync state update
|
// Advance to next subpass
|
||||||
|
{
|
||||||
|
let render_pass_state = self.builder_state.render_pass.as_mut().unwrap();
|
||||||
|
let begin_render_pass_state = match &mut render_pass_state.render_pass {
|
||||||
|
RenderPassStateType::BeginRenderPass(x) => x,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
begin_render_pass_state.subpass.next_subpass();
|
||||||
|
render_pass_state.contents = contents;
|
||||||
|
render_pass_state.rendering_info =
|
||||||
|
PipelineRenderingCreateInfo::from_subpass(&begin_render_pass_state.subpass);
|
||||||
|
render_pass_state.attachments = Some(RenderPassStateAttachments::from_subpass(
|
||||||
|
&begin_render_pass_state.subpass,
|
||||||
|
begin_render_pass_state.framebuffer.as_ref().unwrap(),
|
||||||
|
));
|
||||||
|
|
||||||
|
if render_pass_state.rendering_info.view_mask != 0 {
|
||||||
|
// When multiview is enabled, at the beginning of each subpass, all
|
||||||
|
// non-render pass state is undefined.
|
||||||
|
self.builder_state = Default::default();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start of next subpass
|
||||||
|
{
|
||||||
|
// TODO: Apply barriers and layout transitions
|
||||||
|
|
||||||
|
let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
|
||||||
|
record_subpass_attachments_load(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
render_pass_state,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
self.next_command_index += 1;
|
self.next_command_index += 1;
|
||||||
self
|
self
|
||||||
@ -673,9 +739,29 @@ where
|
|||||||
(fns.v1_0.cmd_end_render_pass)(self.handle());
|
(fns.v1_0.cmd_end_render_pass)(self.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.builder_state.render_pass = None;
|
let command_index = self.next_command_index;
|
||||||
|
let command_name = "end_render_pass";
|
||||||
|
|
||||||
// TODO: sync state update
|
// End of last subpass
|
||||||
|
{
|
||||||
|
let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
|
||||||
|
record_subpass_attachments_resolve(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
render_pass_state,
|
||||||
|
);
|
||||||
|
record_subpass_attachments_store(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
render_pass_state,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Apply barriers and layout transitions
|
||||||
|
|
||||||
|
self.builder_state.render_pass = None;
|
||||||
|
|
||||||
self.next_command_index += 1;
|
self.next_command_index += 1;
|
||||||
self
|
self
|
||||||
@ -1268,127 +1354,129 @@ where
|
|||||||
|
|
||||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||||
pub unsafe fn begin_rendering_unchecked(&mut self, rendering_info: RenderingInfo) -> &mut Self {
|
pub unsafe fn begin_rendering_unchecked(&mut self, rendering_info: RenderingInfo) -> &mut Self {
|
||||||
|
{
|
||||||
|
let &RenderingInfo {
|
||||||
|
render_area_offset,
|
||||||
|
render_area_extent,
|
||||||
|
layer_count,
|
||||||
|
view_mask,
|
||||||
|
ref color_attachments,
|
||||||
|
ref depth_attachment,
|
||||||
|
ref stencil_attachment,
|
||||||
|
contents,
|
||||||
|
_ne,
|
||||||
|
} = &rendering_info;
|
||||||
|
|
||||||
|
let map_attachment_info = |attachment_info: &Option<_>| {
|
||||||
|
if let Some(attachment_info) = attachment_info {
|
||||||
|
let &RenderingAttachmentInfo {
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
resolve_info: ref resolve,
|
||||||
|
load_op,
|
||||||
|
store_op,
|
||||||
|
clear_value,
|
||||||
|
_ne: _,
|
||||||
|
} = attachment_info;
|
||||||
|
|
||||||
|
let (resolve_mode, resolve_image_view, resolve_image_layout) =
|
||||||
|
if let Some(resolve) = resolve {
|
||||||
|
let &RenderingAttachmentResolveInfo {
|
||||||
|
mode,
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
} = resolve;
|
||||||
|
|
||||||
|
(mode.into(), image_view.handle(), image_layout.into())
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
ash::vk::ResolveModeFlags::NONE,
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
ash::vk::RenderingAttachmentInfo {
|
||||||
|
image_view: image_view.handle(),
|
||||||
|
image_layout: image_layout.into(),
|
||||||
|
resolve_mode,
|
||||||
|
resolve_image_view,
|
||||||
|
resolve_image_layout,
|
||||||
|
load_op: load_op.into(),
|
||||||
|
store_op: store_op.into(),
|
||||||
|
clear_value: clear_value.map_or_else(Default::default, Into::into),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ash::vk::RenderingAttachmentInfo {
|
||||||
|
image_view: ash::vk::ImageView::null(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let color_attachments_vk: SmallVec<[_; 2]> =
|
||||||
|
color_attachments.iter().map(map_attachment_info).collect();
|
||||||
|
let depth_attachment_vk = map_attachment_info(depth_attachment);
|
||||||
|
let stencil_attachment_vk = map_attachment_info(stencil_attachment);
|
||||||
|
|
||||||
|
let rendering_info_vk = ash::vk::RenderingInfo {
|
||||||
|
flags: contents.into(),
|
||||||
|
render_area: ash::vk::Rect2D {
|
||||||
|
offset: ash::vk::Offset2D {
|
||||||
|
x: render_area_offset[0] as i32,
|
||||||
|
y: render_area_offset[1] as i32,
|
||||||
|
},
|
||||||
|
extent: ash::vk::Extent2D {
|
||||||
|
width: render_area_extent[0],
|
||||||
|
height: render_area_extent[1],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
layer_count,
|
||||||
|
view_mask,
|
||||||
|
color_attachment_count: color_attachments_vk.len() as u32,
|
||||||
|
p_color_attachments: color_attachments_vk.as_ptr(),
|
||||||
|
p_depth_attachment: &depth_attachment_vk,
|
||||||
|
p_stencil_attachment: &stencil_attachment_vk,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let fns = self.device().fns();
|
||||||
|
|
||||||
|
if self.device().api_version() >= Version::V1_3 {
|
||||||
|
(fns.v1_3.cmd_begin_rendering)(self.handle(), &rendering_info_vk);
|
||||||
|
} else {
|
||||||
|
debug_assert!(self.device().enabled_extensions().khr_dynamic_rendering);
|
||||||
|
(fns.khr_dynamic_rendering.cmd_begin_rendering_khr)(
|
||||||
|
self.handle(),
|
||||||
|
&rendering_info_vk,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.builder_state.render_pass = Some(RenderPassState {
|
||||||
|
contents,
|
||||||
|
render_area_offset,
|
||||||
|
render_area_extent,
|
||||||
|
|
||||||
|
rendering_info: PipelineRenderingCreateInfo::from_rendering_info(&rendering_info),
|
||||||
|
attachments: Some(RenderPassStateAttachments::from_rendering_info(
|
||||||
|
&rendering_info,
|
||||||
|
)),
|
||||||
|
|
||||||
|
render_pass: BeginRenderingState {
|
||||||
|
pipeline_used: false,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let RenderingInfo {
|
let RenderingInfo {
|
||||||
render_area_offset,
|
|
||||||
render_area_extent,
|
|
||||||
layer_count,
|
|
||||||
view_mask,
|
|
||||||
color_attachments,
|
color_attachments,
|
||||||
depth_attachment,
|
depth_attachment,
|
||||||
stencil_attachment,
|
stencil_attachment,
|
||||||
contents,
|
..
|
||||||
_ne,
|
|
||||||
} = rendering_info;
|
} = rendering_info;
|
||||||
|
|
||||||
let map_attachment_info = |attachment_info: &Option<_>| {
|
|
||||||
if let Some(attachment_info) = attachment_info {
|
|
||||||
let &RenderingAttachmentInfo {
|
|
||||||
ref image_view,
|
|
||||||
image_layout,
|
|
||||||
resolve_info: ref resolve,
|
|
||||||
load_op,
|
|
||||||
store_op,
|
|
||||||
clear_value,
|
|
||||||
_ne: _,
|
|
||||||
} = attachment_info;
|
|
||||||
|
|
||||||
let (resolve_mode, resolve_image_view, resolve_image_layout) =
|
|
||||||
if let Some(resolve) = resolve {
|
|
||||||
let &RenderingAttachmentResolveInfo {
|
|
||||||
mode,
|
|
||||||
ref image_view,
|
|
||||||
image_layout,
|
|
||||||
} = resolve;
|
|
||||||
|
|
||||||
(mode.into(), image_view.handle(), image_layout.into())
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
ash::vk::ResolveModeFlags::NONE,
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
ash::vk::RenderingAttachmentInfo {
|
|
||||||
image_view: image_view.handle(),
|
|
||||||
image_layout: image_layout.into(),
|
|
||||||
resolve_mode,
|
|
||||||
resolve_image_view,
|
|
||||||
resolve_image_layout,
|
|
||||||
load_op: load_op.into(),
|
|
||||||
store_op: store_op.into(),
|
|
||||||
clear_value: clear_value.map_or_else(Default::default, Into::into),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ash::vk::RenderingAttachmentInfo {
|
|
||||||
image_view: ash::vk::ImageView::null(),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let color_attachments_vk: SmallVec<[_; 2]> =
|
|
||||||
color_attachments.iter().map(map_attachment_info).collect();
|
|
||||||
let depth_attachment_vk = map_attachment_info(&depth_attachment);
|
|
||||||
let stencil_attachment_vk = map_attachment_info(&stencil_attachment);
|
|
||||||
|
|
||||||
let rendering_info = ash::vk::RenderingInfo {
|
|
||||||
flags: contents.into(),
|
|
||||||
render_area: ash::vk::Rect2D {
|
|
||||||
offset: ash::vk::Offset2D {
|
|
||||||
x: render_area_offset[0] as i32,
|
|
||||||
y: render_area_offset[1] as i32,
|
|
||||||
},
|
|
||||||
extent: ash::vk::Extent2D {
|
|
||||||
width: render_area_extent[0],
|
|
||||||
height: render_area_extent[1],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
layer_count,
|
|
||||||
view_mask,
|
|
||||||
color_attachment_count: color_attachments_vk.len() as u32,
|
|
||||||
p_color_attachments: color_attachments_vk.as_ptr(),
|
|
||||||
p_depth_attachment: &depth_attachment_vk,
|
|
||||||
p_stencil_attachment: &stencil_attachment_vk,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let fns = self.device().fns();
|
|
||||||
|
|
||||||
if self.device().api_version() >= Version::V1_3 {
|
|
||||||
(fns.v1_3.cmd_begin_rendering)(self.handle(), &rendering_info);
|
|
||||||
} else {
|
|
||||||
debug_assert!(self.device().enabled_extensions().khr_dynamic_rendering);
|
|
||||||
(fns.khr_dynamic_rendering.cmd_begin_rendering_khr)(self.handle(), &rendering_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.builder_state.render_pass = Some(RenderPassState {
|
|
||||||
contents,
|
|
||||||
render_area_offset,
|
|
||||||
render_area_extent,
|
|
||||||
render_pass: BeginRenderingState {
|
|
||||||
attachments: Some(BeginRenderingAttachments {
|
|
||||||
color_attachments: color_attachments.clone(),
|
|
||||||
depth_attachment: depth_attachment.clone(),
|
|
||||||
stencil_attachment: stencil_attachment.clone(),
|
|
||||||
}),
|
|
||||||
color_attachment_formats: color_attachments
|
|
||||||
.iter()
|
|
||||||
.map(|a| a.as_ref().map(|a| a.image_view.format().unwrap()))
|
|
||||||
.collect(),
|
|
||||||
depth_attachment_format: depth_attachment
|
|
||||||
.as_ref()
|
|
||||||
.map(|a| a.image_view.format().unwrap()),
|
|
||||||
stencil_attachment_format: stencil_attachment
|
|
||||||
.as_ref()
|
|
||||||
.map(|a| a.image_view.format().unwrap()),
|
|
||||||
pipeline_used: false,
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
view_mask,
|
|
||||||
});
|
|
||||||
|
|
||||||
for attachment_info in color_attachments.into_iter().flatten() {
|
for attachment_info in color_attachments.into_iter().flatten() {
|
||||||
let RenderingAttachmentInfo {
|
let RenderingAttachmentInfo {
|
||||||
image_view,
|
image_view,
|
||||||
@ -1461,8 +1549,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: sync state update
|
|
||||||
|
|
||||||
self.next_command_index += 1;
|
self.next_command_index += 1;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -1525,9 +1611,24 @@ where
|
|||||||
(fns.khr_dynamic_rendering.cmd_end_rendering_khr)(self.handle());
|
(fns.khr_dynamic_rendering.cmd_end_rendering_khr)(self.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.builder_state.render_pass = None;
|
let command_index = self.next_command_index;
|
||||||
|
let command_name = "end_rendering";
|
||||||
|
let render_pass_state = self.builder_state.render_pass.as_ref().unwrap();
|
||||||
|
|
||||||
// TODO: sync state update
|
record_subpass_attachments_resolve(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
render_pass_state,
|
||||||
|
);
|
||||||
|
record_subpass_attachments_store(
|
||||||
|
&mut self.resources_usage_state,
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
render_pass_state,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.builder_state.render_pass = None;
|
||||||
|
|
||||||
self.next_command_index += 1;
|
self.next_command_index += 1;
|
||||||
self
|
self
|
||||||
@ -1587,7 +1688,7 @@ where
|
|||||||
|
|
||||||
//let subpass_desc = begin_render_pass_state.subpass.subpass_desc();
|
//let subpass_desc = begin_render_pass_state.subpass.subpass_desc();
|
||||||
//let render_pass = begin_render_pass_state.subpass.render_pass();
|
//let render_pass = begin_render_pass_state.subpass.render_pass();
|
||||||
let is_multiview = render_pass_state.view_mask != 0;
|
let is_multiview = render_pass_state.rendering_info.view_mask != 0;
|
||||||
let mut layer_count = u32::MAX;
|
let mut layer_count = u32::MAX;
|
||||||
|
|
||||||
for &clear_attachment in attachments {
|
for &clear_attachment in attachments {
|
||||||
@ -1596,31 +1697,17 @@ where
|
|||||||
color_attachment,
|
color_attachment,
|
||||||
clear_value,
|
clear_value,
|
||||||
} => {
|
} => {
|
||||||
let attachment_format = match &render_pass_state.render_pass {
|
let attachment_format = *render_pass_state
|
||||||
RenderPassStateType::BeginRenderPass(state) => {
|
.rendering_info
|
||||||
let color_attachments = &state.subpass.subpass_desc().color_attachments;
|
.color_attachment_formats
|
||||||
let atch_ref = color_attachments.get(color_attachment as usize).ok_or(
|
.get(color_attachment as usize)
|
||||||
RenderPassError::ColorAttachmentIndexOutOfRange {
|
.ok_or(RenderPassError::ColorAttachmentIndexOutOfRange {
|
||||||
color_attachment_index: color_attachment,
|
color_attachment_index: color_attachment,
|
||||||
num_color_attachments: color_attachments.len() as u32,
|
num_color_attachments: render_pass_state
|
||||||
},
|
.rendering_info
|
||||||
)?;
|
.color_attachment_formats
|
||||||
|
.len() as u32,
|
||||||
atch_ref.as_ref().map(|atch_ref| {
|
})?;
|
||||||
state.subpass.render_pass().attachments()
|
|
||||||
[atch_ref.attachment as usize]
|
|
||||||
.format
|
|
||||||
.unwrap()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
RenderPassStateType::BeginRendering(state) => *state
|
|
||||||
.color_attachment_formats
|
|
||||||
.get(color_attachment as usize)
|
|
||||||
.ok_or(RenderPassError::ColorAttachmentIndexOutOfRange {
|
|
||||||
color_attachment_index: color_attachment,
|
|
||||||
num_color_attachments: state.color_attachment_formats.len() as u32,
|
|
||||||
})?,
|
|
||||||
};
|
|
||||||
|
|
||||||
// VUID-vkCmdClearAttachments-aspectMask-02501
|
// VUID-vkCmdClearAttachments-aspectMask-02501
|
||||||
if !attachment_format.map_or(false, |format| {
|
if !attachment_format.map_or(false, |format| {
|
||||||
@ -1645,24 +1732,13 @@ where
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let image_view = match &render_pass_state.render_pass {
|
let image_view = render_pass_state
|
||||||
RenderPassStateType::BeginRenderPass(state) => (state.framebuffer.as_ref())
|
.attachments
|
||||||
.zip(
|
.as_ref()
|
||||||
state.subpass.subpass_desc().color_attachments
|
.and_then(|attachments| {
|
||||||
[color_attachment as usize]
|
attachments.color_attachments[color_attachment as usize].as_ref()
|
||||||
.as_ref(),
|
})
|
||||||
)
|
.map(|attachment_info| &attachment_info.image_view);
|
||||||
.map(|(framebuffer, atch_ref)| {
|
|
||||||
&framebuffer.attachments()[atch_ref.attachment as usize]
|
|
||||||
}),
|
|
||||||
RenderPassStateType::BeginRendering(state) => state
|
|
||||||
.attachments
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|attachments| {
|
|
||||||
attachments.color_attachments[color_attachment as usize].as_ref()
|
|
||||||
})
|
|
||||||
.map(|attachment_info| &attachment_info.image_view),
|
|
||||||
};
|
|
||||||
|
|
||||||
// We only know the layer count if we have a known attachment image.
|
// We only know the layer count if we have a known attachment image.
|
||||||
if let Some(image_view) = image_view {
|
if let Some(image_view) = image_view {
|
||||||
@ -1673,24 +1749,8 @@ where
|
|||||||
ClearAttachment::Depth(_)
|
ClearAttachment::Depth(_)
|
||||||
| ClearAttachment::Stencil(_)
|
| ClearAttachment::Stencil(_)
|
||||||
| ClearAttachment::DepthStencil(_) => {
|
| ClearAttachment::DepthStencil(_) => {
|
||||||
let (depth_format, stencil_format) = match &render_pass_state.render_pass {
|
let depth_format = render_pass_state.rendering_info.depth_attachment_format;
|
||||||
RenderPassStateType::BeginRenderPass(state) => state
|
let stencil_format = render_pass_state.rendering_info.stencil_attachment_format;
|
||||||
.subpass
|
|
||||||
.subpass_desc()
|
|
||||||
.depth_stencil_attachment
|
|
||||||
.as_ref()
|
|
||||||
.map_or((None, None), |atch_ref| {
|
|
||||||
let format = state.subpass.render_pass().attachments()
|
|
||||||
[atch_ref.attachment as usize]
|
|
||||||
.format
|
|
||||||
.unwrap();
|
|
||||||
(Some(format), Some(format))
|
|
||||||
}),
|
|
||||||
RenderPassStateType::BeginRendering(state) => (
|
|
||||||
state.depth_attachment_format,
|
|
||||||
state.stencil_attachment_format,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
// VUID-vkCmdClearAttachments-aspectMask-02502
|
// VUID-vkCmdClearAttachments-aspectMask-02502
|
||||||
if matches!(
|
if matches!(
|
||||||
@ -1718,24 +1778,11 @@ where
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let image_view = match &render_pass_state.render_pass {
|
let image_view = render_pass_state
|
||||||
RenderPassStateType::BeginRenderPass(state) => (state.framebuffer.as_ref())
|
.attachments
|
||||||
.zip(
|
.as_ref()
|
||||||
state
|
.and_then(|attachments| attachments.depth_attachment.as_ref())
|
||||||
.subpass
|
.map(|attachment_info| &attachment_info.image_view);
|
||||||
.subpass_desc()
|
|
||||||
.depth_stencil_attachment
|
|
||||||
.as_ref(),
|
|
||||||
)
|
|
||||||
.map(|(framebuffer, atch_ref)| {
|
|
||||||
&framebuffer.attachments()[atch_ref.attachment as usize]
|
|
||||||
}),
|
|
||||||
RenderPassStateType::BeginRendering(state) => state
|
|
||||||
.attachments
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|attachments| attachments.depth_attachment.as_ref())
|
|
||||||
.map(|attachment_info| &attachment_info.image_view),
|
|
||||||
};
|
|
||||||
|
|
||||||
// We only know the layer count if we have a known attachment image.
|
// We only know the layer count if we have a known attachment image.
|
||||||
if let Some(image_view) = image_view {
|
if let Some(image_view) = image_view {
|
||||||
@ -1838,3 +1885,364 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn record_subpass_attachments_resolve(
|
||||||
|
resources_usage_state: &mut ResourcesState,
|
||||||
|
command_index: usize,
|
||||||
|
command_name: &'static str,
|
||||||
|
render_pass_state: &RenderPassState,
|
||||||
|
) {
|
||||||
|
let attachments = render_pass_state.attachments.as_ref().unwrap();
|
||||||
|
|
||||||
|
let record_attachment = |resources_usage_state: &mut ResourcesState,
|
||||||
|
attachment_info,
|
||||||
|
aspects_override,
|
||||||
|
resource_in_command,
|
||||||
|
resolve_resource_in_command| {
|
||||||
|
let &RenderPassStateAttachmentInfo {
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
ref resolve_info,
|
||||||
|
..
|
||||||
|
} = attachment_info;
|
||||||
|
|
||||||
|
let image = image_view.image();
|
||||||
|
let image_inner = image.inner();
|
||||||
|
let mut subresource_range = image_view.subresource_range().clone();
|
||||||
|
subresource_range.array_layers.start += image_inner.first_layer;
|
||||||
|
subresource_range.array_layers.end += image_inner.first_layer;
|
||||||
|
subresource_range.mip_levels.start += image_inner.first_mipmap_level;
|
||||||
|
subresource_range.mip_levels.end += image_inner.first_mipmap_level;
|
||||||
|
|
||||||
|
if let Some(aspects) = aspects_override {
|
||||||
|
subresource_range.aspects = aspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
let use_ref = ResourceUseRef {
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
resource_in_command,
|
||||||
|
secondary_use_ref: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(resolve_info) = resolve_info {
|
||||||
|
let &RenderPassStateAttachmentResolveInfo {
|
||||||
|
image_view: ref resolve_image_view,
|
||||||
|
image_layout: resolve_image_layout,
|
||||||
|
..
|
||||||
|
} = resolve_info;
|
||||||
|
|
||||||
|
let resolve_image = resolve_image_view.image();
|
||||||
|
let resolve_image_inner = resolve_image.inner();
|
||||||
|
let mut resolve_subresource_range = resolve_image_view.subresource_range().clone();
|
||||||
|
resolve_subresource_range.array_layers.start += resolve_image_inner.first_layer;
|
||||||
|
resolve_subresource_range.array_layers.end += resolve_image_inner.first_layer;
|
||||||
|
resolve_subresource_range.mip_levels.start += resolve_image_inner.first_mipmap_level;
|
||||||
|
resolve_subresource_range.mip_levels.end += resolve_image_inner.first_mipmap_level;
|
||||||
|
|
||||||
|
if let Some(aspects) = aspects_override {
|
||||||
|
resolve_subresource_range.aspects = aspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
let resolve_use_ref = ResourceUseRef {
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
resource_in_command: resolve_resource_in_command,
|
||||||
|
secondary_use_ref: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// The resolve operation uses the stages/access for color attachments,
|
||||||
|
// even for depth/stencil attachments.
|
||||||
|
resources_usage_state.record_image_access(
|
||||||
|
&use_ref,
|
||||||
|
image_inner.image,
|
||||||
|
subresource_range,
|
||||||
|
PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentRead,
|
||||||
|
image_layout,
|
||||||
|
);
|
||||||
|
resources_usage_state.record_image_access(
|
||||||
|
&resolve_use_ref,
|
||||||
|
resolve_image_inner.image,
|
||||||
|
resolve_subresource_range,
|
||||||
|
PipelineStageAccess::ColorAttachmentOutput_ColorAttachmentWrite,
|
||||||
|
resolve_image_layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(attachment_info) = attachments.depth_attachment.as_ref() {
|
||||||
|
record_attachment(
|
||||||
|
resources_usage_state,
|
||||||
|
attachment_info,
|
||||||
|
Some(ImageAspects::DEPTH),
|
||||||
|
ResourceInCommand::DepthStencilAttachment,
|
||||||
|
ResourceInCommand::DepthStencilResolveAttachment,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(attachment_info) = attachments.stencil_attachment.as_ref() {
|
||||||
|
record_attachment(
|
||||||
|
resources_usage_state,
|
||||||
|
attachment_info,
|
||||||
|
Some(ImageAspects::STENCIL),
|
||||||
|
ResourceInCommand::DepthStencilAttachment,
|
||||||
|
ResourceInCommand::DepthStencilResolveAttachment,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, attachment_info) in (attachments.color_attachments.iter().enumerate())
|
||||||
|
.filter_map(|(i, a)| a.as_ref().map(|a| (i as u32, a)))
|
||||||
|
{
|
||||||
|
record_attachment(
|
||||||
|
resources_usage_state,
|
||||||
|
attachment_info,
|
||||||
|
None,
|
||||||
|
ResourceInCommand::ColorAttachment { index },
|
||||||
|
ResourceInCommand::ColorResolveAttachment { index },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record_subpass_attachments_store(
|
||||||
|
resources_usage_state: &mut ResourcesState,
|
||||||
|
command_index: usize,
|
||||||
|
command_name: &'static str,
|
||||||
|
render_pass_state: &RenderPassState,
|
||||||
|
) {
|
||||||
|
let attachments = render_pass_state.attachments.as_ref().unwrap();
|
||||||
|
|
||||||
|
let record_attachment = |resources_usage_state: &mut ResourcesState,
|
||||||
|
attachment_info,
|
||||||
|
aspects_override,
|
||||||
|
resource_in_command,
|
||||||
|
resolve_resource_in_command| {
|
||||||
|
let &RenderPassStateAttachmentInfo {
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
store_access,
|
||||||
|
ref resolve_info,
|
||||||
|
..
|
||||||
|
} = attachment_info;
|
||||||
|
|
||||||
|
if let Some(access) = store_access {
|
||||||
|
let image = image_view.image();
|
||||||
|
let image_inner = image.inner();
|
||||||
|
let mut subresource_range = image_view.subresource_range().clone();
|
||||||
|
subresource_range.array_layers.start += image_inner.first_layer;
|
||||||
|
subresource_range.array_layers.end += image_inner.first_layer;
|
||||||
|
subresource_range.mip_levels.start += image_inner.first_mipmap_level;
|
||||||
|
subresource_range.mip_levels.end += image_inner.first_mipmap_level;
|
||||||
|
|
||||||
|
if let Some(aspects) = aspects_override {
|
||||||
|
subresource_range.aspects = aspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
let use_ref = ResourceUseRef {
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
resource_in_command,
|
||||||
|
secondary_use_ref: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
resources_usage_state.record_image_access(
|
||||||
|
&use_ref,
|
||||||
|
image_inner.image,
|
||||||
|
subresource_range,
|
||||||
|
access,
|
||||||
|
image_layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(resolve_info) = resolve_info {
|
||||||
|
let &RenderPassStateAttachmentResolveInfo {
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
store_access,
|
||||||
|
..
|
||||||
|
} = resolve_info;
|
||||||
|
|
||||||
|
if let Some(access) = store_access {
|
||||||
|
let image = image_view.image();
|
||||||
|
let image_inner = image.inner();
|
||||||
|
let mut subresource_range = image_view.subresource_range().clone();
|
||||||
|
subresource_range.array_layers.start += image_inner.first_layer;
|
||||||
|
subresource_range.array_layers.end += image_inner.first_layer;
|
||||||
|
subresource_range.mip_levels.start += image_inner.first_mipmap_level;
|
||||||
|
subresource_range.mip_levels.end += image_inner.first_mipmap_level;
|
||||||
|
|
||||||
|
if let Some(aspects) = aspects_override {
|
||||||
|
subresource_range.aspects = aspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
let use_ref = ResourceUseRef {
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
resource_in_command: resolve_resource_in_command,
|
||||||
|
secondary_use_ref: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
resources_usage_state.record_image_access(
|
||||||
|
&use_ref,
|
||||||
|
image_inner.image,
|
||||||
|
subresource_range,
|
||||||
|
access,
|
||||||
|
image_layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(attachment_info) = attachments.depth_attachment.as_ref() {
|
||||||
|
record_attachment(
|
||||||
|
resources_usage_state,
|
||||||
|
attachment_info,
|
||||||
|
Some(ImageAspects::DEPTH),
|
||||||
|
ResourceInCommand::DepthStencilAttachment,
|
||||||
|
ResourceInCommand::DepthStencilResolveAttachment,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(attachment_info) = attachments.stencil_attachment.as_ref() {
|
||||||
|
record_attachment(
|
||||||
|
resources_usage_state,
|
||||||
|
attachment_info,
|
||||||
|
Some(ImageAspects::STENCIL),
|
||||||
|
ResourceInCommand::DepthStencilAttachment,
|
||||||
|
ResourceInCommand::DepthStencilResolveAttachment,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, attachment_info) in (attachments.color_attachments.iter().enumerate())
|
||||||
|
.filter_map(|(i, a)| a.as_ref().map(|a| (i as u32, a)))
|
||||||
|
{
|
||||||
|
record_attachment(
|
||||||
|
resources_usage_state,
|
||||||
|
attachment_info,
|
||||||
|
None,
|
||||||
|
ResourceInCommand::ColorAttachment { index },
|
||||||
|
ResourceInCommand::ColorResolveAttachment { index },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record_subpass_attachments_load(
|
||||||
|
resources_usage_state: &mut ResourcesState,
|
||||||
|
command_index: usize,
|
||||||
|
command_name: &'static str,
|
||||||
|
render_pass_state: &RenderPassState,
|
||||||
|
) {
|
||||||
|
let attachments = render_pass_state.attachments.as_ref().unwrap();
|
||||||
|
|
||||||
|
let record_attachment = |resources_usage_state: &mut ResourcesState,
|
||||||
|
attachment_info,
|
||||||
|
aspects_override,
|
||||||
|
resource_in_command,
|
||||||
|
resolve_resource_in_command| {
|
||||||
|
let &RenderPassStateAttachmentInfo {
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
load_access,
|
||||||
|
ref resolve_info,
|
||||||
|
..
|
||||||
|
} = attachment_info;
|
||||||
|
|
||||||
|
if let Some(access) = load_access {
|
||||||
|
let image = image_view.image();
|
||||||
|
let image_inner = image.inner();
|
||||||
|
let mut subresource_range = image_view.subresource_range().clone();
|
||||||
|
subresource_range.array_layers.start += image_inner.first_layer;
|
||||||
|
subresource_range.array_layers.end += image_inner.first_layer;
|
||||||
|
subresource_range.mip_levels.start += image_inner.first_mipmap_level;
|
||||||
|
subresource_range.mip_levels.end += image_inner.first_mipmap_level;
|
||||||
|
|
||||||
|
if let Some(aspects) = aspects_override {
|
||||||
|
subresource_range.aspects = aspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
let use_ref = ResourceUseRef {
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
resource_in_command,
|
||||||
|
secondary_use_ref: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
resources_usage_state.record_image_access(
|
||||||
|
&use_ref,
|
||||||
|
image_inner.image,
|
||||||
|
subresource_range,
|
||||||
|
access,
|
||||||
|
image_layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(resolve_info) = resolve_info {
|
||||||
|
let &RenderPassStateAttachmentResolveInfo {
|
||||||
|
ref image_view,
|
||||||
|
image_layout,
|
||||||
|
load_access,
|
||||||
|
..
|
||||||
|
} = resolve_info;
|
||||||
|
|
||||||
|
if let Some(access) = load_access {
|
||||||
|
let image = image_view.image();
|
||||||
|
let image_inner = image.inner();
|
||||||
|
let mut subresource_range = image_view.subresource_range().clone();
|
||||||
|
subresource_range.array_layers.start += image_inner.first_layer;
|
||||||
|
subresource_range.array_layers.end += image_inner.first_layer;
|
||||||
|
subresource_range.mip_levels.start += image_inner.first_mipmap_level;
|
||||||
|
subresource_range.mip_levels.end += image_inner.first_mipmap_level;
|
||||||
|
|
||||||
|
if let Some(aspects) = aspects_override {
|
||||||
|
subresource_range.aspects = aspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
let use_ref = ResourceUseRef {
|
||||||
|
command_index,
|
||||||
|
command_name,
|
||||||
|
resource_in_command: resolve_resource_in_command,
|
||||||
|
secondary_use_ref: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
resources_usage_state.record_image_access(
|
||||||
|
&use_ref,
|
||||||
|
image_inner.image,
|
||||||
|
subresource_range,
|
||||||
|
access,
|
||||||
|
image_layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(attachment_info) = attachments.depth_attachment.as_ref() {
|
||||||
|
record_attachment(
|
||||||
|
resources_usage_state,
|
||||||
|
attachment_info,
|
||||||
|
Some(ImageAspects::DEPTH),
|
||||||
|
ResourceInCommand::DepthStencilAttachment,
|
||||||
|
ResourceInCommand::DepthStencilResolveAttachment,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(attachment_info) = attachments.stencil_attachment.as_ref() {
|
||||||
|
record_attachment(
|
||||||
|
resources_usage_state,
|
||||||
|
attachment_info,
|
||||||
|
Some(ImageAspects::STENCIL),
|
||||||
|
ResourceInCommand::DepthStencilAttachment,
|
||||||
|
ResourceInCommand::DepthStencilResolveAttachment,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, attachment_info) in (attachments.color_attachments.iter().enumerate())
|
||||||
|
.filter_map(|(i, a)| a.as_ref().map(|a| (i as u32, a)))
|
||||||
|
{
|
||||||
|
record_attachment(
|
||||||
|
resources_usage_state,
|
||||||
|
attachment_info,
|
||||||
|
None,
|
||||||
|
ResourceInCommand::ColorAttachment { index },
|
||||||
|
ResourceInCommand::ColorResolveAttachment { index },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -120,10 +120,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
RenderPassStateType::BeginRendering(state),
|
RenderPassStateType::BeginRendering(_),
|
||||||
CommandBufferInheritanceRenderPassType::BeginRendering(inheritance_info),
|
CommandBufferInheritanceRenderPassType::BeginRendering(inheritance_info),
|
||||||
) => {
|
) => {
|
||||||
let attachments = state.attachments.as_ref().unwrap();
|
let attachments = render_pass_state.attachments.as_ref().unwrap();
|
||||||
|
|
||||||
// VUID-vkCmdExecuteCommands-colorAttachmentCount-06027
|
// VUID-vkCmdExecuteCommands-colorAttachmentCount-06027
|
||||||
if inheritance_info.color_attachment_formats.len()
|
if inheritance_info.color_attachment_formats.len()
|
||||||
@ -230,10 +230,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VUID-vkCmdExecuteCommands-viewMask-06031
|
// VUID-vkCmdExecuteCommands-viewMask-06031
|
||||||
if inheritance_info.view_mask != render_pass_state.view_mask {
|
if inheritance_info.view_mask != render_pass_state.rendering_info.view_mask {
|
||||||
return Err(ExecuteCommandsError::RenderPassViewMaskMismatch {
|
return Err(ExecuteCommandsError::RenderPassViewMaskMismatch {
|
||||||
command_buffer_index,
|
command_buffer_index,
|
||||||
required_view_mask: render_pass_state.view_mask,
|
required_view_mask: render_pass_state.rendering_info.view_mask,
|
||||||
inherited_view_mask: inheritance_info.view_mask,
|
inherited_view_mask: inheritance_info.view_mask,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,8 @@ use crate::{
|
|||||||
DynamicState, PartialStateMode, PipelineLayout, StateMode,
|
DynamicState, PartialStateMode, PipelineLayout, StateMode,
|
||||||
},
|
},
|
||||||
shader::{
|
shader::{
|
||||||
DescriptorBindingRequirements, EntryPoint, ShaderExecution, ShaderStage,
|
DescriptorBindingRequirements, EntryPoint, FragmentShaderExecution, FragmentTestsStages,
|
||||||
SpecializationConstants, SpecializationMapEntry,
|
ShaderExecution, ShaderStage, SpecializationConstants, SpecializationMapEntry,
|
||||||
},
|
},
|
||||||
DeviceSize, RequiresOneOf, Version, VulkanError, VulkanObject,
|
DeviceSize, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
@ -364,16 +364,18 @@ where
|
|||||||
|
|
||||||
self.validate_create(&device, &pipeline_layout, &vertex_input_state, has)?;
|
self.validate_create(&device, &pipeline_layout, &vertex_input_state, has)?;
|
||||||
|
|
||||||
let (handle, descriptor_requirements, dynamic_state, shaders) =
|
let (handle, descriptor_requirements, dynamic_state, shaders, fragment_tests_stages) =
|
||||||
unsafe { self.record_create(&device, &pipeline_layout, &vertex_input_state, has)? };
|
unsafe { self.record_create(&device, &pipeline_layout, &vertex_input_state, has)? };
|
||||||
|
|
||||||
let Self {
|
let Self {
|
||||||
mut render_pass,
|
mut render_pass,
|
||||||
cache: _,
|
cache: _,
|
||||||
|
|
||||||
vertex_shader: _,
|
vertex_shader: _,
|
||||||
tessellation_shaders: _,
|
tessellation_shaders: _,
|
||||||
geometry_shader: _,
|
geometry_shader: _,
|
||||||
fragment_shader: _,
|
fragment_shader: _,
|
||||||
|
|
||||||
vertex_input_state: _,
|
vertex_input_state: _,
|
||||||
input_assembly_state,
|
input_assembly_state,
|
||||||
tessellation_state,
|
tessellation_state,
|
||||||
@ -398,9 +400,12 @@ where
|
|||||||
id: GraphicsPipeline::next_id(),
|
id: GraphicsPipeline::next_id(),
|
||||||
layout: pipeline_layout,
|
layout: pipeline_layout,
|
||||||
render_pass: render_pass.take().expect("Missing render pass"),
|
render_pass: render_pass.take().expect("Missing render pass"),
|
||||||
|
|
||||||
shaders,
|
shaders,
|
||||||
descriptor_binding_requirements: descriptor_requirements,
|
descriptor_binding_requirements: descriptor_requirements,
|
||||||
num_used_descriptor_sets,
|
num_used_descriptor_sets,
|
||||||
|
fragment_tests_stages,
|
||||||
|
|
||||||
vertex_input_state, // Can be None if there's a mesh shader, but we don't support that yet
|
vertex_input_state, // Can be None if there's a mesh shader, but we don't support that yet
|
||||||
input_assembly_state, // Can be None if there's a mesh shader, but we don't support that yet
|
input_assembly_state, // Can be None if there's a mesh shader, but we don't support that yet
|
||||||
tessellation_state: has.tessellation_state.then_some(tessellation_state),
|
tessellation_state: has.tessellation_state.then_some(tessellation_state),
|
||||||
@ -1845,7 +1850,7 @@ where
|
|||||||
});
|
});
|
||||||
|
|
||||||
match entry_point.execution() {
|
match entry_point.execution() {
|
||||||
ShaderExecution::Fragment => (),
|
ShaderExecution::Fragment(_) => (),
|
||||||
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2540,6 +2545,7 @@ where
|
|||||||
HashMap<(u32, u32), DescriptorBindingRequirements>,
|
HashMap<(u32, u32), DescriptorBindingRequirements>,
|
||||||
HashMap<DynamicState, bool>,
|
HashMap<DynamicState, bool>,
|
||||||
HashMap<ShaderStage, ()>,
|
HashMap<ShaderStage, ()>,
|
||||||
|
Option<FragmentTestsStages>,
|
||||||
),
|
),
|
||||||
GraphicsPipelineCreationError,
|
GraphicsPipelineCreationError,
|
||||||
> {
|
> {
|
||||||
@ -2572,6 +2578,7 @@ where
|
|||||||
let mut dynamic_state: HashMap<DynamicState, bool> = HashMap::default();
|
let mut dynamic_state: HashMap<DynamicState, bool> = HashMap::default();
|
||||||
let mut stages = HashMap::default();
|
let mut stages = HashMap::default();
|
||||||
let mut stages_vk: SmallVec<[_; 5]> = SmallVec::new();
|
let mut stages_vk: SmallVec<[_; 5]> = SmallVec::new();
|
||||||
|
let mut fragment_tests_stages = None;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Render pass
|
Render pass
|
||||||
@ -3249,6 +3256,13 @@ where
|
|||||||
p_specialization_info: specialization_info_vk as *const _,
|
p_specialization_info: specialization_info_vk as *const _,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
fragment_tests_stages = match entry_point.execution() {
|
||||||
|
ShaderExecution::Fragment(FragmentShaderExecution {
|
||||||
|
fragment_tests_stages,
|
||||||
|
..
|
||||||
|
}) => Some(*fragment_tests_stages),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3700,6 +3714,7 @@ where
|
|||||||
descriptor_binding_requirements,
|
descriptor_binding_requirements,
|
||||||
dynamic_state,
|
dynamic_state,
|
||||||
stages,
|
stages,
|
||||||
|
fragment_tests_stages,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ use self::{
|
|||||||
use super::{DynamicState, Pipeline, PipelineBindPoint, PipelineLayout};
|
use super::{DynamicState, Pipeline, PipelineBindPoint, PipelineLayout};
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
shader::{DescriptorBindingRequirements, ShaderStage},
|
shader::{DescriptorBindingRequirements, FragmentTestsStages, ShaderStage},
|
||||||
VulkanObject,
|
VulkanObject,
|
||||||
};
|
};
|
||||||
use ahash::HashMap;
|
use ahash::HashMap;
|
||||||
@ -108,6 +108,7 @@ pub struct GraphicsPipeline {
|
|||||||
shaders: HashMap<ShaderStage, ()>,
|
shaders: HashMap<ShaderStage, ()>,
|
||||||
descriptor_binding_requirements: HashMap<(u32, u32), DescriptorBindingRequirements>,
|
descriptor_binding_requirements: HashMap<(u32, u32), DescriptorBindingRequirements>,
|
||||||
num_used_descriptor_sets: u32,
|
num_used_descriptor_sets: u32,
|
||||||
|
fragment_tests_stages: Option<FragmentTestsStages>,
|
||||||
|
|
||||||
vertex_input_state: VertexInputState,
|
vertex_input_state: VertexInputState,
|
||||||
input_assembly_state: InputAssemblyState,
|
input_assembly_state: InputAssemblyState,
|
||||||
@ -233,6 +234,12 @@ impl GraphicsPipeline {
|
|||||||
pub fn dynamic_states(&self) -> impl ExactSizeIterator<Item = (DynamicState, bool)> + '_ {
|
pub fn dynamic_states(&self) -> impl ExactSizeIterator<Item = (DynamicState, bool)> + '_ {
|
||||||
self.dynamic_state.iter().map(|(k, v)| (*k, *v))
|
self.dynamic_state.iter().map(|(k, v)| (*k, *v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the pipeline has a fragment shader, returns the fragment tests stages used.
|
||||||
|
#[inline]
|
||||||
|
pub fn fragment_tests_stages(&self) -> Option<FragmentTestsStages> {
|
||||||
|
self.fragment_tests_stages
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pipeline for GraphicsPipeline {
|
impl Pipeline for GraphicsPipeline {
|
||||||
|
@ -7,7 +7,12 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use crate::{format::Format, render_pass::Subpass};
|
use crate::{
|
||||||
|
command_buffer::{CommandBufferInheritanceRenderingInfo, RenderingInfo},
|
||||||
|
format::Format,
|
||||||
|
image::ImageAspects,
|
||||||
|
render_pass::Subpass,
|
||||||
|
};
|
||||||
|
|
||||||
/// Selects the type of render pass that a graphics pipeline is created for.
|
/// Selects the type of render pass that a graphics pipeline is created for.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -79,3 +84,58 @@ impl Default for PipelineRenderingCreateInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PipelineRenderingCreateInfo {
|
||||||
|
pub(crate) fn from_subpass(subpass: &Subpass) -> Self {
|
||||||
|
let subpass_desc = subpass.subpass_desc();
|
||||||
|
let rp_attachments = subpass.render_pass().attachments();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
view_mask: subpass_desc.view_mask,
|
||||||
|
color_attachment_formats: (subpass_desc.color_attachments.iter())
|
||||||
|
.map(|atch_ref| {
|
||||||
|
atch_ref.as_ref().map(|atch_ref| {
|
||||||
|
rp_attachments[atch_ref.attachment as usize].format.unwrap()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
depth_attachment_format: (subpass_desc.depth_stencil_attachment.as_ref())
|
||||||
|
.map(|atch_ref| rp_attachments[atch_ref.attachment as usize].format.unwrap())
|
||||||
|
.filter(|format| format.aspects().intersects(ImageAspects::DEPTH)),
|
||||||
|
stencil_attachment_format: (subpass_desc.depth_stencil_attachment.as_ref())
|
||||||
|
.map(|atch_ref| rp_attachments[atch_ref.attachment as usize].format.unwrap())
|
||||||
|
.filter(|format| format.aspects().intersects(ImageAspects::STENCIL)),
|
||||||
|
_ne: crate::NonExhaustive(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_rendering_info(info: &RenderingInfo) -> Self {
|
||||||
|
Self {
|
||||||
|
view_mask: info.view_mask,
|
||||||
|
color_attachment_formats: (info.color_attachments.iter())
|
||||||
|
.map(|atch_info| {
|
||||||
|
atch_info
|
||||||
|
.as_ref()
|
||||||
|
.map(|atch_info| atch_info.image_view.format().unwrap())
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
depth_attachment_format: (info.depth_attachment.as_ref())
|
||||||
|
.map(|atch_info| atch_info.image_view.format().unwrap()),
|
||||||
|
stencil_attachment_format: (info.stencil_attachment.as_ref())
|
||||||
|
.map(|atch_info| atch_info.image_view.format().unwrap()),
|
||||||
|
_ne: crate::NonExhaustive(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_inheritance_rendering_info(
|
||||||
|
info: &CommandBufferInheritanceRenderingInfo,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
view_mask: info.view_mask,
|
||||||
|
color_attachment_formats: info.color_attachment_formats.clone(),
|
||||||
|
depth_attachment_format: info.depth_attachment_format,
|
||||||
|
stencil_attachment_format: info.stencil_attachment_format,
|
||||||
|
_ne: crate::NonExhaustive(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -426,6 +426,7 @@ pub enum StateMode<F> {
|
|||||||
/// The pipeline has a fixed value for this state. Previously set dynamic state will be lost
|
/// 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.
|
/// when binding it, and will have to be re-set after binding a pipeline that uses it.
|
||||||
Fixed(F),
|
Fixed(F),
|
||||||
|
|
||||||
/// The pipeline expects a dynamic value to be set by a command buffer. Previously set dynamic
|
/// The pipeline expects a dynamic value to be set by a command buffer. Previously set dynamic
|
||||||
/// state is not disturbed when binding it.
|
/// state is not disturbed when binding it.
|
||||||
Dynamic,
|
Dynamic,
|
||||||
|
@ -30,7 +30,7 @@ impl RenderPass {
|
|||||||
pub(super) fn validate(
|
pub(super) fn validate(
|
||||||
device: &Device,
|
device: &Device,
|
||||||
create_info: &mut RenderPassCreateInfo,
|
create_info: &mut RenderPassCreateInfo,
|
||||||
) -> Result<u32, RenderPassCreationError> {
|
) -> Result<(), RenderPassCreationError> {
|
||||||
let properties = device.physical_device().properties();
|
let properties = device.physical_device().properties();
|
||||||
|
|
||||||
let RenderPassCreateInfo {
|
let RenderPassCreateInfo {
|
||||||
@ -41,8 +41,6 @@ impl RenderPass {
|
|||||||
_ne: _,
|
_ne: _,
|
||||||
} = create_info;
|
} = create_info;
|
||||||
|
|
||||||
let mut views_used = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Attachments
|
Attachments
|
||||||
*/
|
*/
|
||||||
@ -191,8 +189,6 @@ impl RenderPass {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
views_used = views_used.max(view_count);
|
|
||||||
|
|
||||||
// VUID-VkSubpassDescription2-colorAttachmentCount-03063
|
// VUID-VkSubpassDescription2-colorAttachmentCount-03063
|
||||||
if color_attachments.len() as u32 > properties.max_color_attachments {
|
if color_attachments.len() as u32 > properties.max_color_attachments {
|
||||||
return Err(
|
return Err(
|
||||||
@ -1041,7 +1037,7 @@ impl RenderPass {
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(views_used)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) unsafe fn create_v2(
|
pub(super) unsafe fn create_v2(
|
||||||
|
@ -109,6 +109,7 @@ pub struct RenderPass {
|
|||||||
dependencies: Vec<SubpassDependency>,
|
dependencies: Vec<SubpassDependency>,
|
||||||
correlated_view_masks: Vec<u32>,
|
correlated_view_masks: Vec<u32>,
|
||||||
|
|
||||||
|
attachment_uses: Vec<Option<AttachmentUse>>,
|
||||||
granularity: [u32; 2],
|
granularity: [u32; 2],
|
||||||
views_used: u32,
|
views_used: u32,
|
||||||
}
|
}
|
||||||
@ -124,7 +125,7 @@ impl RenderPass {
|
|||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
mut create_info: RenderPassCreateInfo,
|
mut create_info: RenderPassCreateInfo,
|
||||||
) -> Result<Arc<RenderPass>, RenderPassCreationError> {
|
) -> Result<Arc<RenderPass>, RenderPassCreationError> {
|
||||||
let views_used = Self::validate(&device, &mut create_info)?;
|
Self::validate(&device, &mut create_info)?;
|
||||||
|
|
||||||
let handle = unsafe {
|
let handle = unsafe {
|
||||||
if device.api_version() >= Version::V1_2
|
if device.api_version() >= Version::V1_2
|
||||||
@ -136,38 +137,7 @@ impl RenderPass {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let RenderPassCreateInfo {
|
unsafe { Ok(Self::from_handle(device, handle, create_info)) }
|
||||||
attachments,
|
|
||||||
subpasses,
|
|
||||||
dependencies,
|
|
||||||
correlated_view_masks,
|
|
||||||
_ne: _,
|
|
||||||
} = create_info;
|
|
||||||
|
|
||||||
let granularity = unsafe { Self::get_granularity(&device, handle) };
|
|
||||||
|
|
||||||
Ok(Arc::new(RenderPass {
|
|
||||||
handle,
|
|
||||||
device,
|
|
||||||
id: Self::next_id(),
|
|
||||||
attachments,
|
|
||||||
subpasses,
|
|
||||||
dependencies,
|
|
||||||
correlated_view_masks,
|
|
||||||
granularity,
|
|
||||||
views_used,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn get_granularity(device: &Arc<Device>, handle: ash::vk::RenderPass) -> [u32; 2] {
|
|
||||||
let fns = device.fns();
|
|
||||||
let mut out = MaybeUninit::uninit();
|
|
||||||
(fns.v1_0.get_render_area_granularity)(device.handle(), handle, out.as_mut_ptr());
|
|
||||||
|
|
||||||
let out = out.assume_init();
|
|
||||||
debug_assert_ne!(out.width, 0);
|
|
||||||
debug_assert_ne!(out.height, 0);
|
|
||||||
[out.width, out.height]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a render pass with one subpass and no attachment.
|
/// Builds a render pass with one subpass and no attachment.
|
||||||
@ -197,15 +167,7 @@ impl RenderPass {
|
|||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
handle: ash::vk::RenderPass,
|
handle: ash::vk::RenderPass,
|
||||||
create_info: RenderPassCreateInfo,
|
create_info: RenderPassCreateInfo,
|
||||||
) -> Result<Arc<RenderPass>, RenderPassCreationError> {
|
) -> Arc<RenderPass> {
|
||||||
let views_used = create_info
|
|
||||||
.subpasses
|
|
||||||
.iter()
|
|
||||||
.map(|subpass| u32::BITS - subpass.view_mask.leading_zeros())
|
|
||||||
.max()
|
|
||||||
.unwrap();
|
|
||||||
let granularity = Self::get_granularity(&device, handle);
|
|
||||||
|
|
||||||
let RenderPassCreateInfo {
|
let RenderPassCreateInfo {
|
||||||
attachments,
|
attachments,
|
||||||
subpasses,
|
subpasses,
|
||||||
@ -214,17 +176,65 @@ impl RenderPass {
|
|||||||
_ne: _,
|
_ne: _,
|
||||||
} = create_info;
|
} = create_info;
|
||||||
|
|
||||||
Ok(Arc::new(RenderPass {
|
let granularity = Self::get_granularity(&device, handle);
|
||||||
|
let mut attachment_uses: Vec<Option<AttachmentUse>> = vec![None; attachments.len()];
|
||||||
|
let mut views_used = 0;
|
||||||
|
|
||||||
|
for (index, subpass_desc) in subpasses.iter().enumerate() {
|
||||||
|
let index = index as u32;
|
||||||
|
let &SubpassDescription {
|
||||||
|
view_mask,
|
||||||
|
ref input_attachments,
|
||||||
|
ref color_attachments,
|
||||||
|
ref resolve_attachments,
|
||||||
|
ref depth_stencil_attachment,
|
||||||
|
..
|
||||||
|
} = subpass_desc;
|
||||||
|
|
||||||
|
for atch_ref in (input_attachments.iter().flatten())
|
||||||
|
.chain(color_attachments.iter().flatten())
|
||||||
|
.chain(resolve_attachments.iter().flatten())
|
||||||
|
.chain(depth_stencil_attachment.iter())
|
||||||
|
{
|
||||||
|
match &mut attachment_uses[atch_ref.attachment as usize] {
|
||||||
|
Some(attachment_use) => attachment_use.last_use_subpass = index,
|
||||||
|
attachment_use @ None => {
|
||||||
|
*attachment_use = Some(AttachmentUse {
|
||||||
|
first_use_subpass: index,
|
||||||
|
last_use_subpass: index,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
views_used = max(views_used, u32::BITS - view_mask.leading_zeros());
|
||||||
|
}
|
||||||
|
|
||||||
|
Arc::new(RenderPass {
|
||||||
handle,
|
handle,
|
||||||
device,
|
device,
|
||||||
id: Self::next_id(),
|
id: Self::next_id(),
|
||||||
|
|
||||||
attachments,
|
attachments,
|
||||||
subpasses,
|
subpasses,
|
||||||
dependencies,
|
dependencies,
|
||||||
correlated_view_masks,
|
correlated_view_masks,
|
||||||
|
|
||||||
|
attachment_uses,
|
||||||
granularity,
|
granularity,
|
||||||
views_used,
|
views_used,
|
||||||
}))
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get_granularity(device: &Arc<Device>, handle: ash::vk::RenderPass) -> [u32; 2] {
|
||||||
|
let fns = device.fns();
|
||||||
|
let mut out = MaybeUninit::uninit();
|
||||||
|
(fns.v1_0.get_render_area_granularity)(device.handle(), handle, out.as_mut_ptr());
|
||||||
|
|
||||||
|
let out = out.assume_init();
|
||||||
|
debug_assert_ne!(out.width, 0);
|
||||||
|
debug_assert_ne!(out.height, 0);
|
||||||
|
[out.width, out.height]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the attachments of the render pass.
|
/// Returns the attachments of the render pass.
|
||||||
@ -292,6 +302,7 @@ impl RenderPass {
|
|||||||
subpasses: subpasses1,
|
subpasses: subpasses1,
|
||||||
dependencies: dependencies1,
|
dependencies: dependencies1,
|
||||||
correlated_view_masks: correlated_view_masks1,
|
correlated_view_masks: correlated_view_masks1,
|
||||||
|
attachment_uses: _,
|
||||||
granularity: _,
|
granularity: _,
|
||||||
views_used: _,
|
views_used: _,
|
||||||
} = self;
|
} = self;
|
||||||
@ -302,6 +313,7 @@ impl RenderPass {
|
|||||||
attachments: attachments2,
|
attachments: attachments2,
|
||||||
subpasses: subpasses2,
|
subpasses: subpasses2,
|
||||||
dependencies: dependencies2,
|
dependencies: dependencies2,
|
||||||
|
attachment_uses: _,
|
||||||
correlated_view_masks: correlated_view_masks2,
|
correlated_view_masks: correlated_view_masks2,
|
||||||
granularity: _,
|
granularity: _,
|
||||||
views_used: _,
|
views_used: _,
|
||||||
@ -713,6 +725,44 @@ impl Subpass {
|
|||||||
self.render_pass
|
self.render_pass
|
||||||
.is_compatible_with_shader(self.subpass_id, shader_interface)
|
.is_compatible_with_shader(self.subpass_id, shader_interface)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn load_op(&self, attachment_index: u32) -> Option<LoadOp> {
|
||||||
|
self.render_pass.attachment_uses[attachment_index as usize]
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|attachment_use| {
|
||||||
|
(attachment_use.first_use_subpass == self.subpass_id)
|
||||||
|
.then(|| self.render_pass.attachments[attachment_index as usize].load_op)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn store_op(&self, attachment_index: u32) -> Option<StoreOp> {
|
||||||
|
self.render_pass.attachment_uses[attachment_index as usize]
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|attachment_use| {
|
||||||
|
(attachment_use.last_use_subpass == self.subpass_id)
|
||||||
|
.then(|| self.render_pass.attachments[attachment_index as usize].store_op)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn stencil_load_op(&self, attachment_index: u32) -> Option<LoadOp> {
|
||||||
|
self.render_pass.attachment_uses[attachment_index as usize]
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|attachment_use| {
|
||||||
|
(attachment_use.first_use_subpass == self.subpass_id).then(|| {
|
||||||
|
self.render_pass.attachments[attachment_index as usize].stencil_load_op
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn stencil_store_op(&self, attachment_index: u32) -> Option<StoreOp> {
|
||||||
|
self.render_pass.attachment_uses[attachment_index as usize]
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|attachment_use| {
|
||||||
|
(attachment_use.last_use_subpass == self.subpass_id).then(|| {
|
||||||
|
self.render_pass.attachments[attachment_index as usize].stencil_store_op
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Subpass> for (Arc<RenderPass>, u32) {
|
impl From<Subpass> for (Arc<RenderPass>, u32) {
|
||||||
@ -1147,7 +1197,7 @@ vulkan_enum! {
|
|||||||
// TODO: document
|
// TODO: document
|
||||||
None = NONE {
|
None = NONE {
|
||||||
api_version: V1_3,
|
api_version: V1_3,
|
||||||
device_extensions: [ext_load_store_op_none],
|
device_extensions: [khr_dynamic_rendering, ext_load_store_op_none, qcom_render_pass_store_ops],
|
||||||
},*/
|
},*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1184,6 +1234,12 @@ vulkan_bitflags_enum! {
|
|||||||
MAX, Max = MAX,
|
MAX, Max = MAX,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub(crate) struct AttachmentUse {
|
||||||
|
first_use_subpass: u32,
|
||||||
|
last_use_subpass: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -467,7 +467,7 @@ pub enum ShaderExecution {
|
|||||||
TessellationControl,
|
TessellationControl,
|
||||||
TessellationEvaluation,
|
TessellationEvaluation,
|
||||||
Geometry(GeometryShaderExecution),
|
Geometry(GeometryShaderExecution),
|
||||||
Fragment,
|
Fragment(FragmentShaderExecution),
|
||||||
Compute,
|
Compute,
|
||||||
RayGeneration,
|
RayGeneration,
|
||||||
AnyHit,
|
AnyHit,
|
||||||
@ -550,6 +550,20 @@ pub enum GeometryShaderOutput {
|
|||||||
TriangleStrip,
|
TriangleStrip,
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/// The mode in which a fragment shader executes.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub struct FragmentShaderExecution {
|
||||||
|
pub fragment_tests_stages: FragmentTestsStages,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The fragment tests stages that will be executed in a fragment shader.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum FragmentTestsStages {
|
||||||
|
Early,
|
||||||
|
Late,
|
||||||
|
EarlyAndLate,
|
||||||
|
}
|
||||||
|
|
||||||
/// The requirements imposed by a shader on a binding within a descriptor set layout, and on any
|
/// The requirements imposed by a shader on a binding within a descriptor set layout, and on any
|
||||||
/// resource that is bound to that binding.
|
/// resource that is bound to that binding.
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
@ -1189,7 +1203,7 @@ impl From<ShaderExecution> for ShaderStage {
|
|||||||
ShaderExecution::TessellationControl => Self::TessellationControl,
|
ShaderExecution::TessellationControl => Self::TessellationControl,
|
||||||
ShaderExecution::TessellationEvaluation => Self::TessellationEvaluation,
|
ShaderExecution::TessellationEvaluation => Self::TessellationEvaluation,
|
||||||
ShaderExecution::Geometry(_) => Self::Geometry,
|
ShaderExecution::Geometry(_) => Self::Geometry,
|
||||||
ShaderExecution::Fragment => Self::Fragment,
|
ShaderExecution::Fragment(_) => Self::Fragment,
|
||||||
ShaderExecution::Compute => Self::Compute,
|
ShaderExecution::Compute => Self::Compute,
|
||||||
ShaderExecution::RayGeneration => Self::Raygen,
|
ShaderExecution::RayGeneration => Self::Raygen,
|
||||||
ShaderExecution::AnyHit => Self::AnyHit,
|
ShaderExecution::AnyHit => Self::AnyHit,
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
//! Extraction of information from SPIR-V modules, that is needed by the rest of Vulkano.
|
//! Extraction of information from SPIR-V modules, that is needed by the rest of Vulkano.
|
||||||
|
|
||||||
use super::DescriptorBindingRequirements;
|
use super::{DescriptorBindingRequirements, FragmentShaderExecution, FragmentTestsStages};
|
||||||
use crate::{
|
use crate::{
|
||||||
descriptor_set::layout::DescriptorType,
|
descriptor_set::layout::DescriptorType,
|
||||||
image::view::ImageViewType,
|
image::view::ImageViewType,
|
||||||
@ -128,32 +128,69 @@ fn shader_execution(
|
|||||||
ExecutionModel::TessellationEvaluation => ShaderExecution::TessellationEvaluation,
|
ExecutionModel::TessellationEvaluation => ShaderExecution::TessellationEvaluation,
|
||||||
|
|
||||||
ExecutionModel::Geometry => {
|
ExecutionModel::Geometry => {
|
||||||
let input = spirv
|
let mut input = None;
|
||||||
.iter_execution_mode()
|
|
||||||
.into_iter()
|
for instruction in spirv.iter_execution_mode() {
|
||||||
.find_map(|instruction| match instruction {
|
let mode = match instruction {
|
||||||
Instruction::ExecutionMode {
|
Instruction::ExecutionMode {
|
||||||
entry_point, mode, ..
|
entry_point, mode, ..
|
||||||
} if *entry_point == function_id => match mode {
|
} if *entry_point == function_id => mode,
|
||||||
ExecutionMode::InputPoints => Some(GeometryShaderInput::Points),
|
_ => continue,
|
||||||
ExecutionMode::InputLines => Some(GeometryShaderInput::Lines),
|
};
|
||||||
ExecutionMode::InputLinesAdjacency => {
|
|
||||||
Some(GeometryShaderInput::LinesWithAdjacency)
|
|
||||||
}
|
|
||||||
ExecutionMode::Triangles => Some(GeometryShaderInput::Triangles),
|
|
||||||
ExecutionMode::InputTrianglesAdjacency => {
|
|
||||||
Some(GeometryShaderInput::TrianglesWithAdjacency)
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.expect("Geometry shader does not have an input primitive ExecutionMode");
|
|
||||||
|
|
||||||
ShaderExecution::Geometry(GeometryShaderExecution { input })
|
match mode {
|
||||||
|
ExecutionMode::InputPoints => {
|
||||||
|
input = Some(GeometryShaderInput::Points);
|
||||||
|
}
|
||||||
|
ExecutionMode::InputLines => {
|
||||||
|
input = Some(GeometryShaderInput::Lines);
|
||||||
|
}
|
||||||
|
ExecutionMode::InputLinesAdjacency => {
|
||||||
|
input = Some(GeometryShaderInput::LinesWithAdjacency);
|
||||||
|
}
|
||||||
|
ExecutionMode::Triangles => {
|
||||||
|
input = Some(GeometryShaderInput::Triangles);
|
||||||
|
}
|
||||||
|
ExecutionMode::InputTrianglesAdjacency => {
|
||||||
|
input = Some(GeometryShaderInput::TrianglesWithAdjacency);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderExecution::Geometry(GeometryShaderExecution {
|
||||||
|
input: input
|
||||||
|
.expect("Geometry shader does not have an input primitive ExecutionMode"),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutionModel::Fragment => ShaderExecution::Fragment,
|
ExecutionModel::Fragment => {
|
||||||
|
let mut fragment_tests_stages = FragmentTestsStages::Late;
|
||||||
|
|
||||||
|
for instruction in spirv.iter_execution_mode() {
|
||||||
|
let mode = match instruction {
|
||||||
|
Instruction::ExecutionMode {
|
||||||
|
entry_point, mode, ..
|
||||||
|
} if *entry_point == function_id => mode,
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[allow(clippy::single_match)]
|
||||||
|
match mode {
|
||||||
|
ExecutionMode::EarlyFragmentTests => {
|
||||||
|
fragment_tests_stages = FragmentTestsStages::Early;
|
||||||
|
}
|
||||||
|
/*ExecutionMode::EarlyAndLateFragmentTestsAMD => {
|
||||||
|
fragment_tests_stages = FragmentTestsStages::EarlyAndLate;
|
||||||
|
}*/
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderExecution::Fragment(FragmentShaderExecution {
|
||||||
|
fragment_tests_stages,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
ExecutionModel::GLCompute => ShaderExecution::Compute,
|
ExecutionModel::GLCompute => ShaderExecution::Compute,
|
||||||
|
|
||||||
@ -164,7 +201,10 @@ fn shader_execution(
|
|||||||
ExecutionModel::MissKHR => ShaderExecution::Miss,
|
ExecutionModel::MissKHR => ShaderExecution::Miss,
|
||||||
ExecutionModel::CallableKHR => ShaderExecution::Callable,
|
ExecutionModel::CallableKHR => ShaderExecution::Callable,
|
||||||
|
|
||||||
ExecutionModel::Kernel | ExecutionModel::TaskNV | ExecutionModel::MeshNV => todo!(),
|
ExecutionModel::TaskNV => ShaderExecution::Task,
|
||||||
|
ExecutionModel::MeshNV => ShaderExecution::Mesh,
|
||||||
|
|
||||||
|
ExecutionModel::Kernel => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user