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
54QT_BEGIN_NAMESPACE
55
56class QVulkanFunctions;
57class QVulkanDeviceFunctions;
58
59static const int QVK_FRAMES_IN_FLIGHT = 2;
60
61static const int QVK_DESC_SETS_PER_POOL = 128;
62static const int QVK_UNIFORM_BUFFERS_PER_POOL = 256;
63static const int QVK_COMBINED_IMAGE_SAMPLERS_PER_POOL = 256;
64static const int QVK_STORAGE_BUFFERS_PER_POOL = 128;
65static const int QVK_STORAGE_IMAGES_PER_POOL = 128;
66
67static const int QVK_MAX_ACTIVE_TIMESTAMP_PAIRS = 16;
68
69// no vk_mem_alloc.h available here, void* is good enough
70typedef void * QVkAlloc;
71typedef void * QVkAllocator;
72
73struct 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
96struct QVkTexture;
97
98struct 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
117struct 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
156struct 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
170struct 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
189struct 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
202struct 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
215struct 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
235struct 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
286Q_DECLARE_TYPEINFO(QVkShaderResourceBindings::BoundResourceData, Q_MOVABLE_TYPE);
287
288struct 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
302struct 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
316struct 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
334 void resetState() {
335 recordingPass = NoPass;
336 currentTarget = nullptr;
337
338 secondaryCbs.clear();
339
340 resetCommands();
341 resetCachedState();
342 }
343
344 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(s: currentVertexBuffers, c: 0, n: sizeof(currentVertexBuffers));
356 memset(s: currentVertexOffsets, c: 0, n: 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;
380 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
539 void resetCommands() {
540 commands.clear();
541 resetPools();
542
543 passResTrackers.clear();
544 currentPassResTrackerIndex = -1;
545 }
546
547 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
572Q_DECLARE_TYPEINFO(QVkCommandBuffer::Command, Q_MOVABLE_TYPE);
573
574struct 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
643class QRhiVulkan : public QRhiImplementation
644{
645public:
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 {
856 DescriptorPoolData() { }
857 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 {
877 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
969Q_DECLARE_TYPEINFO(QRhiVulkan::DescriptorPoolData, Q_MOVABLE_TYPE);
970Q_DECLARE_TYPEINFO(QRhiVulkan::DeferredReleaseEntry, Q_MOVABLE_TYPE);
971Q_DECLARE_TYPEINFO(QRhiVulkan::TextureReadback, Q_MOVABLE_TYPE);
972Q_DECLARE_TYPEINFO(QRhiVulkan::BufferReadback, Q_MOVABLE_TYPE);
973
974QT_END_NAMESPACE
975
976#endif
977

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