Browse Source

Vk: ability to list descriptor set layouts in PipelineLayoutCreateInfo.

pull/504/head
Vladimír Vondruš 5 years ago
parent
commit
c656c55298
  1. 20
      doc/snippets/MagnumVk.cpp
  2. 6
      src/Magnum/Vk/DescriptorSetLayout.h
  3. 43
      src/Magnum/Vk/PipelineLayout.cpp
  4. 18
      src/Magnum/Vk/PipelineLayout.h
  5. 36
      src/Magnum/Vk/PipelineLayoutCreateInfo.h
  6. 47
      src/Magnum/Vk/Test/PipelineLayoutTest.cpp
  7. 30
      src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp

20
doc/snippets/MagnumVk.cpp

@ -55,7 +55,7 @@
#include "Magnum/Vk/MemoryAllocateInfo.h" #include "Magnum/Vk/MemoryAllocateInfo.h"
#include "Magnum/Vk/Mesh.h" #include "Magnum/Vk/Mesh.h"
#include "Magnum/Vk/Pipeline.h" #include "Magnum/Vk/Pipeline.h"
#include "Magnum/Vk/PipelineLayout.h" #include "Magnum/Vk/PipelineLayoutCreateInfo.h"
#include "Magnum/Vk/PixelFormat.h" #include "Magnum/Vk/PixelFormat.h"
#include "Magnum/Vk/Queue.h" #include "Magnum/Vk/Queue.h"
#include "Magnum/Vk/RasterizationPipelineCreateInfo.h" #include "Magnum/Vk/RasterizationPipelineCreateInfo.h"
@ -1021,6 +1021,24 @@ cmd.bindPipeline(pipeline);
/* [Pipeline-usage] */ /* [Pipeline-usage] */
} }
{
Vk::Device device{NoCreate};
/* The include should be a no-op here since it was already included above */
/* [PipelineLayout-creation] */
#include <Magnum/Vk/PipelineLayoutCreateInfo.h>
DOXYGEN_IGNORE()
Vk::DescriptorSetLayout layout1{DOXYGEN_IGNORE(NoCreate)};
Vk::DescriptorSetLayout layout2{DOXYGEN_IGNORE(NoCreate)};
DOXYGEN_IGNORE()
Vk::PipelineLayout{device, Vk::PipelineLayoutCreateInfo{
layout1, layout2, DOXYGEN_IGNORE(layout1)
}};
/* [PipelineLayout-creation] */
}
{ {
Vk::Device device{NoCreate}; Vk::Device device{NoCreate};
/* The include should be a no-op here since it was already included above */ /* The include should be a no-op here since it was already included above */

6
src/Magnum/Vk/DescriptorSetLayout.h

@ -85,6 +85,12 @@ specify additional flags per binding. All of them require a certain
@ref DescriptorSetLayoutBinding::Flag for more information: @ref DescriptorSetLayoutBinding::Flag for more information:
@snippet MagnumVk.cpp DescriptorSetLayout-creation-binding-flags @snippet MagnumVk.cpp DescriptorSetLayout-creation-binding-flags
@section Vk-DescriptorSetLayout-usage Descriptor set layout usage
A descriptor set layout is used in a @ref PipelineLayout creation and
subsequently for descriptor set allocation from a descriptor pool. See the
corresponding class documentation for more information.
*/ */
class MAGNUM_VK_EXPORT DescriptorSetLayout { class MAGNUM_VK_EXPORT DescriptorSetLayout {
public: public:

43
src/Magnum/Vk/PipelineLayout.cpp

@ -26,16 +26,32 @@
#include "PipelineLayout.h" #include "PipelineLayout.h"
#include "PipelineLayoutCreateInfo.h" #include "PipelineLayoutCreateInfo.h"
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Utility/Algorithms.h>
#include "Magnum/Vk/Assert.h" #include "Magnum/Vk/Assert.h"
#include "Magnum/Vk/Device.h" #include "Magnum/Vk/Device.h"
#include "Magnum/Vk/Result.h" #include "Magnum/Vk/Result.h"
namespace Magnum { namespace Vk { namespace Magnum { namespace Vk {
PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(): _info{} { PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const Containers::ArrayView<const VkDescriptorSetLayout> descriptorSetLayouts): _info{} {
/* Make a copy of the descriptor set layout list */
Containers::ArrayView<VkDescriptorSetLayout> descriptorSetLayoutsCopy;
_data = Containers::ArrayTuple{
{Containers::NoInit, descriptorSetLayouts.size(), descriptorSetLayoutsCopy}
};
Utility::copy(descriptorSetLayouts, descriptorSetLayoutsCopy);
_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; _info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
_info.setLayoutCount = descriptorSetLayoutsCopy.size();
_info.pSetLayouts = descriptorSetLayoutsCopy;
} }
PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(): PipelineLayoutCreateInfo{Containers::ArrayView<const VkDescriptorSetLayout>{}} {}
PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const std::initializer_list<VkDescriptorSetLayout> descriptorSetLayouts): PipelineLayoutCreateInfo{Containers::arrayView(descriptorSetLayouts)} {}
PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(NoInitT) noexcept {} PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(NoInitT) noexcept {}
PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const VkPipelineLayoutCreateInfo& info): PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const VkPipelineLayoutCreateInfo& info):
@ -43,6 +59,31 @@ PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const VkPipelineLayoutCreateI
member instead of doing a copy */ member instead of doing a copy */
_info(info) {} _info(info) {}
PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(PipelineLayoutCreateInfo&& other) noexcept:
/* Can't use {} with GCC 4.8 here because it tries to initialize the first
member instead of doing a copy */
_info(other._info),
_data{std::move(other._data)}
{
/* Ensure the previous instance doesn't reference state that's now ours */
/** @todo this is now more like a destructible move, do it more selectively
and clear only what's really ours and not external? */
other._info.pNext = nullptr;
other._info.setLayoutCount = 0;
other._info.pSetLayouts = nullptr;
other._info.pushConstantRangeCount = 0;
other._info.pPushConstantRanges = nullptr;
}
PipelineLayoutCreateInfo::~PipelineLayoutCreateInfo() = default;
PipelineLayoutCreateInfo& PipelineLayoutCreateInfo::operator=(PipelineLayoutCreateInfo&& other) noexcept {
using std::swap;
swap(other._info, _info);
swap(other._data, _data);
return *this;
}
PipelineLayout PipelineLayout::wrap(Device& device, const VkPipelineLayout handle, const HandleFlags flags) { PipelineLayout PipelineLayout::wrap(Device& device, const VkPipelineLayout handle, const HandleFlags flags) {
PipelineLayout out{NoCreate}; PipelineLayout out{NoCreate};
out._device = &device; out._device = &device;

18
src/Magnum/Vk/PipelineLayout.h

@ -43,7 +43,23 @@ namespace Magnum { namespace Vk {
@brief Pipeline layout @brief Pipeline layout
@m_since_latest @m_since_latest
Wraps a @type_vk_keyword{PipelineLayout}. Used in a @ref Pipeline. Wraps a @type_vk_keyword{PipelineLayout}. Specifies what descriptor set layouts
and push constants are used in a @ref Pipeline.
@section Vk-PipelineLayout-creation Pipeline layout creation
Except for the rare case when your shader doesn't have any bindings, in which
case a default-constructed @ref PipelineLayoutCreateInfo would be enough,
you'll want to list @ref DescriptorSetLayout instances for all descriptor sets
needed by shaders in the pipeline:
@snippet MagnumVk.cpp PipelineLayout-creation
@section Vk-PipelineLayout-usage Pipeline layout usage
Once created, the pipeline layout instance is used for @ref Pipeline creation
and for descriptor set binding. See the corresponding class documentation for
more information.
*/ */
class MAGNUM_VK_EXPORT PipelineLayout { class MAGNUM_VK_EXPORT PipelineLayout {
public: public:

36
src/Magnum/Vk/PipelineLayoutCreateInfo.h

@ -30,6 +30,8 @@
* @m_since_latest * @m_since_latest
*/ */
#include <Corrade/Containers/ArrayTuple.h>
#include "Magnum/Tags.h" #include "Magnum/Tags.h"
#include "Magnum/Vk/Vk.h" #include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h" #include "Magnum/Vk/Vulkan.h"
@ -41,19 +43,34 @@ namespace Magnum { namespace Vk {
@brief Pipeline layout creation info @brief Pipeline layout creation info
@m_since_latest @m_since_latest
Wraps a @type_vk_keyword{PipelineLayoutCreateInfo}. Wraps a @type_vk_keyword{PipelineLayoutCreateInfo}. See
@ref Vk-PipelineLayout-creation "Pipeline layout creation" for usage
information.
*/ */
class MAGNUM_VK_EXPORT PipelineLayoutCreateInfo { class MAGNUM_VK_EXPORT PipelineLayoutCreateInfo {
public: public:
/* VkPipelineLayoutCreateFlagBits is currently empty, so no reason
to expose */
/** /**
* @brief Constructor * @brief Constructor
* @param descriptorSetLayouts Descriptor set layouts used in this
* pipeline layout
* *
* The following @type_vk{PipelineLayoutCreateInfo} fields are * The following @type_vk{PipelineLayoutCreateInfo} fields are
* pre-filled in addition to `sType`, everything else is zero-filled: * pre-filled in addition to `sType`, everything else is zero-filled:
* *
* - <em>(none)</em> * - `setLayoutCount` and `pSetLayouts` to a copy of
* @p descriptorSetLayouts
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT
explicit PipelineLayoutCreateInfo(Containers::ArrayView<const VkDescriptorSetLayout> descriptorSetLayouts = {});
#else /* so we don't need to include ArrayView */
explicit PipelineLayoutCreateInfo(Containers::ArrayView<const VkDescriptorSetLayout> descriptorSetLayouts);
explicit PipelineLayoutCreateInfo(); explicit PipelineLayoutCreateInfo();
#endif
/** @overload */
explicit PipelineLayoutCreateInfo(std::initializer_list<VkDescriptorSetLayout> descriptorSetLayouts);
/** /**
* @brief Construct without initializing the contents * @brief Construct without initializing the contents
@ -72,6 +89,20 @@ class MAGNUM_VK_EXPORT PipelineLayoutCreateInfo {
*/ */
explicit PipelineLayoutCreateInfo(const VkPipelineLayoutCreateInfo& info); explicit PipelineLayoutCreateInfo(const VkPipelineLayoutCreateInfo& info);
/** @brief Copying is not allowed */
PipelineLayoutCreateInfo(const PipelineLayoutCreateInfo&) = delete;
/** @brief Move constructor */
PipelineLayoutCreateInfo(PipelineLayoutCreateInfo&& other) noexcept;
~PipelineLayoutCreateInfo();
/** @brief Copying is not allowed */
PipelineLayoutCreateInfo& operator=(const PipelineLayoutCreateInfo&) = delete;
/** @brief Move assignment */
PipelineLayoutCreateInfo& operator=(PipelineLayoutCreateInfo&& other) noexcept;
/** @brief Underlying @type_vk{PipelineLayoutCreateInfo} structure */ /** @brief Underlying @type_vk{PipelineLayoutCreateInfo} structure */
VkPipelineLayoutCreateInfo& operator*() { return _info; } VkPipelineLayoutCreateInfo& operator*() { return _info; }
/** @overload */ /** @overload */
@ -85,6 +116,7 @@ class MAGNUM_VK_EXPORT PipelineLayoutCreateInfo {
private: private:
VkPipelineLayoutCreateInfo _info; VkPipelineLayoutCreateInfo _info;
Containers::ArrayTuple _data;
}; };
}} }}

47
src/Magnum/Vk/Test/PipelineLayoutTest.cpp

@ -24,6 +24,7 @@
*/ */
#include <new> #include <new>
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include "Magnum/Vk/PipelineLayoutCreateInfo.h" #include "Magnum/Vk/PipelineLayoutCreateInfo.h"
@ -34,8 +35,11 @@ struct PipelineLayoutTest: TestSuite::Tester {
explicit PipelineLayoutTest(); explicit PipelineLayoutTest();
void createInfoConstruct(); void createInfoConstruct();
void createInfoConstructDescriptorSetLayouts();
void createInfoConstructNoInit(); void createInfoConstructNoInit();
void createInfoConstructFromVk(); void createInfoConstructFromVk();
void createInfoConstructCopy();
void createInfoConstructMove();
void constructNoCreate(); void constructNoCreate();
void constructCopy(); void constructCopy();
@ -43,8 +47,11 @@ struct PipelineLayoutTest: TestSuite::Tester {
PipelineLayoutTest::PipelineLayoutTest() { PipelineLayoutTest::PipelineLayoutTest() {
addTests({&PipelineLayoutTest::createInfoConstruct, addTests({&PipelineLayoutTest::createInfoConstruct,
&PipelineLayoutTest::createInfoConstructDescriptorSetLayouts,
&PipelineLayoutTest::createInfoConstructNoInit, &PipelineLayoutTest::createInfoConstructNoInit,
&PipelineLayoutTest::createInfoConstructFromVk, &PipelineLayoutTest::createInfoConstructFromVk,
&PipelineLayoutTest::createInfoConstructCopy,
&PipelineLayoutTest::createInfoConstructMove,
&PipelineLayoutTest::constructNoCreate, &PipelineLayoutTest::constructNoCreate,
&PipelineLayoutTest::constructCopy}); &PipelineLayoutTest::constructCopy});
@ -52,8 +59,20 @@ PipelineLayoutTest::PipelineLayoutTest() {
void PipelineLayoutTest::createInfoConstruct() { void PipelineLayoutTest::createInfoConstruct() {
PipelineLayoutCreateInfo info; PipelineLayoutCreateInfo info;
/** @todo expand once there's actually something */
CORRADE_COMPARE(info->flags, 0); CORRADE_COMPARE(info->flags, 0);
CORRADE_COMPARE(info->setLayoutCount, 0);
}
void PipelineLayoutTest::createInfoConstructDescriptorSetLayouts() {
VkDescriptorSetLayout layouts[]{reinterpret_cast<VkDescriptorSetLayout>(0xdead), reinterpret_cast<VkDescriptorSetLayout>(0xbeef)};
PipelineLayoutCreateInfo info{layouts};
CORRADE_COMPARE(info->setLayoutCount, 2);
CORRADE_VERIFY(info->pSetLayouts);
/* The contents should be copied */
CORRADE_VERIFY(info->pSetLayouts != layouts);
CORRADE_COMPARE(info->pSetLayouts[0], reinterpret_cast<VkDescriptorSetLayout>(0xdead));
CORRADE_COMPARE(info->pSetLayouts[1], reinterpret_cast<VkDescriptorSetLayout>(0xbeef));
} }
void PipelineLayoutTest::createInfoConstructNoInit() { void PipelineLayoutTest::createInfoConstructNoInit() {
@ -76,6 +95,32 @@ void PipelineLayoutTest::createInfoConstructFromVk() {
CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
} }
void PipelineLayoutTest::createInfoConstructCopy() {
CORRADE_VERIFY(!std::is_copy_constructible<PipelineLayoutCreateInfo>{});
CORRADE_VERIFY(!std::is_copy_assignable<PipelineLayoutCreateInfo>{});
}
void PipelineLayoutTest::createInfoConstructMove() {
PipelineLayoutCreateInfo a{reinterpret_cast<VkDescriptorSetLayout>(0xdead), reinterpret_cast<VkDescriptorSetLayout>(0xbeef)};
CORRADE_COMPARE(a->setLayoutCount, 2);
CORRADE_VERIFY(a->pSetLayouts);
PipelineLayoutCreateInfo b = std::move(a);
CORRADE_COMPARE(a->setLayoutCount, 0);
CORRADE_VERIFY(!a->pSetLayouts);
CORRADE_COMPARE(b->setLayoutCount, 2);
CORRADE_VERIFY(b->pSetLayouts);
CORRADE_COMPARE(b->pSetLayouts[1], reinterpret_cast<VkDescriptorSetLayout>(0xbeef));
PipelineLayoutCreateInfo c;
c = std::move(b);
CORRADE_COMPARE(b->setLayoutCount, 0);
CORRADE_VERIFY(!b->pSetLayouts);
CORRADE_COMPARE(c->setLayoutCount, 2);
CORRADE_VERIFY(c->pSetLayouts);
CORRADE_COMPARE(c->pSetLayouts[1], reinterpret_cast<VkDescriptorSetLayout>(0xbeef));
}
void PipelineLayoutTest::constructNoCreate() { void PipelineLayoutTest::constructNoCreate() {
{ {
PipelineLayout layout{NoCreate}; PipelineLayout layout{NoCreate};

30
src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp

@ -25,6 +25,7 @@
#include <Corrade/Containers/Reference.h> #include <Corrade/Containers/Reference.h>
#include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h"
#include "Magnum/Vk/PipelineLayoutCreateInfo.h" #include "Magnum/Vk/PipelineLayoutCreateInfo.h"
#include "Magnum/Vk/Result.h" #include "Magnum/Vk/Result.h"
#include "Magnum/Vk/VulkanTester.h" #include "Magnum/Vk/VulkanTester.h"
@ -34,21 +35,24 @@ namespace Magnum { namespace Vk { namespace Test { namespace {
struct PipelineLayoutVkTest: VulkanTester { struct PipelineLayoutVkTest: VulkanTester {
explicit PipelineLayoutVkTest(); explicit PipelineLayoutVkTest();
void construct(); void constructEmpty();
void constructWithDescriptorSetLayout();
void constructMove(); void constructMove();
void wrap(); void wrap();
}; };
PipelineLayoutVkTest::PipelineLayoutVkTest() { PipelineLayoutVkTest::PipelineLayoutVkTest() {
addTests({&PipelineLayoutVkTest::construct, addTests({&PipelineLayoutVkTest::constructEmpty,
&PipelineLayoutVkTest::constructWithDescriptorSetLayout,
&PipelineLayoutVkTest::constructMove, &PipelineLayoutVkTest::constructMove,
&PipelineLayoutVkTest::wrap}); &PipelineLayoutVkTest::wrap});
} }
void PipelineLayoutVkTest::construct() { void PipelineLayoutVkTest::constructEmpty() {
{ {
/* Rare, but should still work */
PipelineLayout layout{device(), PipelineLayoutCreateInfo{}}; PipelineLayout layout{device(), PipelineLayoutCreateInfo{}};
CORRADE_VERIFY(layout.handle()); CORRADE_VERIFY(layout.handle());
CORRADE_COMPARE(layout.handleFlags(), HandleFlag::DestroyOnDestruction); CORRADE_COMPARE(layout.handleFlags(), HandleFlag::DestroyOnDestruction);
@ -58,6 +62,26 @@ void PipelineLayoutVkTest::construct() {
CORRADE_VERIFY(true); CORRADE_VERIFY(true);
} }
void PipelineLayoutVkTest::constructWithDescriptorSetLayout() {
{
DescriptorSetLayout descriptorSetLayout1{device(), DescriptorSetLayoutCreateInfo{
{{15, DescriptorType::UniformBuffer}}
}};
DescriptorSetLayout descriptorSetLayout2{device(), DescriptorSetLayoutCreateInfo{
{{1, DescriptorType::CombinedImageSampler}}
}};
PipelineLayout layout{device(), PipelineLayoutCreateInfo{
descriptorSetLayout1, descriptorSetLayout2
}};
CORRADE_VERIFY(layout.handle());
CORRADE_COMPARE(layout.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void PipelineLayoutVkTest::constructMove() { void PipelineLayoutVkTest::constructMove() {
PipelineLayout a{device(), PipelineLayoutCreateInfo{}}; PipelineLayout a{device(), PipelineLayoutCreateInfo{}};
VkPipelineLayout handle = a.handle(); VkPipelineLayout handle = a.handle();

Loading…
Cancel
Save