Browse Source

Vk: add an Image wrapper.

Not exactly sure about the usage, so no docs yet. Will come once memory
allocation is complete.
pull/234/head
Vladimír Vondruš 6 years ago
parent
commit
fcd0afb306
  1. 3
      doc/vulkan-mapping.dox
  2. 2
      src/Magnum/Vk/CMakeLists.txt
  3. 105
      src/Magnum/Vk/Image.cpp
  4. 418
      src/Magnum/Vk/Image.h
  5. 2
      src/Magnum/Vk/Test/CMakeLists.txt
  6. 204
      src/Magnum/Vk/Test/ImageTest.cpp
  7. 185
      src/Magnum/Vk/Test/ImageVkTest.cpp
  8. 1
      src/Magnum/Vk/Vk.h

3
doc/vulkan-mapping.dox

@ -134,7 +134,7 @@ Vulkan function | Matching API
@fn_vk{CreateEvent}, \n @fn_vk{DestroyEvent} | |
@fn_vk{CreateFence}, \n @fn_vk{DestroyFence} | |
@fn_vk{CreateFramebuffer}, \n @fn_vk{DestroyFramebuffer} | |
@fn_vk{CreateImage}, \n @fn_vk{DestroyImage} | |
@fn_vk{CreateImage}, \n @fn_vk{DestroyImage} | @ref Image constructor and destructor
@fn_vk{CreateImageView}, \n @fn_vk{DestroyImageView} | |
@fn_vk{CreateInstance}, \n @fn_vk{DestroyInstance} | @ref Instance constructor and destructor
@fn_vk{CreatePipeline}, \n @fn_vk{DestroyPipeline} | |
@ -328,6 +328,7 @@ Vulkan structure | Matching API
Vulkan structure | Matching API
--------------------------------------- | ------------
@type_vk{ImageCreateInfo} | @ref ImageCreateInfo
@type_vk{InstanceCreateInfo} | @ref InstanceCreateInfo
*/

2
src/Magnum/Vk/CMakeLists.txt

