UIRendererVk.h#
↰ Parent directory (Vulkan
)
Contains implementations of functions for the classes in UIRenderer.h.
Includes#
PVRUtils/Vulkan/HelperVk.h
PVRUtils/Vulkan/MemoryAllocator.h
PVRUtils/Vulkan/SpriteVk.h
PVRVk/ApiObjectsVk.h
PVRVk/CommandBufferVk.h
PVRVk/RenderPassVk.h
Included By#
Namespaces#
Classes#
Source Code#
#pragma once
#include "PVRUtils/Vulkan/SpriteVk.h"
#include "PVRUtils/Vulkan/HelperVk.h"
#include "PVRVk/CommandBufferVk.h"
#include "PVRVk/RenderPassVk.h"
#include "PVRVk/ApiObjectsVk.h"
#include "PVRUtils/Vulkan/MemoryAllocator.h"
namespace pvr {
namespace ui {
class UIRenderer
{
public:
struct ProgramData
{
enum Uniform
{
UniformMVPmtx,
UniformFontTexture,
UniformColor,
UniformAlphaMode,
UniformUVmtx,
NumUniform
};
enum Attribute
{
AttributeVertex,
AttributeUV,
NumAttribute
};
int32_t uniforms[NumUniform];
int32_t attributes[NumAttribute];
};
const pvrvk::Buffer& getFontIbo()
{
if (!_fontIbo)
{
// create the FontIBO
std::vector<uint16_t> fontFaces;
fontFaces.resize(impl::Font_::FontElement);
for (uint32_t i = 0; i < impl::Font_::MaxRenderableLetters; ++i)
{
fontFaces[i * 6] = static_cast<uint16_t>(0 + i * 4);
fontFaces[i * 6 + 1] = static_cast<uint16_t>(3 + i * 4);
fontFaces[i * 6 + 2] = static_cast<uint16_t>(1 + i * 4);
fontFaces[i * 6 + 3] = static_cast<uint16_t>(3 + i * 4);
fontFaces[i * 6 + 4] = static_cast<uint16_t>(0 + i * 4);
fontFaces[i * 6 + 5] = static_cast<uint16_t>(2 + i * 4);
}
_fontIbo = utils::createBuffer(getDevice().lock(), pvrvk::BufferCreateInfo(sizeof(fontFaces[0]) * impl::Font_::FontElement, pvrvk::BufferUsageFlags::e_INDEX_BUFFER_BIT),
pvrvk::MemoryPropertyFlags::e_HOST_VISIBLE_BIT, pvrvk::MemoryPropertyFlags::e_HOST_VISIBLE_BIT, _vmaAllocator, pvr::utils::vma::AllocationCreateFlags::e_MAPPED_BIT);
pvr::utils::updateHostVisibleBuffer(_fontIbo, &fontFaces[0], 0, static_cast<uint32_t>(sizeof(fontFaces[0]) * fontFaces.size()), true);
}
return _fontIbo;
}
const pvrvk::Buffer& getImageVbo()
{
if (!_imageVbo)
{
// create the image vbo
const float verts[] = {
/* Position */
-1.f, 1.f, 0.f, 1.0f, 0.0f, 1.0f, // upper left
-1.f, -1.f, 0.f, 1.0f, 0.f, 0.0f, // lower left
1.f, 1.f, 0.f, 1.0f, 1.f, 1.f, // upper right
-1.f, -1.f, 0.f, 1.0f, 0.f, 0.0f, // lower left
1.f, -1.f, 0.f, 1.0f, 1.f, 0.0f, // lower right
1.f, 1.f, 0.f, 1.0f, 1.f, 1.f, // upper right
};
_imageVbo = utils::createBuffer(getDevice().lock(), pvrvk::BufferCreateInfo(sizeof(verts), pvrvk::BufferUsageFlags::e_VERTEX_BUFFER_BIT),
pvrvk::MemoryPropertyFlags::e_HOST_VISIBLE_BIT, pvrvk::MemoryPropertyFlags::e_HOST_VISIBLE_BIT, _vmaAllocator, pvr::utils::vma::AllocationCreateFlags::e_MAPPED_BIT);
pvr::utils::updateHostVisibleBuffer(_imageVbo, static_cast<const void*>(verts), 0, sizeof(verts), true);
}
return _imageVbo;
}
UIRenderer() : _screenRotation(.0f), _numSprites(0) {}
UIRenderer(UIRenderer&& rhs)
: _renderpass(std::move(rhs._renderpass)), _subpass(std::move(rhs._subpass)), _programData(std::move(rhs._programData)), _defaultFont(std::move(rhs._defaultFont)),
_sdkLogo(std::move(rhs._sdkLogo)), _defaultTitle(std::move(rhs._defaultTitle)), _defaultDescription(std::move(rhs._defaultDescription)),
_defaultControls(std::move(rhs._defaultControls)), _device(std::move(rhs._device)), _pipelineLayout(std::move(rhs._pipelineLayout)), _pipeline(std::move(rhs._pipeline)),
_texDescLayout(std::move(rhs._texDescLayout)), _uboMvpDescLayout(std::move(rhs._uboMvpDescLayout)), _uboMaterialLayout(std::move(rhs._uboMaterialLayout)),
_samplerBilinear(std::move(rhs._samplerBilinear)), _samplerTrilinear(std::move(rhs._samplerTrilinear)), _descPool(std::move(rhs._descPool)),
_activeCommandBuffer(std::move(rhs._activeCommandBuffer)), _mustEndCommandBuffer(std::move(rhs._mustEndCommandBuffer)), _fontIbo(std::move(rhs._fontIbo)),
_imageVbo(std::move(rhs._imageVbo)), _screenDimensions(std::move(rhs._screenDimensions)), _screenRotation(std::move(rhs._screenRotation)),
_groupId(std::move(rhs._groupId)), _uboMvp(std::move(rhs._uboMvp)), _uboMaterial(std::move(rhs._uboMaterial)), _numSprites(std::move(rhs._numSprites)),
_sprites(std::move(rhs._sprites)), _textElements(std::move(rhs._textElements)), _fonts(std::move(rhs._fonts))
{
updateResourceOwnsership();
}
UIRenderer& operator=(UIRenderer&& rhs)
{
if (this == &rhs) { return *this; }
_renderpass = std::move(rhs._renderpass);
_subpass = std::move(rhs._subpass);
_programData = std::move(rhs._programData);
_defaultFont = std::move(rhs._defaultFont);
_sdkLogo = std::move(rhs._sdkLogo);
_defaultTitle = std::move(rhs._defaultTitle);
_defaultDescription = std::move(rhs._defaultDescription);
_defaultControls = std::move(rhs._defaultControls);
_device = std::move(rhs._device);
_pipelineLayout = std::move(rhs._pipelineLayout);
_pipeline = std::move(rhs._pipeline);
_texDescLayout = std::move(rhs._texDescLayout);
_uboMvpDescLayout = std::move(rhs._uboMvpDescLayout);
_uboMaterialLayout = std::move(rhs._uboMaterialLayout);
_samplerBilinear = std::move(rhs._samplerBilinear);
_samplerTrilinear = std::move(rhs._samplerTrilinear);
_descPool = std::move(rhs._descPool);
_activeCommandBuffer = std::move(rhs._activeCommandBuffer);
_mustEndCommandBuffer = std::move(rhs._mustEndCommandBuffer);
_fontIbo = std::move(rhs._fontIbo);
_imageVbo = std::move(rhs._imageVbo);
_screenDimensions = std::move(rhs._screenDimensions);
_screenRotation = std::move(rhs._screenRotation);
_groupId = std::move(rhs._groupId);
_uboMvp = std::move(rhs._uboMvp);
_uboMaterial = std::move(rhs._uboMaterial);
_numSprites = std::move(rhs._numSprites);
updateResourceOwnsership();
return *this;
}
UIRenderer& operator=(const UIRenderer& rhs) = delete;
UIRenderer(UIRenderer& rhs) = delete;
pvrvk::DeviceWeakPtr& getDevice() { return _device; }
const pvrvk::DeviceWeakPtr& getDevice() const { return _device; }
const ProgramData& getProgramData() { return _programData; }
pvrvk::GraphicsPipeline getPipeline() { return _pipeline; }
pvr::utils::vma::Allocator& getMemoryAllocator() { return _vmaAllocator; }
const pvr::utils::vma::Allocator& getMemoryAllocator() const { return _vmaAllocator; }
bool isRendering() { return _activeCommandBuffer->isRecording(); }
void init(uint32_t width, uint32_t height, bool fullscreen, const pvrvk::RenderPass& renderpass, uint32_t subpass, bool isFrameBufferSrgb, pvrvk::CommandPool& commandPool,
pvrvk::Queue& queue, bool createDefaultLogo = true, bool createDefaultTitle = true, bool createDefaultFont = true, uint32_t maxNumInstances = 64, uint32_t maxNumSprites = 64);
void init(uint32_t width, uint32_t height, bool fullscreen, const pvrvk::RenderPass& renderpass, uint32_t subpass, bool isFrameBufferSrgb, pvrvk::CommandPool& commandPool,
pvrvk::Queue& queue, const pvrvk::ImageView& fontView, const pvr::TextureHeader& textureHeader , const pvrvk::Sampler& fontSampler = pvrvk::Sampler(), bool createDefaultLogo = true, bool createDefaultTitle = true,
uint32_t maxNumInstances = 64, uint32_t maxNumSprites = 64);
~UIRenderer()
{
_defaultFont.reset();
_defaultTitle.reset();
_defaultDescription.reset();
_defaultControls.reset();
_sdkLogo.reset();
_uboMaterial.reset();
_uboMvp.reset();
_texDescLayout.reset();
_uboMvpDescLayout.reset();
_uboMaterialLayout.reset();
_pipelineLayout.reset();
_pipeline.reset();
_pipelineCache.reset();
_samplerBilinear.reset();
_samplerTrilinear.reset();
_activeCommandBuffer.reset();
_fontIbo.reset();
_imageVbo.reset();
_sprites.clear();
_fonts.clear();
_textElements.clear();
_screenRotation = .0f;
_numSprites = 0;
_renderpass.reset();
_vmaAllocator.reset();
_descPool.reset();
_device.reset();
}
TextElement createTextElement(const std::string& text, uint32_t maxLength) { return createTextElement(text, _defaultFont, maxLength); }
TextElement createTextElement(const std::string& text, const Font& font, uint32_t maxLength);
TextElement createTextElement(const Font& font, uint32_t maxLength) { return createTextElement(std::string(""), font, maxLength); }
TextElement createTextElement(const std::wstring& text, uint32_t maxLength) { return createTextElement(text, _defaultFont, maxLength); }
TextElement createTextElement(const std::wstring& text, const Font& font, uint32_t maxLength);
Text createText(const TextElement& textElement);
Text createText(uint32_t maxLength = 255) { return createText(createTextElement("", maxLength)); }
Text createText(const std::string& text, uint32_t maxLength = 0) { return createText(createTextElement(text, maxLength)); }
Text createText(const Font& font, const std::string& text, uint32_t maxLength = 0) { return createText(createTextElement(text, font, maxLength)); }
Text createText(const Font& font, uint32_t maxLength = 255) { return createText(createTextElement("", font, maxLength)); }
Text createText(const std::wstring& text, uint32_t maxLength = 0) { return createText(createTextElement(text, maxLength)); }
Text createText(const Font& font, const std::wstring& text) { return createText(createTextElement(text, font, static_cast<uint32_t>(text.length()))); }
Text createText(const Font& font, const std::wstring& text, uint32_t maxLength = 0) { return createText(createTextElement(text, font, maxLength)); }
float getRenderingDimX() const { return _screenDimensions.x; }
float getRenderingDimY() const { return _screenDimensions.y; }
glm::vec2 getRenderingDim() const { return _screenDimensions; }
pvrvk::Rect2D getViewport() const
{
return pvrvk::Rect2D(pvrvk::Offset2D(0, 0), pvrvk::Extent2D(static_cast<int32_t>(getRenderingDimX()), static_cast<uint32_t>(getRenderingDimY())));
}
void setRenderingDimX(float value) { _screenDimensions.x = value; }
void setRenderingDimY(float value) { _screenDimensions.y = value; }
Font createFont(const pvrvk::ImageView& image, const TextureHeader& textureHeader, const pvrvk::Sampler& sampler = pvrvk::Sampler());
Image createImage(const pvrvk::ImageView& image, const pvrvk::Sampler& sampler = pvrvk::Sampler());
Image createImageFromAtlas(const pvrvk::ImageView& image, const pvrvk::Rect2Df& uv, const pvrvk::Sampler& sampler = pvrvk::Sampler());
MatrixGroup createMatrixGroup();
PixelGroup createPixelGroup();
void beginRendering(pvrvk::SecondaryCommandBuffer& commandBuffer) { beginRendering(commandBuffer, pvrvk::Framebuffer(), true); }
void beginRendering(pvrvk::SecondaryCommandBuffer& commandBuffer, const pvrvk::Framebuffer& framebuffer, bool useRenderPass = false)
{
if (!commandBuffer->isRecording())
{
if (useRenderPass) { commandBuffer->begin(_renderpass, _subpass); }
else
{
commandBuffer->begin(framebuffer, _subpass);
}
_mustEndCommandBuffer = true;
}
else
{
_mustEndCommandBuffer = false;
}
pvr::utils::beginCommandBufferDebugLabel(commandBuffer, pvrvk::DebugUtilsLabel("PVRUtilsVk::UIRenderer::Rendering"));
commandBuffer->bindPipeline(getPipeline()); // bind the uirenderer pipeline
_activeCommandBuffer = commandBuffer;
}
void beginRendering(pvrvk::CommandBuffer& commandBuffer)
{
debug_assertion(commandBuffer->isRecording(),
"UIRenderer: If a Primary command buffer is passed to the UIRenderer,"
" it must be in the Recording state");
pvr::utils::beginCommandBufferDebugLabel(commandBuffer, pvrvk::DebugUtilsLabel("PVRUtilsVk::UIRenderer::Rendering"));
_mustEndCommandBuffer = false;
commandBuffer->bindPipeline(getPipeline()); // bind the uirenderer pipeline
_activeCommandBuffer = commandBuffer;
}
void beginRendering(pvrvk::SecondaryCommandBuffer commandBuffer, pvrvk::GraphicsPipeline& pipe) { beginRendering(commandBuffer, pipe, pvrvk::Framebuffer(), true); }
void beginRendering(pvrvk::SecondaryCommandBuffer commandBuffer, pvrvk::GraphicsPipeline& pipe, const pvrvk::Framebuffer& framebuffer, bool useRenderPass = false)
{
if (!commandBuffer->isRecording())
{
if (useRenderPass) { commandBuffer->begin(_renderpass, _subpass); }
else
{
commandBuffer->begin(framebuffer, _subpass);
}
_mustEndCommandBuffer = true;
}
else
{
_mustEndCommandBuffer = false;
}
pvr::utils::beginCommandBufferDebugLabel(commandBuffer, pvrvk::DebugUtilsLabel("PVRUtilsVk::UIRenderer::Rendering"));
commandBuffer->bindPipeline(pipe);
_activeCommandBuffer = commandBuffer;
}
void beginRendering(pvrvk::CommandBuffer commandBuffer, pvrvk::GraphicsPipeline& pipe)
{
debug_assertion(commandBuffer->isRecording(),
"UIRenderer: If a Primary command buffer is passed to the UIRenderer,"
" it must be in the Recording state");
pvr::utils::beginCommandBufferDebugLabel(commandBuffer, pvrvk::DebugUtilsLabel("PVRUtilsVk::UIRenderer::Rendering"));
_mustEndCommandBuffer = false;
commandBuffer->bindPipeline(pipe);
_activeCommandBuffer = commandBuffer;
}
void endRendering()
{
if (_activeCommandBuffer)
{
pvr::utils::endCommandBufferDebugLabel(_activeCommandBuffer);
if (_mustEndCommandBuffer)
{
_mustEndCommandBuffer = false;
_activeCommandBuffer->end();
}
_activeCommandBuffer.reset();
}
}
pvrvk::CommandBufferBase& getActiveCommandBuffer() { return _activeCommandBuffer; }
const Font& getDefaultFont() const { return _defaultFont; }
Font& getDefaultFont() { return _defaultFont; }
const Image& getSdkLogo() const { return _sdkLogo; }
Image& getSdkLogo() { return _sdkLogo; }
const Text& getDefaultTitle() const { return _defaultTitle; }
Text& getDefaultTitle() { return _defaultTitle; }
const Text& getDefaultDescription() const { return _defaultDescription; }
Text& getDefaultDescription() { return _defaultDescription; }
const Text& getDefaultControls() const { return _defaultControls; }
Text& getDefaultControls() { return _defaultControls; }
pvrvk::PipelineLayout getPipelineLayout() { return _pipelineLayout; }
glm::mat4 getProjection() const { return pvr::math::ortho(Api::Vulkan, 0.0, getRenderingDimX(), 0.0f, getRenderingDimY()); }
void rotateScreen90degreeCCW()
{
_screenRotation += glm::pi<float>() * .5f;
std::swap(_screenDimensions.x, _screenDimensions.y);
}
void rotateScreen90degreeCW()
{
_screenRotation -= glm::pi<float>() * .5f;
std::swap(_screenDimensions.x, _screenDimensions.y);
}
glm::mat4 getScreenRotation() const { return glm::rotate(_screenRotation, glm::vec3(0.0f, 0.0f, 1.f)); }
const pvrvk::DescriptorSetLayout& getTexDescriptorSetLayout() const { return _texDescLayout; }
const pvrvk::DescriptorSetLayout& getUboDescSetLayout() const { return _uboMvpDescLayout; }
uint32_t getMaxRenderableSprites() const { return _uboMaterial._numArrayId; }
uint32_t getMaxInstances() const { return _uboMvp._numArrayId; }
uint32_t getNumAvailableSprites() const { return _uboMaterial.getNumAvailableBufferArrays(); }
uint32_t getNumAvailableInstances() const { return _uboMvp.getNumAvailableBufferArrays(); }
pvrvk::DescriptorPool& getDescriptorPool() { return _descPool; }
pvrvk::Sampler& getSamplerBilinear() { return _samplerBilinear; }
pvrvk::Sampler& getSamplerTrilinear() { return _samplerTrilinear; }
private:
void updateResourceOwnsership()
{
std::for_each(_sprites.begin(), _sprites.end(), [this](SpriteWeakRef& sprite) { sprite.lock()->setUIRenderer(this); });
std::for_each(_fonts.begin(), _fonts.end(), [this](FontWeakRef& font) { font.lock()->setUIRenderer(this); });
std::for_each(_textElements.begin(), _textElements.end(), [this](TextElementWeakRef& textElement) { textElement.lock()->setUIRenderer(this); });
}
friend class pvr::ui::impl::Image_;
friend class pvr::ui::impl::Text_;
friend class pvr::ui::impl::Group_;
friend class pvr::ui::impl::Sprite_;
friend class pvr::ui::impl::Font_;
uint64_t generateGroupId() { return _groupId++; }
struct UboMvp
{
friend class ::pvr::ui::UIRenderer;
UboMvp() : _freeArrayId(0) {}
void init(pvrvk::Device& device, pvrvk::DescriptorSetLayout& descLayout, pvrvk::DescriptorPool& pool, UIRenderer& uirenderer);
void initLayout(pvrvk::Device& device, uint32_t numElements);
void reset()
{
_buffer.reset();
_uboDescSetSet.reset();
}
void updateMvp(uint32_t bufferArrayId, const glm::mat4x4& mvp);
int32_t getNewBufferSlice()
{
if (_freeArrayIds.size())
{
const uint32_t id = _freeArrayIds.back();
_freeArrayIds.pop_back();
return static_cast<int32_t>(id);
}
return (_freeArrayId < _numArrayId ? static_cast<int32_t>(_freeArrayId++) : -1);
}
void releaseBufferSlice(uint32_t id)
{
debug_assertion(id < _numArrayId, "Invalid id");
_freeArrayIds.emplace_back(id);
}
void bindUboDynamic(pvrvk::CommandBufferBase& cb, const pvrvk::PipelineLayout& pipelayout, uint32_t mvpBufferSlice)
{
uint32_t dynamicOffsets[] = { static_cast<uint32_t>(_structuredBufferView.getDynamicSliceOffset(mvpBufferSlice)) };
cb->bindDescriptorSet(pvrvk::PipelineBindPoint::e_GRAPHICS, pipelayout, 1, _uboDescSetSet, dynamicOffsets, ARRAY_SIZE(dynamicOffsets));
}
uint32_t getNumAvailableBufferArrays() const { return static_cast<uint32_t>((_numArrayId - _freeArrayId) + _freeArrayIds.size()); }
private:
uint32_t _freeArrayId;
utils::StructuredBufferView _structuredBufferView;
pvrvk::Buffer _buffer;
pvr::utils::vma::Allocation _memAllocation;
pvrvk::DescriptorSet _uboDescSetSet;
uint32_t _numArrayId;
std::vector<uint32_t> _freeArrayIds;
};
struct UboMaterial
{
public:
friend class ::pvr::ui::UIRenderer;
UboMaterial() : _freeArrayId(0) {}
void reset()
{
_buffer.reset();
_uboDescSetSet.reset();
}
void init(pvrvk::Device& device, pvrvk::DescriptorSetLayout& descLayout, pvrvk::DescriptorPool& pool, UIRenderer& uirenderer);
void initLayout(pvrvk::Device& device, uint32_t numArrayId);
void updateMaterial(uint32_t arrayIndex, const glm::vec4& color, int32_t alphaMode, const glm::mat4& uv);
int32_t getNewBufferArray()
{
if (_freeArrayIds.size())
{
const uint32_t id = _freeArrayIds.back();
_freeArrayIds.pop_back();
return static_cast<int32_t>(id);
}
return (_freeArrayId < _numArrayId ? static_cast<int32_t>(_freeArrayId++) : -1);
}
void releaseBufferArray(uint32_t id)
{
debug_assertion(id < _numArrayId, "Invalid id");
_freeArrayIds.emplace_back(id);
}
void bindUboDynamic(pvrvk::CommandBufferBase& cb, const pvrvk::PipelineLayout& pipelayout, uint32_t bufferSlice)
{
uint32_t dynamicOffsets[] = { static_cast<uint32_t>(_structuredBufferView.getDynamicSliceOffset(bufferSlice)) };
cb->bindDescriptorSet(pvrvk::PipelineBindPoint::e_GRAPHICS, pipelayout, 2, _uboDescSetSet, dynamicOffsets, ARRAY_SIZE(dynamicOffsets));
}
uint32_t getNumAvailableBufferArrays() const { return static_cast<uint32_t>(((_numArrayId - _freeArrayId) + _freeArrayIds.size())); }
private:
pvrvk::DescriptorSet _uboDescSetSet;
uint32_t _freeArrayId;
uint32_t _numArrayId;
utils::StructuredBufferView _structuredBufferView;
pvrvk::Buffer _buffer;
std::vector<uint32_t> _freeArrayIds;
};
UboMvp& getUbo() { return _uboMvp; }
UboMaterial& getMaterial() { return _uboMaterial; }
void setUpUboPoolLayouts(uint32_t numInstances, uint32_t numSprites);
void setUpUboPools(uint32_t numInstances, uint32_t numSprites);
void initCreateDefaultFont(pvrvk::CommandBuffer& cmdBuffer);
void initCreateDefaultSdkLogo(pvrvk::CommandBuffer& cmdBuffer);
void initCreateDefaultSampler();
void initCreateDefaultTitle();
void initCreatePipeline(bool isFramebufferSrgb);
void initCreateDescriptorSetLayout();
pvr::utils::vma::Allocator _vmaAllocator;
std::vector<SpriteWeakRef> _sprites;
std::vector<TextElementWeakRef> _textElements;
std::vector<FontWeakRef> _fonts;
pvrvk::RenderPass _renderpass;
uint32_t _subpass;
ProgramData _programData;
Font _defaultFont;
Image _sdkLogo;
Text _defaultTitle;
Text _defaultDescription;
Text _defaultControls;
pvrvk::DeviceWeakPtr _device;
pvrvk::PipelineLayout _pipelineLayout;
pvrvk::GraphicsPipeline _pipeline;
pvrvk::PipelineCache _pipelineCache;
pvrvk::DescriptorSetLayout _texDescLayout;
pvrvk::DescriptorSetLayout _uboMvpDescLayout;
pvrvk::DescriptorSetLayout _uboMaterialLayout;
pvrvk::Sampler _samplerBilinear;
pvrvk::Sampler _samplerTrilinear;
pvrvk::DescriptorPool _descPool;
pvrvk::CommandBufferBase _activeCommandBuffer;
bool _mustEndCommandBuffer;
pvrvk::Buffer _fontIbo;
pvrvk::Buffer _imageVbo;
glm::vec2 _screenDimensions;
float _screenRotation;
uint64_t _groupId = 1;
UboMvp _uboMvp;
UboMaterial _uboMaterial;
uint32_t _numSprites;
// Methods and Members related to MoltenVK support.
#ifdef VK_USE_PLATFORM_MACOS_MVK
MVKConfiguration mvkConfig;
size_t sizeOfMVK = 0;
bool isFullImageViewSwizzleMVK = false;
#endif
};
} // namespace ui
} // namespace pvr