diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-08-03 00:55:20 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-08-03 00:55:20 +0000 |
| commit | 26003b33992221c28bc63b92afb5ab4719cce4bb (patch) | |
| tree | ad19cf2d1a0284188d532da4c3814b079e5e93e9 /Graphics/GraphicsEngine | |
| parent | Few improvements to render pass API (diff) | |
| download | DiligentCore-26003b33992221c28bc63b92afb5ab4719cce4bb.tar.gz DiligentCore-26003b33992221c28bc63b92afb5ab4719cce4bb.zip | |
Added more render pass desc validation
Diffstat (limited to 'Graphics/GraphicsEngine')
| -rw-r--r-- | Graphics/GraphicsEngine/src/FramebufferBase.cpp | 82 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/src/RenderPassBase.cpp | 186 |
2 files changed, 190 insertions, 78 deletions
diff --git a/Graphics/GraphicsEngine/src/FramebufferBase.cpp b/Graphics/GraphicsEngine/src/FramebufferBase.cpp index 89b1aa5f..fa1f8d10 100644 --- a/Graphics/GraphicsEngine/src/FramebufferBase.cpp +++ b/Graphics/GraphicsEngine/src/FramebufferBase.cpp @@ -34,11 +34,11 @@ namespace Diligent void ValidateFramebufferDesc(const FramebufferDesc& Desc) { -#define LOG_FRAMEBUFFER_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Framebuffer '", (Desc.Name ? Desc.Name : ""), "': ", ##__VA_ARGS__) +#define LOG_FRAMEBUFFER_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of framebuffer '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) if (Desc.pRenderPass == nullptr) { - LOG_FRAMEBUFFER_ERROR_AND_THROW("Render pass must not be null"); + LOG_FRAMEBUFFER_ERROR_AND_THROW("render pass must not be null."); } for (Uint32 i = 0; i < Desc.AttachmentCount; ++i) @@ -48,30 +48,31 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, and attachmentCount is not 0, // pAttachments must be a valid pointer to an array of attachmentCount valid VkImageView handles. // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-flags-02778 - LOG_FRAMEBUFFER_ERROR_AND_THROW("Framebuffer attachment ", i, " is null"); + LOG_FRAMEBUFFER_ERROR_AND_THROW("framebuffer attachment ", i, " is null."); } } const auto& RPDesc = Desc.pRenderPass->GetDesc(); if (Desc.AttachmentCount < RPDesc.AttachmentCount) { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The number of framebuffer attachments (", Desc.AttachmentCount, + LOG_FRAMEBUFFER_ERROR_AND_THROW("the number of framebuffer attachments (", Desc.AttachmentCount, ") is smaller than the number of attachments (", RPDesc.AttachmentCount, ") in the render pass '", RPDesc.Name, "'."); } for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i) { - const auto& AttDesc = RPDesc.pAttachments[i]; - const auto& TexDesc = Desc.ppAttachments[i]->GetTexture()->GetDesc(); + const auto& AttDesc = RPDesc.pAttachments[i]; + const auto& ViewDesc = Desc.ppAttachments[i]->GetDesc(); + const auto& TexDesc = Desc.ppAttachments[i]->GetTexture()->GetDesc(); // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments // must have been created with a VkFormat value that matches the VkFormat specified by the corresponding // VkAttachmentDescription in renderPass // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00880 - if (TexDesc.Format != AttDesc.Format) + if (ViewDesc.Format != AttDesc.Format) { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The format (", GetTextureFormatAttribs(TexDesc.Format).Name, ") of attachment ", i, + LOG_FRAMEBUFFER_ERROR_AND_THROW("the format (", GetTextureFormatAttribs(ViewDesc.Format).Name, ") of attachment ", i, " does not match the format (", GetTextureFormatAttribs(AttDesc.Format).Name, ") defined by the render pass for the same attachment."); } @@ -82,7 +83,7 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00881 if (TexDesc.SampleCount != AttDesc.SampleCount) { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The sample count (", Uint32{TexDesc.SampleCount}, ") of attachment ", i, + LOG_FRAMEBUFFER_ERROR_AND_THROW("the sample count (", Uint32{TexDesc.SampleCount}, ") of attachment ", i, " does not match the sample count (", Uint32{AttDesc.SampleCount}, ") defined by the render pass for the same attachment."); } @@ -97,16 +98,9 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) continue; - // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments - // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not - // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount - // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 - if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) - { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The attachment index (", AttchRef.AttachmentIndex, ") of input attachment reference ", input_attachment, - " of subpass ", i, " of render pass '", RPDesc.Name, - "' exceeds the number of attachments in the framebuffer (", Desc.AttachmentCount, ")"); - } + VERIFY(AttchRef.AttachmentIndex < Desc.AttachmentCount, + "Input attachment index (", AttchRef.AttachmentIndex, ") must be less than the attachment count (", + Desc.AttachmentCount, ") as this is ensured by ValidateRenderPassDesc."); const auto& TexDesc = Desc.ppAttachments[AttchRef.AttachmentIndex]->GetTexture()->GetDesc(); @@ -116,7 +110,7 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00879 if ((TexDesc.BindFlags & BIND_INPUT_ATTACHMENT) == 0) { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, + LOG_FRAMEBUFFER_ERROR_AND_THROW("the attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, " is used as input attachment by subpass ", i, " of render pass '", RPDesc.Name, "', but was not created with BIND_INPUT_ATTACHMENT bind flag"); @@ -129,16 +123,9 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) continue; - // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments - // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not - // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount - // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 - if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) - { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The attachment index (", AttchRef.AttachmentIndex, ") of render target attachment reference ", rt_attachment, - " of subpass ", i, " of render pass '", RPDesc.Name, - "' exceeds the number of attachments in the framebuffer (", Desc.AttachmentCount, ")"); - } + VERIFY(AttchRef.AttachmentIndex < Desc.AttachmentCount, + "Render target attachment index (", AttchRef.AttachmentIndex, ") must be less than the attachment count (", + Desc.AttachmentCount, ") as this is ensured by ValidateRenderPassDesc."); const auto& TexDesc = Desc.ppAttachments[AttchRef.AttachmentIndex]->GetTexture()->GetDesc(); @@ -148,7 +135,7 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00877 if ((TexDesc.BindFlags & BIND_RENDER_TARGET) == 0) { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, + LOG_FRAMEBUFFER_ERROR_AND_THROW("the attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, " is used as render target attachment by subpass ", i, " of render pass '", RPDesc.Name, "', but was not created with BIND_RENDER_TARGET bind flag"); @@ -163,16 +150,9 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) continue; - // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments - // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not - // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount - // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 - if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) - { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The attachment index (", AttchRef.AttachmentIndex, ") of resolve attachment reference ", rslv_attachment, - " of subpass ", i, " of render pass '", RPDesc.Name, - "' exceeds the number of attachments in the framebuffer (", Desc.AttachmentCount, ")"); - } + VERIFY(AttchRef.AttachmentIndex < Desc.AttachmentCount, + "Resolve attachment index (", AttchRef.AttachmentIndex, ") must be less than the attachment count (", + Desc.AttachmentCount, ") as this is ensured by ValidateRenderPassDesc."); const auto& TexDesc = Desc.ppAttachments[AttchRef.AttachmentIndex]->GetTexture()->GetDesc(); @@ -182,7 +162,7 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00877 if ((TexDesc.BindFlags & BIND_RENDER_TARGET) == 0) { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, + LOG_FRAMEBUFFER_ERROR_AND_THROW("the attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, " is used as resolve attachment by subpass ", i, " of render pass '", RPDesc.Name, "', but was not created with BIND_RENDER_TARGET bind flag"); @@ -195,16 +175,9 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) const auto& AttchRef = *Subpass.pDepthStencilAttachment; if (AttchRef.AttachmentIndex != ATTACHMENT_UNUSED) { - // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments - // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not - // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount - // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 - if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) - { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The attachment index (", AttchRef.AttachmentIndex, ") of depth-stencil attachment reference of subpass ", i, - " of render pass '", RPDesc.Name, - "' exceeds the number of attachments in the framebuffer (", Desc.AttachmentCount, ")"); - } + VERIFY(AttchRef.AttachmentIndex < Desc.AttachmentCount, + "Depth-stencil attachment index (", AttchRef.AttachmentIndex, ") must be less than the attachment count (", + Desc.AttachmentCount, ") as this is ensured by ValidateRenderPassDesc."); const auto& TexDesc = Desc.ppAttachments[AttchRef.AttachmentIndex]->GetTexture()->GetDesc(); @@ -214,16 +187,13 @@ void ValidateFramebufferDesc(const FramebufferDesc& Desc) // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-02633 if ((TexDesc.BindFlags & BIND_DEPTH_STENCIL) == 0) { - LOG_FRAMEBUFFER_ERROR_AND_THROW("The attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, + LOG_FRAMEBUFFER_ERROR_AND_THROW("the attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, " is used as detph-stencil attachment by subpass ", i, " of render pass '", RPDesc.Name, "', but was not created with BIND_DEPTH_STENCIL bind flag"); } } } - - //for (Uint32 prsv_attachment = 0; prsv_attachment < Subpass.PreserveAttachmentCount; ++prsv_attachment) - // ; } } diff --git a/Graphics/GraphicsEngine/src/RenderPassBase.cpp b/Graphics/GraphicsEngine/src/RenderPassBase.cpp index f060c8a0..683d86aa 100644 --- a/Graphics/GraphicsEngine/src/RenderPassBase.cpp +++ b/Graphics/GraphicsEngine/src/RenderPassBase.cpp @@ -35,27 +35,27 @@ namespace Diligent void ValidateRenderPassDesc(const RenderPassDesc& Desc) { -#define LOG_RENDER_PASS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Render pass '", (Desc.Name ? Desc.Name : ""), "': ", ##__VA_ARGS__) +#define LOG_RENDER_PASS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of render pass '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) if (Desc.AttachmentCount != 0 && Desc.pAttachments == nullptr) { // If attachmentCount is not 0, pAttachments must be a valid pointer to an // array of attachmentCount valid VkAttachmentDescription structures. // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-pAttachments-parameter - LOG_RENDER_PASS_ERROR_AND_THROW("The attachment count (", Desc.AttachmentCount, ") is not zero, but pAttachments is null"); + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment count (", Desc.AttachmentCount, ") is not zero, but pAttachments is null."); } if (Desc.SubpassCount == 0) { // subpassCount must be greater than 0. // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-subpassCount-arraylength - LOG_RENDER_PASS_ERROR_AND_THROW("Render pass must have at least one subpass"); + LOG_RENDER_PASS_ERROR_AND_THROW("render pass must have at least one subpass."); } if (Desc.pSubpasses == nullptr) { // pSubpasses must be a valid pointer to an array of subpassCount valid VkSubpassDescription structures. // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-pSubpasses-parameter - LOG_RENDER_PASS_ERROR_AND_THROW("pSubpasses must not be null"); + LOG_RENDER_PASS_ERROR_AND_THROW("pSubpasses must not be null."); } if (Desc.DependencyCount != 0 && Desc.pDependencies == nullptr) @@ -63,20 +63,20 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc) // If dependencyCount is not 0, pDependencies must be a valid pointer to an array of // dependencyCount valid VkSubpassDependency structures. // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-pDependencies-parameter - LOG_RENDER_PASS_ERROR_AND_THROW("The dependency count (", Desc.DependencyCount, ") is not zero, but pDependencies is null"); + LOG_RENDER_PASS_ERROR_AND_THROW("the dependency count (", Desc.DependencyCount, ") is not zero, but pDependencies is null."); } for (Uint32 i = 0; i < Desc.AttachmentCount; ++i) { const auto& Attachment = Desc.pAttachments[i]; if (Attachment.Format == TEX_FORMAT_UNKNOWN) - LOG_RENDER_PASS_ERROR_AND_THROW("the format of attachment ", i, " is unknown"); + LOG_RENDER_PASS_ERROR_AND_THROW("the format of attachment ", i, " is unknown."); if (Attachment.SampleCount == 0) - LOG_RENDER_PASS_ERROR_AND_THROW("the sample count of attachment ", i, " is zero"); + LOG_RENDER_PASS_ERROR_AND_THROW("the sample count of attachment ", i, " is zero."); if (!IsPowerOfTwo(Attachment.SampleCount)) - LOG_RENDER_PASS_ERROR_AND_THROW("the sample count of attachment ", i, "(", Attachment.SampleCount, ") is not power of two"); + LOG_RENDER_PASS_ERROR_AND_THROW("the sample count (", Uint32{Attachment.SampleCount}, ") of attachment ", i, " is not power of two."); const auto& FmtInfo = GetTextureFormatAttribs(Attachment.Format); if (FmtInfo.ComponentType == COMPONENT_TYPE_DEPTH || @@ -89,7 +89,7 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc) Attachment.InitialState != RESOURCE_STATE_RESOLVE_DEST && Attachment.InitialState != RESOURCE_STATE_RESOLVE_SOURCE) { - LOG_RENDER_PASS_ERROR_AND_THROW("the initial state of depth-stencil attachment ", i, " (", GetResourceStateString(Attachment.InitialState), ") is invalid"); + LOG_RENDER_PASS_ERROR_AND_THROW("the initial state of depth-stencil attachment ", i, " (", GetResourceStateString(Attachment.InitialState), ") is invalid."); } if (Attachment.FinalState != RESOURCE_STATE_DEPTH_WRITE && @@ -99,7 +99,7 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc) Attachment.FinalState != RESOURCE_STATE_RESOLVE_DEST && Attachment.FinalState != RESOURCE_STATE_RESOLVE_SOURCE) { - LOG_RENDER_PASS_ERROR_AND_THROW("the final state of depth-stencil attachment ", i, " (", GetResourceStateString(Attachment.FinalState), ") is invalid"); + LOG_RENDER_PASS_ERROR_AND_THROW("the final state of depth-stencil attachment ", i, " (", GetResourceStateString(Attachment.FinalState), ") is invalid."); } } else @@ -110,7 +110,7 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc) Attachment.InitialState != RESOURCE_STATE_RESOLVE_DEST && Attachment.InitialState != RESOURCE_STATE_RESOLVE_SOURCE) { - LOG_RENDER_PASS_ERROR_AND_THROW("the initial state of color attachment ", i, " (", GetResourceStateString(Attachment.InitialState), ") is invalid"); + LOG_RENDER_PASS_ERROR_AND_THROW("the initial state of color attachment ", i, " (", GetResourceStateString(Attachment.InitialState), ") is invalid."); } if (Attachment.FinalState != RESOURCE_STATE_RENDER_TARGET && @@ -119,28 +119,170 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc) Attachment.FinalState != RESOURCE_STATE_RESOLVE_DEST && Attachment.FinalState != RESOURCE_STATE_RESOLVE_SOURCE) { - LOG_RENDER_PASS_ERROR_AND_THROW("the final state of color attachment ", i, " (", GetResourceStateString(Attachment.FinalState), ") is invalid"); + LOG_RENDER_PASS_ERROR_AND_THROW("the final state of color attachment ", i, " (", GetResourceStateString(Attachment.FinalState), ") is invalid."); } } } - for (Uint32 i = 0; i < Desc.SubpassCount; ++i) + for (Uint32 subpass = 0; subpass < Desc.SubpassCount; ++subpass) { - const auto& Subpass = Desc.pSubpasses[i]; + const auto& Subpass = Desc.pSubpasses[subpass]; if (Subpass.InputAttachmentCount != 0 && Subpass.pInputAttachments == nullptr) { - LOG_RENDER_PASS_ERROR_AND_THROW("the input attachment count (", Subpass.InputAttachmentCount, ") of subpass ", i, - " is not zero, while pInputAttachments is null"); + LOG_RENDER_PASS_ERROR_AND_THROW("the input attachment count (", Subpass.InputAttachmentCount, ") of subpass ", subpass, + " is not zero, while pInputAttachments is null."); } if (Subpass.RenderTargetAttachmentCount != 0 && Subpass.pRenderTargetAttachments == nullptr) { - LOG_RENDER_PASS_ERROR_AND_THROW("the render target attachment count (", Subpass.RenderTargetAttachmentCount, ") of subpass ", i, - " is not zero, while pRenderTargetAttachments is null"); + LOG_RENDER_PASS_ERROR_AND_THROW("the render target attachment count (", Subpass.RenderTargetAttachmentCount, ") of subpass ", subpass, + " is not zero, while pRenderTargetAttachments is null."); } if (Subpass.PreserveAttachmentCount != 0 && Subpass.pPreserveAttachments == nullptr) { - LOG_RENDER_PASS_ERROR_AND_THROW("the preserve attachment count (", Subpass.PreserveAttachmentCount, ") of subpass ", i, - " is not zero, while pPreserveAttachments is null"); + LOG_RENDER_PASS_ERROR_AND_THROW("the preserve attachment count (", Subpass.PreserveAttachmentCount, ") of subpass ", subpass, + " is not zero, while pPreserveAttachments is null."); + } + + for (Uint32 input_attachment = 0; input_attachment < Subpass.InputAttachmentCount; ++input_attachment) + { + const auto& AttchRef = Subpass.pInputAttachments[input_attachment]; + if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) + continue; + + // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments + // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not + // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 + if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", AttchRef.AttachmentIndex, ") of input attachment reference ", input_attachment, + " of subpass ", subpass, " must be less than the number of attachments (", Desc.AttachmentCount, ")."); + } + } + + for (Uint32 rt_attachment = 0; rt_attachment < Subpass.RenderTargetAttachmentCount; ++rt_attachment) + { + const auto& AttchRef = Subpass.pRenderTargetAttachments[rt_attachment]; + if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) + continue; + + // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments + // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not + // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 + if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", AttchRef.AttachmentIndex, ") of render target attachment reference ", rt_attachment, + " of subpass ", subpass, " must be less than the number of attachments (", Desc.AttachmentCount, ")."); + } + } + + if (Subpass.pResolveAttachments != nullptr) + { + for (Uint32 rslv_attachment = 0; rslv_attachment < Subpass.RenderTargetAttachmentCount; ++rslv_attachment) + { + const auto& AttchRef = Subpass.pResolveAttachments[rslv_attachment]; + if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) + continue; + + // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments + // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not + // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 + if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", AttchRef.AttachmentIndex, ") of resolve attachment reference ", rslv_attachment, + " of subpass ", subpass, " must be less than the number of attachments (", Desc.AttachmentCount, ")."); + } + } + } + + if (Subpass.pDepthStencilAttachment != nullptr) + { + const auto& AttchRef = *Subpass.pDepthStencilAttachment; + if (AttchRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments + // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not + // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 + if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", AttchRef.AttachmentIndex, ") of depth-stencil attachment reference of subpass ", subpass, + " must be less than the number of attachments (", Desc.AttachmentCount, ")."); + } + } + } + + for (Uint32 prsv_attachment = 0; prsv_attachment < Subpass.PreserveAttachmentCount; ++prsv_attachment) + { + const auto PrsvAttachment = Subpass.pPreserveAttachments[prsv_attachment]; + if (PrsvAttachment == ATTACHMENT_UNUSED) + { + // The attachment member of each element of pPreserveAttachments must not be VK_ATTACHMENT_UNUSED + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-attachment-00853 + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index of preserve attachment reference ", prsv_attachment, + " of subpass ", subpass, " is ATTACHMENT_UNUSED."); + } + + if (PrsvAttachment >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", PrsvAttachment, ") of preserve attachment reference ", prsv_attachment, + " of subpass ", subpass, " exceeds the number of attachments (", Desc.AttachmentCount, ")."); + } + } + + if (Subpass.pResolveAttachments != nullptr) + { + for (Uint32 attchmnt = 0; attchmnt < Subpass.RenderTargetAttachmentCount; ++attchmnt) + { + const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[attchmnt]; + const auto& RslvAttachmentRef = Subpass.pResolveAttachments[attchmnt]; + if (RslvAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && RTAttachmentRef.AttachmentIndex == ATTACHMENT_UNUSED) + { + // If pResolveAttachments is not NULL, for each resolve attachment that is not VK_ATTACHMENT_UNUSED, + // the corresponding color attachment must not be VK_ATTACHMENT_UNUSED + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-pResolveAttachments-00847 + LOG_RENDER_PASS_ERROR_AND_THROW("pResolveAttachments of subpass ", subpass, " is not null and resolve attachment reference ", attchmnt, + " is not ATTACHMENT_UNUSED, but corresponding render target attachment reference is ATTACHMENT_UNUSED."); + } + + if (RslvAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && Desc.pAttachments[RTAttachmentRef.AttachmentIndex].SampleCount == 1) + { + // If pResolveAttachments is not NULL, for each resolve attachment that is not VK_ATTACHMENT_UNUSED, + // the corresponding color attachment must not have a sample count of VK_SAMPLE_COUNT_1_BIT + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-pResolveAttachments-00848 + LOG_RENDER_PASS_ERROR_AND_THROW("Render target attachment at index ", RTAttachmentRef.AttachmentIndex, " referenced by", + " attachment reference ", attchmnt, " of subpass ", subpass, + " is used as the source of resolve operation, but its sample count is 1."); + } + + if (RslvAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && Desc.pAttachments[RslvAttachmentRef.AttachmentIndex].SampleCount != 1) + { + // If pResolveAttachments is not NULL, each resolve attachment that is not VK_ATTACHMENT_UNUSED must + // have a sample count of VK_SAMPLE_COUNT_1_BIT + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-pResolveAttachments-00849 + LOG_RENDER_PASS_ERROR_AND_THROW("Resolve attachment at index ", RslvAttachmentRef.AttachmentIndex, " referenced by", + " attachment reference ", attchmnt, " of subpass ", subpass, + " must have sample count of 1."); + } + + if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && RslvAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && + Desc.pAttachments[RTAttachmentRef.AttachmentIndex].Format != Desc.pAttachments[RslvAttachmentRef.AttachmentIndex].Format) + { + // If pResolveAttachments is not NULL, each resolve attachment that is not VK_ATTACHMENT_UNUSED + // must have the same VkFormat as its corresponding color attachment. + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-pResolveAttachments-00850 + LOG_RENDER_PASS_ERROR_AND_THROW("The format (", + GetTextureFormatAttribs(Desc.pAttachments[RTAttachmentRef.AttachmentIndex].Format).Name, + ") of render target attachment at index ", RTAttachmentRef.AttachmentIndex, + " referenced by attachment reference ", attchmnt, " of subpass ", subpass, + " does not match the format (", + GetTextureFormatAttribs(Desc.pAttachments[RslvAttachmentRef.AttachmentIndex].Format).Name, + ") of the corresponding resolve attachment at index ", + RslvAttachmentRef.AttachmentIndex, "."); + } + } } } @@ -150,11 +292,11 @@ void ValidateRenderPassDesc(const RenderPassDesc& Desc) if (Dependency.SrcStageMask == PIPELINE_STAGE_FLAG_UNDEFINED) { - LOG_RENDER_PASS_ERROR_AND_THROW("the source stage mask of subpass dependency ", i, " is undefined"); + LOG_RENDER_PASS_ERROR_AND_THROW("the source stage mask of subpass dependency ", i, " is undefined."); } if (Dependency.DstStageMask == PIPELINE_STAGE_FLAG_UNDEFINED) { - LOG_RENDER_PASS_ERROR_AND_THROW("the destination stage mask of subpass dependency ", i, " is undefined"); + LOG_RENDER_PASS_ERROR_AND_THROW("the destination stage mask of subpass dependency ", i, " is undefined."); } } } |
