|
32 | 32 | #include <vector> |
33 | 33 |
|
34 | 34 | #include "dawn/common/Enumerator.h" |
| 35 | +#include "dawn/common/Range.h" |
35 | 36 | #include "dawn/native/BindGroupTracker.h" |
36 | 37 | #include "dawn/native/CommandEncoder.h" |
37 | 38 | #include "dawn/native/CommandValidation.h" |
@@ -484,11 +485,165 @@ void RecordResolveQuerySetCmd(VkCommandBuffer commands, |
484 | 485 | } |
485 | 486 | } |
486 | 487 |
|
| 488 | +VkClearValue ToVkClearValue(dawn::native::Color clearColor, TextureComponentType baseType) { |
| 489 | + VkClearValue clearValue; |
| 490 | + switch (baseType) { |
| 491 | + case TextureComponentType::Float: { |
| 492 | + const std::array<float, 4> appliedClearColor = ConvertToFloatColor(clearColor); |
| 493 | + for (uint32_t j = 0; j < 4; ++j) { |
| 494 | + clearValue.color.float32[j] = appliedClearColor[j]; |
| 495 | + } |
| 496 | + break; |
| 497 | + } |
| 498 | + case TextureComponentType::Uint: { |
| 499 | + const std::array<uint32_t, 4> appliedClearColor = |
| 500 | + ConvertToUnsignedIntegerColor(clearColor); |
| 501 | + for (uint32_t j = 0; j < 4; ++j) { |
| 502 | + clearValue.color.uint32[j] = appliedClearColor[j]; |
| 503 | + } |
| 504 | + break; |
| 505 | + } |
| 506 | + case TextureComponentType::Sint: { |
| 507 | + const std::array<int32_t, 4> appliedClearColor = |
| 508 | + ConvertToSignedIntegerColor(clearColor); |
| 509 | + for (uint32_t j = 0; j < 4; ++j) { |
| 510 | + clearValue.color.int32[j] = appliedClearColor[j]; |
| 511 | + } |
| 512 | + break; |
| 513 | + } |
| 514 | + } |
| 515 | + return clearValue; |
| 516 | +} |
| 517 | + |
487 | 518 | } // anonymous namespace |
488 | 519 |
|
| 520 | +MaybeError RecordBeginDynamicRenderPass(CommandRecordingContext* recordingContext, |
| 521 | + Device* device, |
| 522 | + BeginRenderPassCmd* renderPass) { |
| 523 | + // Needed to work around some quirks introduced by vulkan_platform.h which causes some platforms |
| 524 | + // to hit compiler errors if Vulkan struct members are assigned to VK_NULL_HANDLE directly. |
| 525 | + static const VkImageView nullImageView = VK_NULL_HANDLE; |
| 526 | + |
| 527 | + VkRenderingInfoKHR renderInfo; |
| 528 | + renderInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR; |
| 529 | + renderInfo.pNext = nullptr; |
| 530 | + renderInfo.flags = 0; |
| 531 | + renderInfo.renderArea.offset.x = 0; |
| 532 | + renderInfo.renderArea.offset.y = 0; |
| 533 | + renderInfo.renderArea.extent.width = renderPass->width; |
| 534 | + renderInfo.renderArea.extent.height = renderPass->height; |
| 535 | + renderInfo.layerCount = 1; |
| 536 | + renderInfo.viewMask = 0; |
| 537 | + renderInfo.pDepthAttachment = nullptr; |
| 538 | + renderInfo.pStencilAttachment = nullptr; |
| 539 | + |
| 540 | + PerColorAttachment<VkRenderingAttachmentInfoKHR> colorAttachments; |
| 541 | + |
| 542 | + ColorAttachmentMask attachmentMask = renderPass->attachmentState->GetColorAttachmentsMask(); |
| 543 | + ColorAttachmentIndex attachmentCount = GetHighestBitIndexPlusOne(attachmentMask); |
| 544 | + |
| 545 | + // Initialize all potentially used color attachments with null/default values, which allows the |
| 546 | + // attachments to be sparse. |
| 547 | + for (auto i : Range(attachmentCount)) { |
| 548 | + auto& colorAttachment = colorAttachments[i]; |
| 549 | + colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; |
| 550 | + colorAttachment.pNext = nullptr; |
| 551 | + colorAttachment.imageView = nullImageView; |
| 552 | + colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| 553 | + colorAttachment.resolveMode = VK_RESOLVE_MODE_NONE; |
| 554 | + colorAttachment.resolveImageView = nullImageView; |
| 555 | + colorAttachment.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| 556 | + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; |
| 557 | + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; |
| 558 | + } |
| 559 | + |
| 560 | + // Set the color attachments used by this pass. May be sparse. |
| 561 | + for (auto i : attachmentMask) { |
| 562 | + auto& attachmentInfo = renderPass->colorAttachments[i]; |
| 563 | + TextureView* view = ToBackend(attachmentInfo.view.Get()); |
| 564 | + if (view == nullptr) { |
| 565 | + continue; |
| 566 | + } |
| 567 | + |
| 568 | + auto& colorAttachment = colorAttachments[i]; |
| 569 | + if (view->GetDimension() == wgpu::TextureViewDimension::e3D) { |
| 570 | + VkImageView handleFor2DViewOn3D; |
| 571 | + DAWN_TRY_ASSIGN(handleFor2DViewOn3D, |
| 572 | + view->GetOrCreate2DViewOn3D(attachmentInfo.depthSlice)); |
| 573 | + colorAttachment.imageView = handleFor2DViewOn3D; |
| 574 | + } else { |
| 575 | + colorAttachment.imageView = view->GetHandle(); |
| 576 | + } |
| 577 | + |
| 578 | + if (attachmentInfo.resolveTarget != nullptr) { |
| 579 | + TextureView* resolveView = ToBackend(attachmentInfo.resolveTarget.Get()); |
| 580 | + colorAttachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; |
| 581 | + colorAttachment.resolveImageView = resolveView->GetHandle(); |
| 582 | + colorAttachment.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| 583 | + } |
| 584 | + |
| 585 | + colorAttachment.loadOp = VulkanAttachmentLoadOp(attachmentInfo.loadOp); |
| 586 | + colorAttachment.storeOp = VulkanAttachmentStoreOp(attachmentInfo.storeOp); |
| 587 | + colorAttachment.clearValue = ToVkClearValue( |
| 588 | + attachmentInfo.clearColor, view->GetFormat().GetAspectInfo(Aspect::Color).baseType); |
| 589 | + } |
| 590 | + |
| 591 | + renderInfo.colorAttachmentCount = static_cast<uint32_t>(attachmentCount); |
| 592 | + renderInfo.pColorAttachments = colorAttachments.data(); |
| 593 | + |
| 594 | + // Set the depth/stencil attachment used by this pass. |
| 595 | + VkRenderingAttachmentInfoKHR depthAttachment; |
| 596 | + VkRenderingAttachmentInfoKHR stencilAttachment; |
| 597 | + if (renderPass->attachmentState->HasDepthStencilAttachment()) { |
| 598 | + const auto& attachmentInfo = renderPass->depthStencilAttachment; |
| 599 | + TextureView* view = ToBackend(attachmentInfo.view.Get()); |
| 600 | + DAWN_ASSERT(view); |
| 601 | + |
| 602 | + const Format& dsFormat = view->GetTexture()->GetFormat(); |
| 603 | + VkImageLayout imageLayout = VulkanImageLayoutForDepthStencilAttachment( |
| 604 | + dsFormat, attachmentInfo.depthReadOnly, attachmentInfo.stencilReadOnly); |
| 605 | + |
| 606 | + if (dsFormat.HasDepth()) { |
| 607 | + depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; |
| 608 | + depthAttachment.pNext = nullptr; |
| 609 | + depthAttachment.imageView = view->GetHandle(); |
| 610 | + depthAttachment.imageLayout = imageLayout; |
| 611 | + depthAttachment.resolveMode = VK_RESOLVE_MODE_NONE; |
| 612 | + depthAttachment.resolveImageView = nullImageView; |
| 613 | + depthAttachment.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| 614 | + depthAttachment.loadOp = VulkanAttachmentLoadOp(attachmentInfo.depthLoadOp); |
| 615 | + depthAttachment.storeOp = VulkanAttachmentStoreOp(attachmentInfo.depthStoreOp); |
| 616 | + depthAttachment.clearValue.depthStencil.depth = attachmentInfo.clearDepth; |
| 617 | + renderInfo.pDepthAttachment = &depthAttachment; |
| 618 | + } |
| 619 | + |
| 620 | + if (dsFormat.HasStencil()) { |
| 621 | + stencilAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR; |
| 622 | + stencilAttachment.pNext = nullptr; |
| 623 | + stencilAttachment.imageView = view->GetHandle(); |
| 624 | + stencilAttachment.imageLayout = imageLayout; |
| 625 | + stencilAttachment.resolveMode = VK_RESOLVE_MODE_NONE; |
| 626 | + stencilAttachment.resolveImageView = nullImageView; |
| 627 | + stencilAttachment.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| 628 | + stencilAttachment.loadOp = VulkanAttachmentLoadOp(attachmentInfo.stencilLoadOp); |
| 629 | + stencilAttachment.storeOp = VulkanAttachmentStoreOp(attachmentInfo.stencilStoreOp); |
| 630 | + stencilAttachment.clearValue.depthStencil.stencil = attachmentInfo.clearStencil; |
| 631 | + renderInfo.pStencilAttachment = &stencilAttachment; |
| 632 | + } |
| 633 | + } |
| 634 | + |
| 635 | + device->fn.CmdBeginRenderingKHR(recordingContext->commandBuffer, &renderInfo); |
| 636 | + |
| 637 | + return {}; |
| 638 | +} |
| 639 | + |
489 | 640 | MaybeError RecordBeginRenderPass(CommandRecordingContext* recordingContext, |
490 | 641 | Device* device, |
491 | 642 | BeginRenderPassCmd* renderPass) { |
| 643 | + if (device->IsToggleEnabled(Toggle::VulkanUseDynamicRendering)) { |
| 644 | + return RecordBeginDynamicRenderPass(recordingContext, device, renderPass); |
| 645 | + } |
| 646 | + |
492 | 647 | VkCommandBuffer commands = recordingContext->commandBuffer; |
493 | 648 |
|
494 | 649 | // Query a VkRenderPass from the cache |
@@ -537,34 +692,8 @@ MaybeError RecordBeginRenderPass(CommandRecordingContext* recordingContext, |
537 | 692 | continue; |
538 | 693 | } |
539 | 694 |
|
540 | | - VkClearValue clearValue; |
541 | | - switch (view->GetFormat().GetAspectInfo(Aspect::Color).baseType) { |
542 | | - case TextureComponentType::Float: { |
543 | | - const std::array<float, 4> appliedClearColor = |
544 | | - ConvertToFloatColor(attachmentInfo.clearColor); |
545 | | - for (uint32_t j = 0; j < 4; ++j) { |
546 | | - clearValue.color.float32[j] = appliedClearColor[j]; |
547 | | - } |
548 | | - break; |
549 | | - } |
550 | | - case TextureComponentType::Uint: { |
551 | | - const std::array<uint32_t, 4> appliedClearColor = |
552 | | - ConvertToUnsignedIntegerColor(attachmentInfo.clearColor); |
553 | | - for (uint32_t j = 0; j < 4; ++j) { |
554 | | - clearValue.color.uint32[j] = appliedClearColor[j]; |
555 | | - } |
556 | | - break; |
557 | | - } |
558 | | - case TextureComponentType::Sint: { |
559 | | - const std::array<int32_t, 4> appliedClearColor = |
560 | | - ConvertToSignedIntegerColor(attachmentInfo.clearColor); |
561 | | - for (uint32_t j = 0; j < 4; ++j) { |
562 | | - clearValue.color.int32[j] = appliedClearColor[j]; |
563 | | - } |
564 | | - break; |
565 | | - } |
566 | | - } |
567 | | - |
| 695 | + VkClearValue clearValue = ToVkClearValue( |
| 696 | + attachmentInfo.clearColor, view->GetFormat().GetAspectInfo(Aspect::Color).baseType); |
568 | 697 | uint32_t depthSlice = view->GetDimension() == wgpu::TextureViewDimension::e3D |
569 | 698 | ? attachmentInfo.depthSlice |
570 | 699 | : 0; |
@@ -636,6 +765,16 @@ MaybeError RecordBeginRenderPass(CommandRecordingContext* recordingContext, |
636 | 765 | return {}; |
637 | 766 | } |
638 | 767 |
|
| 768 | +void RecordEndRenderPass(CommandRecordingContext* recordingContext, Device* device) { |
| 769 | + VkCommandBuffer commands = recordingContext->commandBuffer; |
| 770 | + |
| 771 | + if (device->IsToggleEnabled(Toggle::VulkanUseDynamicRendering)) { |
| 772 | + device->fn.CmdEndRenderingKHR(commands); |
| 773 | + } else { |
| 774 | + device->fn.CmdEndRenderPass(commands); |
| 775 | + } |
| 776 | +} |
| 777 | + |
639 | 778 | // static |
640 | 779 | Ref<CommandBuffer> CommandBuffer::Create(CommandEncoder* encoder, |
641 | 780 | const CommandBufferDescriptor* descriptor) { |
@@ -1560,7 +1699,7 @@ MaybeError CommandBuffer::RecordRenderPass(CommandRecordingContext* recordingCon |
1560 | 1699 | device->fn.CmdEndQuery(commands, ToBackend(querySet)->GetHandle(), 0); |
1561 | 1700 | } |
1562 | 1701 |
|
1563 | | - device->fn.CmdEndRenderPass(commands); |
| 1702 | + RecordEndRenderPass(recordingContext, device); |
1564 | 1703 |
|
1565 | 1704 | // Write timestamp at the end of render pass if it's set. |
1566 | 1705 | // We've observed that this must be called after the render pass ends or the |
|
0 commit comments