/**************************************************************************** ** ** 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]; QVarLengthArray 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(NativeTexture src) override; NativeTexture nativeTexture() 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; 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, AddressMode w); ~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; bool isCompatible(const QRhiRenderPassDescriptor *other) const override; const QRhiNativeHandles *nativeHandles() override; VkRenderPass rp = VK_NULL_HANDLE; bool ownsRp = false; QVarLengthArray attDescs; QVarLengthArray colorRefs; QVarLengthArray resolveRefs; bool hasDepthStencil = false; VkAttachmentReference dsRef; QRhiVulkanRenderPassNativeHandles nativeHandlesStruct; 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; QVarLengthArray 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; }; }; QVarLengthArray 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; const QRhiNativeHandles *nativeHandles(); VkCommandBuffer cb = VK_NULL_HANDLE; // primary bool useSecondaryCb = false; QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct; enum PassType { NoPass, RenderPass, ComputePass }; void resetState() { recordingPass = NoPass; currentTarget = nullptr; secondaryCbs.clear(); resetCommands(); 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)); inExternal = false; } 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]; QVarLengthArray secondaryCbs; bool inExternal; struct { QHash > writtenResources; void reset() { writtenResources.clear(); } } computePassState; 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, ExecuteSecondary }; 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; int count; int index; } imageBarrier; struct { VkPipelineStageFlags srcStageMask; VkPipelineStageFlags dstStageMask; int count; int index; } 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; int markerNameIndex; } debugMarkerInsert; struct { int trackerIndex; } transitionResources; struct { int x, y, z; } dispatch; struct { VkCommandBuffer cb; } executeSecondary; } args; }; QVector commands; QVarLengthArray passResTrackers; int currentPassResTrackerIndex; void resetCommands() { commands.clear(); resetPools(); passResTrackers.clear(); currentPassResTrackerIndex = -1; } void resetPools() { pools.clearValue.clear(); pools.bufferImageCopy.clear(); pools.dynamicOffset.clear(); pools.vertexBuffer.clear(); pools.vertexBufferOffset.clear(); pools.debugMarkerData.clear(); pools.imageBarrier.clear(); pools.bufferBarrier.clear(); } struct { QVarLengthArray clearValue; QVarLengthArray bufferImageCopy; QVarLengthArray dynamicOffset; QVarLengthArray vertexBuffer; QVarLengthArray vertexBufferOffset; QVarLengthArray debugMarkerData; QVarLengthArray imageBarrier; QVarLengthArray bufferBarrier; } 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 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; // primary 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, QRhiSampler::AddressMode w) 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, QRhi::BeginFrameFlags flags) override; QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) 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 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; bool makeThreadLocalNativeContextCurrent() override; void releaseCachedResources() override; bool isDeviceLost() const 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(QVkRenderPassDescriptor *rpD, bool hasDepthStencil, VkSampleCountFlagBits samples, VkFormat colorFormat); bool createOffscreenRenderPass(QVkRenderPassDescriptor *rpD, const QRhiColorAttachment *firstColorAttachment, const QRhiColorAttachment *lastColorAttachment, bool preserveColor, bool preserveDs, QRhiRenderBuffer *depthStencilBuffer, QRhiTexture *depthTexture); bool ensurePipelineCache(); VkShaderModule createShader(const QByteArray &spirv); void prepareNewFrame(QRhiCommandBuffer *cb); VkCommandBuffer startSecondaryCommandBuffer(QVkRenderTargetData *rtD = nullptr); void endAndEnqueueSecondaryCommandBuffer(VkCommandBuffer cb, QVkCommandBuffer *cbD); void deferredReleaseSecondaryCommandBuffer(VkCommandBuffer cb); QRhi::FrameOpResult startPrimaryCommandBuffer(VkCommandBuffer *cb); QRhi::FrameOpResult endAndSubmitPrimaryCommandBuffer(VkCommandBuffer cb, VkFence cmdFence, VkSemaphore *waitSem, VkSemaphore *signalSem); void waitCommandCompletion(int frameSlot); VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const; using BufferImageCopyList = QVarLengthArray; 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 recordPrimaryCommandBuffer(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; VkPhysicalDeviceFeatures physDevFeatures; VkPhysicalDeviceProperties physDevProperties; VkDeviceSize ubufAlign; VkDeviceSize texbufAlign; bool hasWideLines = false; bool deviceLost = false; 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 descriptorPools; VkQueryPool timestampQueryPool = VK_NULL_HANDLE; QBitArray timestampQueryPoolMap; VkFormat optimalDsFormat = VK_FORMAT_UNDEFINED; QMatrix4x4 clipCorrectMatrix; QVkSwapChain *currentSwapChain = nullptr; QSet swapchains; QRhiVulkanNativeHandles nativeHandlesStruct; struct OffscreenFrame { OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { } bool active = false; QVkCommandBuffer cbWrapper; VkFence cmdFence = VK_NULL_HANDLE; } ofr; struct TextureReadback { int activeFrameSlot = -1; QRhiReadbackDescription desc; QRhiReadbackResult *result; VkBuffer stagingBuf; QVkAlloc stagingAlloc; quint32 byteSize; QSize pixelSize; QRhiTexture::Format format; }; QVector activeTextureReadbacks; struct BufferReadback { int activeFrameSlot = -1; QRhiBufferReadbackResult *result; int byteSize; VkBuffer stagingBuf; QVkAlloc stagingAlloc; }; QVector activeBufferReadbacks; struct DeferredReleaseEntry { enum Type { Pipeline, ShaderResourceBindings, Buffer, RenderBuffer, Texture, Sampler, TextureRenderTarget, RenderPass, StagingBuffer, CommandBuffer }; 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; struct { VkCommandBuffer cb; } commandBuffer; }; }; QVector releaseQueue; }; Q_DECLARE_TYPEINFO(QRhiVulkan::DescriptorPoolData, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QRhiVulkan::DeferredReleaseEntry, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QRhiVulkan::TextureReadback, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QRhiVulkan::BufferReadback, Q_MOVABLE_TYPE); QT_END_NAMESPACE #endif