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

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