1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Gui module
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36 
37 #ifndef QRHIVULKAN_P_H
38 #define QRHIVULKAN_P_H
39 
40 //
41 //  W A R N I N G
42 //  -------------
43 //
44 // This file is not part of the Qt API.  It exists purely as an
45 // implementation detail.  This header file may change from version to
46 // version without notice, or even be removed.
47 //
48 // We mean it.
49 //
50 
51 #include "qrhivulkan_p.h"
52 #include "qrhi_p_p.h"
53 
54 QT_BEGIN_NAMESPACE
55 
56 class QVulkanFunctions;
57 class QVulkanDeviceFunctions;
58 
59 static const int QVK_FRAMES_IN_FLIGHT = 2;
60 
61 static const int QVK_DESC_SETS_PER_POOL = 128;
62 static const int QVK_UNIFORM_BUFFERS_PER_POOL = 256;
63 static const int QVK_COMBINED_IMAGE_SAMPLERS_PER_POOL = 256;
64 static const int QVK_STORAGE_BUFFERS_PER_POOL = 128;
65 static const int QVK_STORAGE_IMAGES_PER_POOL = 128;
66 
67 static const int QVK_MAX_ACTIVE_TIMESTAMP_PAIRS = 16;
68 
69 // no vk_mem_alloc.h available here, void* is good enough
70 typedef void * QVkAlloc;
71 typedef void * QVkAllocator;
72 
73 struct QVkBuffer : public QRhiBuffer
74 {
75     QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
76     ~QVkBuffer();
77     void release() override;
78     bool build() override;
79     QRhiBuffer::NativeBuffer nativeBuffer() override;
80 
81     VkBuffer buffers[QVK_FRAMES_IN_FLIGHT];
82     QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
83     QVarLengthArray<QRhiResourceUpdateBatchPrivate::BufferOp, 16> pendingDynamicUpdates[QVK_FRAMES_IN_FLIGHT];
84     VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
85     QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
86     struct UsageState {
87         VkAccessFlags access = 0;
88         VkPipelineStageFlags stage = 0;
89     };
90     UsageState usageState[QVK_FRAMES_IN_FLIGHT];
91     int lastActiveFrameSlot = -1;
92     uint generation = 0;
93     friend class QRhiVulkan;
94 };
95 
96 struct QVkTexture;
97 
98 struct QVkRenderBuffer : public QRhiRenderBuffer
99 {
100     QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
101                     int sampleCount, Flags flags);
102     ~QVkRenderBuffer();
103     void release() override;
104     bool build() override;
105     QRhiTexture::Format backingFormat() const override;
106 
107     VkDeviceMemory memory = VK_NULL_HANDLE;
108     VkImage image = VK_NULL_HANDLE;
109     VkImageView imageView = VK_NULL_HANDLE;
110     VkSampleCountFlagBits samples;
111     QVkTexture *backingTexture = nullptr;
112     VkFormat vkformat;
113     int lastActiveFrameSlot = -1;
114     friend class QRhiVulkan;
115 };
116 
117 struct QVkTexture : public QRhiTexture
118 {
119     QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
120                int sampleCount, Flags flags);
121     ~QVkTexture();
122     void release() override;
123     bool build() override;
124     bool buildFrom(NativeTexture src) override;
125     NativeTexture nativeTexture() override;
126     void setNativeLayout(int layout) override;
127 
128     bool prepareBuild(QSize *adjustedSize = nullptr);
129     bool finishBuild();
130     VkImageView imageViewForLevel(int level);
131 
132     VkImage image = VK_NULL_HANDLE;
133     VkImageView imageView = VK_NULL_HANDLE;
134     QVkAlloc imageAlloc = nullptr;
135     VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
136     QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
137     VkImageView perLevelImageViews[QRhi::MAX_LEVELS];
138     bool owns = true;
139     struct UsageState {
140         // no tracking of subresource layouts (some operations can keep
141         // subresources in different layouts for some time, but that does not
142         // need to be kept track of)
143         VkImageLayout layout;
144         VkAccessFlags access;
145         VkPipelineStageFlags stage;
146     };
147     UsageState usageState;
148     VkFormat vkformat;
149     uint mipLevelCount = 0;
150     VkSampleCountFlagBits samples;
151     int lastActiveFrameSlot = -1;
152     uint generation = 0;
153     friend class QRhiVulkan;
154 };
155 
156 struct QVkSampler : public QRhiSampler
157 {
158     QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
159                AddressMode u, AddressMode v, AddressMode w);
160     ~QVkSampler();
161     void release() override;
162     bool build() override;
163 
164     VkSampler sampler = VK_NULL_HANDLE;
165     int lastActiveFrameSlot = -1;
166     uint generation = 0;
167     friend class QRhiVulkan;
168 };
169 
170 struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor
171 {
172     QVkRenderPassDescriptor(QRhiImplementation *rhi);
173     ~QVkRenderPassDescriptor();
174     void release() override;
175     bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
176     const QRhiNativeHandles *nativeHandles() override;
177 
178     VkRenderPass rp = VK_NULL_HANDLE;
179     bool ownsRp = false;
180     QVarLengthArray<VkAttachmentDescription, 8> attDescs;
181     QVarLengthArray<VkAttachmentReference, 8> colorRefs;
182     QVarLengthArray<VkAttachmentReference, 8> resolveRefs;
183     bool hasDepthStencil = false;
184     VkAttachmentReference dsRef;
185     QRhiVulkanRenderPassNativeHandles nativeHandlesStruct;
186     int lastActiveFrameSlot = -1;
187 };
188 
189 struct QVkRenderTargetData
190 {
191     VkFramebuffer fb = VK_NULL_HANDLE;
192     QVkRenderPassDescriptor *rp = nullptr;
193     QSize pixelSize;
194     float dpr = 1;
195     int sampleCount = 1;
196     int colorAttCount = 0;
197     int dsAttCount = 0;
198     int resolveAttCount = 0;
199     static const int MAX_COLOR_ATTACHMENTS = 8;
200 };
201 
202 struct QVkReferenceRenderTarget : public QRhiRenderTarget
203 {
204     QVkReferenceRenderTarget(QRhiImplementation *rhi);
205     ~QVkReferenceRenderTarget();
206     void release() override;
207 
208     QSize pixelSize() const override;
209     float devicePixelRatio() const override;
210     int sampleCount() const override;
211 
212     QVkRenderTargetData d;
213 };
214 
215 struct QVkTextureRenderTarget : public QRhiTextureRenderTarget
216 {
217     QVkTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
218     ~QVkTextureRenderTarget();
219     void release() override;
220 
221     QSize pixelSize() const override;
222     float devicePixelRatio() const override;
223     int sampleCount() const override;
224 
225     QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
226     bool build() override;
227 
228     QVkRenderTargetData d;
229     VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
230     VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
231     int lastActiveFrameSlot = -1;
232     friend class QRhiVulkan;
233 };
234 
235 struct QVkShaderResourceBindings : public QRhiShaderResourceBindings
236 {
237     QVkShaderResourceBindings(QRhiImplementation *rhi);
238     ~QVkShaderResourceBindings();
239     void release() override;
240     bool build() override;
241 
242     QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
243     int poolIndex = -1;
244     VkDescriptorSetLayout layout = VK_NULL_HANDLE;
245     VkDescriptorSet descSets[QVK_FRAMES_IN_FLIGHT]; // multiple sets to support dynamic buffers
246     int lastActiveFrameSlot = -1;
247     uint generation = 0;
248 
249     // Keep track of the generation number of each referenced QRhi* to be able
250     // to detect that the underlying descriptor set became out of date and they
251     // need to be written again with the up-to-date VkBuffer etc. objects.
252     struct BoundUniformBufferData {
253         quint64 id;
254         uint generation;
255     };
256     struct BoundSampledTextureData {
257         int count;
258         struct {
259             quint64 texId;
260             uint texGeneration;
261             quint64 samplerId;
262             uint samplerGeneration;
263         } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
264     };
265     struct BoundStorageImageData {
266         quint64 id;
267         uint generation;
268     };
269     struct BoundStorageBufferData {
270         quint64 id;
271         uint generation;
272     };
273     struct BoundResourceData {
274         union {
275             BoundUniformBufferData ubuf;
276             BoundSampledTextureData stex;
277             BoundStorageImageData simage;
278             BoundStorageBufferData sbuf;
279         };
280     };
281     QVarLengthArray<BoundResourceData, 8> boundResourceData[QVK_FRAMES_IN_FLIGHT];
282 
283     friend class QRhiVulkan;
284 };
285 
286 Q_DECLARE_TYPEINFO(QVkShaderResourceBindings::BoundResourceData, Q_MOVABLE_TYPE);
287 
288 struct QVkGraphicsPipeline : public QRhiGraphicsPipeline
289 {
290     QVkGraphicsPipeline(QRhiImplementation *rhi);
291     ~QVkGraphicsPipeline();
292     void release() override;
293     bool build() override;
294 
295     VkPipelineLayout layout = VK_NULL_HANDLE;
296     VkPipeline pipeline = VK_NULL_HANDLE;
297     int lastActiveFrameSlot = -1;
298     uint generation = 0;
299     friend class QRhiVulkan;
300 };
301 
302 struct QVkComputePipeline : public QRhiComputePipeline
303 {
304     QVkComputePipeline(QRhiImplementation *rhi);
305     ~QVkComputePipeline();
306     void release() override;
307     bool build() override;
308 
309     VkPipelineLayout layout = VK_NULL_HANDLE;
310     VkPipeline pipeline = VK_NULL_HANDLE;
311     int lastActiveFrameSlot = -1;
312     uint generation = 0;
313     friend class QRhiVulkan;
314 };
315 
316 struct QVkCommandBuffer : public QRhiCommandBuffer
317 {
318     QVkCommandBuffer(QRhiImplementation *rhi);
319     ~QVkCommandBuffer();
320     void release() override;
321 
322     const QRhiNativeHandles *nativeHandles();
323 
324     VkCommandBuffer cb = VK_NULL_HANDLE; // primary
325     bool useSecondaryCb = false;
326     QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct;
327 
328     enum PassType {
329         NoPass,
330         RenderPass,
331         ComputePass
332     };
333 
resetStateQVkCommandBuffer334     void resetState() {
335         recordingPass = NoPass;
336         currentTarget = nullptr;
337 
338         secondaryCbs.clear();
339 
340         resetCommands();
341         resetCachedState();
342     }
343 
resetCachedStateQVkCommandBuffer344     void resetCachedState() {
345         currentGraphicsPipeline = nullptr;
346         currentComputePipeline = nullptr;
347         currentPipelineGeneration = 0;
348         currentGraphicsSrb = nullptr;
349         currentComputeSrb = nullptr;
350         currentSrbGeneration = 0;
351         currentDescSetSlot = -1;
352         currentIndexBuffer = VK_NULL_HANDLE;
353         currentIndexOffset = 0;
354         currentIndexFormat = VK_INDEX_TYPE_UINT16;
355         memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
356         memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
357         inExternal = false;
358     }
359 
360     PassType recordingPass;
361     QRhiRenderTarget *currentTarget;
362     QRhiGraphicsPipeline *currentGraphicsPipeline;
363     QRhiComputePipeline *currentComputePipeline;
364     uint currentPipelineGeneration;
365     QRhiShaderResourceBindings *currentGraphicsSrb;
366     QRhiShaderResourceBindings *currentComputeSrb;
367     uint currentSrbGeneration;
368     int currentDescSetSlot;
369     VkBuffer currentIndexBuffer;
370     quint32 currentIndexOffset;
371     VkIndexType currentIndexFormat;
372     static const int VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32;
373     VkBuffer currentVertexBuffers[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
374     quint32 currentVertexOffsets[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
375     QVarLengthArray<VkCommandBuffer, 4> secondaryCbs;
376     bool inExternal;
377 
378     struct {
379         QHash<QRhiResource *, QPair<VkAccessFlags, bool> > writtenResources;
resetQVkCommandBuffer::__anon947c54120308380         void reset() {
381             writtenResources.clear();
382         }
383     } computePassState;
384 
385     struct Command {
386         enum Cmd {
387             CopyBuffer,
388             CopyBufferToImage,
389             CopyImage,
390             CopyImageToBuffer,
391             ImageBarrier,
392             BufferBarrier,
393             BlitImage,
394             BeginRenderPass,
395             EndRenderPass,
396             BindPipeline,
397             BindDescriptorSet,
398             BindVertexBuffer,
399             BindIndexBuffer,
400             SetViewport,
401             SetScissor,
402             SetBlendConstants,
403             SetStencilRef,
404             Draw,
405             DrawIndexed,
406             DebugMarkerBegin,
407             DebugMarkerEnd,
408             DebugMarkerInsert,
409             TransitionPassResources,
410             Dispatch,
411             ExecuteSecondary
412         };
413         Cmd cmd;
414 
415         union Args {
416             struct {
417                 VkBuffer src;
418                 VkBuffer dst;
419                 VkBufferCopy desc;
420             } copyBuffer;
421             struct {
422                 VkBuffer src;
423                 VkImage dst;
424                 VkImageLayout dstLayout;
425                 int count;
426                 int bufferImageCopyIndex;
427             } copyBufferToImage;
428             struct {
429                 VkImage src;
430                 VkImageLayout srcLayout;
431                 VkImage dst;
432                 VkImageLayout dstLayout;
433                 VkImageCopy desc;
434             } copyImage;
435             struct {
436                 VkImage src;
437                 VkImageLayout srcLayout;
438                 VkBuffer dst;
439                 VkBufferImageCopy desc;
440             } copyImageToBuffer;
441             struct {
442                 VkPipelineStageFlags srcStageMask;
443                 VkPipelineStageFlags dstStageMask;
444                 int count;
445                 int index;
446             } imageBarrier;
447             struct {
448                 VkPipelineStageFlags srcStageMask;
449                 VkPipelineStageFlags dstStageMask;
450                 int count;
451                 int index;
452             } bufferBarrier;
453             struct {
454                 VkImage src;
455                 VkImageLayout srcLayout;
456                 VkImage dst;
457                 VkImageLayout dstLayout;
458                 VkFilter filter;
459                 VkImageBlit desc;
460             } blitImage;
461             struct {
462                 VkRenderPassBeginInfo desc;
463                 int clearValueIndex;
464             } beginRenderPass;
465             struct {
466             } endRenderPass;
467             struct {
468                 VkPipelineBindPoint bindPoint;
469                 VkPipeline pipeline;
470             } bindPipeline;
471             struct {
472                 VkPipelineBindPoint bindPoint;
473                 VkPipelineLayout pipelineLayout;
474                 VkDescriptorSet descSet;
475                 int dynamicOffsetCount;
476                 int dynamicOffsetIndex;
477             } bindDescriptorSet;
478             struct {
479                 int startBinding;
480                 int count;
481                 int vertexBufferIndex;
482                 int vertexBufferOffsetIndex;
483             } bindVertexBuffer;
484             struct {
485                 VkBuffer buf;
486                 VkDeviceSize ofs;
487                 VkIndexType type;
488             } bindIndexBuffer;
489             struct {
490                 VkViewport viewport;
491             } setViewport;
492             struct {
493                 VkRect2D scissor;
494             } setScissor;
495             struct {
496                 float c[4];
497             } setBlendConstants;
498             struct {
499                 uint32_t ref;
500             } setStencilRef;
501             struct {
502                 uint32_t vertexCount;
503                 uint32_t instanceCount;
504                 uint32_t firstVertex;
505                 uint32_t firstInstance;
506             } draw;
507             struct {
508                 uint32_t indexCount;
509                 uint32_t instanceCount;
510                 uint32_t firstIndex;
511                 int32_t vertexOffset;
512                 uint32_t firstInstance;
513             } drawIndexed;
514             struct {
515                 VkDebugMarkerMarkerInfoEXT marker;
516                 int markerNameIndex;
517             } debugMarkerBegin;
518             struct {
519             } debugMarkerEnd;
520             struct {
521                 VkDebugMarkerMarkerInfoEXT marker;
522                 int markerNameIndex;
523             } debugMarkerInsert;
524             struct {
525                 int trackerIndex;
526             } transitionResources;
527             struct {
528                 int x, y, z;
529             } dispatch;
530             struct {
531                 VkCommandBuffer cb;
532             } executeSecondary;
533         } args;
534     };
535     QVector<Command> commands;
536     QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers;
537     int currentPassResTrackerIndex;
538 
resetCommandsQVkCommandBuffer539     void resetCommands() {
540         commands.clear();
541         resetPools();
542 
543         passResTrackers.clear();
544         currentPassResTrackerIndex = -1;
545     }
546 
resetPoolsQVkCommandBuffer547     void resetPools() {
548         pools.clearValue.clear();
549         pools.bufferImageCopy.clear();
550         pools.dynamicOffset.clear();
551         pools.vertexBuffer.clear();
552         pools.vertexBufferOffset.clear();
553         pools.debugMarkerData.clear();
554         pools.imageBarrier.clear();
555         pools.bufferBarrier.clear();
556     }
557 
558     struct {
559         QVarLengthArray<VkClearValue, 4> clearValue;
560         QVarLengthArray<VkBufferImageCopy, 16> bufferImageCopy;
561         QVarLengthArray<uint32_t, 4> dynamicOffset;
562         QVarLengthArray<VkBuffer, 4> vertexBuffer;
563         QVarLengthArray<VkDeviceSize, 4> vertexBufferOffset;
564         QVarLengthArray<QByteArray, 4> debugMarkerData;
565         QVarLengthArray<VkImageMemoryBarrier, 8> imageBarrier;
566         QVarLengthArray<VkBufferMemoryBarrier, 8> bufferBarrier;
567     } pools;
568 
569     friend class QRhiVulkan;
570 };
571 
572 Q_DECLARE_TYPEINFO(QVkCommandBuffer::Command, Q_MOVABLE_TYPE);
573 
574 struct QVkSwapChain : public QRhiSwapChain
575 {
576     QVkSwapChain(QRhiImplementation *rhi);
577     ~QVkSwapChain();
578     void release() override;
579 
580     QRhiCommandBuffer *currentFrameCommandBuffer() override;
581     QRhiRenderTarget *currentFrameRenderTarget() override;
582 
583     QSize surfacePixelSize() override;
584 
585     QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
586     bool buildOrResize() override;
587 
588     bool ensureSurface();
589 
590     static const quint32 MAX_BUFFER_COUNT = 3;
591 
592     QWindow *window = nullptr;
593     QSize pixelSize;
594     bool supportsReadback = false;
595     VkSwapchainKHR sc = VK_NULL_HANDLE;
596     int bufferCount = 0;
597     VkSurfaceKHR surface = VK_NULL_HANDLE;
598     VkSurfaceKHR lastConnectedSurface = VK_NULL_HANDLE;
599     VkFormat colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
600     VkColorSpaceKHR colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
601     QVkRenderBuffer *ds = nullptr;
602     VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
603     QVector<VkPresentModeKHR> supportedPresentationModes;
604     VkDeviceMemory msaaImageMem = VK_NULL_HANDLE;
605     QVkReferenceRenderTarget rtWrapper;
606     QVkCommandBuffer cbWrapper;
607 
608     struct ImageResources {
609         VkImage image = VK_NULL_HANDLE;
610         VkImageView imageView = VK_NULL_HANDLE;
611         VkFramebuffer fb = VK_NULL_HANDLE;
612         VkImage msaaImage = VK_NULL_HANDLE;
613         VkImageView msaaImageView = VK_NULL_HANDLE;
614         enum LastUse {
615             ScImageUseNone,
616             ScImageUseRender,
617             ScImageUseTransferSource
618         };
619         LastUse lastUse = ScImageUseNone;
620     } imageRes[MAX_BUFFER_COUNT];
621 
622     struct FrameResources {
623         VkFence imageFence = VK_NULL_HANDLE;
624         bool imageFenceWaitable = false;
625         VkSemaphore imageSem = VK_NULL_HANDLE;
626         VkSemaphore drawSem = VK_NULL_HANDLE;
627         bool imageAcquired = false;
628         bool imageSemWaitable = false;
629         quint32 imageIndex = 0;
630         VkCommandBuffer cmdBuf = VK_NULL_HANDLE; // primary
631         VkFence cmdFence = VK_NULL_HANDLE;
632         bool cmdFenceWaitable = false;
633         int timestampQueryIndex = -1;
634     } frameRes[QVK_FRAMES_IN_FLIGHT];
635 
636     quint32 currentImageIndex = 0; // index in imageRes
637     quint32 currentFrameSlot = 0; // index in frameRes
638     int frameCount = 0;
639 
640     friend class QRhiVulkan;
641 };
642 
643 class QRhiVulkan : public QRhiImplementation
644 {
645 public:
646     QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *importDevice = nullptr);
647 
648     bool create(QRhi::Flags flags) override;
649     void destroy() override;
650 
651     QRhiGraphicsPipeline *createGraphicsPipeline() override;
652     QRhiComputePipeline *createComputePipeline() override;
653     QRhiShaderResourceBindings *createShaderResourceBindings() override;
654     QRhiBuffer *createBuffer(QRhiBuffer::Type type,
655                              QRhiBuffer::UsageFlags usage,
656                              int size) override;
657     QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
658                                          const QSize &pixelSize,
659                                          int sampleCount,
660                                          QRhiRenderBuffer::Flags flags) override;
661     QRhiTexture *createTexture(QRhiTexture::Format format,
662                                const QSize &pixelSize,
663                                int sampleCount,
664                                QRhiTexture::Flags flags) override;
665     QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
666                                QRhiSampler::Filter minFilter,
667                                QRhiSampler::Filter mipmapMode,
668                                QRhiSampler:: AddressMode u,
669                                QRhiSampler::AddressMode v,
670                                QRhiSampler::AddressMode w) override;
671 
672     QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
673                                                        QRhiTextureRenderTarget::Flags flags) override;
674 
675     QRhiSwapChain *createSwapChain() override;
676     QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
677     QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
678     QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
679     QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
680     QRhi::FrameOpResult finish() override;
681 
682     void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
683 
684     void beginPass(QRhiCommandBuffer *cb,
685                    QRhiRenderTarget *rt,
686                    const QColor &colorClearValue,
687                    const QRhiDepthStencilClearValue &depthStencilClearValue,
688                    QRhiResourceUpdateBatch *resourceUpdates) override;
689     void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
690 
691     void setGraphicsPipeline(QRhiCommandBuffer *cb,
692                              QRhiGraphicsPipeline *ps) override;
693 
694     void setShaderResources(QRhiCommandBuffer *cb,
695                             QRhiShaderResourceBindings *srb,
696                             int dynamicOffsetCount,
697                             const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
698 
699     void setVertexInput(QRhiCommandBuffer *cb,
700                         int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
701                         QRhiBuffer *indexBuf, quint32 indexOffset,
702                         QRhiCommandBuffer::IndexFormat indexFormat) override;
703 
704     void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
705     void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
706     void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
707     void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
708 
709     void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
710               quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
711 
712     void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
713                      quint32 instanceCount, quint32 firstIndex,
714                      qint32 vertexOffset, quint32 firstInstance) override;
715 
716     void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
717     void debugMarkEnd(QRhiCommandBuffer *cb) override;
718     void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
719 
720     void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
721     void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
722     void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
723     void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
724 
725     const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
726     void beginExternal(QRhiCommandBuffer *cb) override;
727     void endExternal(QRhiCommandBuffer *cb) override;
728 
729     QVector<int> supportedSampleCounts() const override;
730     int ubufAlignment() const override;
731     bool isYUpInFramebuffer() const override;
732     bool isYUpInNDC() const override;
733     bool isClipDepthZeroToOne() const override;
734     QMatrix4x4 clipSpaceCorrMatrix() const override;
735     bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
736     bool isFeatureSupported(QRhi::Feature feature) const override;
737     int resourceLimit(QRhi::ResourceLimit limit) const override;
738     const QRhiNativeHandles *nativeHandles() override;
739     void sendVMemStatsToProfiler() override;
740     bool makeThreadLocalNativeContextCurrent() override;
741     void releaseCachedResources() override;
742     bool isDeviceLost() const override;
743 
744     VkResult createDescriptorPool(VkDescriptorPool *pool);
745     bool allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex);
746     uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex);
747     bool createTransientImage(VkFormat format, const QSize &pixelSize, VkImageUsageFlags usage,
748                               VkImageAspectFlags aspectMask, VkSampleCountFlagBits samples,
749                               VkDeviceMemory *mem, VkImage *images, VkImageView *views, int count);
750 
751     bool recreateSwapChain(QRhiSwapChain *swapChain);
752     void releaseSwapChainResources(QRhiSwapChain *swapChain);
753 
754     VkFormat optimalDepthStencilFormat();
755     VkSampleCountFlagBits effectiveSampleCount(int sampleCount);
756     bool createDefaultRenderPass(QVkRenderPassDescriptor *rpD,
757                                  bool hasDepthStencil,
758                                  VkSampleCountFlagBits samples,
759                                  VkFormat colorFormat);
760     bool createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
761                                    const QRhiColorAttachment *firstColorAttachment,
762                                    const QRhiColorAttachment *lastColorAttachment,
763                                    bool preserveColor,
764                                    bool preserveDs,
765                                    QRhiRenderBuffer *depthStencilBuffer,
766                                    QRhiTexture *depthTexture);
767     bool ensurePipelineCache();
768     VkShaderModule createShader(const QByteArray &spirv);
769 
770     void prepareNewFrame(QRhiCommandBuffer *cb);
771     VkCommandBuffer startSecondaryCommandBuffer(QVkRenderTargetData *rtD = nullptr);
772     void endAndEnqueueSecondaryCommandBuffer(VkCommandBuffer cb, QVkCommandBuffer *cbD);
773     void deferredReleaseSecondaryCommandBuffer(VkCommandBuffer cb);
774     QRhi::FrameOpResult startPrimaryCommandBuffer(VkCommandBuffer *cb);
775     QRhi::FrameOpResult endAndSubmitPrimaryCommandBuffer(VkCommandBuffer cb, VkFence cmdFence,
776                                                          VkSemaphore *waitSem, VkSemaphore *signalSem);
777     void waitCommandCompletion(int frameSlot);
778     VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
779     using BufferImageCopyList = QVarLengthArray<VkBufferImageCopy, 16>;
780     void prepareUploadSubres(QVkTexture *texD, int layer, int level,
781                              const QRhiTextureSubresourceUploadDescription &subresDesc,
782                              size_t *curOfs, void *mp,
783                              BufferImageCopyList *copyInfos);
784     void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
785     void executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot);
786     void enqueueTransitionPassResources(QVkCommandBuffer *cbD);
787     void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD);
788     void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
789                                QVkBuffer *bufD,
790                                int slot,
791                                QRhiPassResourceTracker::BufferAccess access,
792                                QRhiPassResourceTracker::BufferStage stage);
793     void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker,
794                                 QVkTexture *texD,
795                                 QRhiPassResourceTracker::TextureAccess access,
796                                 QRhiPassResourceTracker::TextureStage stage);
797     void recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhiPassResourceTracker &tracker);
798     void activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRenderTarget *rtD);
799     void executeDeferredReleases(bool forced = false);
800     void finishActiveReadbacks(bool forced = false);
801 
802     void setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot = -1);
803     void trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, int slot,
804                               VkAccessFlags access, VkPipelineStageFlags stage);
805     void trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
806                              VkImageLayout layout, VkAccessFlags access, VkPipelineStageFlags stage);
807     void subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
808                             VkImageLayout oldLayout, VkImageLayout newLayout,
809                             VkAccessFlags srcAccess, VkAccessFlags dstAccess,
810                             VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage,
811                             int startLayer, int layerCount,
812                             int startLevel, int levelCount);
813     void updateShaderResourceBindings(QRhiShaderResourceBindings *srb, int descSetIdx = -1);
814 
815     QVulkanInstance *inst = nullptr;
816     QWindow *maybeWindow = nullptr;
817     QByteArrayList requestedDeviceExtensions;
818     bool importedDevice = false;
819     VkPhysicalDevice physDev = VK_NULL_HANDLE;
820     VkDevice dev = VK_NULL_HANDLE;
821     bool importedCmdPool = false;
822     VkCommandPool cmdPool = VK_NULL_HANDLE;
823     int gfxQueueFamilyIdx = -1;
824     VkQueue gfxQueue = VK_NULL_HANDLE;
825     bool hasCompute = false;
826     quint32 timestampValidBits = 0;
827     bool importedAllocator = false;
828     QVkAllocator allocator = nullptr;
829     QVulkanFunctions *f = nullptr;
830     QVulkanDeviceFunctions *df = nullptr;
831     VkPhysicalDeviceFeatures physDevFeatures;
832     VkPhysicalDeviceProperties physDevProperties;
833     VkDeviceSize ubufAlign;
834     VkDeviceSize texbufAlign;
835     bool hasWideLines = false;
836     bool deviceLost = false;
837 
838     bool debugMarkersAvailable = false;
839     bool vertexAttribDivisorAvailable = false;
840     PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = nullptr;
841     PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = nullptr;
842     PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = nullptr;
843     PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectName = nullptr;
844 
845     PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
846     PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
847     PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
848     PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
849     PFN_vkQueuePresentKHR vkQueuePresentKHR;
850     PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
851     PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
852     PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
853 
854     VkPipelineCache pipelineCache = VK_NULL_HANDLE;
855     struct DescriptorPoolData {
DescriptorPoolDataDescriptorPoolData856         DescriptorPoolData() { }
DescriptorPoolDataDescriptorPoolData857         DescriptorPoolData(VkDescriptorPool pool_)
858             : pool(pool_)
859         { }
860         VkDescriptorPool pool = VK_NULL_HANDLE;
861         int refCount = 0;
862         int allocedDescSets = 0;
863     };
864     QVector<DescriptorPoolData> descriptorPools;
865 
866     VkQueryPool timestampQueryPool = VK_NULL_HANDLE;
867     QBitArray timestampQueryPoolMap;
868 
869     VkFormat optimalDsFormat = VK_FORMAT_UNDEFINED;
870     QMatrix4x4 clipCorrectMatrix;
871 
872     QVkSwapChain *currentSwapChain = nullptr;
873     QSet<QVkSwapChain *> swapchains;
874     QRhiVulkanNativeHandles nativeHandlesStruct;
875 
876     struct OffscreenFrame {
OffscreenFrameOffscreenFrame877         OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
878         bool active = false;
879         QVkCommandBuffer cbWrapper;
880         VkFence cmdFence = VK_NULL_HANDLE;
881     } ofr;
882 
883     struct TextureReadback {
884         int activeFrameSlot = -1;
885         QRhiReadbackDescription desc;
886         QRhiReadbackResult *result;
887         VkBuffer stagingBuf;
888         QVkAlloc stagingAlloc;
889         quint32 byteSize;
890         QSize pixelSize;
891         QRhiTexture::Format format;
892     };
893     QVector<TextureReadback> activeTextureReadbacks;
894     struct BufferReadback {
895         int activeFrameSlot = -1;
896         QRhiBufferReadbackResult *result;
897         int byteSize;
898         VkBuffer stagingBuf;
899         QVkAlloc stagingAlloc;
900     };
901     QVector<BufferReadback> activeBufferReadbacks;
902 
903     struct DeferredReleaseEntry {
904         enum Type {
905             Pipeline,
906             ShaderResourceBindings,
907             Buffer,
908             RenderBuffer,
909             Texture,
910             Sampler,
911             TextureRenderTarget,
912             RenderPass,
913             StagingBuffer,
914             CommandBuffer
915         };
916         Type type;
917         int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1
918         union {
919             struct {
920                 VkPipeline pipeline;
921                 VkPipelineLayout layout;
922             } pipelineState;
923             struct {
924                 int poolIndex;
925                 VkDescriptorSetLayout layout;
926             } shaderResourceBindings;
927             struct {
928                 VkBuffer buffers[QVK_FRAMES_IN_FLIGHT];
929                 QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
930                 VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
931                 QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
932             } buffer;
933             struct {
934                 VkDeviceMemory memory;
935                 VkImage image;
936                 VkImageView imageView;
937             } renderBuffer;
938             struct {
939                 VkImage image;
940                 VkImageView imageView;
941                 QVkAlloc allocation;
942                 VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
943                 QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
944                 VkImageView extraImageViews[QRhi::MAX_LEVELS];
945             } texture;
946             struct {
947                 VkSampler sampler;
948             } sampler;
949             struct {
950                 VkFramebuffer fb;
951                 VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
952                 VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
953             } textureRenderTarget;
954             struct {
955                 VkRenderPass rp;
956             } renderPass;
957             struct {
958                 VkBuffer stagingBuffer;
959                 QVkAlloc stagingAllocation;
960             } stagingBuffer;
961             struct {
962                 VkCommandBuffer cb;
963             } commandBuffer;
964         };
965     };
966     QVector<DeferredReleaseEntry> releaseQueue;
967 };
968 
969 Q_DECLARE_TYPEINFO(QRhiVulkan::DescriptorPoolData, Q_MOVABLE_TYPE);
970 Q_DECLARE_TYPEINFO(QRhiVulkan::DeferredReleaseEntry, Q_MOVABLE_TYPE);
971 Q_DECLARE_TYPEINFO(QRhiVulkan::TextureReadback, Q_MOVABLE_TYPE);
972 Q_DECLARE_TYPEINFO(QRhiVulkan::BufferReadback, Q_MOVABLE_TYPE);
973 
974 QT_END_NAMESPACE
975 
976 #endif
977