diff options
Diffstat (limited to 'src/gui/rhi/qrhivulkan_p_p.h')
-rw-r--r-- | src/gui/rhi/qrhivulkan_p_p.h | 915 |
1 files changed, 915 insertions, 0 deletions
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h new file mode 100644 index 0000000000..cec9016603 --- /dev/null +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -0,0 +1,915 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Gui module +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRHIVULKAN_P_H +#define QRHIVULKAN_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qrhivulkan_p.h" +#include "qrhi_p_p.h" + +QT_BEGIN_NAMESPACE + +class QVulkanFunctions; +class QVulkanDeviceFunctions; + +static const int QVK_FRAMES_IN_FLIGHT = 2; + +static const int QVK_DESC_SETS_PER_POOL = 128; +static const int QVK_UNIFORM_BUFFERS_PER_POOL = 256; +static const int QVK_COMBINED_IMAGE_SAMPLERS_PER_POOL = 256; +static const int QVK_STORAGE_BUFFERS_PER_POOL = 128; +static const int QVK_STORAGE_IMAGES_PER_POOL = 128; + +static const int QVK_MAX_ACTIVE_TIMESTAMP_PAIRS = 16; + +// no vk_mem_alloc.h available here, void* is good enough +typedef void * QVkAlloc; +typedef void * QVkAllocator; + +struct QVkBuffer : public QRhiBuffer +{ + QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size); + ~QVkBuffer(); + void release() override; + bool build() override; + + VkBuffer buffers[QVK_FRAMES_IN_FLIGHT]; + QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT]; + QVector<QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate> pendingDynamicUpdates[QVK_FRAMES_IN_FLIGHT]; + VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT]; + QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT]; + struct UsageState { + VkAccessFlags access = 0; + VkPipelineStageFlags stage = 0; + }; + UsageState usageState[QVK_FRAMES_IN_FLIGHT]; + int lastActiveFrameSlot = -1; + uint generation = 0; + friend class QRhiVulkan; +}; + +struct QVkTexture; + +struct QVkRenderBuffer : public QRhiRenderBuffer +{ + QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, + int sampleCount, Flags flags); + ~QVkRenderBuffer(); + void release() override; + bool build() override; + QRhiTexture::Format backingFormat() const override; + + VkDeviceMemory memory = VK_NULL_HANDLE; + VkImage image = VK_NULL_HANDLE; + VkImageView imageView = VK_NULL_HANDLE; + VkSampleCountFlagBits samples; + QVkTexture *backingTexture = nullptr; + VkFormat vkformat; + int lastActiveFrameSlot = -1; + friend class QRhiVulkan; +}; + +struct QVkTexture : public QRhiTexture +{ + QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, + int sampleCount, Flags flags); + ~QVkTexture(); + void release() override; + bool build() override; + bool buildFrom(const QRhiNativeHandles *src) override; + const QRhiNativeHandles *nativeHandles() override; + + bool prepareBuild(QSize *adjustedSize = nullptr); + bool finishBuild(); + VkImageView imageViewForLevel(int level); + + VkImage image = VK_NULL_HANDLE; + VkImageView imageView = VK_NULL_HANDLE; + QVkAlloc imageAlloc = nullptr; + VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT]; + QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT]; + VkImageView perLevelImageViews[QRhi::MAX_LEVELS]; + bool owns = true; + QRhiVulkanTextureNativeHandles nativeHandlesStruct; + struct UsageState { + // no tracking of subresource layouts (some operations can keep + // subresources in different layouts for some time, but that does not + // need to be kept track of) + VkImageLayout layout; + VkAccessFlags access; + VkPipelineStageFlags stage; + }; + UsageState usageState; + VkFormat vkformat; + uint mipLevelCount = 0; + VkSampleCountFlagBits samples; + int lastActiveFrameSlot = -1; + uint generation = 0; + friend class QRhiVulkan; +}; + +struct QVkSampler : public QRhiSampler +{ + QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, + AddressMode u, AddressMode v); + ~QVkSampler(); + void release() override; + bool build() override; + + VkSampler sampler = VK_NULL_HANDLE; + int lastActiveFrameSlot = -1; + uint generation = 0; + friend class QRhiVulkan; +}; + +struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor +{ + QVkRenderPassDescriptor(QRhiImplementation *rhi); + ~QVkRenderPassDescriptor(); + void release() override; + + VkRenderPass rp = VK_NULL_HANDLE; + bool ownsRp = false; + int lastActiveFrameSlot = -1; +}; + +struct QVkRenderTargetData +{ + VkFramebuffer fb = VK_NULL_HANDLE; + QVkRenderPassDescriptor *rp = nullptr; + QSize pixelSize; + float dpr = 1; + int sampleCount = 1; + int colorAttCount = 0; + int dsAttCount = 0; + int resolveAttCount = 0; + static const int MAX_COLOR_ATTACHMENTS = 8; +}; + +struct QVkReferenceRenderTarget : public QRhiRenderTarget +{ + QVkReferenceRenderTarget(QRhiImplementation *rhi); + ~QVkReferenceRenderTarget(); + void release() override; + + QSize pixelSize() const override; + float devicePixelRatio() const override; + int sampleCount() const override; + + QVkRenderTargetData d; +}; + +struct QVkTextureRenderTarget : public QRhiTextureRenderTarget +{ + QVkTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags); + ~QVkTextureRenderTarget(); + void release() override; + + QSize pixelSize() const override; + float devicePixelRatio() const override; + int sampleCount() const override; + + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; + bool build() override; + + QVkRenderTargetData d; + VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS]; + VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS]; + int lastActiveFrameSlot = -1; + friend class QRhiVulkan; +}; + +struct QVkShaderResourceBindings : public QRhiShaderResourceBindings +{ + QVkShaderResourceBindings(QRhiImplementation *rhi); + ~QVkShaderResourceBindings(); + void release() override; + bool build() override; + + QVector<QRhiShaderResourceBinding> sortedBindings; + int poolIndex = -1; + VkDescriptorSetLayout layout = VK_NULL_HANDLE; + VkDescriptorSet descSets[QVK_FRAMES_IN_FLIGHT]; // multiple sets to support dynamic buffers + int lastActiveFrameSlot = -1; + uint generation = 0; + + // Keep track of the generation number of each referenced QRhi* to be able + // to detect that the underlying descriptor set became out of date and they + // need to be written again with the up-to-date VkBuffer etc. objects. + struct BoundUniformBufferData { + quint64 id; + uint generation; + }; + struct BoundSampledTextureData { + quint64 texId; + uint texGeneration; + quint64 samplerId; + uint samplerGeneration; + }; + struct BoundStorageImageData { + quint64 id; + uint generation; + }; + struct BoundStorageBufferData { + quint64 id; + uint generation; + }; + struct BoundResourceData { + union { + BoundUniformBufferData ubuf; + BoundSampledTextureData stex; + BoundStorageImageData simage; + BoundStorageBufferData sbuf; + }; + }; + QVector<BoundResourceData> boundResourceData[QVK_FRAMES_IN_FLIGHT]; + + friend class QRhiVulkan; +}; + +Q_DECLARE_TYPEINFO(QVkShaderResourceBindings::BoundResourceData, Q_MOVABLE_TYPE); + +struct QVkGraphicsPipeline : public QRhiGraphicsPipeline +{ + QVkGraphicsPipeline(QRhiImplementation *rhi); + ~QVkGraphicsPipeline(); + void release() override; + bool build() override; + + VkPipelineLayout layout = VK_NULL_HANDLE; + VkPipeline pipeline = VK_NULL_HANDLE; + int lastActiveFrameSlot = -1; + uint generation = 0; + friend class QRhiVulkan; +}; + +struct QVkComputePipeline : public QRhiComputePipeline +{ + QVkComputePipeline(QRhiImplementation *rhi); + ~QVkComputePipeline(); + void release() override; + bool build() override; + + VkPipelineLayout layout = VK_NULL_HANDLE; + VkPipeline pipeline = VK_NULL_HANDLE; + int lastActiveFrameSlot = -1; + uint generation = 0; + friend class QRhiVulkan; +}; + +struct QVkCommandBuffer : public QRhiCommandBuffer +{ + QVkCommandBuffer(QRhiImplementation *rhi); + ~QVkCommandBuffer(); + void release() override; + + VkCommandBuffer cb = VK_NULL_HANDLE; + QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct; + + const QRhiNativeHandles *nativeHandles() { + nativeHandlesStruct.commandBuffer = cb; + return &nativeHandlesStruct; + } + + enum PassType { + NoPass, + RenderPass, + ComputePass + }; + + void resetState() { + resetCommands(); + recordingPass = NoPass; + currentTarget = nullptr; + resetCachedState(); + } + + void resetCachedState() { + currentGraphicsPipeline = nullptr; + currentComputePipeline = nullptr; + currentPipelineGeneration = 0; + currentGraphicsSrb = nullptr; + currentComputeSrb = nullptr; + currentSrbGeneration = 0; + currentDescSetSlot = -1; + currentIndexBuffer = VK_NULL_HANDLE; + currentIndexOffset = 0; + currentIndexFormat = VK_INDEX_TYPE_UINT16; + memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers)); + memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets)); + } + + PassType recordingPass; + QRhiRenderTarget *currentTarget; + QRhiGraphicsPipeline *currentGraphicsPipeline; + QRhiComputePipeline *currentComputePipeline; + uint currentPipelineGeneration; + QRhiShaderResourceBindings *currentGraphicsSrb; + QRhiShaderResourceBindings *currentComputeSrb; + uint currentSrbGeneration; + int currentDescSetSlot; + VkBuffer currentIndexBuffer; + quint32 currentIndexOffset; + VkIndexType currentIndexFormat; + static const int VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32; + VkBuffer currentVertexBuffers[VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + quint32 currentVertexOffsets[VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + + struct Command { + enum Cmd { + CopyBuffer, + CopyBufferToImage, + CopyImage, + CopyImageToBuffer, + ImageBarrier, + BufferBarrier, + BlitImage, + BeginRenderPass, + EndRenderPass, + BindPipeline, + BindDescriptorSet, + BindVertexBuffer, + BindIndexBuffer, + SetViewport, + SetScissor, + SetBlendConstants, + SetStencilRef, + Draw, + DrawIndexed, + DebugMarkerBegin, + DebugMarkerEnd, + DebugMarkerInsert, + TransitionPassResources, + Dispatch + }; + Cmd cmd; + + union Args { + struct { + VkBuffer src; + VkBuffer dst; + VkBufferCopy desc; + } copyBuffer; + struct { + VkBuffer src; + VkImage dst; + VkImageLayout dstLayout; + int count; + int bufferImageCopyIndex; + } copyBufferToImage; + struct { + VkImage src; + VkImageLayout srcLayout; + VkImage dst; + VkImageLayout dstLayout; + VkImageCopy desc; + } copyImage; + struct { + VkImage src; + VkImageLayout srcLayout; + VkBuffer dst; + VkBufferImageCopy desc; + } copyImageToBuffer; + struct { + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkImageMemoryBarrier desc; + } imageBarrier; + struct { + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkBufferMemoryBarrier desc; + } bufferBarrier; + struct { + VkImage src; + VkImageLayout srcLayout; + VkImage dst; + VkImageLayout dstLayout; + VkFilter filter; + VkImageBlit desc; + } blitImage; + struct { + VkRenderPassBeginInfo desc; + int clearValueIndex; + } beginRenderPass; + struct { + } endRenderPass; + struct { + VkPipelineBindPoint bindPoint; + VkPipeline pipeline; + } bindPipeline; + struct { + VkPipelineBindPoint bindPoint; + VkPipelineLayout pipelineLayout; + VkDescriptorSet descSet; + int dynamicOffsetCount; + int dynamicOffsetIndex; + } bindDescriptorSet; + struct { + int startBinding; + int count; + int vertexBufferIndex; + int vertexBufferOffsetIndex; + } bindVertexBuffer; + struct { + VkBuffer buf; + VkDeviceSize ofs; + VkIndexType type; + } bindIndexBuffer; + struct { + VkViewport viewport; + } setViewport; + struct { + VkRect2D scissor; + } setScissor; + struct { + float c[4]; + } setBlendConstants; + struct { + uint32_t ref; + } setStencilRef; + struct { + uint32_t vertexCount; + uint32_t instanceCount; + uint32_t firstVertex; + uint32_t firstInstance; + } draw; + struct { + uint32_t indexCount; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t vertexOffset; + uint32_t firstInstance; + } drawIndexed; + struct { + VkDebugMarkerMarkerInfoEXT marker; + int markerNameIndex; + } debugMarkerBegin; + struct { + } debugMarkerEnd; + struct { + VkDebugMarkerMarkerInfoEXT marker; + } debugMarkerInsert; + struct { + int trackerIndex; + } transitionResources; + struct { + int x, y, z; + } dispatch; + } args; + }; + QVector<Command> commands; + QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers; + int currentPassResTrackerIndex; + + void resetCommands() { + commands.clear(); + passResTrackers.clear(); + currentPassResTrackerIndex = -1; + resetPools(); + } + + void resetPools() { + pools.clearValue.clear(); + pools.bufferImageCopy.clear(); + pools.dynamicOffset.clear(); + pools.vertexBuffer.clear(); + pools.vertexBufferOffset.clear(); + pools.debugMarkerName.clear(); + } + + struct { + QVarLengthArray<VkClearValue, 4> clearValue; + QVarLengthArray<VkBufferImageCopy, 16> bufferImageCopy; + QVarLengthArray<uint32_t, 4> dynamicOffset; + QVarLengthArray<VkBuffer, 4> vertexBuffer; + QVarLengthArray<VkDeviceSize, 4> vertexBufferOffset; + QVarLengthArray<QByteArray, 4> debugMarkerName; + } pools; + + friend class QRhiVulkan; +}; + +Q_DECLARE_TYPEINFO(QVkCommandBuffer::Command, Q_MOVABLE_TYPE); + +struct QVkSwapChain : public QRhiSwapChain +{ + QVkSwapChain(QRhiImplementation *rhi); + ~QVkSwapChain(); + void release() override; + + QRhiCommandBuffer *currentFrameCommandBuffer() override; + QRhiRenderTarget *currentFrameRenderTarget() override; + + QSize surfacePixelSize() override; + + QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; + bool buildOrResize() override; + + bool ensureSurface(); + + static const quint32 MAX_BUFFER_COUNT = 3; + + QWindow *window = nullptr; + QSize pixelSize; + bool supportsReadback = false; + VkSwapchainKHR sc = VK_NULL_HANDLE; + int bufferCount = 0; + VkSurfaceKHR surface = VK_NULL_HANDLE; + VkSurfaceKHR lastConnectedSurface = VK_NULL_HANDLE; + VkFormat colorFormat = VK_FORMAT_B8G8R8A8_UNORM; + VkColorSpaceKHR colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + QVkRenderBuffer *ds = nullptr; + VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; + QVector<VkPresentModeKHR> supportedPresentationModes; + VkDeviceMemory msaaImageMem = VK_NULL_HANDLE; + QVkReferenceRenderTarget rtWrapper; + QVkCommandBuffer cbWrapper; + + struct ImageResources { + VkImage image = VK_NULL_HANDLE; + VkImageView imageView = VK_NULL_HANDLE; + VkFramebuffer fb = VK_NULL_HANDLE; + VkImage msaaImage = VK_NULL_HANDLE; + VkImageView msaaImageView = VK_NULL_HANDLE; + enum LastUse { + ScImageUseNone, + ScImageUseRender, + ScImageUseTransferSource + }; + LastUse lastUse = ScImageUseNone; + } imageRes[MAX_BUFFER_COUNT]; + + struct FrameResources { + VkFence imageFence = VK_NULL_HANDLE; + bool imageFenceWaitable = false; + VkSemaphore imageSem = VK_NULL_HANDLE; + VkSemaphore drawSem = VK_NULL_HANDLE; + bool imageAcquired = false; + bool imageSemWaitable = false; + quint32 imageIndex = 0; + VkCommandBuffer cmdBuf = VK_NULL_HANDLE; + VkFence cmdFence = VK_NULL_HANDLE; + bool cmdFenceWaitable = false; + int timestampQueryIndex = -1; + } frameRes[QVK_FRAMES_IN_FLIGHT]; + + quint32 currentImageIndex = 0; // index in imageRes + quint32 currentFrameSlot = 0; // index in frameRes + int frameCount = 0; + + friend class QRhiVulkan; +}; + +class QRhiVulkan : public QRhiImplementation +{ +public: + QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *importDevice = nullptr); + + bool create(QRhi::Flags flags) override; + void destroy() override; + + QRhiGraphicsPipeline *createGraphicsPipeline() override; + QRhiComputePipeline *createComputePipeline() override; + QRhiShaderResourceBindings *createShaderResourceBindings() override; + QRhiBuffer *createBuffer(QRhiBuffer::Type type, + QRhiBuffer::UsageFlags usage, + int size) override; + QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type, + const QSize &pixelSize, + int sampleCount, + QRhiRenderBuffer::Flags flags) override; + QRhiTexture *createTexture(QRhiTexture::Format format, + const QSize &pixelSize, + int sampleCount, + QRhiTexture::Flags flags) override; + QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + QRhiSampler::Filter mipmapMode, + QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override; + + QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, + QRhiTextureRenderTarget::Flags flags) override; + + QRhiSwapChain *createSwapChain() override; + QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override; + QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override; + QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override; + QRhi::FrameOpResult endOffscreenFrame() override; + QRhi::FrameOpResult finish() override; + + void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + + void beginPass(QRhiCommandBuffer *cb, + QRhiRenderTarget *rt, + const QColor &colorClearValue, + const QRhiDepthStencilClearValue &depthStencilClearValue, + QRhiResourceUpdateBatch *resourceUpdates) override; + void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + + void setGraphicsPipeline(QRhiCommandBuffer *cb, + QRhiGraphicsPipeline *ps) override; + + void setShaderResources(QRhiCommandBuffer *cb, + QRhiShaderResourceBindings *srb, + int dynamicOffsetCount, + const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override; + + void setVertexInput(QRhiCommandBuffer *cb, + int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, + QRhiBuffer *indexBuf, quint32 indexOffset, + QRhiCommandBuffer::IndexFormat indexFormat) override; + + void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override; + void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override; + void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override; + void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override; + + void draw(QRhiCommandBuffer *cb, quint32 vertexCount, + quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override; + + void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, + quint32 instanceCount, quint32 firstIndex, + qint32 vertexOffset, quint32 firstInstance) override; + + void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override; + void debugMarkEnd(QRhiCommandBuffer *cb) override; + void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; + + void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; + void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; + + const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override; + void beginExternal(QRhiCommandBuffer *cb) override; + void endExternal(QRhiCommandBuffer *cb) override; + + QVector<int> supportedSampleCounts() const override; + int ubufAlignment() const override; + bool isYUpInFramebuffer() const override; + bool isYUpInNDC() const override; + bool isClipDepthZeroToOne() const override; + QMatrix4x4 clipSpaceCorrMatrix() const override; + bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; + bool isFeatureSupported(QRhi::Feature feature) const override; + int resourceLimit(QRhi::ResourceLimit limit) const override; + const QRhiNativeHandles *nativeHandles() override; + void sendVMemStatsToProfiler() override; + void makeThreadLocalNativeContextCurrent() override; + + VkResult createDescriptorPool(VkDescriptorPool *pool); + bool allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex); + uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex); + bool createTransientImage(VkFormat format, const QSize &pixelSize, VkImageUsageFlags usage, + VkImageAspectFlags aspectMask, VkSampleCountFlagBits samples, + VkDeviceMemory *mem, VkImage *images, VkImageView *views, int count); + + bool recreateSwapChain(QRhiSwapChain *swapChain); + void releaseSwapChainResources(QRhiSwapChain *swapChain); + + VkFormat optimalDepthStencilFormat(); + VkSampleCountFlagBits effectiveSampleCount(int sampleCount); + bool createDefaultRenderPass(VkRenderPass *rp, + bool hasDepthStencil, + VkSampleCountFlagBits samples, + VkFormat colorFormat); + bool createOffscreenRenderPass(VkRenderPass *rp, + const QVector<QRhiColorAttachment> &colorAttachments, + bool preserveColor, + bool preserveDs, + QRhiRenderBuffer *depthStencilBuffer, + QRhiTexture *depthTexture); + bool ensurePipelineCache(); + VkShaderModule createShader(const QByteArray &spirv); + + void prepareNewFrame(QRhiCommandBuffer *cb); + QRhi::FrameOpResult startCommandBuffer(VkCommandBuffer *cb); + QRhi::FrameOpResult endAndSubmitCommandBuffer(VkCommandBuffer cb, VkFence cmdFence, + VkSemaphore *waitSem, VkSemaphore *signalSem); + void waitCommandCompletion(int frameSlot); + VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const; + using BufferImageCopyList = QVarLengthArray<VkBufferImageCopy, 16>; + void prepareUploadSubres(QVkTexture *texD, int layer, int level, + const QRhiTextureSubresourceUploadDescription &subresDesc, + size_t *curOfs, void *mp, + BufferImageCopyList *copyInfos); + void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates); + void executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD); + void enqueueTransitionPassResources(QVkCommandBuffer *cbD); + void recordCommandBuffer(QVkCommandBuffer *cbD); + void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker, + QVkBuffer *bufD, + int slot, + QRhiPassResourceTracker::BufferAccess access, + QRhiPassResourceTracker::BufferStage stage); + void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker, + QVkTexture *texD, + QRhiPassResourceTracker::TextureAccess access, + QRhiPassResourceTracker::TextureStage stage); + void recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhiPassResourceTracker &tracker); + void activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRenderTarget *rtD); + void executeDeferredReleases(bool forced = false); + void finishActiveReadbacks(bool forced = false); + + void setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot = -1); + void trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, int slot, + VkAccessFlags access, VkPipelineStageFlags stage); + void trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD, + VkImageLayout layout, VkAccessFlags access, VkPipelineStageFlags stage); + void subresourceBarrier(QVkCommandBuffer *cbD, VkImage image, + VkImageLayout oldLayout, VkImageLayout newLayout, + VkAccessFlags srcAccess, VkAccessFlags dstAccess, + VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage, + int startLayer, int layerCount, + int startLevel, int levelCount); + void updateShaderResourceBindings(QRhiShaderResourceBindings *srb, int descSetIdx = -1); + + QVulkanInstance *inst = nullptr; + QWindow *maybeWindow = nullptr; + bool importedDevice = false; + VkPhysicalDevice physDev = VK_NULL_HANDLE; + VkDevice dev = VK_NULL_HANDLE; + bool importedCmdPool = false; + VkCommandPool cmdPool = VK_NULL_HANDLE; + int gfxQueueFamilyIdx = -1; + VkQueue gfxQueue = VK_NULL_HANDLE; + bool hasCompute = false; + quint32 timestampValidBits = 0; + bool importedAllocator = false; + QVkAllocator allocator = nullptr; + QVulkanFunctions *f = nullptr; + QVulkanDeviceFunctions *df = nullptr; + VkPhysicalDeviceProperties physDevProperties; + VkDeviceSize ubufAlign; + VkDeviceSize texbufAlign; + + bool debugMarkersAvailable = false; + bool vertexAttribDivisorAvailable = false; + PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = nullptr; + PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = nullptr; + PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = nullptr; + PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectName = nullptr; + + PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr; + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; + PFN_vkQueuePresentKHR vkQueuePresentKHR; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr; + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; + + VkPipelineCache pipelineCache = VK_NULL_HANDLE; + struct DescriptorPoolData { + DescriptorPoolData() { } + DescriptorPoolData(VkDescriptorPool pool_) + : pool(pool_) + { } + VkDescriptorPool pool = VK_NULL_HANDLE; + int refCount = 0; + int allocedDescSets = 0; + }; + QVector<DescriptorPoolData> descriptorPools; + + VkQueryPool timestampQueryPool = VK_NULL_HANDLE; + QBitArray timestampQueryPoolMap; + + VkFormat optimalDsFormat = VK_FORMAT_UNDEFINED; + QMatrix4x4 clipCorrectMatrix; + + QVkSwapChain *currentSwapChain = nullptr; + QSet<QVkSwapChain *> swapchains; + QRhiVulkanNativeHandles nativeHandlesStruct; + + struct OffscreenFrame { + OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { } + bool active = false; + QVkCommandBuffer cbWrapper; + VkFence cmdFence = VK_NULL_HANDLE; + } ofr; + + struct ActiveReadback { + int activeFrameSlot = -1; + QRhiReadbackDescription desc; + QRhiReadbackResult *result; + VkBuffer buf; + QVkAlloc bufAlloc; + quint32 bufSize; + QSize pixelSize; + QRhiTexture::Format format; + }; + QVector<ActiveReadback> activeReadbacks; + + struct DeferredReleaseEntry { + enum Type { + Pipeline, + ShaderResourceBindings, + Buffer, + RenderBuffer, + Texture, + Sampler, + TextureRenderTarget, + RenderPass, + StagingBuffer + }; + Type type; + int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1 + union { + struct { + VkPipeline pipeline; + VkPipelineLayout layout; + } pipelineState; + struct { + int poolIndex; + VkDescriptorSetLayout layout; + } shaderResourceBindings; + struct { + VkBuffer buffers[QVK_FRAMES_IN_FLIGHT]; + QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT]; + VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT]; + QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT]; + } buffer; + struct { + VkDeviceMemory memory; + VkImage image; + VkImageView imageView; + } renderBuffer; + struct { + VkImage image; + VkImageView imageView; + QVkAlloc allocation; + VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT]; + QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT]; + VkImageView extraImageViews[QRhi::MAX_LEVELS]; + } texture; + struct { + VkSampler sampler; + } sampler; + struct { + VkFramebuffer fb; + VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS]; + VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS]; + } textureRenderTarget; + struct { + VkRenderPass rp; + } renderPass; + struct { + VkBuffer stagingBuffer; + QVkAlloc stagingAllocation; + } stagingBuffer; + }; + }; + QVector<DeferredReleaseEntry> releaseQueue; +}; + +Q_DECLARE_TYPEINFO(QRhiVulkan::DescriptorPoolData, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QRhiVulkan::DeferredReleaseEntry, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QRhiVulkan::ActiveReadback, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +#endif |