Browse Source

Vk: image view wrapper.

This was done quite a long time ago but then I got stuck on device
features for cubemaps. Sigh.
pull/491/head
Vladimír Vondruš 5 years ago
parent
commit
4a93c092b0
  1. 18
      doc/snippets/MagnumVk.cpp
  2. 6
      doc/vulkan-mapping.dox
  3. 3
      src/Magnum/Vk/CMakeLists.txt
  4. 10
      src/Magnum/Vk/Image.cpp
  5. 39
      src/Magnum/Vk/Image.h
  6. 32
      src/Magnum/Vk/ImageCreateInfo.h
  7. 119
      src/Magnum/Vk/ImageView.cpp
  8. 148
      src/Magnum/Vk/ImageView.h
  9. 336
      src/Magnum/Vk/ImageViewCreateInfo.h
  10. 4
      src/Magnum/Vk/Test/CMakeLists.txt
  11. 408
      src/Magnum/Vk/Test/ImageViewTest.cpp
  12. 213
      src/Magnum/Vk/Test/ImageViewVkTest.cpp
  13. 2
      src/Magnum/Vk/Test/ImageVkTest.cpp
  14. 3
      src/Magnum/Vk/Vk.h

18
doc/snippets/MagnumVk.cpp

@ -41,6 +41,7 @@
#include "Magnum/Vk/InstanceCreateInfo.h"
#include "Magnum/Vk/Integration.h"
#include "Magnum/Vk/ImageCreateInfo.h"
#include "Magnum/Vk/ImageViewCreateInfo.h"
#include "Magnum/Vk/LayerProperties.h"
#include "Magnum/Vk/MemoryAllocateInfo.h"
#include "Magnum/Vk/Queue.h"
@ -324,6 +325,23 @@ image.bindMemory(memory, 0);
/* [Image-creation-custom-allocation] */
}
{
Vk::Device device{NoCreate};
/* The include should be a no-op here since it was already included above */
/* [ImageView-creation] */
#include <Magnum/Vk/ImageViewCreateInfo.h>
DOXYGEN_IGNORE()
Vk::Image image{device, Vk::ImageCreateInfo2DArray{ /* created before */
DOXYGEN_IGNORE(Vk::ImageUsage::Sampled, {}, {}, 1)
}, DOXYGEN_IGNORE(Vk::MemoryFlag::DeviceLocal)
};
Vk::ImageView view{device, Vk::ImageViewCreateInfo2DArray{image}};
/* [ImageView-creation] */
}
{
int argc{};
const char** argv{};

6
doc/vulkan-mapping.dox

@ -152,7 +152,7 @@ Vulkan function | Matching API
@fn_vk{CreateFence}, \n @fn_vk{DestroyFence} | |
@fn_vk{CreateFramebuffer}, \n @fn_vk{DestroyFramebuffer} | |
@fn_vk{CreateImage}, \n @fn_vk{DestroyImage} | @ref Image constructor and destructor
@fn_vk{CreateImageView}, \n @fn_vk{DestroyImageView} | |
@fn_vk{CreateImageView}, \n @fn_vk{DestroyImageView} | @ref ImageView constructor and destructor
@fn_vk{CreateInstance}, \n @fn_vk{DestroyInstance} | @ref Instance constructor and destructor
@fn_vk{CreatePipeline}, \n @fn_vk{DestroyPipeline} | |
@fn_vk{CreatePipelineCache}, \n @fn_vk{DestroyPipelineCache} | |
@ -492,14 +492,14 @@ Vulkan structure | Matching API
@type_vk{ImageCreateInfo} | @ref ImageCreateInfo
@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} | |
@type_vk{ImageSubresourceRange} | not exposed, internal to @ref ImageViewCreateInfo
@type_vk{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} | |
@type_vk{ImageSparseMemoryRequirementsInfo2} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{ImageStencilUsageCreateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | |
@type_vk{ImageViewCreateInfo} | |
@type_vk{ImageViewCreateInfo} | @ref ImageViewCreateInfo
@type_vk{ImageViewUsageCreateInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@type_vk{InputAttachmentAspectReference} | |
@type_vk{InstanceCreateInfo} | @ref InstanceCreateInfo

3
src/Magnum/Vk/CMakeLists.txt

@ -48,6 +48,7 @@ set(MagnumVk_GracefulAssert_SRCS
Enums.cpp
ExtensionProperties.cpp
Image.cpp
ImageView.cpp
LayerProperties.cpp
Memory.cpp
RenderPass.cpp)
@ -69,6 +70,8 @@ set(MagnumVk_HEADERS
Handle.h
Image.h
ImageCreateInfo.h
ImageView.h
ImageViewCreateInfo.h
Instance.h
InstanceCreateInfo.h
Integration.h

10
src/Magnum/Vk/Image.cpp

@ -60,15 +60,16 @@ ImageCreateInfo::ImageCreateInfo(const VkImageCreateInfo& info):
member instead of doing a copy */
_info(info) {}
Image Image::wrap(Device& device, const VkImage handle, const HandleFlags flags) {
Image Image::wrap(Device& device, const VkImage handle, const VkFormat format, const HandleFlags flags) {
Image out{NoCreate};
out._device = &device;
out._handle = handle;
out._flags = flags;
out._format = format;
return out;
}
Image::Image(Device& device, const ImageCreateInfo& info, NoAllocateT): _device{&device}, _flags{HandleFlag::DestroyOnDestruction}, _dedicatedMemory{NoCreate} {
Image::Image(Device& device, const ImageCreateInfo& info, NoAllocateT): _device{&device}, _flags{HandleFlag::DestroyOnDestruction}, _format{info->format}, _dedicatedMemory{NoCreate} {
MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateImage(device, info, nullptr, &_handle));
}
@ -80,9 +81,9 @@ Image::Image(Device& device, const ImageCreateInfo& info, const MemoryFlags memo
}});
}
Image::Image(NoCreateT): _device{}, _handle{}, _dedicatedMemory{NoCreate} {}
Image::Image(NoCreateT): _device{}, _handle{}, _format{}, _dedicatedMemory{NoCreate} {}
Image::Image(Image&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags}, _dedicatedMemory{std::move(other._dedicatedMemory)} {
Image::Image(Image&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags}, _format{other._format}, _dedicatedMemory{std::move(other._dedicatedMemory)} {
other._handle = {};
}
@ -96,6 +97,7 @@ Image& Image::operator=(Image&& other) noexcept {
swap(other._device, _device);
swap(other._handle, _handle);
swap(other._flags, _flags);
swap(other._format, _format);
swap(other._dedicatedMemory, _dedicatedMemory);
return *this;
}

39
src/Magnum/Vk/Image.h

@ -166,6 +166,8 @@ constructor together with specifying @ref MemoryFlags for memory allocation.
accessible through @ref dedicatedMemory(). This behavior may change in the
future.
With an @ref Image ready, you may want to proceed to @ref ImageView creation.
@subsection Vk-Image-creation-custom-allocation Custom memory allocation
Using @ref Image(Device&, const ImageCreateInfo&, NoAllocateT), the image will
@ -188,16 +190,23 @@ 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
* @param device Vulkan device the image is created on
* @param handle The @type_vk{Image} handle
* @param format Image format
* @param flags Handle flags
*
* The @p handle is expected to be originating from @p device. The
* @p format parameter is used for convenience @ref ImageView creation.
* If it's unknown, use @val_vk{FORMAT_UNDEFINED,Format} --- you will
* then be able to only create image views by passing a concrete format
* to @ref ImageViewCreateInfo.
*
* 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.
* 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 = {});
static Image wrap(Device& device, VkImage handle, VkFormat format, HandleFlags flags = {});
/**
* @brief Construct an image without allocating
@ -265,6 +274,9 @@ class MAGNUM_VK_EXPORT Image {
/** @brief Handle flags */
HandleFlags handleFlags() const { return _flags; }
/** @brief Image format */
VkFormat format() const { return _format; }
/**
* @brief Image memory requirements
*
@ -336,6 +348,19 @@ class MAGNUM_VK_EXPORT Image {
VkImage _handle;
HandleFlags _flags;
/* On 64-bit there would be a 7 byte padding after _flags otherwise, we
can use that to store information about image format for convenient
view creation. On 32-bit it won't fit, but the extra memory use is
still worth the advantages.
Originally I wanted to store a desired VkImageViewType here as well,
but the logic to what actually should be the view type is rather
involved and not safe to rely on (e.g., implicit view type would be
2D_ARRAY if there's more than one layer and then if you'd use just
one layer it suddenly becomes just 2D, breaking everything). */
VkFormat _format;
Memory _dedicatedMemory;
};

