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

source code of qtbase/src/gui/rhi/qrhivulkan_p.h