/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include #include namespace AZ { namespace Render { RPI::Ptr CheckerboardPass::Create(const RPI::PassDescriptor& descriptor) { return aznew CheckerboardPass(descriptor); } CheckerboardPass::CheckerboardPass(const RPI::PassDescriptor& descriptor) : Base(descriptor) { // CheckerboardPass defines its own viewport and scissor m_overrideViewportState = true; m_overrideScissorSate = true; } void CheckerboardPass::FrameBeginInternal(FramePrepareParams params) { float width = (params.m_viewportState.m_maxX - params.m_viewportState.m_minX) * 0.5f; float height = (params.m_viewportState.m_maxY - params.m_viewportState.m_minY) * 0.5f; m_viewportState = params.m_viewportState; m_viewportState.m_minX += 0.5f * m_frameOffset; m_viewportState.m_maxX = m_viewportState.m_minX + width; m_viewportState.m_maxY = m_viewportState.m_minY + height; m_scissorState = params.m_scissorState; m_scissorState.m_maxX = m_scissorState.m_minX + (m_scissorState.m_maxX - m_scissorState.m_minX) / 2; m_scissorState.m_maxY = m_scissorState.m_minY + (m_scissorState.m_maxY - m_scissorState.m_minY) / 2; Base::FrameBeginInternal(params); } void CheckerboardPass::BuildInternal() { Data::Instance pool = RPI::ImageSystemInterface::Get()->GetSystemAttachmentPool(); // Create persistent attachment images to replace transient pass attachments // It's better to check if it connects to output slots too for (RPI::Ptr& attachment : m_ownedAttachments) { if (attachment->m_lifetime == RHI::AttachmentLifetimeType::Transient) { if (attachment->m_descriptor.m_type == RHI::AttachmentType::Image) { // Force update image attachment descriptor to sync up size and format attachment->Update(); attachment->m_lifetime = RHI::AttachmentLifetimeType::Imported; // update image descriptor to new size and samples RHI::ImageDescriptor &imageDesc = attachment->m_descriptor.m_image; imageDesc.m_multisampleState.m_samples = 2; imageDesc.m_size.m_width /= 2; imageDesc.m_size.m_height /= 2; // using hard coded clear value here until we can get the information from pass templated data // [GFX TODO][ATOM-5406] We need a clear value for PassAttachmentDesc and PassAttachment RHI::ClearValue clearValue = RHI::ClearValue::CreateVector4Float(0, 0, 0, 0); if (imageDesc.m_format == RHI::Format::D32_FLOAT_S8X24_UINT) //hacky condition check { imageDesc.m_bindFlags |= RHI::ImageBindFlags::DepthStencil; } else { imageDesc.m_bindFlags |= RHI::ImageBindFlags::Color; } m_imageAttachments[attachment->m_name][0] = RPI::AttachmentImage::Create(*pool.get(), imageDesc, Name(AZStd::string::format("%s_0", attachment->m_path.GetCStr())), &clearValue, nullptr); m_imageAttachments[attachment->m_name][1] = RPI::AttachmentImage::Create(*pool.get(), imageDesc, Name(AZStd::string::format("%s_1", attachment->m_path.GetCStr())), &clearValue, nullptr); attachment->m_path = m_imageAttachments[attachment->m_name][0]->GetAttachmentId(); attachment->m_importedResource = m_imageAttachments[attachment->m_name][0]; } } } // reset frame offset to 0 since attachments are rebuilt m_frameOffset = 0; Base::BuildInternal(); } Data::Instance CheckerboardPass::GetAttachmentImage(Name attachmentName, uint8_t frameOffset) { if (m_imageAttachments.find(attachmentName) != m_imageAttachments.end()) { return m_imageAttachments[attachmentName][frameOffset]; } return nullptr; } void CheckerboardPass::FrameEndInternal() { m_frameOffset = 1 - m_frameOffset; // For next frame, we switch the internal attachment image for each owned pass attachments // So we can preserve the render target from current frame for (RPI::Ptr& attachment : m_ownedAttachments) { if (attachment->m_descriptor.m_type == RHI::AttachmentType::Image) { Data::Instance nextAttachment = GetAttachmentImage(attachment->m_name, m_frameOffset); if (nextAttachment) { // update the attachment id and resource attachment->m_path = nextAttachment->GetAttachmentId(); attachment->m_importedResource = nextAttachment; // the attachment id saved in bindings need to be updated too. so the frame attachment will be attached properly. for (auto& binding : m_attachmentBindings) { if (binding.m_attachment == attachment) { binding.m_unifiedScopeDesc.m_attachmentId = nextAttachment->GetAttachmentId(); break; } } } } } Base::FrameEndInternal(); } } // namespace Render } // namespace AZ