32
src/Magnum/Vk/ImageCreateInfo.h

@ -239,7 +239,9 @@ CORRADE_ENUMSET_OPERATORS(ImageCreateInfo::Flags)
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.
`layers` set to @cpp 1 @ce. You can use both @ref ImageViewCreateInfo1D and
@ref ImageViewCreateInfo1DArray for view creation, although the array will need
to have only one layer.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, ImageLayout, Flags)
@ -264,7 +266,9 @@ class ImageCreateInfo1D: public ImageCreateInfo {
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.
set to @cpp 1 @ce. You can use both @ref ImageViewCreateInfo2D and
@ref ImageViewCreateInfo2DArray for view creation, although the array will need
to have only one layer.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, ImageLayout, Flags)
@ -288,7 +292,8 @@ class ImageCreateInfo2D: public ImageCreateInfo {
@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.
@val_vk{IMAGE_TYPE_3D,ImageType} with `layers` set to @cpp 1 @ce. Use
@ref ImageViewCreateInfo3D for view creation.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, ImageLayout, Flags)
@ -313,7 +318,9 @@ class ImageCreateInfo3D: public ImageCreateInfo {
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.
@cpp 1 @ce and `layers` set to @cpp size.y() @ce. You can use both
@ref ImageViewCreateInfo1D and @ref ImageViewCreateInfo1DArray for view
creation.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, ImageLayout, Flags)
@ -338,7 +345,11 @@ class ImageCreateInfo1DArray: public ImageCreateInfo {
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.
@cpp 1 @ce and `layers` set to @cpp size.z() @ce. You can use both
@ref ImageViewCreateInfo2D, @ref ImageViewCreateInfo2DArray for view creation
and if you set @ref Flag::CubeCompatible a @ref ImageViewCreateInfoCubeMap as
well, although in that case it's better to use @ref ImageCreateInfoCubeMap that
does this automatically.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, ImageLayout, Flags)
@ -364,7 +375,11 @@ class ImageCreateInfo2DArray: public ImageCreateInfo {
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.
@ref Flag::CubeCompatible. You can use any of @ref ImageViewCreateInfo2D,
@ref ImageViewCreateInfo2DArray, @ref ImageViewCreateInfoCubeMap or
@ref ImageViewCreateInfoCubeMapArray for view creation, although the last one
will need to have exactly six layers, and requires
@ref DeviceFeature::ImageCubeArray to be enabled.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, ImageLayout, Flags)
@ -390,7 +405,10 @@ class ImageCreateInfoCubeMap: public ImageCreateInfo {
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.
@ref Flag::CubeCompatible. You can use any of @ref ImageViewCreateInfo2D,
@ref ImageViewCreateInfo2DArray, @ref ImageViewCreateInfoCubeMap or
@ref ImageViewCreateInfoCubeMapArray for view creation, note the last
requires @ref DeviceFeature::ImageCubeArray to be enabled.
Note that same as with the
@ref ImageCreateInfo::ImageCreateInfo(VkImageType, ImageUsages, VkFormat, const Vector3i&, Int, Int, Int, ImageLayout, Flags)

119
src/Magnum/Vk/ImageView.cpp

@ -0,0 +1,119 @@
/*
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 "ImageView.h"
#include "ImageViewCreateInfo.h"
#include "Magnum/Vk/Assert.h"
#include "Magnum/Vk/Device.h"
#include "Magnum/Vk/Image.h"
namespace Magnum { namespace Vk {
namespace {
/* Vulkan, it would kill you if 0 was a valid default, right?! ffs */
/** @todo this might be useful elsewhere as well */
VkImageAspectFlags aspectFor(const VkFormat format) {
if(format == VK_FORMAT_D16_UNORM_S8_UINT ||
format == VK_FORMAT_D24_UNORM_S8_UINT ||
format == VK_FORMAT_D32_SFLOAT_S8_UINT)
return VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT;
if(format == VK_FORMAT_D16_UNORM ||
format == VK_FORMAT_D32_SFLOAT)
return VK_IMAGE_ASPECT_DEPTH_BIT;
if(format == VK_FORMAT_S8_UINT)
return VK_IMAGE_ASPECT_STENCIL_BIT;
/** @todo planar formats */
return VK_IMAGE_ASPECT_COLOR_BIT;
}
}
ImageViewCreateInfo::ImageViewCreateInfo(const VkImageViewType type, const VkImage image, const VkFormat format, const UnsignedInt layerOffset, const UnsignedInt layerCount, const UnsignedInt levelOffset, const UnsignedInt levelCount, const Flags flags): _info{} {
_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
_info.flags = VkImageViewCreateFlags(flags);
_info.image = image;
_info.viewType = type;
_info.format = format;
_info.subresourceRange.aspectMask = aspectFor(format);
_info.subresourceRange.baseMipLevel = levelOffset;
_info.subresourceRange.levelCount = levelCount;
_info.subresourceRange.baseArrayLayer = layerOffset;
_info.subresourceRange.layerCount = layerCount;
}
ImageViewCreateInfo::ImageViewCreateInfo(const VkImageViewType type, Image& image, const UnsignedInt layerOffset, const UnsignedInt layerCount, const UnsignedInt levelOffset, const UnsignedInt levelCount, const Flags flags): ImageViewCreateInfo{type, image, image.format(), layerOffset, layerCount, levelOffset, levelCount, flags} {
CORRADE_ASSERT(image.format(),
"Vk::ImageViewCreateInfo: the image has unknown format, you have to specify it explicitly", );
}
ImageViewCreateInfo::ImageViewCreateInfo(NoInitT) noexcept {}
ImageViewCreateInfo::ImageViewCreateInfo(const VkImageViewCreateInfo& info):
/* Can't use {} with GCC 4.8 here because it tries to initialize the first
member instead of doing a copy */
_info(info) {}
ImageView ImageView::wrap(Device& device, const VkImageView handle, const HandleFlags flags) {
ImageView out{NoCreate};
out._device = &device;
out._handle = handle;
out._flags = flags;
return out;
}
ImageView::ImageView(Device& device, const ImageViewCreateInfo& info): _device{&device}, _flags{HandleFlag::DestroyOnDestruction} {
MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateImageView(device, info, nullptr, &_handle));
}
ImageView::ImageView(NoCreateT): _device{}, _handle{} {}
ImageView::ImageView(ImageView&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags} {
other._handle = {};
}
ImageView::~ImageView() {
if(_handle && (_flags & HandleFlag::DestroyOnDestruction))
(**_device).DestroyImageView(*_device, _handle, nullptr);
}
ImageView& ImageView::operator=(ImageView&& other) noexcept {
using std::swap;
swap(other._device, _device);
swap(other._handle, _handle);
swap(other._flags, _flags);
return *this;
}
VkImageView ImageView::release() {
const VkImageView handle = _handle;
_handle = {};
return handle;
}
}}

