CheckerboardPass.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Atom/RPI.Public/Image/AttachmentImagePool.h>
  9. #include <Atom/RPI.Public/Image/ImageSystemInterface.h>
  10. #include <Checkerboard/CheckerboardPass.h>
  11. namespace AZ
  12. {
  13. namespace Render
  14. {
  15. RPI::Ptr<Render::CheckerboardPass> CheckerboardPass::Create(const RPI::PassDescriptor& descriptor)
  16. {
  17. return aznew CheckerboardPass(descriptor);
  18. }
  19. CheckerboardPass::CheckerboardPass(const RPI::PassDescriptor& descriptor)
  20. : Base(descriptor)
  21. {
  22. // CheckerboardPass defines its own viewport and scissor
  23. m_overrideViewportState = true;
  24. m_overrideScissorSate = true;
  25. }
  26. void CheckerboardPass::FrameBeginInternal(FramePrepareParams params)
  27. {
  28. float width = (params.m_viewportState.m_maxX - params.m_viewportState.m_minX) * 0.5f;
  29. float height = (params.m_viewportState.m_maxY - params.m_viewportState.m_minY) * 0.5f;
  30. m_viewportState = params.m_viewportState;
  31. m_viewportState.m_minX += 0.5f * m_frameOffset;
  32. m_viewportState.m_maxX = m_viewportState.m_minX + width;
  33. m_viewportState.m_maxY = m_viewportState.m_minY + height;
  34. m_scissorState = params.m_scissorState;
  35. m_scissorState.m_maxX = m_scissorState.m_minX + (m_scissorState.m_maxX - m_scissorState.m_minX) / 2;
  36. m_scissorState.m_maxY = m_scissorState.m_minY + (m_scissorState.m_maxY - m_scissorState.m_minY) / 2;
  37. Base::FrameBeginInternal(params);
  38. }
  39. void CheckerboardPass::BuildInternal()
  40. {
  41. Data::Instance<RPI::AttachmentImagePool> pool = RPI::ImageSystemInterface::Get()->GetSystemAttachmentPool();
  42. // Create persistent attachment images to replace transient pass attachments
  43. // It's better to check if it connects to output slots too
  44. for (RPI::Ptr<RPI::PassAttachment>& attachment : m_ownedAttachments)
  45. {
  46. if (attachment->m_lifetime == RHI::AttachmentLifetimeType::Transient)
  47. {
  48. if (attachment->m_descriptor.m_type == RHI::AttachmentType::Image)
  49. {
  50. // Force update image attachment descriptor to sync up size and format
  51. attachment->Update();
  52. attachment->m_lifetime = RHI::AttachmentLifetimeType::Imported;
  53. // update image descriptor to new size and samples
  54. RHI::ImageDescriptor &imageDesc = attachment->m_descriptor.m_image;
  55. imageDesc.m_multisampleState.m_samples = 2;
  56. imageDesc.m_size.m_width /= 2;
  57. imageDesc.m_size.m_height /= 2;
  58. // using hard coded clear value here until we can get the information from pass templated data
  59. // [GFX TODO][ATOM-5406] We need a clear value for PassAttachmentDesc and PassAttachment
  60. RHI::ClearValue clearValue = RHI::ClearValue::CreateVector4Float(0, 0, 0, 0);
  61. if (imageDesc.m_format == RHI::Format::D32_FLOAT_S8X24_UINT) //hacky condition check
  62. {
  63. imageDesc.m_bindFlags |= RHI::ImageBindFlags::DepthStencil;
  64. }
  65. else
  66. {
  67. imageDesc.m_bindFlags |= RHI::ImageBindFlags::Color;
  68. }
  69. m_imageAttachments[attachment->m_name][0] = RPI::AttachmentImage::Create(*pool.get(), imageDesc,
  70. Name(AZStd::string::format("%s_0", attachment->m_path.GetCStr())), &clearValue, nullptr);
  71. m_imageAttachments[attachment->m_name][1] = RPI::AttachmentImage::Create(*pool.get(), imageDesc,
  72. Name(AZStd::string::format("%s_1", attachment->m_path.GetCStr())), &clearValue, nullptr);
  73. attachment->m_path = m_imageAttachments[attachment->m_name][0]->GetAttachmentId();
  74. attachment->m_importedResource = m_imageAttachments[attachment->m_name][0];
  75. }
  76. }
  77. }
  78. // reset frame offset to 0 since attachments are rebuilt
  79. m_frameOffset = 0;
  80. Base::BuildInternal();
  81. }
  82. Data::Instance<RPI::AttachmentImage> CheckerboardPass::GetAttachmentImage(Name attachmentName, uint8_t frameOffset)
  83. {
  84. if (m_imageAttachments.find(attachmentName) != m_imageAttachments.end())
  85. {
  86. return m_imageAttachments[attachmentName][frameOffset];
  87. }
  88. return nullptr;
  89. }
  90. void CheckerboardPass::FrameEndInternal()
  91. {
  92. m_frameOffset = 1 - m_frameOffset;
  93. // For next frame, we switch the internal attachment image for each owned pass attachments
  94. // So we can preserve the render target from current frame
  95. for (RPI::Ptr<RPI::PassAttachment>& attachment : m_ownedAttachments)
  96. {
  97. if (attachment->m_descriptor.m_type == RHI::AttachmentType::Image)
  98. {
  99. Data::Instance<RPI::AttachmentImage> nextAttachment = GetAttachmentImage(attachment->m_name, m_frameOffset);
  100. if (nextAttachment)
  101. {
  102. // update the attachment id and resource
  103. attachment->m_path = nextAttachment->GetAttachmentId();
  104. attachment->m_importedResource = nextAttachment;
  105. // the attachment id saved in bindings need to be updated too. so the frame attachment will be attached properly.
  106. for (auto& binding : m_attachmentBindings)
  107. {
  108. if (binding.GetAttachment() == attachment)
  109. {
  110. binding.m_unifiedScopeDesc.m_attachmentId = nextAttachment->GetAttachmentId();
  111. break;
  112. }
  113. }
  114. }
  115. }
  116. }
  117. Base::FrameEndInternal();
  118. }
  119. } // namespace Render
  120. } // namespace AZ