diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index c2504b555..58b457327 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -48,6 +48,7 @@ #include "Magnum/Vk/ImageViewCreateInfo.h" #include "Magnum/Vk/LayerProperties.h" #include "Magnum/Vk/MemoryAllocateInfo.h" +#include "Magnum/Vk/Pipeline.h" #include "Magnum/Vk/PixelFormat.h" #include "Magnum/Vk/Queue.h" #include "Magnum/Vk/RenderPassCreateInfo.h" @@ -634,7 +635,7 @@ Vk::RenderPass renderPass{device, Vk::RenderPassCreateInfo{} Vk::AttachmentLoadOperation::Clear, Vk::AttachmentStoreOperation::Store, Vk::ImageLayout::Undefined, - Vk::ImageLayout::ColorAttachment}, + Vk::ImageLayout::TransferSource}, Vk::AttachmentDescription{Vk::PixelFormat::Depth24UnormStencil8UI, Vk::AttachmentLoadOperation::Clear, Vk::AttachmentStoreOperation::DontCare, @@ -649,8 +650,20 @@ Vk::RenderPass renderPass{device, Vk::RenderPassCreateInfo{} Vk::AttachmentReference{1, Vk::ImageLayout::DepthStencilAttachment} ) ) -}; /* [RenderPass-creation] */ +/* [RenderPass-dependencies] */ + .setDependencies({ + Vk::SubpassDependency{ + 0, + Vk::PipelineStage::ColorAttachmentOutput, + Vk::Access::ColorAttachmentWrite, + + Vk::SubpassDependency::External, + Vk::PipelineStage::Transfer, + Vk::Access::TransferRead} + }) +}; +/* [RenderPass-dependencies] */ } { diff --git a/doc/vk-renderpass-layouts.dot b/doc/vk-renderpass-layouts.dot new file mode 100644 index 000000000..c8d8f4b26 --- /dev/null +++ b/doc/vk-renderpass-layouts.dot @@ -0,0 +1,52 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +digraph "RenderPass layout transition" { + node [shape=circle margin="0.03,0.03" width=1.5] + rankdir=LR + + colorUndefined [label="Undefined"] + depthUndefined [label="Undefined"] + + // For some reason the cluster_ prefix is important + subgraph cluster_renderpass { + label="Render pass" + + subgraph cluster_subpass { + label="Subpass" + class="m-primary" + + colorAttachment [label="Color\nAttachment" class="m-success"] + depthAttachment [label="Depth\nAttachment" class="m-warning"] + } + } + + transferSource [label="Transfer\nSource" class="m-info"] + + colorUndefined -> colorAttachment [class="m-success" label="Clear"] + depthUndefined -> depthAttachment [class="m-warning" label="Clear"] + + colorAttachment -> transferSource [class="m-info" label="Store"] +} diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 0073a1503..cdb8c9710 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -86,6 +86,7 @@ set(MagnumVk_HEADERS LayerProperties.h Memory.h MemoryAllocateInfo.h + Pipeline.h PixelFormat.h Queue.h RenderPass.h diff --git a/src/Magnum/Vk/Pipeline.h b/src/Magnum/Vk/Pipeline.h new file mode 100644 index 000000000..3f31c6ef4 --- /dev/null +++ b/src/Magnum/Vk/Pipeline.h @@ -0,0 +1,399 @@ +#ifndef Magnum_Vk_Pipeline_h +#define Magnum_Vk_Pipeline_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Enum @ref Magnum::Vk::PipelineStage, @ref Magnum::Vk::Access, @ref Magnum::Vk::DependencyFlag, enum set @ref Magnum::Vk::PipelineStages, @ref Magnum::Vk::Accesses, @ref Magnum::Vk::DependencyFlags + * @m_since_latest + */ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { + +/** +@brief Pipeline stage +@m_since_latest + +Wraps @type_vk_keyword{PipelineStageFlagBits}. +@see @ref PipelineStages, @ref SubpassDependency +@m_enum_values_as_keywords +*/ +enum class PipelineStage: UnsignedInt { + /** + * Top of pipe. Equivalent to @ref PipelineStage::AllCommands with + * empty @ref Accesses when specified in the second synchronization scope, + * but specifies no stages in the first scope. + */ + TopOfPipe = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + + /** Where indirect draw/dispatch/raytrace data structures are consumed */ + DrawIndirect = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, + + /** Where vertex and index buffers are consumed */ + VertexInput = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + + /** Execution of a vertex shader */ + VertexShader = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + + /** + * Execution of a tessellation control shader. + * + * @requires_vk_feature @ref DeviceFeature::TessellationShader + */ + TessellationControlShader = VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, + + /** + * Execution of a tessellation evaluation shader. + * + * @requires_vk_feature @ref DeviceFeature::TessellationShader + */ + TessellationEvaluationShader = VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, + + /** + * Execution of a geometry shader + * + * @requires_vk_feature @ref DeviceFeature::GeometryShader + */ + GeometryShader = VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, + + /** Execution of a fragment shader */ + FragmentShader = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + + /** + * Where early fragment tests (depth and stencil tests before fragment + * shader execution) are performed. Includes also subpass load operations + * for framebuffer attachments with a depth/stencil format. + */ + EarlyFragmentTests = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + + /** + * Where late fragment tests (depth and stencil tests after fragment shader + * execution) are performed. Includes also subpass store operations for + * framebuffer attachments with a depth/stencil format. + */ + LateFragmentTests = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + + /** + * Where the final color values are output from the pipeline. Includes also + * subpass load and store operations and multisample resolve operations for + * framebuffer attachments with a color or depth/stencil format. + */ + ColorAttachmentOutput = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + + /** Execution of a compute shader */ + ComputeShader = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + + /** Copy, blit, resolve and clear commands */ + Transfer = VK_PIPELINE_STAGE_TRANSFER_BIT, + + /** + * Equivalent to @ref PipelineStage::AllCommands with empty @ref Accesses + * when specified in the first synchronization scope, but specifies no + * stages in the second scope. + */ + BottomOfPipe = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + + /** Execution of host read/writes of device memory */ + Host = VK_PIPELINE_STAGE_HOST_BIT, + + /** Execution of commands related to an acceleration structure */ + AccelerationStructureBuild = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + + /** Execution of ray tracing shaders */ + RayTracingShader = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + + /** + * Execution of all graphics stages. While numerically a single bit, it's + * equivalent to the logical OR of a supported and enabled subset of the + * following: + * + * - @ref PipelineStage::DrawIndirect + * - @ref PipelineStage::VertexInput + * - @ref PipelineStage::VertexShader + * - @ref PipelineStage::TessellationControlShader + * - @ref PipelineStage::TessellationEvaluationShader + * - @ref PipelineStage::GeometryShader + * - @ref PipelineStage::FragmentShader + * - @ref PipelineStage::EarlyFragmentTests + * - @ref PipelineStage::LateFragmentTests + * - @ref PipelineStage::ColorAttachmentOutput + * + * Note that this *does not* include @ref PipelineStage::RayTracingShader + * or @ref PipelineStage::AccelerationStructureBuild. + */ + AllGraphics = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + + /** All commands */ + AllCommands = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT +}; + +/** +@brief Pipeline stages +@m_since_latest + +Type-safe wrapper for @type_vk_keyword{PipelineStageFlags}. +@see @ref SubpassDependency +*/ +typedef Containers::EnumSet PipelineStages; + +CORRADE_ENUMSET_OPERATORS(PipelineStages) + +/** +@brief Memory access type participating in a memory dependency +@m_since_latest + +Wraps @type_vk_keyword{AccessFlagBits}. Certain access types are performed only +on a subset of pipeline stages and thus can be used only if a corresponding +@ref PipelineStage is present --- see documentation of each value for more +information. +@see @ref Accesses, @ref SubpassDependency +@m_enum_values_as_keywords +*/ +enum class Access: UnsignedInt { + /** + * Indirect command data read as part of an indirect build, trace, drawing + * or dispatch command. + * + * Valid for @ref PipelineStage::DrawIndirect and + * @ref PipelineStage::AccelerationStructureBuild "AccelerationStructureBuild". + */ + IndirectCommandRead = VK_ACCESS_INDIRECT_COMMAND_READ_BIT, + + /** + * Index buffer read as part of an indexed drawing command. + * + * Valid for @ref PipelineStage::VertexInput. + */ + IndexRead = VK_ACCESS_INDEX_READ_BIT, + + /** + * Vertex buffer read as part of a drawing command. + * + * Valid for @ref PipelineStage::VertexInput. + */ + VertexAttributeRead = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + + /** + * Uniform buffer read. + * + * Valid for @ref PipelineStage::VertexShader, + * @ref PipelineStage::FragmentShader "FragmentShader", + * @ref PipelineStage::GeometryShader "GeometryShader", + * @ref PipelineStage::TessellationControlShader "TessellationControlShader", + * @ref PipelineStage::TessellationEvaluationShader "TessellationEvaluationShader", + * @ref PipelineStage::ComputeShader "ComputeShader" and + * @ref PipelineStage::RayTracingShader "RayTracingShader". + */ + UniformRead = VK_ACCESS_UNIFORM_READ_BIT, + + /** + * Input atachment read within a render pass during fragment shader + * execution. + * + * Valid for @ref PipelineStage::FragmentShader. + */ + InputAttachmentRead = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + + /** + * Storage buffer, physical storage buffer, shader binding table, uniform + * texel buffer, storage texel buffer, sampled image, or storage image + * read. + * + * Valid for @ref PipelineStage::AccelerationStructureBuild, + * @ref PipelineStage::VertexShader "VertexShader", + * @ref PipelineStage::FragmentShader "FragmentShader", + * @ref PipelineStage::GeometryShader "GeometryShader", + * @ref PipelineStage::TessellationControlShader "TessellationControlShader", + * @ref PipelineStage::TessellationEvaluationShader "TessellationEvaluationShader", + * @ref PipelineStage::ComputeShader "ComputeShader" and + * @ref PipelineStage::RayTracingShader "RayTracingShader". + */ + ShaderRead = VK_ACCESS_SHADER_READ_BIT, + + /** + * Storage buffer, physical storage buffer, storage texel buffer, or + * storage image write. + * + * Valid for @ref PipelineStage::VertexShader, + * @ref PipelineStage::FragmentShader "FragmentShader", + * @ref PipelineStage::GeometryShader "GeometryShader", + * @ref PipelineStage::TessellationControlShader "TessellationControlShader", + * @ref PipelineStage::TessellationEvaluationShader "TessellationEvaluationShader", + * @ref PipelineStage::ComputeShader "ComputeShader" and + * @ref PipelineStage::RayTracingShader "RayTracingShader". + */ + ShaderWrite = VK_ACCESS_SHADER_WRITE_BIT, + + /** + * Color attachment read via blending, logic operations or certain subpass + * load operations. Doesn't include advanced blend operations. + * + * Valid for @ref PipelineStage::ColorAttachmentOutput. + */ + ColorAttachmentRead = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + + /** + * Color, resolve or depth/stencil resolve attachment write during a render + * pass or via certain subpass load and store operations. + * + * Valid for @ref PipelineStage::ColorAttachmentOutput. + */ + ColorAttachmentWrite = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + + /** + * Depth/stencil attachment read via depth or stencil operations or certain + * subpass load operations. + * + * Valid for @ref PipelineStage::EarlyFragmentTests and + * @ref PipelineStage::LateFragmentTests "LateFragmentTests". + */ + DepthStencilAttachmentRead = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + + /** + * Depth/stencil attachment write via depth or stencil operations or + * certain subpass load and store operations. + * + * Valid for @ref PipelineStage::EarlyFragmentTests and + * @ref PipelineStage::LateFragmentTests "LateFragmentTests". + */ + DepthStencilAttachmentWrite = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + + /** + * Buffer or image read in a copy operation. + * + * Valid for @ref PipelineStage::Transfer and + * @ref PipelineStage::AccelerationStructureBuild "AccelerationStructureBuild". + */ + TransferRead = VK_ACCESS_TRANSFER_READ_BIT, + + /** + * Buffer or image write in a copy or clear operation. + * + * Valid for @ref PipelineStage::Transfer and + * @ref PipelineStage::AccelerationStructureBuild "AccelerationStructureBuild". + */ + TransferWrite = VK_ACCESS_TRANSFER_WRITE_BIT, + + /** + * Direct memory read from a host. + * + * Valid for @ref PipelineStage::Host. + */ + HostRead = VK_ACCESS_HOST_READ_BIT, + + /** + * Direct memory write from a host. + * + * Valid for @ref PipelineStage::Host. + */ + HostWrite = VK_ACCESS_HOST_WRITE_BIT, + + /** + * All read accesses. Valid for any @ref PipelineStage, treated as + * equivalent of a combination of all `*Read` flags valid in given context. + */ + MemoryRead = VK_ACCESS_MEMORY_READ_BIT, + + /** + * All write accesses. Valid for any @ref PipelineStage, treated as + * equivalent of a combination of all `*Write` flags valid in given + * context. + */ + MemoryWrite = VK_ACCESS_MEMORY_WRITE_BIT, + + /** + * Acceleration structure read as part of a trace, build, or copy command, + * or an acceleration structure scratch buffer read as part of a build + * command. + * + * Valid for @ref PipelineStage::AccelerationStructureBuild, + * @ref PipelineStage::VertexShader "VertexShader", + * @ref PipelineStage::FragmentShader "FragmentShader", + * @ref PipelineStage::GeometryShader "GeometryShader", + * @ref PipelineStage::TessellationControlShader "TessellationControlShader", + * @ref PipelineStage::TessellationEvaluationShader "TessellationEvaluationShader", + * @ref PipelineStage::ComputeShader "ComputeShader" and + * @ref PipelineStage::RayTracingShader "RayTracingShader". + */ + AccelerationStructureRead = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, + + /** + * Acceleration structure or acceleration structure scratch buffer write as + * part of a build or copy command. + * + * Valid for @ref PipelineStage::AccelerationStructureBuild. + */ + AccelerationStructureWrite = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR +}; + +/** +@brief Memory access type participating in a memory dependency +@m_since_latest + +Type-safe wrapper for @type_vk_keyword{AccessFlags}. +@see @ref SubpassDependency +*/ +typedef Containers::EnumSet Accesses; + +CORRADE_ENUMSET_OPERATORS(Accesses) + +/** +@brief Execution and memory dependency flag +@m_since_latest + +Wraps @type_vk_keyword{DependencyFlagBits}. +@see @ref DependencyFlags, @ref SubpassDependency +@m_enum_values_as_keywords +*/ +enum class DependencyFlag: UnsignedInt { + /** + * Dependencies will be framebuffer-local. This flag has to be set in + * case @ref SubpassDependency source and destination stage index is equal. + */ + ByRegion = VK_DEPENDENCY_BY_REGION_BIT, + + /** @todo DeviceGroup, ViewLocal */ +}; + +/** +@brief Execution and memory dependency flags +@m_since_latest + +Type-safe wrapper for @type_vk_keyword{DependencyFlags}. +@see @ref SubpassDependency +*/ +typedef Containers::EnumSet DependencyFlags; + +CORRADE_ENUMSET_OPERATORS(DependencyFlags) + +}} + +#endif diff --git a/src/Magnum/Vk/RenderPass.cpp b/src/Magnum/Vk/RenderPass.cpp index b9b0fe0cd..e16661adb 100644 --- a/src/Magnum/Vk/RenderPass.cpp +++ b/src/Magnum/Vk/RenderPass.cpp @@ -450,6 +450,17 @@ Containers::Array SubpassDescription::vkSubpassDescription }; } +SubpassDependency::SubpassDependency(const UnsignedInt sourceSubpass, const PipelineStages sourceStages, const Accesses sourceAccesses, const UnsignedInt destinationSubpass, const PipelineStages destinationStages, const Accesses destinationAccesses, const DependencyFlags flags): _dependency{} { + _dependency.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2; + _dependency.srcSubpass = sourceSubpass; + _dependency.dstSubpass = destinationSubpass; + _dependency.srcStageMask = VkPipelineStageFlags(sourceStages); + _dependency.dstStageMask = VkPipelineStageFlags(destinationStages); + _dependency.srcAccessMask = VkAccessFlags(sourceAccesses); + _dependency.dstAccessMask = VkAccessFlags(destinationAccesses); + _dependency.dependencyFlags = VkDependencyFlags(flags); +} + SubpassDependency::SubpassDependency(NoInitT) noexcept {} SubpassDependency::SubpassDependency(const VkSubpassDependency2& dependency): diff --git a/src/Magnum/Vk/RenderPass.h b/src/Magnum/Vk/RenderPass.h index c0763eb56..73c2d1163 100644 --- a/src/Magnum/Vk/RenderPass.h +++ b/src/Magnum/Vk/RenderPass.h @@ -77,6 +77,12 @@ specify what implicit layout transitions (if any) need to happen between start of the render pass and the first subpass, between subpasses and between last subpass and end of the render pass. +The following snippet shows attachment and subpass setup for a single-pass +color/depth render. Commonly the image is used in some way after the render +pass, in this case it'll get transferred to the host, as indicated by +@ref ImageLayout::TransferSource. That will also need an explicit subpass +dependency, as explained below. + @snippet MagnumVk.cpp RenderPass-creation @@ -92,6 +98,29 @@ subpass and end of the render pass. @ref ImageLayout::DepthStencilAttachment "DepthStencilAttachment" or just any other. With @ref ImageLayout::Undefined we don't need to explicitly handle that case. + +@subsection Vk-RenderPass-creation-subpass-dependencies Subpass dependencies + +As shown above, the application is required to specify @ref ImageLayout at the +start and end of the render pass as well as layouts in which the attachments +are expected to be inside a particular subpass, and Vulkan then takes care of +doing layout transitions at a proper time. If a transition from one layout to +another needs to occur, a @ref SubpassDependency defines when, and if none is +explicitly specified, an implicit dependency is added by Vulkan. The above +setup can be visualized as this, with implicit transitions shown as arrows: + +@dotfile vk-renderpass-layouts.dot + +The implicit dependencies added by Vulkan only ensure that the transition from +@ref ImageLayout::Undefined to @ref ImageLayout::ColorAttachment "ColorAttachment" +/ @ref ImageLayout::DepthStencilAttachment "DepthStencilAttachment" happen *at +some point* before the start of the renderpass, and the transition to +@ref ImageLayout::TransferSource "TransferSource" is *eventually* done as well. +In this case the initial transition is fine; for the transfer we however need +it to happen before the actual transfer command, and thus an explicit +dependency is needed: + +@snippet MagnumVk.cpp RenderPass-dependencies */ class MAGNUM_VK_EXPORT RenderPass { public: diff --git a/src/Magnum/Vk/RenderPassCreateInfo.h b/src/Magnum/Vk/RenderPassCreateInfo.h index a1f06a18b..81fccc900 100644 --- a/src/Magnum/Vk/RenderPassCreateInfo.h +++ b/src/Magnum/Vk/RenderPassCreateInfo.h @@ -716,6 +716,48 @@ fields that were left out. */ class MAGNUM_VK_EXPORT SubpassDependency { public: + enum: UnsignedInt { + /** Subpass index identifying an external dependency */ + External = VK_SUBPASS_EXTERNAL, + }; + + /** + * @brief Constructor + * @param sourceSubpass Source subpass index or @ref External + * @param sourceStages Source stages. Has to contain at least + * one stage. + * @param sourceAccesses Source memory access types + * participating in a dependency. Each has to be supported by at + * least one stage in @p sourceStages. + * @param destinationSubpass Destination subpass index or + * @ref External + * @param destinationStages Destination stages. Has to contain at + * least one stage. + * @param destinationAccesses Destination memory access types + * participating in a dependency. Each has to be supported by at + * least one stage in @p destinationStages. + * @param flags Flags + * + * The @p sourceSubpass has to be less than or equal to + * @p destinationSubpass to avoid cyclic dependencies and ensure a + * valid execution order. One of them (but not both) can be also + * @ref External to specify an external dependency. + * + * The following @type_vk{SubpassDependency2} fields are pre-filled in + * addition to `sType`, everything else is zero-filled. Note that the + * parameter order is shuffled here to group source and destination + * parameters together instead of grouping by data type: + * + * - `srcSubpass` to @p sourceSubpass + * - `dstSubpass` to @p destinationSubpass + * - `srcStageMask` to @p sourceStages + * - `dstStageMask` to @p destinationStages + * - `srcAccessMask` to @p sourceAccesses + * - `dstAccessMask` to @p destinationAccesses + * - `dependencyFlags` to @p flags + */ + explicit SubpassDependency(UnsignedInt sourceSubpass, PipelineStages sourceStages, Accesses sourceAccesses, UnsignedInt destinationSubpass, PipelineStages destinationStages, Accesses destinationAccesses, DependencyFlags flags = {}); + /** * @brief Construct without initializing the contents * diff --git a/src/Magnum/Vk/Test/RenderPassTest.cpp b/src/Magnum/Vk/Test/RenderPassTest.cpp index 887de1480..6c2326af0 100644 --- a/src/Magnum/Vk/Test/RenderPassTest.cpp +++ b/src/Magnum/Vk/Test/RenderPassTest.cpp @@ -36,6 +36,7 @@ #include "Magnum/Vk/Framebuffer.h" #include "Magnum/Vk/Image.h" #include "Magnum/Vk/Integration.h" +#include "Magnum/Vk/Pipeline.h" #include "Magnum/Vk/RenderPassCreateInfo.h" #include "Magnum/Vk/Test/pixelFormatTraits.h" @@ -80,6 +81,7 @@ struct RenderPassTest: TestSuite::Tester { template void subpassDescriptionConvertToVkNoResolveAttachments(); void subpassDescriptionRvalue(); + void subpassDependencyConstruct(); void subpassDependencyConstructNoInit(); template void subpassDependencyConstructFromVk(); template void subpassDependencyConvertToVk(); @@ -163,6 +165,7 @@ RenderPassTest::RenderPassTest() { &RenderPassTest::subpassDescriptionConvertToVkNoResolveAttachments, &RenderPassTest::subpassDescriptionRvalue, + &RenderPassTest::subpassDependencyConstruct, &RenderPassTest::subpassDependencyConstructNoInit, &RenderPassTest::subpassDependencyConstructFromVk, &RenderPassTest::subpassDependencyConstructFromVk, @@ -719,6 +722,26 @@ void RenderPassTest::subpassDescriptionRvalue() { CORRADE_VERIFY(&description); } +void RenderPassTest::subpassDependencyConstruct() { + SubpassDependency dependency{ + 15, + PipelineStage::ComputeShader|PipelineStage::Transfer, + Access::TransferRead|Access::UniformRead, + + SubpassDependency::External, + PipelineStage::AllGraphics, + Access::MemoryWrite, + + DependencyFlag::ByRegion}; + CORRADE_COMPARE(dependency->srcSubpass, 15); + CORRADE_COMPARE(dependency->dstSubpass, VK_SUBPASS_EXTERNAL); + CORRADE_COMPARE(dependency->srcStageMask, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT|VK_PIPELINE_STAGE_TRANSFER_BIT); + CORRADE_COMPARE(dependency->dstStageMask, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT); + CORRADE_COMPARE(dependency->srcAccessMask, VK_ACCESS_TRANSFER_READ_BIT|VK_ACCESS_UNIFORM_READ_BIT); + CORRADE_COMPARE(dependency->dstAccessMask, VK_ACCESS_MEMORY_WRITE_BIT); + CORRADE_COMPARE(dependency->dependencyFlags, VK_DEPENDENCY_BY_REGION_BIT); +} + void RenderPassTest::subpassDependencyConstructNoInit() { SubpassDependency dependency{NoInit}; dependency->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; @@ -757,7 +780,24 @@ template void RenderPassTest::subpassDependencyConstructFr template void RenderPassTest::subpassDependencyConvertToVk() { setTestCaseTemplateName(Traits::name()); - CORRADE_SKIP("No SubpassDependency APIs to test."); + SubpassDependency dependency{ + 15, + PipelineStage::ComputeShader|PipelineStage::Transfer, + Access::TransferRead|Access::UniformRead, + + SubpassDependency::External, + PipelineStage::AllGraphics, + Access::MemoryWrite, + + DependencyFlag::ByRegion}; + T out = Traits::convert(dependency); + CORRADE_COMPARE(out.srcSubpass, 15); + CORRADE_COMPARE(out.dstSubpass, VK_SUBPASS_EXTERNAL); + CORRADE_COMPARE(out.srcStageMask, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT|VK_PIPELINE_STAGE_TRANSFER_BIT); + CORRADE_COMPARE(out.dstStageMask, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT); + CORRADE_COMPARE(out.srcAccessMask, VK_ACCESS_TRANSFER_READ_BIT|VK_ACCESS_UNIFORM_READ_BIT); + CORRADE_COMPARE(out.dstAccessMask, VK_ACCESS_MEMORY_WRITE_BIT); + CORRADE_COMPARE(out.dependencyFlags, VK_DEPENDENCY_BY_REGION_BIT); } void RenderPassTest::createInfoConstruct() { diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 2703a2404..ebe4900c1 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -36,12 +36,16 @@ namespace Magnum { namespace Vk { #ifndef DOXYGEN_GENERATING_OUTPUT +enum class Access: UnsignedInt; +typedef Containers::EnumSet Accesses; class Buffer; class BufferCreateInfo; class CommandBuffer; /* CommandBufferBeginInfo is useful only in combination with CommandBuffer */ class CommandPool; class CommandPoolCreateInfo; +enum class DependencyFlag: UnsignedInt; +typedef Containers::EnumSet DependencyFlags; class Device; class DeviceCreateInfo; enum class DeviceFeature: UnsignedShort; @@ -76,6 +80,8 @@ enum class MemoryFlag: UnsignedInt; typedef Containers::EnumSet MemoryFlags; enum class MemoryHeapFlag: UnsignedInt; typedef Containers::EnumSet MemoryHeapFlags; +enum class PipelineStage: UnsignedInt; +typedef Containers::EnumSet PipelineStages; enum class PixelFormat: Int; class Queue; enum class QueueFlag: UnsignedInt;