148
src/Magnum/Vk/ImageView.h

@ -0,0 +1,148 @@
#ifndef Magnum_Vk_ImageView_h
#define Magnum_Vk_ImageView_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::ImageView
* @m_since_latest
*/
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h"
#include "Magnum/Vk/visibility.h"
namespace Magnum { namespace Vk {
/**
@brief Image view
@m_since_latest
View onto an @ref Image. Wraps a @type_vk_keyword{ImageView}.
@section Vk-ImageView-creation Image view creation
Similarly to @ref Image, a view is created by passing one of the
@ref ImageViewCreateInfo subclasses with desired layer/level range to the
@ref Image constructor. Commonly you'd use the same @ref ImageViewCreateInfo
subclass as @ref ImageCreateInfo, but other combinations are possible as well
--- see docs of each subclass for more information.
@snippet MagnumVk.cpp ImageView-creation
While it would be *technically* possible to infer a view type from the
originating @ref Image and thus avoid having to specify the type twice, the
mapping isn't crystal clear in all cases and could cause hard-to-detect issues
if you suddenly get an unexpected view type. Thus the view type is required to
be always explicitly specified.
*/
class MAGNUM_VK_EXPORT ImageView {
public:
/**
* @brief Wrap existing Vulkan handle
* @param device Vulkan device the image view is created on
* @param handle The @type_vk{ImageView} handle
* @param flags Handle flags
*
* The @p handle is expected to be originating from @p device. Unlike
* an image view created using a constructor, the Vulkan image view is
* by default not deleted on destruction, use @p flags for different
* behavior.
* @see @ref release()
*/
static ImageView wrap(Device& device, VkImageView handle, HandleFlags flags = {});
/**
* @brief Constructor
* @param device Vulkan device to create the image on
* @param info Image creation info
*
* @see @fn_vk_keyword{CreateImageView}
*/
explicit ImageView(Device& device, const ImageViewCreateInfo& info);
/**
* @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 ImageView(NoCreateT);
/** @brief Copying is not allowed */
ImageView(const ImageView&) = delete;
/** @brief Move constructor */
ImageView(ImageView&& other) noexcept;
/**
* @brief Destructor
*
* Destroys associated @type_vk{ImageView} handle, unless the instance
* was created using @ref wrap() without
* @ref HandleFlag::DestroyOnDestruction specified.
* @see @fn_vk_keyword{DestroyImageView}, @ref release()
*/
~ImageView();
/** @brief Copying is not allowed */
ImageView& operator=(const ImageView&) = delete;
/** @brief Move assignment */
ImageView& operator=(ImageView&& other) noexcept;
/** @brief Underlying @type_vk{ImageView} handle */
VkImageView handle() { return _handle; }
/** @overload */
operator VkImageView() { return _handle; }
/** @brief Handle flags */
HandleFlags handleFlags() const { return _flags; }
/**
* @brief Release the underlying Vulkan image view
*
* Releases ownership of the Vulkan image view and returns its handle
* so @fn_vk{DestroyImageView} is not called on destruction. The
* internal state is then equivalent to moved-from state.
* @see @ref wrap()
*/
VkImageView release();
private:
/* Can't be a reference because of the NoCreate constructor */
Device* _device;
VkImageView _handle;
HandleFlags _flags;
};
}}
#endif

336
src/Magnum/Vk/ImageViewCreateInfo.h

