From 14389c99d503f82578a01ea6e147986c5ed1c73a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 7 Feb 2021 22:32:26 +0100 Subject: [PATCH] Vk: save current dynamic state on a pipeline bind. Will be used for the draw() command. --- src/Magnum/Vk/CommandBuffer.cpp | 6 +++ src/Magnum/Vk/CommandBuffer.h | 19 +++++++- src/Magnum/Vk/Pipeline.cpp | 4 ++ src/Magnum/Vk/Test/PipelineVkTest.cpp | 65 +++++++++++++++++++++++++-- 4 files changed, 89 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Vk/CommandBuffer.cpp b/src/Magnum/Vk/CommandBuffer.cpp index 6e78948c2..65a4529e5 100644 --- a/src/Magnum/Vk/CommandBuffer.cpp +++ b/src/Magnum/Vk/CommandBuffer.cpp @@ -84,6 +84,12 @@ CommandBuffer& CommandBuffer::begin(const CommandBufferBeginInfo& info) { } void CommandBuffer::end() { + /* Clear everything that is valid only for the duration of this command + buffer recording -- so when the user calls reset() and begin() again, + the old values are not preserved */ + /** @todo do this on begin() too? */ + _dynamicRasterizationStates = {}; + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS((**_device).EndCommandBuffer(_handle)); } diff --git a/src/Magnum/Vk/CommandBuffer.h b/src/Magnum/Vk/CommandBuffer.h index cd8440668..fcaa5a4f9 100644 --- a/src/Magnum/Vk/CommandBuffer.h +++ b/src/Magnum/Vk/CommandBuffer.h @@ -31,6 +31,7 @@ */ #include +#include #include #include "Magnum/Tags.h" @@ -259,6 +260,17 @@ class MAGNUM_VK_EXPORT CommandBuffer { /** @brief Handle flags */ HandleFlags handleFlags() const { return _flags; } + /** + * @brief Dynamic states used by currently bound rasterization pipeline + * + * If no rasterization pipeline is bound or there are no dynamic states + * on the currently bound one, returns an empty set. + * @see @ref bindPipeline() + */ + DynamicRasterizationStates dynamicRasterizationStates() const { + return _dynamicRasterizationStates; + } + /** * @brief Reset the command buffer * @@ -361,8 +373,10 @@ class MAGNUM_VK_EXPORT CommandBuffer { * @brief Bind a pipeline * @return Reference to self (for method chaining) * - * Can be called both inside and outside a render pass. See - * @ref Vk-Pipeline-usage for a usage example. + * Can be called both inside and outside a render pass. If the pipeline + * is a rasterization pipeline, the set of its dynamic states is stored + * in @ref dynamicRasterizationStates() for use by drawing and other + * commands. See @ref Vk-Pipeline-usage for a usage example. * @see @fn_vk_keyword{CmdBindPipeline} */ CommandBuffer& bindPipeline(Pipeline& pipeline); @@ -765,6 +779,7 @@ class MAGNUM_VK_EXPORT CommandBuffer { VkCommandPool _pool; /* Used only for vkFreeCommandBuffers() */ VkCommandBuffer _handle; HandleFlags _flags; + DynamicRasterizationStates _dynamicRasterizationStates; }; }} diff --git a/src/Magnum/Vk/Pipeline.cpp b/src/Magnum/Vk/Pipeline.cpp index e4e926ee7..217d9fec0 100644 --- a/src/Magnum/Vk/Pipeline.cpp +++ b/src/Magnum/Vk/Pipeline.cpp @@ -412,6 +412,10 @@ ImageMemoryBarrier::ImageMemoryBarrier(const VkImageMemoryBarrier& barrier): _barrier(barrier) {} CommandBuffer& CommandBuffer::bindPipeline(Pipeline& pipeline) { + /* Save the set of dynamic states for future use */ + if(pipeline.bindPoint() == PipelineBindPoint::Rasterization) + _dynamicRasterizationStates = pipeline.dynamicRasterizationStates(); + (**_device).CmdBindPipeline(_handle, VkPipelineBindPoint(pipeline.bindPoint()), pipeline); return *this; } diff --git a/src/Magnum/Vk/Test/PipelineVkTest.cpp b/src/Magnum/Vk/Test/PipelineVkTest.cpp index c2bccb7b3..789286055 100644 --- a/src/Magnum/Vk/Test/PipelineVkTest.cpp +++ b/src/Magnum/Vk/Test/PipelineVkTest.cpp @@ -67,7 +67,8 @@ struct PipelineVkTest: VulkanTester { void dynamicRasterizationStatesNotRasterization(); - void cmdBind(); + void cmdBindRasterization(); + void cmdBindCompute(); void cmdBarrier(); void cmdBarrierExecutionOnly(); @@ -89,7 +90,8 @@ PipelineVkTest::PipelineVkTest() { &PipelineVkTest::dynamicRasterizationStatesNotRasterization, - &PipelineVkTest::cmdBind, + &PipelineVkTest::cmdBindRasterization, + &PipelineVkTest::cmdBindCompute, &PipelineVkTest::cmdBarrier, &PipelineVkTest::cmdBarrierExecutionOnly, @@ -447,7 +449,64 @@ void PipelineVkTest::dynamicRasterizationStatesNotRasterization() { CORRADE_COMPARE(out.str(), "Vk::Pipeline::dynamicRasterizationStates(): not a rasterization pipeline\n"); } -void PipelineVkTest::cmdBind() { +void PipelineVkTest::cmdBindRasterization() { + CommandPool pool{device(), CommandPoolCreateInfo{ + /* This might blow up if queue() isn't the one matching this family */ + device().properties().pickQueueFamily(QueueFlag::Graphics|QueueFlag::Compute)}}; + + RenderPass renderPass{device(), RenderPassCreateInfo{} + .setAttachments({ + AttachmentDescription{PixelFormat::RGBA8Unorm, + AttachmentLoadOperation::Clear, + AttachmentStoreOperation::Store, + ImageLayout::Undefined, + ImageLayout::ColorAttachment} + }) + .addSubpass(SubpassDescription{}.setColorAttachments({ + AttachmentReference{0, ImageLayout::ColorAttachment} + })) + }; + + /* Not sure if this is really needed, but the shader needs those inputs so + playing it safe */ + MeshLayout meshLayout{MeshPrimitive::Triangles}; + meshLayout + .addBinding(0, 2*4*4) + .addAttribute(0, 0, Vk::VertexFormat::Vector4, 0) + .addAttribute(1, 0, Vk::VertexFormat::Vector4, 4*4); + + PipelineLayout pipelineLayout{device(), PipelineLayoutCreateInfo{}}; + + Shader shader{device(), ShaderCreateInfo{ + Utility::Directory::read(Utility::Directory::join(VK_TEST_DIR, "triangle-shaders.spv")) + }}; + + ShaderSet shaderSet; + shaderSet + .addShader(ShaderStage::Vertex, shader, "ver"_s) + .addShader(ShaderStage::Fragment, shader, "fra"_s); + + Pipeline pipeline{device(), RasterizationPipelineCreateInfo{ + shaderSet, meshLayout, pipelineLayout, renderPass, 0, 1} + .setViewport({{}, {200, 200}}) + .setDynamicStates(DynamicRasterizationState::LineWidth|DynamicRasterizationState::DepthBias) + }; + + CommandBuffer cmd = pool.allocate(); + + cmd.begin(); + CORRADE_COMPARE(cmd.dynamicRasterizationStates(), DynamicRasterizationStates{}); + + cmd.bindPipeline(pipeline); + CORRADE_COMPARE(cmd.dynamicRasterizationStates(), DynamicRasterizationState::LineWidth|DynamicRasterizationState::DepthBias); + + /* Should be reset again on end() so if it's reset() and begun again it + doesn't show a no-longer-true value */ + cmd.end(); + CORRADE_COMPARE(cmd.dynamicRasterizationStates(), DynamicRasterizationStates{}); +} + +void PipelineVkTest::cmdBindCompute() { CommandPool pool{device(), CommandPoolCreateInfo{ /* This might blow up if queue() isn't the one matching this family */ device().properties().pickQueueFamily(QueueFlag::Graphics|QueueFlag::Compute)}};