@ -31,6 +31,7 @@ set(MagnumVk_SRCS
CommandPool.cpp
Extensions.cpp
Handle.cpp
Image.cpp
Instance.cpp
Memory.cpp
Result.cpp
@ -56,6 +57,7 @@ set(MagnumVk_HEADERS
Extensions.h
ExtensionProperties.h
Handle.h
Image.h
Instance.h
Integration.h
LayerProperties.h

105
src/Magnum/Vk/Image.cpp

@ -0,0 +1,105 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 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 "Image.h"
#include "Magnum/Vk/Device.h"
#include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/Integration.h"
#include "Magnum/Vk/Result.h"
namespace Magnum { namespace Vk {
ImageCreateInfo::ImageCreateInfo(const VkImageType type, const ImageUsages usages, const VkFormat format, const Vector3i& size, const Int layers, const Int levels, const Int samples, const Flags flags): _info{} {
_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
_info.flags = VkImageCreateFlags(flags);
_info.imageType = type;
_info.format = format;
_info.extent = VkExtent3D(size);
_info.mipLevels = levels;
_info.arrayLayers = layers;
_info.samples = VkSampleCountFlagBits(samples);
_info.tiling = VK_IMAGE_TILING_OPTIMAL;
_info.usage = VkImageUsageFlags(usages);
/* _info.sharingMode is implicitly VK_SHARING_MODE_EXCLUSIVE;
_info.queueFamilyIndexCount and _info.pQueueFamilyIndices should be
filled only for VK_SHARING_MODE_CONCURRENT */
/* _info.initialLayout is implicitly VK_IMAGE_LAYOUT_UNDEFINED. The only
other possible value is VK_IMAGE_LAYOUT_PREDEFINED, which however also
needs VK_IMAGE_TILING_LINEAR, one sample and possibly other restrictions
-- https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkImageCreateInfo.html#_description
Such images need to be allocated from host-visible memory which on
discrete GPUs is not fast for device access and thus is recommended to
go through a staging buffer (not image) instead. This is however still
useful for iGPUs, as the the memory is shared and this avoid an
expensive extra copy. */
}
ImageCreateInfo::ImageCreateInfo(NoInitT) noexcept {}
ImageCreateInfo::ImageCreateInfo(const VkImageCreateInfo& info):
/* Can't use {} with GCC 4.8 here because it tries to initialize the first
member instead of doing a copy */
_info(info) {}
Image Image::wrap(Device& device, const VkImage handle, const HandleFlags flags) {
Image out{NoCreate};
out._device = &device;
out._handle = handle;
out._flags = flags;
return out;
}
Image::Image(Device& device, const ImageCreateInfo& info, NoAllocateT): _device{&device}, _flags{HandleFlag::DestroyOnDestruction} {
MAGNUM_VK_INTERNAL_ASSERT_RESULT(device->CreateImage(device, info, nullptr, &_handle));
}
Image::Image(NoCreateT): _device{}, _handle{} {}
Image::Image(Image&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags} {
other._handle = {};
}
Image::~Image() {
if(_handle && (_flags & HandleFlag::DestroyOnDestruction))
(**_device).DestroyImage(*_device, _handle, nullptr);
}
Image& Image::operator=(Image&& other) noexcept {
using std::swap;
swap(other._device, _device);
swap(other._handle, _handle);
swap(other._flags, _flags);
return *this;
}
VkImage Image::release() {
const VkImage handle = _handle;
_handle = {};
return handle;
}
}}

418
src/Magnum/Vk/Image.h

@ -0,0 +1,418 @@
#ifndef Magnum_Vk_Image_h
#define Magnum_Vk_Image_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 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.
*/
/** @file
* @brief Class @ref Magnum::Vk::ImageCreateInfo, @ref Magnum::Vk::ImageCreateInfo1D, @ref Magnum::Vk::ImageCreateInfo2D, @ref Magnum::Vk::ImageCreateInfo3D, @ref Magnum::Vk::ImageCreateInfo1DArray, @ref Magnum::Vk::ImageCreateInfo2DArray, @ref Magnum::Vk::ImageCreateInfoCubeMap, @ref Magnum::Vk::ImageCreateInfoCubeMapArray, @ref Magnum::Vk::Image, enum @ref Magnum::Vk::ImageUsage, enum set @ref Magnum::Vk::ImageUsages
* @m_since_latest
*/
#include <Corrade/Containers/EnumSet.h>
#include "Magnum/DimensionTraits.h"
#include "Magnum/Magnum.h"
#include "Magnum/Math/Vector3.h"
#include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h"
#include "Magnum/Vk/visibility.h"
namespace Magnum { namespace Vk {
/**
@brief Image usage
@m_since_latest
Wraps a @type_vk_keyword{ImageUsageFlagBits}.
@see @ref ImageUsages, @ref ImageCreateInfo
@m_enum_values_as_keywords
*/
enum class ImageUsage: UnsignedInt {
/** Source of a transfer command */
TransferSource = VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/** Destination of a transfer command */
TransferDestination = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
/** Sampled by a shader */
Sampled = VK_IMAGE_USAGE_SAMPLED_BIT,
/** Shader storage */
Storage = VK_IMAGE_USAGE_STORAGE_BIT,
/** Color attachment */
ColorAttachment = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
/** Depth/stencil attachment */
DepthStencilAttachment = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
/** Transient attachment */
TransientAttachment = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/** Input attachment in a shader or framebuffer */
InputAttachment = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
};
/**
@brief Image usages
@m_since_latest
Type-safe wrapper for @type_vk_keyword{ImageUsageFlags}.
@see @ref ImageCreateInfo
*/
typedef Containers::EnumSet<ImageUsage> ImageUsages;
CORRADE_ENUMSET_OPERATORS(ImageUsages)
/**
@brief Image creation info
@m_since_latest
Wraps a @type_vk_keyword{ImageCreateInfo}. See @ref Image for usage
information.
@see @ref ImageCreateInfo1D, @ref ImageCreateInfo2D, @ref ImageCreateInfo3D,
@ref ImageCreateInfo1DArray, @ref ImageCreateInfo2DArray,
@ref ImageCreateInfoCubeMap, @ref ImageCreateInfoCubeMapArray
*/
class MAGNUM_VK_EXPORT ImageCreateInfo {
public:
/**
* @brief Image creation flag
*
* Wraps @type_vk_keyword{ImageCreateFlagBits}.
* @see @ref Flags, @ref ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, Flags)
* @m_enum_values_as_keywords
*/
enum class Flag: UnsignedInt {
/** @todo sparse binding/residency/aliased */
/** Allow creating a view of different format */
MutableFormat = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
/** Allow creating a cube map view */
CubeCompatible = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
/** @todo alias, 2D array compatible ... (Vulkan 1.1+) */
};
/**
* @brief Image creation flags
*
* Type-safe wrapper for @type_vk_keyword{ImageCreateFlags}.
* @see @ref ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, Flags),
* @ref ImageCreateInfo1D, @ref ImageCreateInfo2D,
* @ref ImageCreateInfo3D, @ref ImageCreateInfo1DArray,
* @ref ImageCreateInfo2DArray, @ref ImageCreateInfoCubeMap,
* @ref ImageCreateInfoCubeMapArray
*/
typedef Containers::EnumSet<Flag> Flags;
/**
* @brief Constructor
* @param type Image type
* @param usages Desired image usage. At least one flag is required.
* @param format Image format
* @param size Image size
* @param layers Array layer count
* @param levels Mip level count
* @param samples Sample count
* @param flags Image creation flags
*
* The following @type_vk{ImageCreateInfo} fields are pre-filled in
* addition to `sType`, everything else is zero-filled:
*
* - `flags`
* - `imageType` to @p type
* - `format`
* - `extent` to @p size
* - `mipLevels` to @p levels
* - `arrayLayers` to @p layers
* - `samples`
* - `tiling` to @val_vk{IMAGE_TILING_OPTIMAL,ImageTiling}
* - `usage` to @p usages
* - `sharingMode` to @val_vk{SHARING_MODE_EXCLUSIVE,SharingMode}
* - `initialLayout` to @val_vk{IMAGE_LAYOUT_UNDEFINED,ImageLayout}
*
* There are various restrictions on @p size, @p layers, @p levels for
* a particular @p type --- for common image types you're encouraged to
* make use of @ref ImageCreateInfo1D, @ref ImageCreateInfo2D,
* @ref ImageCreateInfo3D, @ref ImageCreateInfo1DArray,
* @ref ImageCreateInfo2DArray, @ref ImageCreateInfoCubeMap and
* @ref ImageCreateInfoCubeMapArray convenience classes instead of
* this constructor.
*/
explicit ImageCreateInfo(VkImageType type, ImageUsages usages, VkFormat format, const Vector3i& size, Int layers, Int levels, Int samples = 1, Flags flags = {});
/**
* @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 ImageCreateInfo(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 ImageCreateInfo(const VkImageCreateInfo& info);
/** @brief Underlying @type_vk{ImageCreateInfo} structure */
VkImageCreateInfo& operator*() { return _info; }
/** @overload */
const VkImageCreateInfo& operator*() const { return _info; }
/** @overload */
VkImageCreateInfo* operator->() { return &_info; }
/** @overload */
const VkImageCreateInfo* operator->() const { return &_info; }
/** @overload */
operator const VkImageCreateInfo*() const { return &_info; }
private:
VkImageCreateInfo _info;
};
CORRADE_ENUMSET_OPERATORS(ImageCreateInfo::Flags)
/**
@brief Convenience constructor for 1D images
@m_since_latest
Compared to the base @ref ImageCreateInfo constructor creates an image of type
@val_vk{IMAGE_TYPE_1D,ImageType} with the last two `size` components and
`layers` set to @cpp 1 @ce.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, Flags)
constructor, at least one @ref ImageUsage value is required.
*/
class ImageCreateInfo1D: public ImageCreateInfo {
public:
/** @brief Constructor */
explicit ImageCreateInfo1D(ImageUsages usages, VkFormat format, Int size, Int levels, Int samples = 1, Flags flags = {}): ImageCreateInfo{VK_IMAGE_TYPE_1D, usages, format, {size, 1, 1}, 1, levels, samples, flags} {}
};
/**
@brief Convenience constructor for 2D images
@m_since_latest
Compared to the base @ref ImageCreateInfo constructor creates an image of type
@val_vk{IMAGE_TYPE_2D,ImageType} with the last `size` component and `layers`
set to @cpp 1 @ce.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, Flags)
constructor, at least one @ref ImageUsage value is required.
*/
class ImageCreateInfo2D: public ImageCreateInfo {
public:
/** @brief Constructor */
explicit ImageCreateInfo2D(ImageUsages usages, VkFormat format, const Vector2i& size, Int levels, Int samples = 1, Flags flags = {}): ImageCreateInfo{VK_IMAGE_TYPE_2D, usages, format, {size, 1}, 1, levels, samples, flags} {}
};
/**
@brief Convenience constructor for 3D images
@m_since_latest
Compared to the base @ref ImageCreateInfo constructor creates an image of type
@val_vk{IMAGE_TYPE_3D,ImageType} with `layers` set to @cpp 1 @ce.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, Flags)
constructor, at least one @ref ImageUsage value is required.
*/
class ImageCreateInfo3D: public ImageCreateInfo {
public:
/** @brief Constructor */
explicit ImageCreateInfo3D(ImageUsages usages, VkFormat format, const Vector3i& size, Int levels, Int samples = 1, Flags flags = {}): ImageCreateInfo{VK_IMAGE_TYPE_3D, usages, format, size, 1, levels, samples, flags} {}
};
/**
@brief Convenience constructor for 1D array images
@m_since_latest
Compared to the base @ref ImageCreateInfo constructor creates an image of type
@val_vk{IMAGE_TYPE_1D,ImageType} with the last two `size` components set to
@cpp 1 @ce and `layers` set to @cpp size.y() @ce.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, Flags)
constructor, at least one @ref ImageUsage value is required.
*/
class ImageCreateInfo1DArray: public ImageCreateInfo {
public:
/** @brief Constructor */
explicit ImageCreateInfo1DArray(ImageUsages usages, VkFormat format, const Vector2i& size, Int levels, Int samples = 1, Flags flags = {}): ImageCreateInfo{VK_IMAGE_TYPE_1D, usages, format, {size.x(), 1, 1}, size.y(), levels, samples, flags} {}
};
/**
@brief Convenience constructor for 2D array images
@m_since_latest
Compared to the base @ref ImageCreateInfo constructor creates an image of type
@val_vk{IMAGE_TYPE_2D,ImageType} with the last `size` component set to
@cpp 1 @ce and `layers` set to @cpp size.z() @ce.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, Flags)
constructor, at least one @ref ImageUsage value is required.
*/
class ImageCreateInfo2DArray: public ImageCreateInfo {
public:
/** @brief Constructor */
explicit ImageCreateInfo2DArray(ImageUsages usages, VkFormat format, const Vector3i& size, Int levels, Int samples = 1, Flags flags = {}): ImageCreateInfo{VK_IMAGE_TYPE_2D, usages, format, {size.xy(), 1}, size.z(), levels, samples, flags} {}
};
/**
@brief Convenience constructor for cube map images
@m_since_latest
Compared to the base @ref ImageCreateInfo constructor creates an image of type
@val_vk{IMAGE_TYPE_2D,ImageType} with the last `size` component set to
@cpp 1 @ce, `layers` set to @cpp 6 @ce and `flags` additionally having
@ref Flag::CubeCompatible.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, Flags)
constructor, at least one @ref ImageUsage value is required.
*/
class ImageCreateInfoCubeMap: public ImageCreateInfo {
public:
/** @brief Constructor */
explicit ImageCreateInfoCubeMap(ImageUsages usages, VkFormat format, const Vector2i& size, Int levels, Int samples = 1, Flags flags = {}): ImageCreateInfo{VK_IMAGE_TYPE_2D, usages, format, {size, 1}, 6, levels, samples, flags|Flag::CubeCompatible} {}
};
/**
@brief Convenience constructor for cube map array images
@m_since_latest
Compared to the base @ref ImageCreateInfo constructor creates an image of type
@val_vk{IMAGE_TYPE_2D,ImageType} with the last `size` component set to
@cpp 1 @ce, `layers` set to @cpp size.y() @ce and `flags` additionally having
@ref Flag::CubeCompatible.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, Flags)
constructor, at least one @ref ImageUsage value is required.
*/
class ImageCreateInfoCubeMapArray: public ImageCreateInfo {
public:
/** @brief Constructor */
explicit ImageCreateInfoCubeMapArray(ImageUsages usages, VkFormat format, const Vector3i& size, Int levels, Int samples = 1, Flags flags = {}): ImageCreateInfo{VK_IMAGE_TYPE_2D, usages, format, {size.xy(), 1}, size.z(), levels, samples, flags|Flag::CubeCompatible} {}
};
/**
@brief Image
@m_since_latest
Wraps a @type_vk_keyword{Image}.
*/
class MAGNUM_VK_EXPORT Image {
public:
/**
* @brief Wrap existing Vulkan handle
* @param device Vulkan device the image is created on
* @param handle The @type_vk{Image} handle
* @param flags Handle flags
*
* The @p handle is expected to be originating from @p device. Unlike
* an image created using a constructor, the Vulkan image is by default
* not deleted on destruction, use @p flags for different behavior.
* @see @ref release()
*/
static Image wrap(Device& device, VkImage handle, HandleFlags flags = {});
/**
* @brief Construct an image without allocating
* @param device Vulkan device to create the image on
* @param info Image creation info
*
* @see @fn_vk_keyword{CreateImage}
*/
explicit Image(Device& device, const ImageCreateInfo& info, NoAllocateT);
/**
* @brief Construct without creating the image
*
* The constructed instance is equivalent to moved-from state. Useful
* in cases where you will overwrite the instance later anyway. Move
* another object over it to make it useful.
*/
explicit Image(NoCreateT);
/** @brief Copying is not allowed */
Image(const Image&) = delete;
/** @brief Move constructor */
Image(Image&& other) noexcept;
/**
* @brief Destructor
*
* Destroys associated @type_vk{Image} handle, unless the instance
* was created using @ref wrap() without @ref HandleFlag::DestroyOnDestruction
* specified.
* @see @fn_vk_keyword{DestroyImage}, @ref release()
*/
~Image();
/** @brief Copying is not allowed */
Image& operator=(const Image&) = delete;
/** @brief Move assignment */
Image& operator=(Image&& other) noexcept;
/** @brief Underlying @type_vk{Image} handle */
VkImage handle() { return _handle; }
/** @overload */
operator VkImage() { return _handle; }
/** @brief Handle flags */
HandleFlags handleFlags() const { return _flags; }
/**
* @brief Release the underlying Vulkan image
*
* Releases ownership of the Vulkan image and returns its handle so
* @fn_vk{DestroyImage} is not called on destruction. The internal
* state is then equivalent to moved-from state.
* @see @ref wrap()
*/
VkImage release();
private:
/* Can't be a reference because of the NoCreate constructor */
Device* _device;
VkImage _handle;
HandleFlags _flags;
};
}}
#endif

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

@ -32,6 +32,7 @@ corrade_add_test(VkEnumsTest EnumsTest.cpp LIBRARIES MagnumVkTestLib)
corrade_add_test(VkExtensionsTest ExtensionsTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkExtensionPropertiesTest ExtensionPropertiesTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkHandleTest HandleTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkImageTest ImageTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkInstanceTest InstanceTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkIntegrationTest IntegrationTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkLayerPropertiesTest LayerPropertiesTest.cpp LIBRARIES MagnumVk)
@ -46,6 +47,7 @@ if(BUILD_VK_TESTS)
corrade_add_test(VkDevicePropertiesVkTest DevicePropertiesVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester)
corrade_add_test(VkExtensionPropertiesVkTest ExtensionPropertiesVkTest.cpp LIBRARIES MagnumVkTestLib)
corrade_add_test(VkLayerPropertiesVkTest LayerPropertiesVkTest.cpp LIBRARIES MagnumVkTestLib)
corrade_add_test(VkImageVkTest ImageVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkInstanceVkTest InstanceVkTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkVersionVkTest VersionVkTest.cpp LIBRARIES MagnumVk)
endif()

204
src/Magnum/Vk/Test/ImageTest.cpp

@ -0,0 +1,204 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 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/Integration.h"
namespace Magnum { namespace Vk { namespace Test { namespace {
struct ImageTest: TestSuite::Tester {
explicit ImageTest();
void createInfoConstruct();
void createInfoConstruct1D();
void createInfoConstruct2D();
void createInfoConstruct3D();
void createInfoConstruct1DArray();
void createInfoConstruct2DArray();
void createInfoConstructCubeMap();
void createInfoConstructCubeMapArray();
void createInfoConstructNoInit();
void createInfoConstructFromVk();
void constructNoCreate();
void constructCopy();
};
ImageTest::ImageTest() {
addTests({&ImageTest::createInfoConstruct,
&ImageTest::createInfoConstruct1D,
&ImageTest::createInfoConstruct2D,
&ImageTest::createInfoConstruct3D,
&ImageTest::createInfoConstruct1DArray,
&ImageTest::createInfoConstruct2DArray,
&ImageTest::createInfoConstructCubeMap,
&ImageTest::createInfoConstructCubeMapArray,
&ImageTest::createInfoConstructNoInit,
&ImageTest::createInfoConstructFromVk,
&ImageTest::constructNoCreate,
&ImageTest::constructCopy});
}
void ImageTest::createInfoConstruct() {
ImageCreateInfo info{VK_IMAGE_TYPE_2D, ImageUsage::Sampled, VK_FORMAT_R8G8B8A8_UNORM, {256, 128, 1}, 6, 8, 16, ImageCreateInfo::Flag::CubeCompatible};
CORRADE_COMPARE(info->flags, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
CORRADE_COMPARE(info->imageType, VK_IMAGE_TYPE_2D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_UNORM);
CORRADE_COMPARE(Vector3i(info->extent), (Vector3i{256, 128, 1}));
CORRADE_COMPARE(info->mipLevels, 8);
CORRADE_COMPARE(info->arrayLayers, 6);
CORRADE_COMPARE(info->samples, VK_SAMPLE_COUNT_16_BIT);
CORRADE_COMPARE(info->usage, VK_IMAGE_USAGE_SAMPLED_BIT);
CORRADE_COMPARE(info->tiling, VK_IMAGE_TILING_OPTIMAL);
CORRADE_COMPARE(info->sharingMode, VK_SHARING_MODE_EXCLUSIVE);
CORRADE_COMPARE(info->initialLayout, VK_IMAGE_LAYOUT_UNDEFINED);
}
void ImageTest::createInfoConstruct1D() {
ImageCreateInfo1D info{ImageUsage::Storage, VK_FORMAT_R8G8B8A8_UNORM, 256, 8, 16, ImageCreateInfo::Flag::MutableFormat};
CORRADE_COMPARE(info->flags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
CORRADE_COMPARE(info->imageType, VK_IMAGE_TYPE_1D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_UNORM);
CORRADE_COMPARE(Vector3i(info->extent), (Vector3i{256, 1, 1}));
CORRADE_COMPARE(info->mipLevels, 8);
CORRADE_COMPARE(info->arrayLayers, 1);
CORRADE_COMPARE(info->samples, VK_SAMPLE_COUNT_16_BIT);
CORRADE_COMPARE(info->usage, VK_IMAGE_USAGE_STORAGE_BIT);
}
void ImageTest::createInfoConstruct2D() {
ImageCreateInfo2D info{ImageUsage::TransferDestination, VK_FORMAT_R8G8B8A8_UNORM, {256, 64}, 8, 16, ImageCreateInfo::Flag::MutableFormat};
CORRADE_COMPARE(info->flags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
CORRADE_COMPARE(info->imageType, VK_IMAGE_TYPE_2D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_UNORM);
CORRADE_COMPARE(Vector3i(info->extent), (Vector3i{256, 64, 1}));
CORRADE_COMPARE(info->mipLevels, 8);
CORRADE_COMPARE(info->arrayLayers, 1);
CORRADE_COMPARE(info->samples, VK_SAMPLE_COUNT_16_BIT);
CORRADE_COMPARE(info->usage, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
}
void ImageTest::createInfoConstruct3D() {
ImageCreateInfo3D info{ImageUsage::InputAttachment, VK_FORMAT_R8G8B8A8_UNORM, {256, 64, 32}, 8, 16, ImageCreateInfo::Flag::MutableFormat};
CORRADE_COMPARE(info->flags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
CORRADE_COMPARE(info->imageType, VK_IMAGE_TYPE_3D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_UNORM);
CORRADE_COMPARE(Vector3i(info->extent), (Vector3i{256, 64, 32}));
CORRADE_COMPARE(info->mipLevels, 8);
CORRADE_COMPARE(info->arrayLayers, 1);
CORRADE_COMPARE(info->samples, VK_SAMPLE_COUNT_16_BIT);
CORRADE_COMPARE(info->usage, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
}
void ImageTest::createInfoConstruct1DArray() {
ImageCreateInfo1DArray info{ImageUsage::TransferDestination, VK_FORMAT_R8G8B8A8_UNORM, {256, 64}, 8, 16, ImageCreateInfo::Flag::MutableFormat};
CORRADE_COMPARE(info->flags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
CORRADE_COMPARE(info->imageType, VK_IMAGE_TYPE_1D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_UNORM);
CORRADE_COMPARE(Vector3i(info->extent), (Vector3i{256, 1, 1}));
CORRADE_COMPARE(info->mipLevels, 8);
CORRADE_COMPARE(info->arrayLayers, 64);
CORRADE_COMPARE(info->samples, VK_SAMPLE_COUNT_16_BIT);
CORRADE_COMPARE(info->usage, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
}
void ImageTest::createInfoConstruct2DArray() {
ImageCreateInfo2DArray info{ImageUsage::TransferDestination, VK_FORMAT_R8G8B8A8_UNORM, {256, 64, 32}, 8, 16, ImageCreateInfo::Flag::MutableFormat};
CORRADE_COMPARE(info->flags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
CORRADE_COMPARE(info->imageType, VK_IMAGE_TYPE_2D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_UNORM);
CORRADE_COMPARE(Vector3i(info->extent), (Vector3i{256, 64, 1}));
CORRADE_COMPARE(info->mipLevels, 8);
CORRADE_COMPARE(info->arrayLayers, 32);
CORRADE_COMPARE(info->samples, VK_SAMPLE_COUNT_16_BIT);
CORRADE_COMPARE(info->usage, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
}
void ImageTest::createInfoConstructCubeMap() {
ImageCreateInfoCubeMap info{ImageUsage::TransferDestination, VK_FORMAT_R8G8B8A8_UNORM, {256, 256}, 8, 16, ImageCreateInfo::Flag::MutableFormat};
CORRADE_COMPARE(info->flags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT|VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
CORRADE_COMPARE(info->imageType, VK_IMAGE_TYPE_2D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_UNORM);
CORRADE_COMPARE(Vector3i(info->extent), (Vector3i{256, 256, 1}));
CORRADE_COMPARE(info->mipLevels, 8);
CORRADE_COMPARE(info->arrayLayers, 6);
CORRADE_COMPARE(info->samples, VK_SAMPLE_COUNT_16_BIT);
CORRADE_COMPARE(info->usage, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
}
void ImageTest::createInfoConstructCubeMapArray() {
ImageCreateInfoCubeMapArray info{ImageUsage::TransferDestination, VK_FORMAT_R8G8B8A8_UNORM, {256, 256, 36}, 8, 16, ImageCreateInfo::Flag::MutableFormat};
CORRADE_COMPARE(info->flags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT|VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
CORRADE_COMPARE(info->imageType, VK_IMAGE_TYPE_2D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_UNORM);
CORRADE_COMPARE(Vector3i(info->extent), (Vector3i{256, 256, 1}));
CORRADE_COMPARE(info->mipLevels, 8);
CORRADE_COMPARE(info->arrayLayers, 36);
CORRADE_COMPARE(info->samples, VK_SAMPLE_COUNT_16_BIT);
CORRADE_COMPARE(info->usage, VK_IMAGE_USAGE_TRANSFER_DST_BIT);
}
void ImageTest::createInfoConstructNoInit() {
ImageCreateInfo info{NoInit};
info->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
new(&info) ImageCreateInfo{NoInit};
CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
CORRADE_VERIFY((std::is_nothrow_constructible<ImageCreateInfo, NoInitT>::value));
/* Implicit construction is not allowed */
CORRADE_VERIFY(!(std::is_convertible<NoInitT, ImageCreateInfo>::value));
}
void ImageTest::createInfoConstructFromVk() {
VkImageCreateInfo vkInfo;
vkInfo.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
ImageCreateInfo info{vkInfo};
CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
}
void ImageTest::constructNoCreate() {
{
Image image{NoCreate};
CORRADE_VERIFY(!image.handle());
}
/* Implicit construction is not allowed */
CORRADE_VERIFY(!(std::is_convertible<NoCreateT, Image>::value));
}
void ImageTest::constructCopy() {
CORRADE_VERIFY(!(std::is_constructible<Image, const Image&>{}));
CORRADE_VERIFY(!(std::is_assignable<Image, const Image&>{}));
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::ImageTest)

185
src/Magnum/Vk/Test/ImageVkTest.cpp

@ -0,0 +1,185 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 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/Image.h"
#include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/Result.h"
#include "Magnum/Vk/VulkanTester.h"
namespace Magnum { namespace Vk { namespace Test { namespace {
struct ImageVkTest: VulkanTester {
explicit ImageVkTest();
void construct1D();
void construct2D();
void construct3D();
void construct1DArray();
void construct2DArray();
void constructCubeMap();
void constructCubeMapArray();
void constructMove();
void wrap();
};
ImageVkTest::ImageVkTest() {
addTests({&ImageVkTest::construct1D,
&ImageVkTest::construct2D,
&ImageVkTest::construct3D,
&ImageVkTest::construct1DArray,
&ImageVkTest::construct2DArray,
&ImageVkTest::constructCubeMap,
&ImageVkTest::constructCubeMapArray,
&ImageVkTest::constructMove,
&ImageVkTest::wrap});
}
void ImageVkTest::construct1D() {
{
Image image{device(), ImageCreateInfo1D{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, 256, 8}, NoAllocate};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageVkTest::construct2D() {
{
Image image{device(), ImageCreateInfo2D{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256}, 8}, NoAllocate};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageVkTest::construct3D() {
{
Image image{device(), ImageCreateInfo3D{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256, 64}, 8}, NoAllocate};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageVkTest::construct1DArray() {
{
Image image{device(), ImageCreateInfo1DArray{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 64}, 8}, NoAllocate};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageVkTest::construct2DArray() {
{
Image image{device(), ImageCreateInfo2DArray{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256, 64}, 8}, NoAllocate};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageVkTest::constructCubeMap() {
{
Image image{device(), ImageCreateInfoCubeMap{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256}, 8}, NoAllocate};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageVkTest::constructCubeMapArray() {
{
Image image{device(), ImageCreateInfoCubeMapArray{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256, 36}, 8}, NoAllocate};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageVkTest::constructMove() {
Image a{device(), ImageCreateInfo2D{ImageUsage::ColorAttachment,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256}, 1}, NoAllocate};
VkImage handle = a.handle();
Image b = std::move(a);
CORRADE_VERIFY(!a.handle());
CORRADE_COMPARE(b.handle(), handle);
CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction);
Image c{NoCreate};
c = std::move(b);
CORRADE_VERIFY(!b.handle());
CORRADE_COMPARE(b.handleFlags(), HandleFlags{});
CORRADE_COMPARE(c.handle(), handle);
CORRADE_COMPARE(c.handleFlags(), HandleFlag::DestroyOnDestruction);
CORRADE_VERIFY(std::is_nothrow_move_constructible<Image>::value);
CORRADE_VERIFY(std::is_nothrow_move_assignable<Image>::value);
}
void ImageVkTest::wrap() {
VkImage image{};
CORRADE_COMPARE(Result(device()->CreateImage(device(),
ImageCreateInfo2D{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256}, 8},
nullptr, &image)), Result::Success);
CORRADE_VERIFY(image);
auto wrapped = Image::wrap(device(), image, HandleFlag::DestroyOnDestruction);
CORRADE_COMPARE(wrapped.handle(), image);
/* Release the handle again, destroy by hand */
CORRADE_COMPARE(wrapped.release(), image);
CORRADE_VERIFY(!wrapped.handle());
device()->DestroyImage(device(), image, nullptr);
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::ImageVkTest)

1
src/Magnum/Vk/Vk.h

@ -46,6 +46,7 @@ class Extension;
class ExtensionProperties;
enum class HandleFlag: UnsignedByte;
typedef Containers::EnumSet<HandleFlag> HandleFlags;
class Image;
class Instance;
class InstanceCreateInfo;
class InstanceExtension;

Loading…
Cancel
Save