diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index 666fdcbc9..eed64d40b 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -37,6 +37,7 @@ #include "Magnum/Vk/BufferCreateInfo.h" #include "Magnum/Vk/CommandBuffer.h" #include "Magnum/Vk/CommandPoolCreateInfo.h" +#include "Magnum/Vk/ComputePipelineCreateInfo.h" #include "Magnum/Vk/DeviceCreateInfo.h" #include "Magnum/Vk/DeviceFeatures.h" #include "Magnum/Vk/DeviceProperties.h" @@ -812,6 +813,23 @@ Vk::Pipeline pipeline{device, Vk::RasterizationPipelineCreateInfo{ /* [Pipeline-creation-rasterization] */ } +{ +Vk::Device device{NoCreate}; +/* The include should be a no-op here since it was already included above */ +/* [Pipeline-creation-compute] */ +#include + +DOXYGEN_IGNORE() + +Vk::ShaderSet shaderSet{DOXYGEN_IGNORE()}; +Vk::PipelineLayout pipelineLayout{DOXYGEN_IGNORE(NoCreate)}; + +Vk::Pipeline pipeline{device, Vk::ComputePipelineCreateInfo{ + shaderSet, pipelineLayout +}}; +/* [Pipeline-creation-compute] */ +} + { Vk::Device device{NoCreate}; /* The include should be a no-op here since it was already included above */ diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index 46b186491..eff43902e 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -434,7 +434,7 @@ Vulkan structure | Matching API @type_vk{CommandBufferInheritanceInfo} | | @type_vk{CommandPoolCreateInfo} | @ref CommandPoolCreateInfo @type_vk{ComponentMapping} | | -@type_vk{ComputePipelineCreateInfo} | | +@type_vk{ComputePipelineCreateInfo} | @ref ComputePipelineCreateInfo @type_vk{ConformanceVersion} | | @type_vk{CopyBufferInfo2KHR} @m_class{m-label m-flat m-warning} **KHR** | @ref CopyBufferInfo @type_vk{CopyBufferToImageInfo2KHR} @m_class{m-label m-flat m-warning} **KHR** | @ref CopyBufferToImageInfo @@ -919,7 +919,7 @@ Vulkan enum | Matching API @type_vk{PipelineCacheCreateFlagBits}, \n @type_vk{PipelineCacheCreateFlags} | | @type_vk{PipelineCacheHeaderVersion} | | @type_vk{PipelineCacheCreateFlagBits}, \n @type_vk{PipelineCacheCreateFlags} | | -@type_vk{PipelineCreateFlagBits}, \n @type_vk{PipelineCreateFlags} | @ref RasterizationPipelineCreateInfo::Flag, \n @ref RasterizationPipelineCreateInfo::Flags +@type_vk{PipelineCreateFlagBits}, \n @type_vk{PipelineCreateFlags} | @ref RasterizationPipelineCreateInfo::Flag, \n @ref RasterizationPipelineCreateInfo::Flags, \n @ref ComputePipelineCreateInfo::Flag, \n @ref ComputePipelineCreateInfo::Flags @type_vk{PipelineShaderStageCreateFlagBits}, \n @type_vk{PipelineShaderStageCreateFlags} | | @type_vk{PipelineStageFlagBits}, \n @type_vk{PipelineStageFlags} | @ref PipelineStage, \n @ref PipelineStages @type_vk{PointClippingBehavior} @m_class{m-label m-flat m-success} **KHR, 1.1** | | diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index a3e6dbe67..b5f3c79d3 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -70,6 +70,7 @@ set(MagnumVk_HEADERS CommandBuffer.h CommandPool.h CommandPoolCreateInfo.h + ComputePipelineCreateInfo.h Device.h DeviceCreateInfo.h DeviceFeatures.h diff --git a/src/Magnum/Vk/ComputePipelineCreateInfo.h b/src/Magnum/Vk/ComputePipelineCreateInfo.h new file mode 100644 index 000000000..7240b6a58 --- /dev/null +++ b/src/Magnum/Vk/ComputePipelineCreateInfo.h @@ -0,0 +1,154 @@ +#ifndef Magnum_Vk_ComputePipelineCreateInfo_h +#define Magnum_Vk_ComputePipelineCreateInfo_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 Class @ref Magnum::Vk::ComputePipelineCreateInfo + * @m_since_latest + */ + +#include + +#include "Magnum/Tags.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" +#include "Magnum/Vk/visibility.h" + +namespace Magnum { namespace Vk { + +/** +@brief Compute pipeline creation info +@m_since_latest + +Wraps a @type_vk_keyword{ComputePipelineCreateInfo}. See +@ref Vk-Pipeline-creation-compute "Compute pipeline creation" for usage +information. +@see @ref RasterizationPipelineCreateInfo +*/ +class MAGNUM_VK_EXPORT ComputePipelineCreateInfo { + public: + /** + * @brief Compute pipeline creation flag + * + * Wraps the compute-related subset of + * @type_vk_keyword{PipelineCreateFlagBits}. + * @see @ref Flags, @ref ComputePipelineCreateInfo(const ShaderSet&, VkPipelineLayout, Flags) + * @m_enum_values_as_keywords + */ + enum class Flag: UnsignedInt { + /** + * Create the pipeline without optimization. + * + * @m_class{m-note m-success} + * + * @par + * Setting this flag on single-use pipelines might help + * drivers pick a better tradeoff between CPU time spent + * optimizing the pipeline and GPU time spent executing it. + */ + DisableOptimization = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT, + + /** + * Allow derivatives to be subsequently created from this pipeline. + */ + AllowDerivatives = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT, + + /** Derivative of a pipeline created earlier. */ + Derivative = VK_PIPELINE_CREATE_DERIVATIVE_BIT + }; + + /** + * @brief Compite pipeline creation flags + * + * Type-safe wrapper for the compute-related subset of + * @type_vk_keyword{PipelineCreateFlags}. + * @see @ref ComputePipelineCreateInfo(const ShaderSet&, VkPipelineLayout, Flags) + */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param shaderSet Shader to use for this pipeline. Expected + * to have just one entry. + * @param pipelineLayout A @ref PipelineLayout or a raw Vulkan + * pipeline layout handle + * @param flags Compute pipeline creation flags + * + * Note that the @p shaderSet structure internals are referenced, not + * copied, and thus have to stay in scope until the @ref Pipeline + * object is created. + * + * The following @type_vk{ComputePipelineCreateInfo} fields are + * pre-filled in addition to `sType`, everything else is zero-filled: + * + * - `flags` + * - `stage` to @p shaderSet + * - `layout` to @p pipelineLayout + */ + explicit ComputePipelineCreateInfo(const ShaderSet& shaderSet, VkPipelineLayout pipelineLayout, Flags flags = {}); + + /** + * @brief Construct without initializing the contents + * + * Note that not even the `sType` field nor the nested structure + * pointers are set --- the structure has to be fully initialized + * afterwards in order to be usable. + */ + explicit ComputePipelineCreateInfo(NoInitT) noexcept; + + /** + * @brief Construct from existing data + * + * Copies the existing values verbatim, pointers are kept unchanged + * without taking over the ownership. Modifying the newly created + * instance will not modify the original data nor the pointed-to data. + */ + explicit ComputePipelineCreateInfo(const VkComputePipelineCreateInfo& info); + + /** @brief Underlying @type_vk{GraphicsPipelineCreateInfo} structure */ + VkComputePipelineCreateInfo& operator*() { return _info; } + /** @overload */ + const VkComputePipelineCreateInfo& operator*() const { return _info; } + /** @overload */ + VkComputePipelineCreateInfo* operator->() { return &_info; } + /** @overload */ + const VkComputePipelineCreateInfo* operator->() const { return &_info; } + /** @overload */ + operator const VkComputePipelineCreateInfo*() const { return &_info; } + + private: + VkComputePipelineCreateInfo _info; +}; + +CORRADE_ENUMSET_OPERATORS(ComputePipelineCreateInfo::Flags) + +}} + +/* Make the definition complete -- it doesn't make sense to have a CreateInfo + without the corresponding object anyway. */ +#include "Magnum/Vk/Pipeline.h" + +#endif diff --git a/src/Magnum/Vk/Pipeline.cpp b/src/Magnum/Vk/Pipeline.cpp index ad1659971..4183ab314 100644 --- a/src/Magnum/Vk/Pipeline.cpp +++ b/src/Magnum/Vk/Pipeline.cpp @@ -25,6 +25,7 @@ #include "Pipeline.h" #include "RasterizationPipelineCreateInfo.h" +#include "ComputePipelineCreateInfo.h" #include "CommandBuffer.h" #include @@ -259,6 +260,23 @@ RasterizationPipelineCreateInfo& RasterizationPipelineCreateInfo::setDynamicStat return *this; } +ComputePipelineCreateInfo::ComputePipelineCreateInfo(const ShaderSet& shaderSet, const VkPipelineLayout pipelineLayout, const Flags flags): _info{} { + CORRADE_ASSERT(shaderSet.stages().size() == 1, + "Vk::ComputePipelineCreateInfo: the shader set has to contain exactly one shader, got" << shaderSet.stages().size(), ); + + _info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + _info.flags = VkPipelineCreateFlags(flags); + _info.stage = shaderSet.stages()[0]; + _info.layout = pipelineLayout; +} + +ComputePipelineCreateInfo::ComputePipelineCreateInfo(NoInitT) noexcept {} + +ComputePipelineCreateInfo::ComputePipelineCreateInfo(const VkComputePipelineCreateInfo& info): + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _info(info) {} + Pipeline Pipeline::wrap(Device& device, const VkPipeline handle, const HandleFlags flags) { Pipeline out{NoCreate}; out._device = &device; @@ -283,6 +301,10 @@ Pipeline::Pipeline(Device& device, const RasterizationPipelineCreateInfo& info): MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateGraphicsPipelines(device, {}, 1, info, nullptr, &_handle)); } +Pipeline::Pipeline(Device& device, const ComputePipelineCreateInfo& info): _device{&device}, _flags{HandleFlag::DestroyOnDestruction} { + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateComputePipelines(device, {}, 1, info, nullptr, &_handle)); +} + Pipeline::Pipeline(NoCreateT): _device{}, _handle{} {} Pipeline::Pipeline(Pipeline&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags} { diff --git a/src/Magnum/Vk/Pipeline.h b/src/Magnum/Vk/Pipeline.h index 583e713c5..5f3e9911a 100644 --- a/src/Magnum/Vk/Pipeline.h +++ b/src/Magnum/Vk/Pipeline.h @@ -60,6 +60,14 @@ Certain aspects of the pipeline can be set as dynamic using @relativeref{RasterizationPipelineCreateInfo,setDynamicStates()} --- in that case a subset of the values passed to the constructor will be ignored. See the particular @ref DynamicRasterizationState values for more information. + +@section Vk-Pipeline-creation-compute Compute pipeline creation + +Compared to a rasterization pipeline, @ref ComputePipelineCreateInfo only takes +a @ref ShaderSet containing a single @ref ShaderStage::Compute shader and a +@link PipelineLayout @endlink: + +@snippet MagnumVk.cpp Pipeline-creation-compute */ class MAGNUM_VK_EXPORT Pipeline { public: @@ -86,6 +94,15 @@ class MAGNUM_VK_EXPORT Pipeline { */ explicit Pipeline(Device& device, const RasterizationPipelineCreateInfo& info); + /** + * @brief Construct a compute pipeline + * @param device Vulkan device to create the pipeline on + * @param info Compite pipeline creation info + * + * @see @fn_vk_keyword{CreateComputePipelines} + */ + explicit Pipeline(Device& device, const ComputePipelineCreateInfo& info); + /** * @brief Construct without creating the pipeline layout * diff --git a/src/Magnum/Vk/RasterizationPipelineCreateInfo.h b/src/Magnum/Vk/RasterizationPipelineCreateInfo.h index 834408c05..b647f5255 100644 --- a/src/Magnum/Vk/RasterizationPipelineCreateInfo.h +++ b/src/Magnum/Vk/RasterizationPipelineCreateInfo.h @@ -291,6 +291,7 @@ Wraps a @type_vk_keyword{GraphicsPipelineCreateInfo}, along with See @ref Vk-Pipeline-creation-rasterization "Rasterization pipeline creation" for usage information. +@see @ref ComputePipelineCreateInfo */ class MAGNUM_VK_EXPORT RasterizationPipelineCreateInfo { public: diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index eb45cf97d..6655ef8fa 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -43,7 +43,7 @@ corrade_add_test(VkIntegrationTest IntegrationTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkLayerPropertiesTest LayerPropertiesTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkMemoryTest MemoryTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkMeshLayoutTest MeshLayoutTest.cpp LIBRARIES MagnumVkTestLib) -corrade_add_test(VkPipelineTest PipelineTest.cpp LIBRARIES MagnumVk) +corrade_add_test(VkPipelineTest PipelineTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkPipelineLayoutTest PipelineLayoutTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkPixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkQueueTest QueueTest.cpp LIBRARIES MagnumVk) @@ -178,7 +178,7 @@ if(BUILD_VK_TESTS) corrade_add_test(VkMemoryVkTest MemoryVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkPipelineVkTest PipelineVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester - FILES triangle-shaders.spv) + FILES triangle-shaders.spv compute-noop.spv) target_include_directories(VkPipelineVkTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) corrade_add_test(VkPipelineLayoutVkTest PipelineLayoutVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkQueueVkTest QueueVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) diff --git a/src/Magnum/Vk/Test/PipelineTest.cpp b/src/Magnum/Vk/Test/PipelineTest.cpp index 4933f7db3..95ca5eda1 100644 --- a/src/Magnum/Vk/Test/PipelineTest.cpp +++ b/src/Magnum/Vk/Test/PipelineTest.cpp @@ -24,17 +24,21 @@ */ #include +#include #include #include #include +#include #include "Magnum/Math/Range.h" +#include "Magnum/Vk/ComputePipelineCreateInfo.h" #include "Magnum/Vk/Device.h" #include "Magnum/Vk/Image.h" #include "Magnum/Vk/MeshLayout.h" #include "Magnum/Vk/Pipeline.h" #include "Magnum/Vk/PixelFormat.h" #include "Magnum/Vk/RasterizationPipelineCreateInfo.h" +#include "Magnum/Vk/Shader.h" #include "Magnum/Vk/ShaderSet.h" namespace Magnum { namespace Vk { namespace Test { namespace { @@ -57,6 +61,12 @@ struct PipelineTest: TestSuite::Tester { void rasterizationCreateInfoViewport2DImplicitScissor(); void rasterizationCreateInfoDynamicState(); + void computeCreateInfoConstruct(); + void computeCreateInfoConstructOwnedEntrypoint(); + void computeCreateInfoConstructNotSingleShader(); + void computeCreateInfoConstructNoInit(); + void computeCreateInfoConstructFromVk(); + void constructNoCreate(); void constructCopy(); @@ -90,6 +100,12 @@ PipelineTest::PipelineTest() { &PipelineTest::rasterizationCreateInfoViewport2DImplicitScissor, &PipelineTest::rasterizationCreateInfoDynamicState, + &PipelineTest::computeCreateInfoConstruct, + &PipelineTest::computeCreateInfoConstructOwnedEntrypoint, + &PipelineTest::computeCreateInfoConstructNotSingleShader, + &PipelineTest::computeCreateInfoConstructNoInit, + &PipelineTest::computeCreateInfoConstructFromVk, + &PipelineTest::constructNoCreate, &PipelineTest::constructCopy, @@ -107,6 +123,8 @@ PipelineTest::PipelineTest() { &PipelineTest::imageMemoryBarrierConstructFromVk}); } +using namespace Containers::Literals; + void PipelineTest::dynamicRasterizationStateMapping() { /* Same table is in Pipeline.cpp, here just to have something to test the order with -- without this, correct order can't be verified */ @@ -510,6 +528,65 @@ void PipelineTest::rasterizationCreateInfoDynamicState() { CORRADE_COMPARE(info->pDynamicState->pDynamicStates[2], VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT); } +void PipelineTest::computeCreateInfoConstruct() { + ShaderSet shaderSet; + Containers::StringView name = "dead"_s; + /* Yes, I know Fragment is wrong, it's just for testing */ + shaderSet.addShader(ShaderStage::Fragment, reinterpret_cast(0xbeef), name); + + ComputePipelineCreateInfo info{shaderSet, reinterpret_cast(0xdead), ComputePipelineCreateInfo::Flag::DisableOptimization|ComputePipelineCreateInfo::Flag::AllowDerivatives}; + CORRADE_COMPARE(info->flags, VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT|VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT); + CORRADE_COMPARE(info->stage.stage, VK_SHADER_STAGE_FRAGMENT_BIT); + CORRADE_COMPARE(info->stage.module, reinterpret_cast(0xbeef)); + CORRADE_COMPARE(info->stage.pName, name.data()); + CORRADE_COMPARE(info->layout, reinterpret_cast(0xdead)); +} + +void PipelineTest::computeCreateInfoConstructOwnedEntrypoint() { + ShaderSet shaderSet; + shaderSet.addShader({}, {}, "dead!"_s.except(1)); + + ComputePipelineCreateInfo info{shaderSet, {}}; + CORRADE_COMPARE(info->stage.pName, "dead"_s); + { + CORRADE_EXPECT_FAIL("ComputePipelineCreateInfo currently expects the ShaderSet to stay in scope, referencing its internals."); + CORRADE_VERIFY(info->stage.pName != shaderSet.stages()[0].pName); + } +} + +void PipelineTest::computeCreateInfoConstructNotSingleShader() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + ShaderSet shaderSet; + + std::ostringstream out; + Error redirectError{&out}; + ComputePipelineCreateInfo info{shaderSet, {}}; + CORRADE_COMPARE(out.str(), "Vk::ComputePipelineCreateInfo: the shader set has to contain exactly one shader, got 0\n"); +} + +void PipelineTest::computeCreateInfoConstructNoInit() { + ComputePipelineCreateInfo info{NoInit}; + info->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + new(&info) ComputePipelineCreateInfo{NoInit}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + +void PipelineTest::computeCreateInfoConstructFromVk() { + VkComputePipelineCreateInfo vkInfo; + vkInfo.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + + ComputePipelineCreateInfo info{vkInfo}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); +} + void PipelineTest::constructNoCreate() { { Pipeline pipeline{NoCreate}; diff --git a/src/Magnum/Vk/Test/PipelineVkTest.cpp b/src/Magnum/Vk/Test/PipelineVkTest.cpp index 8a9fa953b..4e7226913 100644 --- a/src/Magnum/Vk/Test/PipelineVkTest.cpp +++ b/src/Magnum/Vk/Test/PipelineVkTest.cpp @@ -33,6 +33,7 @@ #include "Magnum/Vk/BufferCreateInfo.h" #include "Magnum/Vk/CommandBuffer.h" #include "Magnum/Vk/CommandPoolCreateInfo.h" +#include "Magnum/Vk/ComputePipelineCreateInfo.h" #include "Magnum/Vk/DeviceProperties.h" #include "Magnum/Vk/ImageCreateInfo.h" #include "Magnum/Vk/MeshLayout.h" @@ -58,6 +59,7 @@ struct PipelineVkTest: VulkanTester { void constructRasterizationViewportNotSet(); void constructRasterizationViewportNotSetDiscardEnabled(); void constructRasterizationViewportNotSetDynamic(); + void constructCompute(); void constructMove(); void wrap(); @@ -74,6 +76,7 @@ PipelineVkTest::PipelineVkTest() { &PipelineVkTest::constructRasterizationViewportNotSet, &PipelineVkTest::constructRasterizationViewportNotSetDiscardEnabled, &PipelineVkTest::constructRasterizationViewportNotSetDynamic, + &PipelineVkTest::constructCompute, &PipelineVkTest::constructMove, &PipelineVkTest::wrap, @@ -245,6 +248,28 @@ void PipelineVkTest::constructRasterizationViewportNotSetDynamic() { CORRADE_VERIFY(pipeline.handle()); } +void PipelineVkTest::constructCompute() { + { + PipelineLayout pipelineLayout{device(), PipelineLayoutCreateInfo{}}; + + Shader shader{device(), ShaderCreateInfo{ + Utility::Directory::read(Utility::Directory::join(VK_TEST_DIR, "compute-noop.spv")) + }}; + + ShaderSet shaderSet; + shaderSet.addShader(ShaderStage::Compute, shader, "main"_s); + + Pipeline pipeline{device(), ComputePipelineCreateInfo{ + shaderSet, pipelineLayout + }}; + CORRADE_VERIFY(pipeline.handle()); + CORRADE_COMPARE(pipeline.handleFlags(), HandleFlag::DestroyOnDestruction); + } + + /* Shouldn't crash or anything */ + CORRADE_VERIFY(true); +} + void PipelineVkTest::constructMove() { RenderPass renderPass{device(), RenderPassCreateInfo{} .setAttachments({ diff --git a/src/Magnum/Vk/Test/compute-noop.spv b/src/Magnum/Vk/Test/compute-noop.spv new file mode 100644 index 000000000..03cec544c Binary files /dev/null and b/src/Magnum/Vk/Test/compute-noop.spv differ diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 652049c49..7c2f639f8 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -45,6 +45,7 @@ class CommandBuffer; /* CommandBufferBeginInfo is useful only in combination with CommandBuffer */ class CommandPool; class CommandPoolCreateInfo; +class ComputePipelineCreateInfo; /* BufferCopy used only directly inside CopyBufferInfo */ class CopyBufferInfo; /* ImageCopy used only directly inside CopyImageInfo */