ImageVk.h#
The PVRVk Image class and related classes (SwapchainImage, ImageView).
Includes#
PVRVk/DeviceMemoryVk.h
PVRVk/DeviceVk.h
Included By#
Namespaces#
Classes#
Source Code#
#pragma once
#include "PVRVk/DeviceVk.h"
#include "PVRVk/DeviceMemoryVk.h"
namespace pvrvk {
namespace {
inline ImageViewType convertToPVRVkImageViewType(ImageType baseType, uint32_t numArrayLayers, bool isCubeMap)
{
// if it is a cube map it has to be 2D Texture base
if (isCubeMap && baseType != ImageType::e_2D)
{
assert(baseType == ImageType::e_2D && "Cubemap texture must be 2D");
return ImageViewType::e_MAX_ENUM;
}
// array must be atleast 1
if (!numArrayLayers)
{
assert(false && "Number of array layers must be greater than equal to 0");
return ImageViewType::e_MAX_ENUM;
}
// if it is array it must be 1D or 2D texture base
if ((numArrayLayers > 1) && (baseType > ImageType::e_2D))
{
assert(false && "1D and 2D image type supports array texture");
return ImageViewType::e_MAX_ENUM;
}
ImageViewType vkType[] = { ImageViewType::e_1D, ImageViewType::e_1D_ARRAY, ImageViewType::e_2D, ImageViewType::e_2D_ARRAY, ImageViewType::e_3D, ImageViewType::e_CUBE,
ImageViewType::e_CUBE_ARRAY };
if (isCubeMap) { numArrayLayers = (numArrayLayers > 6u) * 6u; }
return vkType[(static_cast<uint32_t>(baseType) * 2) + (isCubeMap ? 3 : 0) + (numArrayLayers > 1 ? 1 : 0)];
}
inline ImageAspectFlags formatToImageAspect(Format format)
{
if (format == Format::e_UNDEFINED) { throw ErrorUnknown("Cannot retrieve VkImageAspectFlags from an undefined VkFormat"); }
if (format < Format::e_D16_UNORM || format > Format::e_D32_SFLOAT_S8_UINT) { return ImageAspectFlags::e_COLOR_BIT; }
const ImageAspectFlags formats[] = {
ImageAspectFlags::e_DEPTH_BIT, // VkFormat::e_D16_UNORM
ImageAspectFlags::e_DEPTH_BIT, // VkFormat::e_X8_D24_UNORM_PACK32
ImageAspectFlags::e_DEPTH_BIT, // VkFormat::e_D32_SFLOAT
ImageAspectFlags::e_STENCIL_BIT, // VkFormat::e_S8_UINT
ImageAspectFlags::e_DEPTH_BIT | ImageAspectFlags::e_STENCIL_BIT, // VkFormat::e_D16_UNORM_S8_UINT
ImageAspectFlags::e_DEPTH_BIT | ImageAspectFlags::e_STENCIL_BIT, // VkFormat::e_D24_UNORM_S8_UINT
ImageAspectFlags::e_DEPTH_BIT | ImageAspectFlags::e_STENCIL_BIT, // VkFormat::e_D32_SFLOAT_S8_UINT
};
return formats[static_cast<uint32_t>(format) - static_cast<uint32_t>(Format::e_D16_UNORM)];
}
} // namespace
struct ImageCreateInfo
{
public:
ImageCreateInfo()
: _flags(ImageCreateFlags::e_NONE), _imageType(ImageType::e_2D), _extent(Extent3D()), _numMipLevels(1), _numArrayLayers(1), _numSamples(SampleCountFlags::e_1_BIT),
_format(Format::e_UNDEFINED), _sharingMode(SharingMode::e_EXCLUSIVE), _usageFlags(ImageUsageFlags::e_NONE), _initialLayout(ImageLayout::e_UNDEFINED),
_tiling(ImageTiling::e_OPTIMAL), _numQueueFamilyIndices(0), _queueFamilyIndices(nullptr)
{}
ImageCreateInfo(ImageType imageType, pvrvk::Format format, const pvrvk::Extent3D& extent, pvrvk::ImageUsageFlags usage, uint32_t numMipLevels = 1, uint32_t numArrayLayers = 1,
pvrvk::SampleCountFlags samples = pvrvk::SampleCountFlags::e_1_BIT, pvrvk::ImageCreateFlags flags = pvrvk::ImageCreateFlags::e_NONE,
ImageTiling tiling = ImageTiling::e_OPTIMAL, SharingMode sharingMode = SharingMode::e_EXCLUSIVE, ImageLayout initialLayout = ImageLayout::e_UNDEFINED,
const uint32_t* queueFamilyIndices = nullptr, uint32_t numQueueFamilyIndices = 0)
: _flags(flags), _imageType(imageType), _extent(extent), _numMipLevels(numMipLevels), _numArrayLayers(numArrayLayers), _numSamples(samples), _format(format),
_sharingMode(sharingMode), _usageFlags(usage), _initialLayout(initialLayout), _tiling(tiling), _numQueueFamilyIndices(numQueueFamilyIndices),
_queueFamilyIndices(queueFamilyIndices)
{}
inline ImageCreateFlags getFlags() const { return _flags; }
inline void setFlags(ImageCreateFlags flags) { this->_flags = flags; }
inline ImageType getImageType() const { return _imageType; }
inline void setImageType(ImageType imageType) { this->_imageType = imageType; }
inline const Extent3D& getExtent() const { return _extent; }
inline void setExtent(Extent3D extent) { this->_extent = extent; }
inline uint32_t getNumMipLevels() const { return _numMipLevels; }
inline void setNumMipLevels(uint32_t numMipLevels) { this->_numMipLevels = numMipLevels; }
inline uint32_t getNumArrayLayers() const { return _numArrayLayers; }
inline void setNumArrayLayers(uint32_t numArrayLayers) { this->_numArrayLayers = numArrayLayers; }
inline SampleCountFlags getNumSamples() const { return _numSamples; }
inline void setNumSamples(SampleCountFlags numSamples) { this->_numSamples = numSamples; }
inline Format getFormat() const { return _format; }
inline void setFormat(Format format) { this->_format = format; }
inline SharingMode getSharingMode() const { return _sharingMode; }
inline void setSharingMode(SharingMode sharingMode) { this->_sharingMode = sharingMode; }
inline ImageUsageFlags getUsageFlags() const { return _usageFlags; }
inline void setUsageFlags(ImageUsageFlags usageFlags) { this->_usageFlags = usageFlags; }
inline ImageLayout getInitialLayout() const { return _initialLayout; }
inline void setInitialLayout(ImageLayout initialLayout) { this->_initialLayout = initialLayout; }
inline ImageTiling getTiling() const { return _tiling; }
inline void setTiling(ImageTiling tiling) { this->_tiling = tiling; }
inline uint32_t getNumQueueFamilyIndices() const { return _numQueueFamilyIndices; }
inline void setNumQueueFamilyIndices(uint32_t numQueueFamilyIndices) { this->_numQueueFamilyIndices = numQueueFamilyIndices; }
inline const uint32_t* getQueueFamilyIndices() const { return _queueFamilyIndices; }
inline void setQueueFamilyIndices(const uint32_t* queueFamilyIndices) { _queueFamilyIndices = queueFamilyIndices; }
private:
ImageCreateFlags _flags;
ImageType _imageType;
Extent3D _extent;
uint32_t _numMipLevels;
uint32_t _numArrayLayers;
SampleCountFlags _numSamples;
Format _format;
SharingMode _sharingMode;
ImageUsageFlags _usageFlags;
ImageLayout _initialLayout;
ImageTiling _tiling;
uint32_t _numQueueFamilyIndices;
const uint32_t* _queueFamilyIndices;
};
namespace impl {
class Image_ : public PVRVkDeviceObjectBase<VkImage, ObjectType::e_IMAGE>, public DeviceObjectDebugUtils<Image_>
{
protected:
friend class Device_;
class make_shared_enabler
{
protected:
make_shared_enabler() {}
friend class Image_;
};
static Image constructShared(const DeviceWeakPtr& device, const ImageCreateInfo& createInfo) { return std::make_shared<Image_>(make_shared_enabler{}, device, createInfo); }
static Image constructShared(const DeviceWeakPtr& device) { return std::make_shared<Image_>(make_shared_enabler{}, device); }
pvrvk::MemoryRequirements _memReqs;
DeviceMemory _memory;
pvrvk::ImageCreateInfo _createInfo;
#ifdef DEBUG
pvrvk::ImageLayout _currentLayout;
#endif
public:
DECLARE_NO_COPY_SEMANTICS(Image_)
virtual ~Image_();
Image_(make_shared_enabler, const DeviceWeakPtr& device, const ImageCreateInfo& createInfo);
Image_(make_shared_enabler, const DeviceWeakPtr& device) : PVRVkDeviceObjectBase(device), DeviceObjectDebugUtils() {}
pvrvk::SubresourceLayout getSubresourceLayout(const pvrvk::ImageSubresource& subresource) const;
pvrvk::ImageCreateInfo getCreateInfo() const { return _createInfo; }
inline ImageCreateFlags getFlags() const { return _createInfo.getFlags(); }
inline ImageType getImageType() const { return _createInfo.getImageType(); }
inline Extent3D getExtent() const { return _createInfo.getExtent(); }
inline uint32_t getNumMipLevels() const { return _createInfo.getNumMipLevels(); }
inline uint32_t getNumArrayLayers() const { return _createInfo.getNumArrayLayers(); }
inline SampleCountFlags getNumSamples() const { return _createInfo.getNumSamples(); }
inline Format getFormat() const { return _createInfo.getFormat(); }
inline SharingMode getSharingMode() const { return _createInfo.getSharingMode(); }
inline ImageUsageFlags getUsageFlags() const { return _createInfo.getUsageFlags(); }
inline ImageLayout getInitialLayout() const { return _createInfo.getInitialLayout(); }
inline ImageTiling getTiling() const { return _createInfo.getTiling(); }
inline uint32_t getNumQueueFamilyIndices() const { return _createInfo.getNumQueueFamilyIndices(); }
inline const uint32_t* const getQueueFamilyIndices() const { return _createInfo.getQueueFamilyIndices(); }
bool isCubeMap() const { return (_createInfo.getFlags() & pvrvk::ImageCreateFlags::e_CUBE_COMPATIBLE_BIT) == pvrvk::ImageCreateFlags::e_CUBE_COMPATIBLE_BIT; }
bool isAllocated() const { return (getVkHandle() != VK_NULL_HANDLE); }
uint16_t getWidth() const { return static_cast<uint16_t>(_createInfo.getExtent().getWidth()); }
uint16_t getHeight() const { return static_cast<uint16_t>(_createInfo.getExtent().getHeight()); }
uint16_t getDepth() const { return static_cast<uint16_t>(_createInfo.getExtent().getDepth()); }
const DeviceMemory& getDeviceMemory() const { return _memory; }
DeviceMemory& getDeviceMemory() { return _memory; }
void bindMemoryNonSparse(DeviceMemory memory, VkDeviceSize offset = 0)
{
if ((_createInfo.getFlags() &
(pvrvk::ImageCreateFlags::e_SPARSE_ALIASED_BIT | pvrvk::ImageCreateFlags::e_SPARSE_BINDING_BIT | pvrvk::ImageCreateFlags::e_SPARSE_RESIDENCY_BIT)) != 0)
{
throw ErrorValidationFailedEXT("Cannot bind memory: Image is Sparce so cannot have bound memory.");
}
if (_memory) { throw ErrorValidationFailedEXT("Cannot bind memory: A memory block is already bound"); }
vkThrowIfFailed(getDevice()->getVkBindings().vkBindImageMemory(getDevice()->getVkHandle(), getVkHandle(), memory->getVkHandle(), offset),
"Failed to bind a memory block to this image");
_memory = memory;
}
const pvrvk::MemoryRequirements& getMemoryRequirement() const { return _memReqs; }
#ifdef DEBUG
pvrvk::ImageLayout getImageLayout() { return _currentLayout; }
void setImageLayout(pvrvk::ImageLayout imageLayout) { _currentLayout = imageLayout; }
#endif
};
class SwapchainImage_ : public Image_
{
private:
friend class ::pvrvk::impl::Swapchain_;
class make_shared_enabler : public Image_::make_shared_enabler
{
private:
make_shared_enabler() : Image_::make_shared_enabler() {}
friend class SwapchainImage_;
};
static SwapchainImage constructShared(const DeviceWeakPtr& device, const VkImage& swapchainImage, const Format& format, const Extent3D& extent, uint32_t numArrayLevels,
uint32_t numMipLevels, const ImageUsageFlags& usage)
{
return std::make_shared<SwapchainImage_>(make_shared_enabler{}, device, swapchainImage, format, extent, numArrayLevels, numMipLevels, usage);
}
public:
DECLARE_NO_COPY_SEMANTICS(SwapchainImage_)
~SwapchainImage_();
SwapchainImage_(make_shared_enabler, const DeviceWeakPtr& device, const VkImage& swapchainImage, const Format& format, const Extent3D& extent, uint32_t numArrayLevels,
uint32_t numMipLevels, const ImageUsageFlags& usage);
};
} // namespace impl
struct ImageViewCreateInfo
{
public:
ImageViewCreateInfo()
: _viewType(ImageViewType::e_2D), _format(Format::e_UNDEFINED), _components(ComponentMapping()), _subresourceRange(ImageSubresourceRange()),
_flags(ImageViewCreateFlags::e_NONE), _pNext(nullptr)
{}
ImageViewCreateInfo(const Image& image, const ComponentMapping& components = ComponentMapping(), const void* pNext = nullptr)
: _image(image), _components(components), _flags(ImageViewCreateFlags::e_NONE), _pNext(pNext)
{
_viewType = convertToPVRVkImageViewType(_image->getImageType(), _image->getNumArrayLayers(), _image->isCubeMap());
_format = _image->getFormat();
_subresourceRange = ImageSubresourceRange(pvrvk::formatToImageAspect(_image->getFormat()), 0, _image->getNumMipLevels(), 0, _image->getNumArrayLayers());
}
ImageViewCreateInfo(const Image& image, pvrvk::ImageViewType viewType, pvrvk::Format format, const ImageSubresourceRange& subresourceRange,
const ComponentMapping& components = ComponentMapping(), ImageViewCreateFlags flags = ImageViewCreateFlags::e_NONE, const void* pNext = nullptr)
: _image(image), _viewType(viewType), _format(format), _components(components), _subresourceRange(subresourceRange), _flags(flags), _pNext(pNext)
{}
inline ImageViewCreateFlags getFlags() const { return _flags; }
inline void setFlags(ImageViewCreateFlags flags) { this->_flags = flags; }
inline Image& getImage() { return _image; }
inline const Image& getImage() const { return _image; }
inline void setImage(const Image& image) { this->_image = image; }
inline ImageViewType getViewType() const { return _viewType; }
inline void setViewType(ImageViewType viewType) { this->_viewType = viewType; }
inline Format getFormat() const { return _format; }
inline void setFormat(Format format) { this->_format = format; }
inline const ComponentMapping& getComponents() const { return _components; }
inline void setComponents(const ComponentMapping& components) { this->_components = components; }
inline const ImageSubresourceRange& getSubresourceRange() const { return _subresourceRange; }
inline void setSubresourceRange(const ImageSubresourceRange& subresourceRange) { this->_subresourceRange = subresourceRange; }
inline const void* getpNext() const { return _pNext; }
inline void setpNext(const void* pNext) { this->_pNext = pNext; }
private:
Image _image;
ImageViewType _viewType;
Format _format;
ComponentMapping _components;
ImageSubresourceRange _subresourceRange;
ImageViewCreateFlags _flags;
const void* _pNext;
};
namespace impl {
class ImageView_ : public PVRVkDeviceObjectBase<VkImageView, ObjectType::e_IMAGE_VIEW>, public DeviceObjectDebugUtils<ImageView_>
{
private:
friend class Device_;
class make_shared_enabler
{
protected:
make_shared_enabler() {}
friend class ImageView_;
};
static ImageView constructShared(const DeviceWeakPtr& device, const ImageViewCreateInfo& createInfo)
{
return std::make_shared<ImageView_>(make_shared_enabler{}, device, createInfo);
}
ImageViewCreateInfo _createInfo;
public:
DECLARE_NO_COPY_SEMANTICS(ImageView_)
ImageView_(make_shared_enabler, const DeviceWeakPtr& device, const ImageViewCreateInfo& createInfo);
~ImageView_();
inline ImageViewCreateFlags getFlags() const { return _createInfo.getFlags(); }
inline Image& getImage() { return _createInfo.getImage(); }
inline const Image& getImage() const { return _createInfo.getImage(); }
inline ImageViewType getViewType() const { return _createInfo.getViewType(); }
inline Format getFormat() const { return _createInfo.getFormat(); }
inline const ComponentMapping& getComponents() const { return _createInfo.getComponents(); }
inline const ImageSubresourceRange& getSubresourceRange() const { return _createInfo.getSubresourceRange(); }
ImageViewCreateInfo getCreateInfo() const { return _createInfo; }
};
} // namespace impl
} // namespace pvrvk