Browse Source

Vk: implement a pipeline barrier command.

pull/494/head
Vladimír Vondruš 5 years ago
parent
commit
aae41288e8
  1. 8
      doc/vulkan-mapping.dox
  2. 1
      src/Magnum/Vk/CMakeLists.txt
  3. 37
      src/Magnum/Vk/CommandBuffer.h
  4. 101
      src/Magnum/Vk/Pipeline.cpp
  5. 205
      src/Magnum/Vk/Pipeline.h
  6. 3
      src/Magnum/Vk/RenderPassCreateInfo.h
  7. 4
      src/Magnum/Vk/Test/CMakeLists.txt
  8. 155
      src/Magnum/Vk/Test/PipelineTest.cpp
  9. 78
      src/Magnum/Vk/Test/PipelineVkTest.cpp
  10. 3
      src/Magnum/Vk/Vk.h

8
doc/vulkan-mapping.dox

@ -144,7 +144,7 @@ Vulkan function | Matching API
@fn_vk{CmdExecuteCommands} | |
@fn_vk{CmdFillBuffer} | |
@fn_vk{CmdInsertDebugUtilsLabelEXT} @m_class{m-label m-flat m-warning} **EXT** | |
@fn_vk{CmdPipelineBarrier} | |
@fn_vk{CmdPipelineBarrier} | @ref CommandBuffer::pipelineBarrier()
@fn_vk{CmdPushConstants} | |
@fn_vk{CmdResetEvent} | |
@fn_vk{CmdResetQueryPool} | |
@ -404,7 +404,7 @@ Vulkan structure | Matching API
@type_vk{BufferCreateInfo} | @ref BufferCreateInfo
@type_vk{BufferDeviceAddressInfo} @m_class{m-label m-flat m-success} **KHR, 1.2** | |
@type_vk{BufferImageCopy}, \n @type_vk{BufferImageCopy2KHR} @m_class{m-label m-flat m-warning} **KHR** | |
@type_vk{BufferMemoryBarrier} | |
@type_vk{BufferMemoryBarrier} | @ref BufferMemoryBarrier
@type_vk{BufferMemoryRequirementsInfo}, \n @type_vk{BufferMemoryRequirementsInfo2} @m_class{m-label m-flat m-success} **KHR, 1.1** | not exposed, internal to @ref Buffer::memoryRequirements()
@type_vk{BufferOpaqueCaptureAddressCreateInfo} @m_class{m-label m-flat m-success} **KHR, 1.2** | |
@type_vk{BufferViewCreateInfo} | |
@ -533,7 +533,7 @@ Vulkan structure | Matching API
@type_vk{ImageFormatListCreateInfo} @m_class{m-label m-flat m-success} **KHR, 1.2** | |
@type_vk{ImageFormatProperties}, \n @type_vk{ImageFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{ImageSubresourceRange} | not exposed, internal to @ref ImageViewCreateInfo
@type_vk{ImageMemoryBarrier} | |
@type_vk{ImageMemoryBarrier} | @ref ImageMemoryBarrier
@type_vk{ImageMemoryRequirementsInfo}, \n @type_vk{ImageMemoryRequirementsInfo2} @m_class{m-label m-flat m-success} **KHR, 1.1** | not exposed, internal to @ref Image::memoryRequirements()
@type_vk{ImagePlaneMemoryRequirementsInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{ImageResolve}, \n @type_vk{ImageResolve2KHR} @m_class{m-label m-flat m-warning} **KHR** | |
@ -561,7 +561,7 @@ Vulkan structure | Matching API
@type_vk{MappedMemoryRange} | |
@type_vk{MemoryAllocateInfo} | @ref MemoryAllocateInfo
@type_vk{MemoryAllocateFlagsInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{MemoryBarrier} | |
@type_vk{MemoryBarrier} | @ref MemoryBarrier
@type_vk{MemoryDedicatedAllocateInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{MemoryDedicatedRequirements} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{MemoryHeap} | @ref DeviceProperties::memoryHeapSize(), \n @ref DeviceProperties::memoryHeapFlags()

1
src/Magnum/Vk/CMakeLists.txt

@ -33,6 +33,7 @@ set(MagnumVk_SRCS
Fence.cpp
Framebuffer.cpp
Handle.cpp
Pipeline.cpp
Queue.cpp
Result.cpp
Shader.cpp

37
src/Magnum/Vk/CommandBuffer.h

@ -30,6 +30,7 @@
* @m_since_latest
*/
#include <initializer_list>
#include <Corrade/Containers/EnumSet.h>
#include "Magnum/Tags.h"
@ -356,6 +357,42 @@ class MAGNUM_VK_EXPORT CommandBuffer {
CommandBuffer& endRenderPass();
#endif
/**
* @brief Insert a memory dependency
* @param sourceStages Source stages. Has to contain at least
* one stage.
* @param destinationStages Destination stages. Has to contain at
* least one stage.
* @param memoryBarriers Global memory barriers, affecting all
* memory
* @param bufferMemoryBarriers Buffer memory barriers, restricted to
* a particular buffer
* @param imageMemoryBarriers Image memory barriers, restricted to a
* particular image. These are also used for performing
* @ref ImageLayout transitions.
* @param dependencyFlags Dependency flags
* @return Reference to self (for method chaining)
*
* Can be called both inside and outside a render pass. When called
* inside a render pass:
*
* - the render pass has to contain at least one
* @ref SubpassDependency to itself, with scopes that are a
* superset of scopes defined here
* - @p bufferMemoryBarriers has to be empty,
* - all images in @p imageMemoryBarriers have to be contained
* in both @ref SubpassDescription::setInputAttachments() and
* @ref SubpassDescription::setColorAttachments() /
* @ref SubpassDescription::setDepthStencilAttachment(),
* - and old and new @ref ImageLayout in @p imageMemoryBarriers have
* to be equal
*
* @see @fn_vk_keyword{CmdPipelineBarrier}
*/
CommandBuffer& pipelineBarrier(PipelineStages sourceStages, PipelineStages destinationStages, Containers::ArrayView<const MemoryBarrier> memoryBarriers, Containers::ArrayView<const BufferMemoryBarrier> bufferMemoryBarriers, Containers::ArrayView<const ImageMemoryBarrier> imageMemoryBarriers, DependencyFlags dependencyFlags = {});
/** @overload */
CommandBuffer& pipelineBarrier(PipelineStages sourceStages, PipelineStages destinationStages, std::initializer_list<MemoryBarrier> memoryBarriers, std::initializer_list<BufferMemoryBarrier> bufferMemoryBarriers, std::initializer_list<ImageMemoryBarrier> imageMemoryBarriers, DependencyFlags dependencyFlags = {});
private:
friend CommandPool;
friend Implementation::DeviceState;

101
src/Magnum/Vk/Pipeline.cpp

@ -0,0 +1,101 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
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.
*/
#include "Pipeline.h"
#include "CommandBuffer.h"
#include <Corrade/Containers/ArrayView.h>
#include "Magnum/Vk/Device.h"
namespace Magnum { namespace Vk {
MemoryBarrier::MemoryBarrier(const Accesses sourceAccesses, const Accesses destinationAccesses): _barrier{} {
_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
_barrier.srcAccessMask = VkAccessFlags(sourceAccesses);
_barrier.dstAccessMask = VkAccessFlags(destinationAccesses);
}
MemoryBarrier::MemoryBarrier(NoInitT) noexcept {}
MemoryBarrier::MemoryBarrier(const VkMemoryBarrier& barrier):
/* Can't use {} with GCC 4.8 here because it tries to initialize the first
member instead of doing a copy */
_barrier(barrier) {}
BufferMemoryBarrier::BufferMemoryBarrier(const Accesses sourceAccesses, const Accesses destinationAccesses, const VkBuffer buffer, const UnsignedLong offset, const UnsignedLong size): _barrier{} {
_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
_barrier.srcAccessMask = VkAccessFlags(sourceAccesses);
_barrier.dstAccessMask = VkAccessFlags(destinationAccesses);
_barrier.buffer = buffer;
_barrier.offset = offset;
_barrier.size = size;
}
BufferMemoryBarrier::BufferMemoryBarrier(NoInitT) noexcept {}
BufferMemoryBarrier::BufferMemoryBarrier(const VkBufferMemoryBarrier& barrier):
/* Can't use {} with GCC 4.8 here because it tries to initialize the first
member instead of doing a copy */
_barrier(barrier) {}
ImageMemoryBarrier::ImageMemoryBarrier(const Accesses sourceAccesses, const Accesses destinationAccesses, const ImageLayout oldLayout, const ImageLayout newLayout, const VkImage image, const ImageAspects aspects, const UnsignedInt layerOffset, const UnsignedInt layerCount, const UnsignedInt levelOffset, const UnsignedInt levelCount): _barrier{} {
_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
_barrier.srcAccessMask = VkAccessFlags(sourceAccesses);
_barrier.dstAccessMask = VkAccessFlags(destinationAccesses);
_barrier.oldLayout = VkImageLayout(oldLayout);
_barrier.newLayout = VkImageLayout(newLayout);
_barrier.image = image;
_barrier.subresourceRange.aspectMask = VkImageAspectFlags(aspects);
_barrier.subresourceRange.baseMipLevel = levelOffset;
_barrier.subresourceRange.levelCount = levelCount;
_barrier.subresourceRange.baseArrayLayer = layerOffset;
_barrier.subresourceRange.layerCount = layerCount;
}
ImageMemoryBarrier::ImageMemoryBarrier(NoInitT) noexcept {}
ImageMemoryBarrier::ImageMemoryBarrier(const VkImageMemoryBarrier& barrier):
/* Can't use {} with GCC 4.8 here because it tries to initialize the first
member instead of doing a copy */
_barrier(barrier) {}
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const Containers::ArrayView<const MemoryBarrier> memoryBarriers, const Containers::ArrayView<const BufferMemoryBarrier> bufferMemoryBarriers, const Containers::ArrayView<const ImageMemoryBarrier> imageMemoryBarriers, const DependencyFlags dependencyFlags) {
/* Once these grow (VkSampleLocationsInfoEXT?), they will need to be
linearized into a separate array first */
static_assert(
sizeof(MemoryBarrier) == sizeof(VkMemoryBarrier) &&
sizeof(BufferMemoryBarrier) == sizeof(VkBufferMemoryBarrier) &&
sizeof(ImageMemoryBarrier) == sizeof(VkImageMemoryBarrier),
"");
(**_device).CmdPipelineBarrier(_handle, VkPipelineStageFlags(sourceStages), VkPipelineStageFlags(destinationStages), VkDependencyFlags(dependencyFlags), memoryBarriers.size(), memoryBarriers[0], bufferMemoryBarriers.size(), bufferMemoryBarriers[0], imageMemoryBarriers.size(), imageMemoryBarriers[0]);
return *this;
}
CommandBuffer& CommandBuffer::pipelineBarrier(const PipelineStages sourceStages, const PipelineStages destinationStages, const std::initializer_list<MemoryBarrier> memoryBarriers, const std::initializer_list<BufferMemoryBarrier> bufferMemoryBarriers, const std::initializer_list<ImageMemoryBarrier> imageMemoryBarriers, const DependencyFlags dependencyFlags) {
return pipelineBarrier(sourceStages, destinationStages, Containers::arrayView(memoryBarriers), Containers::arrayView(bufferMemoryBarriers), Containers::arrayView(imageMemoryBarriers), dependencyFlags);
}
}}

205
src/Magnum/Vk/Pipeline.h

@ -26,13 +26,15 @@
*/
/** @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
* @brief Class @ref Magnum::Vk::MemoryBarrier, @ref Magnum::Vk::BufferMemoryBarrier, @ref Magnum::Vk::ImageMemoryBarrier, 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 <Corrade/Containers/EnumSet.h>
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/Vk/visibility.h"
#include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h"
@ -394,6 +396,207 @@ typedef Containers::EnumSet<DependencyFlag> DependencyFlags;
CORRADE_ENUMSET_OPERATORS(DependencyFlags)
/**
@brief Global memory barrier
@m_since_latest
Wraps a @type_vk_keyword{MemoryBarrier}. This class is subsequently used in
@ref CommandBuffer::pipelineBarrier().
*/
class MAGNUM_VK_EXPORT MemoryBarrier {
public:
/**
* @brief Constructor
* @param sourceAccesses Source memory access types
* participating in a dependency
* @param destinationAccesses Destination memory access types
* participating in a dependency
*
* The following @type_vk{MemoryBarrier} fields are pre-filled in
* addition to `sType`, everything else is zero-filled:
*
* - `srcAccessMask` to @p sourceAccesses
* - `dstAccessMask` to @p destinationAccesses
*/
/*implicit*/ MemoryBarrier(Accesses sourceAccesses, Accesses destinationAccesses);
/**
* @brief Construct without initializing the contents
*
* Note that not even the `sType` field is set --- the structure has to
* be fully initialized afterwards in order to be usable.
*/
explicit MemoryBarrier(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 MemoryBarrier(const VkMemoryBarrier& barrier);
/** @brief Underlying @type_vk{MemoryBarrier} structure */
VkMemoryBarrier& operator*() { return _barrier; }
/** @overload */
const VkMemoryBarrier& operator*() const { return _barrier; }
/** @overload */
VkMemoryBarrier* operator->() { return &_barrier; }
/** @overload */
const VkMemoryBarrier* operator->() const { return &_barrier; }
/** @overload */
operator const VkMemoryBarrier*() const { return &_barrier; }
private:
VkMemoryBarrier _barrier;
};
/**
@brief Memory barrier affecting a single buffer
@m_since_latest
Wraps a @type_vk_keyword{BufferMemoryBarrier}. Compared to @ref MemoryBarrier
only affects a single buffer. This class is subsequently used in
@ref CommandBuffer::pipelineBarrier().
*/
class MAGNUM_VK_EXPORT BufferMemoryBarrier {
public:
/**
* @brief Constructor
* @param sourceAccesses Source memory access types
* participating in a dependency
* @param destinationAccesses Destination memory access types
* participating in a dependency
* @param buffer A @ref Buffer or a raw Vulkan buffer
* handle affected by the barrier
* @param offset Buffer memory offset affected by the
* barrier, in bytes
* @param size Buffer memory size affected by the
* barrier, in bytes
*
* The following @type_vk{BufferMemoryBarrier} fields are pre-filled in
* addition to `sType`, everything else is zero-filled:
*
* - `srcAccessMask` to @p sourceAccesses
* - `dstAccessMask` to @p destinationAccesses
* - `buffer`
* - `offset`
* - `size`
*/
/*implicit*/ BufferMemoryBarrier(Accesses sourceAccesses, Accesses destinationAccesses, VkBuffer buffer, UnsignedLong offset = 0, UnsignedLong size = VK_WHOLE_SIZE);
/**
* @brief Construct without initializing the contents
*
* Note that not even the `sType` field is set --- the structure has to
* be fully initialized afterwards in order to be usable.
*/
explicit BufferMemoryBarrier(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 BufferMemoryBarrier(const VkBufferMemoryBarrier& barrier);
/** @brief Underlying @type_vk{BufferMemoryBarrier} structure */
VkBufferMemoryBarrier& operator*() { return _barrier; }
/** @overload */
const VkBufferMemoryBarrier& operator*() const { return _barrier; }
/** @overload */
VkBufferMemoryBarrier* operator->() { return &_barrier; }
/** @overload */
const VkBufferMemoryBarrier* operator->() const { return &_barrier; }
/** @overload */
operator const VkBufferMemoryBarrier*() const { return &_barrier; }
private:
VkBufferMemoryBarrier _barrier;
};
/**
@brief Memory barrier affecting a single image
@m_since_latest
Wraps a @type_vk_keyword{ImageMemoryBarrier}. Compared to @ref MemoryBarrier
only affects a single image and additionally performs @ref ImageLayout
transitions. This class is subsequently used in
@ref CommandBuffer::pipelineBarrier().
*/
class MAGNUM_VK_EXPORT ImageMemoryBarrier {
public:
/**
* @brief Constructor
* @param sourceAccesses Source memory access types
* participating in a dependency
* @param oldLayout Old layout in an image layout
* transition
* @param destinationAccesses Destination memory access types
* participating in a dependency
* @param newLayout New layout in an image layout
* transition
* @param image An @ref Image or a raw Vulkan image
* handle affected by the barrier
* @param aspects Image aspects affected by the barrier
* @param layerOffset Offset to the first layer affected by
* the barrier
* @param layerCount Layer count affected by the barrier
* @param levelOffset Offset to the first mip level affected
* by the barrier
* @param levelCount Mip level count affected by the barrier
*
* The following @type_vk{ImageMemoryBarrier} fields are pre-filled in
* addition to `sType`, everything else is zero-filled:
*
* - `srcAccessMask` to @p sourceAccesses
* - `dstAccessMask` to @p destinationAccesses
* - `oldLayout`
* - `newLayout`
* - `image`
* - `subresourceRange.aspectMask` to @p aspects
* - `subresourceRange.levelOffset` to @p levelOffset
* - `subresourceRange.levelCount` to @p levelCount
* - `subresourceRange.baseArrayLayer` to @p layerOffset
* - `subresourceRange.layerCount` to @p layerCount
*/
/*implicit*/ ImageMemoryBarrier(Accesses sourceAccesses, Accesses destinationAccesses, ImageLayout oldLayout, ImageLayout newLayout, VkImage image, ImageAspects aspects, UnsignedInt layerOffset = 0, UnsignedInt layerCount = VK_REMAINING_ARRAY_LAYERS, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS);
/**
* @brief Construct without initializing the contents
*
* Note that not even the `sType` field is set --- the structure has to
* be fully initialized afterwards in order to be usable.
*/
explicit ImageMemoryBarrier(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 ImageMemoryBarrier(const VkImageMemoryBarrier& barrier);
/** @brief Underlying @type_vk{ImageMemoryBarrier} structure */
VkImageMemoryBarrier& operator*() { return _barrier; }
/** @overload */
const VkImageMemoryBarrier& operator*() const { return _barrier; }
/** @overload */
VkImageMemoryBarrier* operator->() { return &_barrier; }
/** @overload */
const VkImageMemoryBarrier* operator->() const { return &_barrier; }
/** @overload */
operator const VkImageMemoryBarrier*() const { return &_barrier; }
private:
VkImageMemoryBarrier _barrier;
};
}}
#endif

3
src/Magnum/Vk/RenderPassCreateInfo.h

@ -718,6 +718,9 @@ all fields that are present only in @type_vk{SubpassDependency2} --- in
particular, the whole `pNext` pointer chain is omitted. When performing the
conversion it's your responsibility to ensure nothing significant was in the
fields that were left out.
@see @ref MemoryBarrier, @ref ImageMemoryBarrier,
@ref CommandBuffer::pipelineBarrier()
*/
class MAGNUM_VK_EXPORT SubpassDependency {
public:

4
src/Magnum/Vk/Test/CMakeLists.txt

@ -42,6 +42,7 @@ corrade_add_test(VkInstanceTest InstanceTest.cpp LIBRARIES MagnumVk)
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(VkPipelineTest PipelineTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkPixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumVkTestLib)
corrade_add_test(VkQueueTest QueueTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkResultTest ResultTest.cpp LIBRARIES MagnumVk)
@ -135,6 +136,7 @@ set_target_properties(
VkIntegrationTest
VkLayerPropertiesTest
VkMemoryTest
VkPipelineTest
VkPixelFormatTest
VkQueueTest
VkResultTest
@ -167,6 +169,7 @@ if(BUILD_VK_TESTS)
corrade_add_test(VkImageViewVkTest ImageViewVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkInstanceVkTest InstanceVkTest.cpp LIBRARIES MagnumVkTestLib)
corrade_add_test(VkMemoryVkTest MemoryVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkPipelineVkTest PipelineVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkQueueVkTest QueueVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkRenderPassVkTest RenderPassVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester)
corrade_add_test(VkShaderVkTest ShaderVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
@ -187,6 +190,7 @@ if(BUILD_VK_TESTS)
VkImageViewVkTest
VkInstanceVkTest
VkMemoryVkTest
VkPipelineVkTest
VkQueueVkTest
VkRenderPassVkTest
VkShaderVkTest

155
src/Magnum/Vk/Test/PipelineTest.cpp

@ -0,0 +1,155 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
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.
*/
#include <new>
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/Vk/Image.h"
#include "Magnum/Vk/Pipeline.h"
namespace Magnum { namespace Vk { namespace Test { namespace {
struct PipelineTest: TestSuite::Tester {
explicit PipelineTest();
void memoryBarrierConstruct();
void memoryBarrierConstructNoInit();
void memoryBarrierConstructFromVk();
void bufferMemoryBarrierConstruct();
void bufferMemoryBarrierConstructNoInit();
void bufferMemoryBarrierConstructFromVk();
void imageMemoryBarrierConstruct();
void imageMemoryBarrierConstructNoInit();
void imageMemoryBarrierConstructFromVk();
};
PipelineTest::PipelineTest() {
addTests({&PipelineTest::memoryBarrierConstruct,
&PipelineTest::memoryBarrierConstructNoInit,
&PipelineTest::memoryBarrierConstructFromVk,
&PipelineTest::bufferMemoryBarrierConstruct,
&PipelineTest::bufferMemoryBarrierConstructNoInit,
&PipelineTest::bufferMemoryBarrierConstructFromVk,
&PipelineTest::imageMemoryBarrierConstruct,
&PipelineTest::imageMemoryBarrierConstructNoInit,
&PipelineTest::imageMemoryBarrierConstructFromVk});
}
void PipelineTest::memoryBarrierConstruct() {
MemoryBarrier barrier{Access::ColorAttachmentWrite|Access::DepthStencilAttachmentWrite, Access::TransferRead};
CORRADE_COMPARE(barrier->srcAccessMask, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT|VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
CORRADE_COMPARE(barrier->dstAccessMask, VK_ACCESS_TRANSFER_READ_BIT);
}
void PipelineTest::memoryBarrierConstructNoInit() {
MemoryBarrier barrier{NoInit};
barrier->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
new(&barrier) MemoryBarrier{NoInit};
CORRADE_COMPARE(barrier->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
CORRADE_VERIFY((std::is_nothrow_constructible<MemoryBarrier, NoInitT>::value));
/* Implicit construction is not allowed */
CORRADE_VERIFY(!(std::is_convertible<NoInitT, MemoryBarrier>::value));
}
void PipelineTest::memoryBarrierConstructFromVk() {
VkMemoryBarrier vkBarrier;
vkBarrier.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
MemoryBarrier barrier{vkBarrier};
CORRADE_COMPARE(barrier->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
}
void PipelineTest::bufferMemoryBarrierConstruct() {
BufferMemoryBarrier barrier{Access::ColorAttachmentWrite|Access::DepthStencilAttachmentWrite, Access::TransferRead, reinterpret_cast<VkBuffer>(0xdead), 3, 5};
CORRADE_COMPARE(barrier->srcAccessMask, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT|VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
CORRADE_COMPARE(barrier->dstAccessMask, VK_ACCESS_TRANSFER_READ_BIT);
CORRADE_COMPARE(barrier->buffer, reinterpret_cast<VkBuffer>(0xdead));
CORRADE_COMPARE(barrier->offset, 3);
CORRADE_COMPARE(barrier->size, 5);
}
void PipelineTest::bufferMemoryBarrierConstructNoInit() {
BufferMemoryBarrier barrier{NoInit};
barrier->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
new(&barrier) BufferMemoryBarrier{NoInit};
CORRADE_COMPARE(barrier->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
CORRADE_VERIFY((std::is_nothrow_constructible<BufferMemoryBarrier, NoInitT>::value));
/* Implicit construction is not allowed */
CORRADE_VERIFY(!(std::is_convertible<NoInitT, BufferMemoryBarrier>::value));
}
void PipelineTest::bufferMemoryBarrierConstructFromVk() {
VkBufferMemoryBarrier vkBarrier;
vkBarrier.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
BufferMemoryBarrier barrier{vkBarrier};
CORRADE_COMPARE(barrier->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
}
void PipelineTest::imageMemoryBarrierConstruct() {
ImageMemoryBarrier barrier{Access::ColorAttachmentWrite|Access::DepthStencilAttachmentWrite, Access::TransferRead, ImageLayout::Preinitialized, ImageLayout::TransferSource, reinterpret_cast<VkImage>(0xdead), ImageAspect::Color|ImageAspect::Depth, 3, 5, 7, 9};
CORRADE_COMPARE(barrier->srcAccessMask, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT|VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
CORRADE_COMPARE(barrier->dstAccessMask, VK_ACCESS_TRANSFER_READ_BIT);
CORRADE_COMPARE(barrier->oldLayout, VK_IMAGE_LAYOUT_PREINITIALIZED);
CORRADE_COMPARE(barrier->newLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
CORRADE_COMPARE(barrier->image, reinterpret_cast<VkImage>(0xdead));
CORRADE_COMPARE(barrier->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT|VK_IMAGE_ASPECT_DEPTH_BIT);
CORRADE_COMPARE(barrier->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(barrier->subresourceRange.levelCount, 9);
CORRADE_COMPARE(barrier->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(barrier->subresourceRange.layerCount, 5);
}
void PipelineTest::imageMemoryBarrierConstructNoInit() {
ImageMemoryBarrier barrier{NoInit};
barrier->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
new(&barrier) ImageMemoryBarrier{NoInit};
CORRADE_COMPARE(barrier->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
CORRADE_VERIFY((std::is_nothrow_constructible<ImageMemoryBarrier, NoInitT>::value));
/* Implicit construction is not allowed */
CORRADE_VERIFY(!(std::is_convertible<NoInitT, ImageMemoryBarrier>::value));
}
void PipelineTest::imageMemoryBarrierConstructFromVk() {
VkImageMemoryBarrier vkBarrier;
vkBarrier.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
ImageMemoryBarrier barrier{vkBarrier};
CORRADE_COMPARE(barrier->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::PipelineTest)

78
src/Magnum/Vk/Test/PipelineVkTest.cpp

@ -0,0 +1,78 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
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.
*/
#include "Magnum/Vk/BufferCreateInfo.h"
#include "Magnum/Vk/CommandBuffer.h"
#include "Magnum/Vk/CommandPoolCreateInfo.h"
#include "Magnum/Vk/DeviceProperties.h"
#include "Magnum/Vk/ImageCreateInfo.h"
#include "Magnum/Vk/Pipeline.h"
#include "Magnum/Vk/PixelFormat.h"
#include "Magnum/Vk/VulkanTester.h"
namespace Magnum { namespace Vk { namespace Test { namespace {
struct PipelineVkTest: VulkanTester {
explicit PipelineVkTest();
void pipelineBarrier();
};
PipelineVkTest::PipelineVkTest() {
addTests({&PipelineVkTest::pipelineBarrier});
}
void PipelineVkTest::pipelineBarrier() {
CommandPool pool{device(), CommandPoolCreateInfo{
device().properties().pickQueueFamily(QueueFlag::Graphics)}};
Buffer buffer{device(), BufferCreateInfo{
BufferUsage::TransferDestination|BufferUsage::VertexBuffer, 16
}, MemoryFlag::DeviceLocal};
Image image{device(), ImageCreateInfo2D{
ImageUsage::TransferDestination|ImageUsage::Sampled,
PixelFormat::RGBA8Unorm, {4, 4}, 1
}, MemoryFlag::DeviceLocal};
pool.allocate()
.begin()
.pipelineBarrier(PipelineStage::Transfer, PipelineStage::Host|PipelineStage::VertexInput|PipelineStage::FragmentShader, {
{Access::TransferWrite, Access::HostRead}
}, {
{Access::TransferWrite, Access::VertexAttributeRead, buffer}
}, {
{Access::TransferWrite, Access::ShaderRead,
ImageLayout::Preinitialized, ImageLayout::ShaderReadOnly,
image, ImageAspect::Color}
})
.end();
/* Does not do anything visible, so just test that it didn't blow up */
CORRADE_VERIFY(true);
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::PipelineVkTest)

3
src/Magnum/Vk/Vk.h

@ -40,6 +40,7 @@ enum class Access: UnsignedInt;
typedef Containers::EnumSet<Access> Accesses;
class Buffer;
class BufferCreateInfo;
class BufferMemoryBarrier;
class CommandBuffer;
/* CommandBufferBeginInfo is useful only in combination with CommandBuffer */
class CommandPool;
@ -66,6 +67,7 @@ typedef Containers::EnumSet<ImageAspect> ImageAspects;
enum class ImageLayout: Int;
class ImageCreateInfo;
/* Not forward-declaring ImageCreateInfo1D etc right now, I see no need */
class ImageMemoryBarrier;
class ImageView;
class ImageViewCreateInfo;
/* Not forward-declaring ImageViewCreateInfo1D etc right now, I see no need */
@ -76,6 +78,7 @@ class InstanceExtensionProperties;
class LayerProperties;
class Memory;
class MemoryAllocateInfo;
class MemoryBarrier;
class MemoryMapDeleter;
class MemoryRequirements;
enum class MemoryFlag: UnsignedInt;

Loading…
Cancel
Save