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