@ -0,0 +1,336 @@
#ifndef Magnum_Vk_ImageViewCreateInfo_h
#define Magnum_Vk_ImageViewCreateInfo_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::ImageViewCreateInfo, @ref Magnum::Vk::ImageViewCreateInfo1D, @ref Magnum::Vk::ImageViewCreateInfo2D, @ref Magnum::Vk::ImageViewCreateInfo3D, @ref Magnum::Vk::ImageViewCreateInfo1DArray, @ref Magnum::Vk::ImageViewCreateInfo2DArray, @ref Magnum::Vk::ImageViewCreateInfoCubeMap, @ref Magnum::Vk::ImageViewCreateInfoCubeMapArray
* @m_since_latest
*/
#include <Corrade/Containers/EnumSet.h>
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h"
#include "Magnum/Vk/visibility.h"
namespace Magnum { namespace Vk {
/**
@brief Image view creation info
@m_since_latest
Wraps a @type_vk_keyword{ImageViewCreateInfo}. See
@ref Vk-ImageView-creation "Image creation" for usage information.
@see @ref ImageViewCreateInfo1D, @ref ImageViewCreateInfo2D,
@ref ImageViewCreateInfo3D, @ref ImageViewCreateInfo1DArray,
@ref ImageViewCreateInfo2DArray, @ref ImageViewCreateInfoCubeMap,
@ref ImageViewCreateInfoCubeMapArray
*/
class MAGNUM_VK_EXPORT ImageViewCreateInfo {
public:
/**
* @brief Image view creation flag
*
* Wraps @type_vk_keyword{ImageViewCreateFlagBits}.
* @see @ref Flags, @ref ImageViewCreateInfo(VkImageViewType, VkImage, VkFormat, UnsignedInt, UnsignedInt, UnsignedInt, UnsignedInt, Flags)
* @m_enum_values_as_keywords
*/
enum class Flag: UnsignedInt {
/** @todo @vk_extension{EXT,fragment_density_map}, @vk_extension{EXT,fragment_density_map2} */
};
/**
* @brief ImageView creation flags
*
* Type-safe wrapper for @type_vk_keyword{ImageViewCreateFlags}.
* @see @ref ImageViewCreateInfo(VkImageViewType, VkImage, VkFormat, UnsignedInt, UnsignedInt, UnsignedInt, UnsignedInt, Flags)
*/
typedef Containers::EnumSet<Flag> Flags;
/**
* @brief Constructor
* @param type Image view type
* @param image Image to create a view on
* @param format View format
* @param layerOffset Layer offset
* @param layerCount Layer count
* @param levelOffset Mip level offset
* @param levelCount Mip level count
* @param flags Image view creation flags
*
* The following @type_vk{ImageViewCreateInfo} are pre-filled in
* addition to `sType`, everything else is zero-filled:
*
* - `flags`
* - `image`
* - `viewType` to @p type
* - `format`
* - `subresourceRange.aspectMask` to
* @val_vk{IMAGE_ASPECT_DEPTH_BIT,ImageAspectFlagBits} /
* @val_vk{IMAGE_ASPECT_STENCIL_BIT,ImageAspectFlagBits} if
* @p format is depth / stencil or both and
* @val_vk{IMAGE_ASPECT_COLOR_BIT,ImageAspectFlagBits} otherwise
* - `subresourceRange.levelOffset` to @p levelOffset
* - `subresourceRange.levelCount` to @p levelCount
* - `subresourceRange.baseArrayLayer` to @p layerOffset
* - `subresourceRange.layerCount` to @p layerCount
*
* The @p type and @p format has to be compatible with @p image and
* the mip level and layer sub-range has to be in bounds. For creating
* a view that exactly matches the image type and format, use the
* @ref ImageViewCreateInfo(VkImageViewType, Image&, UnsignedInt, UnsignedInt, UnsignedInt, UnsignedInt, Flags)
* constructor. Otherwise, similarly as with @ref ImageCreateInfo, for
* common view types you're encouraged to make use of
* @ref ImageViewCreateInfo1D, @ref ImageViewCreateInfo2D,
* @ref ImageViewCreateInfo3D, @ref ImageViewCreateInfo1DArray,
* @ref ImageViewCreateInfo2DArray, @ref ImageViewCreateInfoCubeMap and
* @ref ImageViewCreateInfoCubeMapArray convenience classes instead of
* this constructor.
*/
explicit ImageViewCreateInfo(VkImageViewType type, VkImage image, VkFormat format, UnsignedInt layerOffset = 0, UnsignedInt layerCount = VK_REMAINING_ARRAY_LAYERS, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {});
/**
* @brief Construct with format matching given image
*
* Compared to @ref ImageViewCreateInfo(VkImageViewType, VkImage, VkFormat, UnsignedInt, UnsignedInt, UnsignedInt, UnsignedInt, Flags)
* the @p format is taken from the passed @ref Image instance.
*/
explicit ImageViewCreateInfo(VkImageViewType type, Image& image, UnsignedInt layerOffset = 0, UnsignedInt layerCount = VK_REMAINING_ARRAY_LAYERS, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, 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 ImageViewCreateInfo(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 ImageViewCreateInfo(const VkImageViewCreateInfo& info);
/** @brief Underlying @type_vk{BufferCreateInfo} structure */
VkImageViewCreateInfo& operator*() { return _info; }
/** @overload */
const VkImageViewCreateInfo& operator*() const { return _info; }
/** @overload */
VkImageViewCreateInfo* operator->() { return &_info; }
/** @overload */
const VkImageViewCreateInfo* operator->() const { return &_info; }
/** @overload */
operator const VkImageViewCreateInfo*() const { return &_info; }
private:
VkImageViewCreateInfo _info;
};
CORRADE_ENUMSET_OPERATORS(ImageViewCreateInfo::Flags)
/**
@brief Convenience constructor for 1D image views
@m_since_latest
Compared to the base @ref ImageViewCreateInfo constructor creates a view of
type @val_vk{IMAGE_VIEW_TYPE_1D,ImageViewType} with @p layerCount set to
@cpp 1 @ce. The original image is expected to be a
@val_vk{IMAGE_TYPE_1D,ImageType} (e.g., created using @ref ImageCreateInfo1D or
@ref ImageCreateInfo1DArray).
*/
class ImageViewCreateInfo1D: public ImageViewCreateInfo {
public:
/** @brief Constructor */
explicit ImageViewCreateInfo1D(VkImage image, VkFormat format, UnsignedInt layerOffset = 0, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_1D, image, format, layerOffset, 1, levelOffset, levelCount, flags} {}
/** @overload
*
* Compared to the above, @p format is taken from the passed @ref Image
* instance.
*/
explicit ImageViewCreateInfo1D(Image& image, UnsignedInt layerOffset = 0, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_1D, image, layerOffset, 1, levelOffset, levelCount, flags} {}
};
/**
@brief Convenience constructor for 2D image views
@m_since_latest
Compared to the base @ref ImageViewCreateInfo constructor creates a view of
type @val_vk{IMAGE_VIEW_TYPE_2D,ImageViewType} with @p layerCount set to
@cpp 1 @ce. The original image is expected to be a
@val_vk{IMAGE_TYPE_2D,ImageType} (e.g., created using @ref ImageCreateInfo2D,
@ref ImageCreateInfo2DArray, @ref ImageCreateInfoCubeMap or
@ref ImageCreateInfoCubeMapArray).
@todo also mention 3D once we have Flag::2DArrayCompatible
(@vk_extension{KHR,maintenance1}) exposed, restricted additionally with
@vk_extension{KHR,portability_subset}
*/
class ImageViewCreateInfo2D: public ImageViewCreateInfo {
public:
/** @brief Constructor */
explicit ImageViewCreateInfo2D(VkImage image, VkFormat format, UnsignedInt layerOffset = 0, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_2D, image, format, layerOffset, 1, levelOffset, levelCount, flags} {}
/** @overload
*
* Compared to the above, @p format is taken from the passed @ref Image
* instance.
*/
explicit ImageViewCreateInfo2D(Image& image, UnsignedInt layerOffset = 0, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_2D, image, layerOffset, 1, levelOffset, levelCount, flags} {}
};
/**
@brief Convenience constructor for 3D image views
@m_since_latest
Compared to the base @ref ImageViewCreateInfo constructor creates a view of
type @val_vk{IMAGE_VIEW_TYPE_3D,ImageViewType} with @p layerCount set to
@cpp 1 @ce. The original image is expected to be a
@val_vk{IMAGE_TYPE_2D,ImageType} (e.g., created using @ref ImageCreateInfo3D).
*/
class ImageViewCreateInfo3D: public ImageViewCreateInfo {
public:
/** @brief Constructor */
explicit ImageViewCreateInfo3D(VkImage image, VkFormat format, UnsignedInt layerOffset = 0, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_3D, image, format, layerOffset, 1, levelOffset, levelCount, flags} {}
/** @overload
*
* Compared to the above, @p format is taken from the passed @ref Image
* instance.
*/
explicit ImageViewCreateInfo3D(Image& image, UnsignedInt layerOffset = 0, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_3D, image, layerOffset, 1, levelOffset, levelCount, flags} {}
};
/**
@brief Convenience constructor for 1D array image views
@m_since_latest
Compared to the base @ref ImageViewCreateInfo constructor creates a view of
type @val_vk{IMAGE_VIEW_TYPE_1D_ARRAY,ImageViewType}. The original image is
expected to be a @val_vk{IMAGE_TYPE_1D,ImageType} (e.g., created using
@ref ImageCreateInfo1D or @ref ImageCreateInfo1DArray) with enough array layers
to fit the required subrange.
*/
class ImageViewCreateInfo1DArray: public ImageViewCreateInfo {
public:
/** @brief Constructor */
explicit ImageViewCreateInfo1DArray(VkImage image, VkFormat format, UnsignedInt layerOffset = 0, UnsignedInt layerCount = VK_REMAINING_ARRAY_LAYERS, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_1D_ARRAY, image, format, layerOffset, layerCount, levelOffset, levelCount, flags} {}
/** @overload
*
* Compared to the above, @p format is taken from the passed @ref Image
* instance.
*/
explicit ImageViewCreateInfo1DArray(Image& image, UnsignedInt layerOffset = 0, UnsignedInt layerCount = VK_REMAINING_ARRAY_LAYERS, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_1D_ARRAY, image, layerOffset, layerCount, levelOffset, levelCount, flags} {}
};
/**
@brief Convenience constructor for 2D array image views
@m_since_latest
Compared to the base @ref ImageViewCreateInfo constructor creates a view of
type @val_vk{IMAGE_VIEW_TYPE_2D_ARRAY,ImageViewType}. The original image is
expected to be a @val_vk{IMAGE_TYPE_2D,ImageType} (e.g., created using
@ref ImageCreateInfo2D, @ref ImageCreateInfoCubeMap or
@ref ImageCreateInfoCubeMapArray) with enough array layers to fit the required
subrange.
@todo also mention 3D once we have Flag::2DArrayCompatible
(@vk_extension{KHR,maintenance1}) exposed, restricted additionally with
@vk_extension{KHR,portability_subset}
*/
class ImageViewCreateInfo2DArray: public ImageViewCreateInfo {
public:
/** @brief Constructor */
explicit ImageViewCreateInfo2DArray(VkImage image, VkFormat format, UnsignedInt layerOffset = 0, UnsignedInt layerCount = VK_REMAINING_ARRAY_LAYERS, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_2D_ARRAY, image, format, layerOffset, layerCount, levelOffset, levelCount, flags} {}
/** @overload
*
* Compared to the above, @p format is taken from the passed @ref Image
* instance.
*/
explicit ImageViewCreateInfo2DArray(Image& image, UnsignedInt layerOffset = 0, UnsignedInt layerCount = VK_REMAINING_ARRAY_LAYERS, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_2D_ARRAY, image, layerOffset, layerCount, levelOffset, levelCount, flags} {}
};
/**
@brief Convenience constructor for cube map image views
@m_since_latest
Compared to the base @ref ImageViewCreateInfo constructor creates a view of
type @val_vk{IMAGE_VIEW_TYPE_CUBE,ImageViewType} with @p layerCount set to
@cpp 6 @ce. The original image is expected to be a
@val_vk{IMAGE_TYPE_2D,ImageType} with @ref ImageCreateInfo::Flag::CubeCompatible
set (e.g., created using @ref ImageCreateInfoCubeMap or
@ref ImageCreateInfoCubeMapArray).
*/
class ImageViewCreateInfoCubeMap: public ImageViewCreateInfo {
public:
/** @brief Constructor */
explicit ImageViewCreateInfoCubeMap(VkImage image, VkFormat format, UnsignedInt layerOffset = 0, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_CUBE, image, format, layerOffset, 6, levelOffset, levelCount, flags} {}
/** @overload
*
* Compared to the above, @p format is taken from the passed @ref Image
* instance.
*/
explicit ImageViewCreateInfoCubeMap(Image& image, UnsignedInt layerOffset = 0, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_CUBE, image, layerOffset, 6, levelOffset, levelCount, flags} {}
};
/**
@brief Convenience constructor for cube map array image views
@m_since_latest
Compared to the base @ref ImageViewCreateInfo constructor creates a view of
type @val_vk{IMAGE_VIEW_TYPE_CUBE_ARRAY,ImageViewType}. The original image is
expected to be a @val_vk{IMAGE_TYPE_2D,ImageType} with
@ref ImageCreateInfo::Flag::CubeCompatible set (e.g., created using
@ref ImageCreateInfoCubeMap or @ref ImageCreateInfoCubeMapArray) with enough
array layers to fit the required subrange.
@requires_vk_feature @ref DeviceFeature::ImageCubeArray
*/
class ImageViewCreateInfoCubeMapArray: public ImageViewCreateInfo {
public:
/** @brief Constructor */
explicit ImageViewCreateInfoCubeMapArray(VkImage image, VkFormat format, UnsignedInt layerOffset = 0, UnsignedInt layerCount = VK_REMAINING_ARRAY_LAYERS, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, image, format, layerOffset, layerCount, levelOffset, levelCount, flags} {}
/** @overload
*
* Compared to the above, @p format is taken from the passed @ref Image
* instance.
*/
explicit ImageViewCreateInfoCubeMapArray(Image& image, UnsignedInt layerOffset = 0, UnsignedInt layerCount = VK_REMAINING_ARRAY_LAYERS, UnsignedInt levelOffset = 0, UnsignedInt levelCount = VK_REMAINING_MIP_LEVELS, Flags flags = {}): ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, image, layerOffset, layerCount, levelOffset, levelCount, flags} {}
};
}}
/* Make the definition complete -- it doesn't make sense to have a CreateInfo
without the corresponding object anyway. */
#include "Magnum/Vk/ImageView.h"
#endif

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

@ -35,6 +35,7 @@ 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 MagnumVkTestLib)
corrade_add_test(VkImageViewTest ImageViewTest.cpp LIBRARIES MagnumVkTestLib)
corrade_add_test(VkInstanceTest InstanceTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkIntegrationTest IntegrationTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkLayerPropertiesTest LayerPropertiesTest.cpp LIBRARIES MagnumVk)
@ -123,6 +124,7 @@ set_target_properties(
VkExtensionPropertiesTest
VkHandleTest
VkImageTest
VkImageViewTest
VkInstanceTest
VkIntegrationTest
VkLayerPropertiesTest
@ -152,6 +154,7 @@ if(BUILD_VK_TESTS)
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(VkImageViewVkTest ImageViewVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkInstanceVkTest InstanceVkTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkMemoryVkTest MemoryVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester)
corrade_add_test(VkRenderPassVkTest RenderPassVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester)
@ -168,6 +171,7 @@ if(BUILD_VK_TESTS)
VkExtensionPropertiesVkTest
VkLayerPropertiesVkTest
VkImageVkTest
VkImageViewVkTest
VkInstanceVkTest
VkMemoryVkTest
VkRenderPassVkTest

408
src/Magnum/Vk/Test/ImageViewTest.cpp

@ -0,0 +1,408 @@
/*
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 <sstream>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/DebugStl.h>
#include "Magnum/Vk/Device.h"
#include "Magnum/Vk/Image.h"
#include "Magnum/Vk/ImageViewCreateInfo.h"
namespace Magnum { namespace Vk { namespace Test { namespace {
struct ImageViewTest: TestSuite::Tester {
explicit ImageViewTest();
void createInfoConstruct();
void createInfoConstructFromImage();
void createInfoConstructFromImageFormatUknown();
void createInfoConstruct1D();
void createInfoConstruct1DFromImage();
void createInfoConstruct2D();
void createInfoConstruct2DFromImage();
void createInfoConstruct3D();
void createInfoConstruct3DFromImage();
void createInfoConstruct1DArray();
void createInfoConstruct1DArrayFromImage();
void createInfoConstruct2DArray();
void createInfoConstruct2DArrayFromImage();
void createInfoConstructCubeMap();
void createInfoConstructCubeMapFromImage();
void createInfoConstructCubeMapArray();
void createInfoConstructCubeMapArrayFromImage();
void createInfoConstructNoInit();
void createInfoConstructFromVk();
void constructNoCreate();
void constructCopy();
};
const struct {
const char* name;
VkFormat format;
VkImageAspectFlags aspect;
} View2DFormatData[] {
{"color", VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT},
{"depth + stencil", VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT},
{"depth", VK_FORMAT_D16_UNORM, VK_IMAGE_ASPECT_DEPTH_BIT},
{"stencil", VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT}
};
ImageViewTest::ImageViewTest() {
addTests({&ImageViewTest::createInfoConstruct,
&ImageViewTest::createInfoConstructFromImage,
&ImageViewTest::createInfoConstructFromImageFormatUknown,
&ImageViewTest::createInfoConstruct1D,
&ImageViewTest::createInfoConstruct1DFromImage});
addInstancedTests({&ImageViewTest::createInfoConstruct2D},
Containers::arraySize(View2DFormatData));
addTests({&ImageViewTest::createInfoConstruct2DFromImage,
&ImageViewTest::createInfoConstruct3D,
&ImageViewTest::createInfoConstruct3DFromImage,
&ImageViewTest::createInfoConstruct1DArray,
&ImageViewTest::createInfoConstruct1DArrayFromImage,
&ImageViewTest::createInfoConstruct2DArray,
&ImageViewTest::createInfoConstruct2DArrayFromImage,
&ImageViewTest::createInfoConstructCubeMap,
&ImageViewTest::createInfoConstructCubeMapFromImage,
&ImageViewTest::createInfoConstructCubeMapArray,
&ImageViewTest::createInfoConstructCubeMapArrayFromImage,
&ImageViewTest::createInfoConstructNoInit,
&ImageViewTest::createInfoConstructFromVk,
&ImageViewTest::constructNoCreate,
&ImageViewTest::constructCopy});
}
const VkImage imageHandle{reinterpret_cast<VkImage>(0xdeadbeef)};
void ImageViewTest::createInfoConstruct() {
/** @todo use a real flag once it exists */
ImageViewCreateInfo info{VK_IMAGE_VIEW_TYPE_2D, imageHandle, VK_FORMAT_R8G8B8A8_SRGB, 3, 5, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_2D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 5);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstructFromImage() {
Device device{NoCreate};
Image image = Image::wrap(device, imageHandle, VK_FORMAT_R8G8B8A8_SRGB);
/** @todo use a real flag once it exists */
ImageViewCreateInfo info{VK_IMAGE_VIEW_TYPE_2D, image, 3, 5, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_2D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 5);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstructFromImageFormatUknown() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
Device device{NoCreate};
Image image = Image::wrap(device, imageHandle, VK_FORMAT_UNDEFINED);
std::ostringstream out;
Error redirectError{&out};
ImageViewCreateInfo{VK_IMAGE_VIEW_TYPE_2D, image};
CORRADE_COMPARE(out.str(),
"Vk::ImageViewCreateInfo: the image has unknown format, you have to specify it explicitly\n");
}
void ImageViewTest::createInfoConstruct1D() {
/** @todo use a real flag once it exists */
ImageViewCreateInfo1D info{imageHandle, VK_FORMAT_R8G8B8A8_SRGB, 3, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_1D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 1);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstruct1DFromImage() {
Device device{NoCreate};
Image image = Image::wrap(device, imageHandle, VK_FORMAT_R8G8B8A8_SRGB);
/** @todo use a real flag once it exists */
ImageViewCreateInfo1D info{image, 3, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_1D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 1);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstruct2D() {
auto&& data = View2DFormatData[testCaseInstanceId()];
setTestCaseDescription(data.name);
/** @todo use a real flag once it exists */
ImageViewCreateInfo2D info{imageHandle, data.format, 3, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_2D);
CORRADE_COMPARE(info->format, data.format);
CORRADE_COMPARE(info->subresourceRange.aspectMask, data.aspect);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 1);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstruct2DFromImage() {
Device device{NoCreate};
Image image = Image::wrap(device, imageHandle, VK_FORMAT_R8G8B8A8_SRGB);
/** @todo use a real flag once it exists */
ImageViewCreateInfo2D info{image, 3, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_2D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 1);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstruct3D() {
/** @todo use a real flag once it exists */
ImageViewCreateInfo3D info{imageHandle, VK_FORMAT_R8G8B8A8_SRGB, 3, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_3D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 1);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstruct3DFromImage() {
Device device{NoCreate};
Image image = Image::wrap(device, imageHandle, VK_FORMAT_R8G8B8A8_SRGB);
/** @todo use a real flag once it exists */
ImageViewCreateInfo3D info{image, 3, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_3D);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 1);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstruct1DArray() {
/** @todo use a real flag once it exists */
ImageViewCreateInfo1DArray info{imageHandle, VK_FORMAT_R8G8B8A8_SRGB, 3, 5, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_1D_ARRAY);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 5);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstruct1DArrayFromImage() {
Device device{NoCreate};
Image image = Image::wrap(device, imageHandle, VK_FORMAT_R8G8B8A8_SRGB);
/** @todo use a real flag once it exists */
ImageViewCreateInfo1DArray info{image, 3, 5, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_1D_ARRAY);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 5);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstruct2DArray() {
/** @todo use a real flag once it exists */
ImageViewCreateInfo2DArray info{imageHandle, VK_FORMAT_R8G8B8A8_SRGB, 3, 5, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_2D_ARRAY);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 5);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstruct2DArrayFromImage() {
Device device{NoCreate};
Image image = Image::wrap(device, imageHandle, VK_FORMAT_R8G8B8A8_SRGB);
/** @todo use a real flag once it exists */
ImageViewCreateInfo2DArray info{image, 3, 5, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_2D_ARRAY);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 5);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstructCubeMap() {
/** @todo use a real flag once it exists */
ImageViewCreateInfoCubeMap info{imageHandle, VK_FORMAT_R8G8B8A8_SRGB, 3, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_CUBE);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 6);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstructCubeMapFromImage() {
Device device{NoCreate};
Image image = Image::wrap(device, imageHandle, VK_FORMAT_R8G8B8A8_SRGB);
/** @todo use a real flag once it exists */
ImageViewCreateInfoCubeMap info{image, 3, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_CUBE);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 6);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstructCubeMapArray() {
/** @todo use a real flag once it exists */
ImageViewCreateInfoCubeMapArray info{imageHandle, VK_FORMAT_R8G8B8A8_SRGB, 3, 18, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 18);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstructCubeMapArrayFromImage() {
Device device{NoCreate};
Image image = Image::wrap(device, imageHandle, VK_FORMAT_R8G8B8A8_SRGB);
/** @todo use a real flag once it exists */
ImageViewCreateInfoCubeMapArray info{image, 3, 18, 7, 9, ImageViewCreateInfo::Flag(VK_NOT_READY)};
CORRADE_COMPARE(info->flags, VK_NOT_READY);
CORRADE_COMPARE(info->image, imageHandle);
CORRADE_COMPARE(info->viewType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
CORRADE_COMPARE(info->format, VK_FORMAT_R8G8B8A8_SRGB);
CORRADE_COMPARE(info->subresourceRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
CORRADE_COMPARE(info->subresourceRange.baseArrayLayer, 3);
CORRADE_COMPARE(info->subresourceRange.layerCount, 18);
CORRADE_COMPARE(info->subresourceRange.baseMipLevel, 7);
CORRADE_COMPARE(info->subresourceRange.levelCount, 9);
}
void ImageViewTest::createInfoConstructNoInit() {
ImageViewCreateInfo info{NoInit};
info->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
new(&info) ImageViewCreateInfo{NoInit};
CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
CORRADE_VERIFY((std::is_nothrow_constructible<ImageViewCreateInfo, NoInitT>::value));
/* Implicit construction is not allowed */
CORRADE_VERIFY(!(std::is_convertible<NoInitT, ImageViewCreateInfo>::value));
}
void ImageViewTest::createInfoConstructFromVk() {
VkImageViewCreateInfo vkInfo;
vkInfo.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
ImageViewCreateInfo info{vkInfo};
CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2);
}
void ImageViewTest::constructNoCreate() {
{
ImageView view{NoCreate};
CORRADE_VERIFY(!view.handle());
}
/* Implicit construction is not allowed */
CORRADE_VERIFY(!(std::is_convertible<NoCreateT, ImageView>::value));
}
void ImageViewTest::constructCopy() {
CORRADE_VERIFY(!std::is_copy_constructible<ImageView>{});
CORRADE_VERIFY(!std::is_copy_assignable<ImageView>{});
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::ImageViewTest)

213
src/Magnum/Vk/Test/ImageViewVkTest.cpp

@ -0,0 +1,213 @@
/*
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/DeviceCreateInfo.h"
#include "Magnum/Vk/DeviceFeatures.h"
#include "Magnum/Vk/DeviceProperties.h"
#include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/ImageCreateInfo.h"
#include "Magnum/Vk/ImageViewCreateInfo.h"
#include "Magnum/Vk/Result.h"
#include "Magnum/Vk/VulkanTester.h"
namespace Magnum { namespace Vk { namespace Test { namespace {
struct ImageViewVkTest: VulkanTester {
explicit ImageViewVkTest();
void construct1D();
void construct2D();
void construct3D();
void construct1DArray();
void construct2DArray();
void constructCubeMap();
void constructCubeMapArray();
void constructMove();
void wrap();
};
ImageViewVkTest::ImageViewVkTest() {
addTests({&ImageViewVkTest::construct1D,
&ImageViewVkTest::construct2D,
&ImageViewVkTest::construct3D,
&ImageViewVkTest::construct1DArray,
&ImageViewVkTest::construct2DArray,
&ImageViewVkTest::constructCubeMap,
&ImageViewVkTest::constructCubeMapArray,
&ImageViewVkTest::constructMove,
&ImageViewVkTest::wrap});
}
void ImageViewVkTest::construct1D() {
Image image{device(), ImageCreateInfo1D{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, 256, 1}, MemoryFlag::DeviceLocal};
{
ImageView view{device(), ImageViewCreateInfo1D{image}};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageViewVkTest::construct2D() {
Image image{device(), ImageCreateInfo2D{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256}, 1}, MemoryFlag::DeviceLocal};
{
ImageView view{device(), ImageViewCreateInfo2D{image}};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageViewVkTest::construct3D() {
Image image{device(), ImageCreateInfo3D{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256, 10}, 1}, MemoryFlag::DeviceLocal};
{
ImageView view{device(), ImageViewCreateInfo3D{image}};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageViewVkTest::construct1DArray() {
Image image{device(), ImageCreateInfo1DArray{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 10}, 1}, MemoryFlag::DeviceLocal};
{
ImageView view{device(), ImageViewCreateInfo1DArray{image}};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageViewVkTest::construct2DArray() {
Image image{device(), ImageCreateInfo2DArray{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256, 10}, 1}, MemoryFlag::DeviceLocal};
{
ImageView view{device(), ImageViewCreateInfo2DArray{image}};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageViewVkTest::constructCubeMap() {
Image image{device(), ImageCreateInfoCubeMap{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256}, 1}, MemoryFlag::DeviceLocal};
{
ImageView view{device(), ImageViewCreateInfoCubeMap{image}};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageViewVkTest::constructCubeMapArray() {
if(!(device().properties().features() & DeviceFeature::ImageCubeArray))
CORRADE_SKIP("ImageCubeArray feature not supported, can't test.");
/* Create the image on a new device with the feature enabled */
Queue queue2{NoCreate};
Device device2{instance(), DeviceCreateInfo{device().properties()}
.addQueues(0, {0.0f}, {queue2})
.setEnabledFeatures(DeviceFeature::ImageCubeArray)};
Image image{device2, ImageCreateInfoCubeMapArray{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256, 18}, 1}, MemoryFlag::DeviceLocal};
{
ImageView view{device2, ImageViewCreateInfoCubeMapArray{image}};
CORRADE_VERIFY(image.handle());
CORRADE_COMPARE(image.handleFlags(), HandleFlag::DestroyOnDestruction);
}
/* Shouldn't crash or anything */
CORRADE_VERIFY(true);
}
void ImageViewVkTest::constructMove() {
Image image{device(), ImageCreateInfo2D{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256}, 1}, MemoryFlag::DeviceLocal};
ImageView a{device(), ImageViewCreateInfo2D{image}};
VkImageView handle = a.handle();
ImageView b = std::move(a);
CORRADE_VERIFY(!a.handle());
CORRADE_COMPARE(b.handle(), handle);
CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction);
ImageView 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 ImageViewVkTest::wrap() {
Image image{device(), ImageCreateInfo2D{ImageUsage::Sampled,
VK_FORMAT_R8G8B8A8_UNORM, {256, 256}, 1}, MemoryFlag::DeviceLocal};
VkImageView view{};
CORRADE_COMPARE(Result(device()->CreateImageView(device(),
ImageViewCreateInfo2D{image}, nullptr, &view)), Result::Success);
CORRADE_VERIFY(view);
auto wrapped = ImageView::wrap(device(), view, HandleFlag::DestroyOnDestruction);
CORRADE_COMPARE(wrapped.handle(), view);
/* Release the handle again, destroy by hand */
CORRADE_COMPARE(wrapped.release(), view);
CORRADE_VERIFY(!wrapped.handle());
device()->DestroyImageView(device(), view, nullptr);
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::ImageViewVkTest)

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

@ -199,7 +199,7 @@ void ImageVkTest::wrap() {
nullptr, &image)), Result::Success);
CORRADE_VERIFY(image);
auto wrapped = Image::wrap(device(), image, HandleFlag::DestroyOnDestruction);
auto wrapped = Image::wrap(device(), image, VK_FORMAT_R8G8B8A8_UNORM, HandleFlag::DestroyOnDestruction);
CORRADE_COMPARE(wrapped.handle(), image);
/* Release the handle again, destroy by hand */

3
src/Magnum/Vk/Vk.h

@ -55,6 +55,9 @@ class Image;
enum class ImageLayout: Int;
class ImageCreateInfo;
/* Not forward-declaring ImageCreateInfo1D etc right now, I see no need */
class ImageView;
class ImageViewCreateInfo;
/* Not forward-declaring ImageViewCreateInfo1D etc right now, I see no need */
class Instance;
class InstanceCreateInfo;
class InstanceExtension;

Loading…
Cancel
Save