/* * 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 #include #include #include #include #include #include #include #include #include namespace AtomSampleViewer { namespace ShaderInputs { static const char* const ShaderInputImageWorldMatrix{ "m_worldMatrix" }; static const char* const ShaderInputImageViewProjectionMatrix{ "m_viewProjectionMatrix" }; static const char* const ShaderInputImageLightViewProjectionMatrix{ "m_lightViewProjectionMatrix" }; static const char* const ShaderInputImageLightPosition{ "m_lightPosition" }; static const char* const ShaderInputImageAmbientColor{ "m_ambientColor" }; static const char* const ShaderInputImageDiffuseColor{ "m_diffuseColor" }; static const char* const ShaderInputImageDepthMapTexture{ "m_depthMapTexture" }; } const AZ::Vector3 MultipleViewsComponent::m_up = AZ::Vector3(0.0f, 1.0f, 0.0f); const AZ::Vector3 MultipleViewsComponent::m_lookAt = AZ::Vector3(0.0f, 0.0f, 0.0f); void MultipleViewsComponent::Reflect(AZ::ReflectContext* context) { if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() ->Version(0) ; } } MultipleViewsComponent::MultipleViewsComponent() { m_depthMapID = AZ::RHI::AttachmentId("DepthMapAttachmentID"); m_depthStencilID = AZ::RHI::AttachmentId{ "DepthStencilID" }; m_depthClearValue = AZ::RHI::ClearValue::CreateDepthStencil(1.0f, 0); m_supportRHISamplePipeline = true; } void MultipleViewsComponent::OnFramePrepare(AZ::RHI::FrameGraphBuilder& frameGraphBuilder) { static float time = 0.0f; time += 0.005f; //Update light position and light view matrix m_lightPosition.SetX(12.0f*cosf(time)); m_lightPosition.SetZ(12.0f*sinf(time)); m_lightViewProjectionMatrix = m_lightProjectionMatrix * CreateViewMatrix(m_lightPosition.GetAsVector3(), m_up, m_lookAt); if (m_shaderResourceGroups[0]) { m_shaderResourceGroups[0]->SetConstant(m_shaderInputConstantIndices[0], m_worldMatrix); m_shaderResourceGroups[0]->SetConstant(m_shaderInputConstantIndices[1], m_lightViewProjectionMatrix); m_shaderResourceGroups[0]->Compile(); } if (m_shaderResourceGroups[1]) { m_shaderResourceGroups[1]->SetConstant(m_shaderInputConstantIndices[0], m_worldMatrix); m_shaderResourceGroups[1]->SetConstant(m_shaderInputConstantIndices[1], m_viewProjectionMatrix); m_shaderResourceGroups[1]->SetConstant(m_shaderInputConstantIndices[2], m_lightViewProjectionMatrix); m_shaderResourceGroups[1]->SetConstant(m_shaderInputConstantIndices[3], m_lightPosition); m_shaderResourceGroups[1]->SetConstant(m_shaderInputConstantIndices[4], m_ambientColor); m_shaderResourceGroups[1]->SetConstant(m_shaderInputConstantIndices[5], m_diffuseColor); } BasicRHIComponent::OnFramePrepare(frameGraphBuilder); } void MultipleViewsComponent::Activate() { CreateInputAssemblyBuffersAndViews(); SetupScene(); InitRenderTarget(); ReadDepthShader(); ReadMainShader(); CreateDepthScope(); CreateMainScope(); AZ::RHI::RHISystemNotificationBus::Handler::BusConnect(); } void MultipleViewsComponent::Deactivate() { AZ::RHI::RHISystemNotificationBus::Handler::BusDisconnect(); m_windowContext = nullptr; m_bufferPool = nullptr; m_inputAssemblyBuffer = nullptr; m_shaderResourceGroups.fill(nullptr); m_pipelineStates.fill(nullptr); m_scopeProducers.clear(); } void MultipleViewsComponent::SetupScene() { m_ambientColor = AZ::Vector4(0.15f, 0.15f, 0.15f, 1.0f); m_diffuseColor = AZ::Vector4(1.0f, 1.0f, 1.0f, 1.0f); // World float fieldOfView = AZ::Constants::Pi / 4.0f; float screenAspect = GetViewportWidth() / GetViewportHeight(); m_worldPosition = AZ::Vector3(0.0f, 5.0f, 20.0f); m_worldMatrix = AZ::Matrix4x4::CreateIdentity(); MakePerspectiveFovMatrixRH(m_viewProjectionMatrix, fieldOfView, screenAspect, m_zNear, m_zFar); m_viewProjectionMatrix = m_viewProjectionMatrix *CreateViewMatrix(m_worldPosition, m_up, m_lookAt); // Light float fovY = AZ::Constants::Pi / 2.0f; float aspectRatio = 1.0f; m_lightPosition = AZ::Vector4(-12.0, 8.0f, -12.0f, 1.0f); MakePerspectiveFovMatrixRH(m_lightProjectionMatrix, fovY, aspectRatio, m_zNear, m_zFar); m_lightViewProjectionMatrix = m_lightProjectionMatrix * CreateViewMatrix(m_lightPosition.GetAsVector3(), m_up, m_lookAt); } MultipleViewsComponent::BufferData MultipleViewsComponent::CreateBufferData() { // Create vertices, colors and normals for a cube and a plane BufferData bufferData; { AZStd::vector vertices = { //Front Face AZ::Vector3(1.0, 1.0, 1.0), AZ::Vector3(-1.0, 1.0, 1.0), AZ::Vector3(-1.0, -1.0, 1.0), AZ::Vector3(1.0, -1.0, 1.0), //Back Face AZ::Vector3(1.0, 1.0, -1.0), AZ::Vector3(-1.0, 1.0, -1.0), AZ::Vector3(-1.0, -1.0, -1.0), AZ::Vector3(1.0, -1.0, -1.0), //Left Face AZ::Vector3(-1.0, 1.0, 1.0), AZ::Vector3(-1.0, -1.0, 1.0), AZ::Vector3(-1.0, -1.0, -1.0), AZ::Vector3(-1.0, 1.0, -1.0), //Right Face AZ::Vector3(1.0, 1.0, 1.0), AZ::Vector3(1.0, -1.0, 1.0), AZ::Vector3(1.0, -1.0, -1.0), AZ::Vector3(1.0, 1.0, -1.0), //Top Face AZ::Vector3(1.0, 1.0, 1.0), AZ::Vector3(-1.0, 1.0, 1.0), AZ::Vector3(-1.0, 1.0, -1.0), AZ::Vector3(1.0, 1.0, -1.0), //Bottom Face AZ::Vector3(1.0, -1.0, 1.0), AZ::Vector3(-1.0, -1.0, 1.0), AZ::Vector3(-1.0, -1.0, -1.0), AZ::Vector3(1.0, -1.0, -1.0), //Plane AZ::Vector3(-10.0, -1.0, -10.0), AZ::Vector3(10.0, -1.0, -10.0), AZ::Vector3(10.0, -1.0, 10.0), AZ::Vector3(-10.0, -1.0, 10.0), }; AZStd::vector colors = { //Front Face AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), //Back Face AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), //Left Face AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), //Right Face AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), //Top Face AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), //Bottom Face AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), //Plane AZ::Vector4(1.0, 0.0, 0.0, 1.0), AZ::Vector4(1.0, 0.0, 0.0, 1.0), AZ::Vector4(1.0, 0.0, 0.0, 1.0), AZ::Vector4(1.0, 0.0, 0.0, 1.0), }; AZStd::vector normals = { //Front Face AZ::Vector3(0.0, 0.0, 1.0), AZ::Vector3(0.0, 0.0, 1.0), AZ::Vector3(0.0, 0.0, 1.0), AZ::Vector3(0.0, 0.0, 1.0), //Back Face AZ::Vector3(0.0, 0.0,-1.0), AZ::Vector3(0.0, 0.0,-1.0), AZ::Vector3(0.0, 0.0,-1.0), AZ::Vector3(0.0, 0.0,-1.0), //Left Face AZ::Vector3(-1.0, 0.0, 0.0), AZ::Vector3(-1.0, 0.0, 0.0), AZ::Vector3(-1.0, 0.0, 0.0), AZ::Vector3(-1.0, 0.0, 0.0), //Right Face AZ::Vector3(1.0, 0.0, 0.0), AZ::Vector3(1.0, 0.0, 0.0), AZ::Vector3(1.0, 0.0, 0.0), AZ::Vector3(1.0, 0.0, 0.0), //Top Face AZ::Vector3(0.0, 1.0, 0.0), AZ::Vector3(0.0, 1.0, 0.0), AZ::Vector3(0.0, 1.0, 0.0), AZ::Vector3(0.0, 1.0, 0.0), //Bottom Face AZ::Vector3(0.0, -1.0, 0.0), AZ::Vector3(0.0, -1.0, 0.0), AZ::Vector3(0.0, -1.0, 0.0), AZ::Vector3(0.0, -1.0, 0.0), //Plane AZ::Vector3(0.0, 1.0, 0.0), AZ::Vector3(0.0, 1.0, 0.0), AZ::Vector3(0.0, 1.0, 0.0), AZ::Vector3(0.0, 1.0, 0.0), }; for (int i = 0; i < geometryVertexCount; ++i) { SetVertexPosition(bufferData.m_positions.data(), i, vertices[i]); SetVertexColor(bufferData.m_colors.data(), i, colors[i]); SetVertexNormal(bufferData.m_normals.data(), i, normals[i]); } bufferData.m_indices = { { //Back 2, 0, 1, 0, 2, 3, //Front 4, 6, 5, 6, 4, 7, //Left 8, 10, 9, 10, 8, 11, //Right 14, 12, 13, 15, 12, 14, //Top 16, 18, 17, 18, 16, 19, //Bottom 22, 20, 21, 23, 20, 22, //Plane Top 24, 26, 25, 26, 24, 27, } }; } return bufferData; } void MultipleViewsComponent::CreateInputAssemblyBuffersAndViews() { using namespace AZ; const AZ::RHI::Ptr device = Utils::GetRHIDevice(); m_bufferPool = AZ::RHI::Factory::Get().CreateBufferPool(); AZ::RHI::BufferPoolDescriptor bufferPoolDesc; bufferPoolDesc.m_bindFlags = AZ::RHI::BufferBindFlags::InputAssembly; bufferPoolDesc.m_heapMemoryLevel = AZ::RHI::HeapMemoryLevel::Device; m_bufferPool->Init(*device, bufferPoolDesc); BufferData bufferData = CreateBufferData(); m_inputAssemblyBuffer = AZ::RHI::Factory::Get().CreateBuffer(); AZ::RHI::ResultCode result = AZ::RHI::ResultCode::Success; AZ::RHI::BufferInitRequest request; request.m_buffer = m_inputAssemblyBuffer.get(); request.m_descriptor = AZ::RHI::BufferDescriptor{ AZ::RHI::BufferBindFlags::InputAssembly, sizeof(bufferData) }; request.m_initialData = &bufferData; result = m_bufferPool->InitBuffer(request); if (result != AZ::RHI::ResultCode::Success) { AZ_Error("MultipleViewsComponent", false, "Failed to initialize buffer with error code %d", result); return; } m_streamBufferViews[0] = { *m_inputAssemblyBuffer, offsetof(BufferData, m_positions), sizeof(BufferData::m_positions), sizeof(VertexPosition) }; m_streamBufferViews[1] = { *m_inputAssemblyBuffer, offsetof(BufferData, m_colors), sizeof(BufferData::m_colors), sizeof(VertexColor) }; m_streamBufferViews[2] = { *m_inputAssemblyBuffer, offsetof(BufferData, m_normals), sizeof(BufferData::m_normals), sizeof(VertexNormal) }; m_indexBufferView = { *m_inputAssemblyBuffer, offsetof(BufferData, m_indices), sizeof(BufferData::m_indices), AZ::RHI::IndexFormat::Uint16 }; RHI::InputStreamLayoutBuilder layoutBuilder; layoutBuilder.AddBuffer()->Channel("POSITION", RHI::Format::R32G32B32_FLOAT); layoutBuilder.AddBuffer()->Channel("COLOR", RHI::Format::R32G32B32A32_FLOAT); layoutBuilder.AddBuffer()->Channel("NORMAL", RHI::Format::R32G32B32_FLOAT); m_inputStreamLayout = layoutBuilder.End(); AZ::RHI::ValidateStreamBufferViews(m_inputStreamLayout, m_streamBufferViews); } void MultipleViewsComponent::InitRenderTarget() { const AZ::RHI::ImageDescriptor imageDescriptor = AZ::RHI::ImageDescriptor::Create2D( AZ::RHI::ImageBindFlags::DepthStencil | AZ::RHI::ImageBindFlags::ShaderRead, s_shadowMapSize, s_shadowMapSize, AZ::RHI::Format::D32_FLOAT); m_transientImageDescriptor = AZ::RHI::TransientImageDescriptor(m_depthMapID, imageDescriptor); } void MultipleViewsComponent::ReadDepthShader() { using namespace AZ; const char* depthShaderFilePath = "Shaders/RHI/MultipleViewsDepth.azshader"; const char* sampleName = "MultipleViewsComponent"; auto shader = LoadShader(depthShaderFilePath, sampleName); if (shader == nullptr) return; AZ::RHI::PipelineStateDescriptorForDraw pipelineDesc; shader->GetVariant(AZ::RPI::ShaderAsset::RootShaderVariantStableId).ConfigurePipelineState(pipelineDesc); pipelineDesc.m_inputStreamLayout = m_inputStreamLayout; pipelineDesc.m_renderStates.m_depthStencilState.m_depth.m_enable = 1; pipelineDesc.m_renderStates.m_depthStencilState.m_depth.m_func = AZ::RHI::ComparisonFunc::LessEqual; RHI::RenderAttachmentLayoutBuilder attachmentsBuilder; attachmentsBuilder.AddSubpass() ->DepthStencilAttachment(AZ::RHI::Format::D32_FLOAT); [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout); AZ_Assert(result == RHI::ResultCode::Success, "Failed to create render attachment layout"); m_pipelineStates[0] = shader->AcquirePipelineState(pipelineDesc); if (!m_pipelineStates[0]) { AZ_Error(sampleName, false, "Failed to acquire default pipeline state for shader '%s'", depthShaderFilePath); return; } m_shaderResourceGroups[0] = CreateShaderResourceGroup(shader, "DepthViewSrg", sampleName); FindShaderInputIndex(&m_shaderInputConstantIndices[0], m_shaderResourceGroups[0], AZ::Name{ShaderInputs::ShaderInputImageWorldMatrix}, sampleName); FindShaderInputIndex(&m_shaderInputConstantIndices[1], m_shaderResourceGroups[0], AZ::Name{ShaderInputs::ShaderInputImageViewProjectionMatrix}, sampleName); } void MultipleViewsComponent::ReadMainShader() { const char* shadowShaderFilePath = "Shaders/RHI/MultipleViewsShadow.azshader"; const char* sampleName = "MultipleViewsComponent"; auto shader = LoadShader(shadowShaderFilePath, sampleName); if (shader == nullptr) return; AZ::RHI::PipelineStateDescriptorForDraw pipelineDesc; shader->GetVariant(AZ::RPI::ShaderAsset::RootShaderVariantStableId).ConfigurePipelineState(pipelineDesc); pipelineDesc.m_inputStreamLayout = m_inputStreamLayout; pipelineDesc.m_renderStates.m_depthStencilState.m_depth.m_enable = 1; pipelineDesc.m_renderStates.m_depthStencilState.m_depth.m_func = AZ::RHI::ComparisonFunc::LessEqual; AZ::RHI::Ptr device = Utils::GetRHIDevice(); AZ::RHI::Format depthStencilFormat = device->GetNearestSupportedFormat(AZ::RHI::Format::D24_UNORM_S8_UINT, AZ::RHI::FormatCapabilities::DepthStencil); AZ::RHI::RenderAttachmentLayoutBuilder attachmentsBuilder; attachmentsBuilder.AddSubpass() ->RenderTargetAttachment(m_outputFormat) ->DepthStencilAttachment(depthStencilFormat); [[maybe_unused]] AZ::RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout); AZ_Assert(result == AZ::RHI::ResultCode::Success, "Failed to create render attachment layout"); m_pipelineStates[1] = shader->AcquirePipelineState(pipelineDesc); if (!m_pipelineStates[1]) { AZ_Error(sampleName, false, "Failed to acquire default pipeline state for shader '%s'", shadowShaderFilePath); return; } m_shaderResourceGroups[1] = CreateShaderResourceGroup(shader, "ShadowViewSrg", sampleName); FindShaderInputIndex(&m_shaderInputConstantIndices[0], m_shaderResourceGroups[1], AZ::Name{ShaderInputs::ShaderInputImageWorldMatrix}, sampleName); FindShaderInputIndex(&m_shaderInputConstantIndices[1], m_shaderResourceGroups[1], AZ::Name{ShaderInputs::ShaderInputImageViewProjectionMatrix}, sampleName); FindShaderInputIndex(&m_shaderInputConstantIndices[2], m_shaderResourceGroups[1], AZ::Name{ShaderInputs::ShaderInputImageLightViewProjectionMatrix}, sampleName); FindShaderInputIndex(&m_shaderInputConstantIndices[3], m_shaderResourceGroups[1], AZ::Name{ShaderInputs::ShaderInputImageLightPosition}, sampleName); FindShaderInputIndex(&m_shaderInputConstantIndices[4], m_shaderResourceGroups[1], AZ::Name{ShaderInputs::ShaderInputImageAmbientColor}, sampleName); FindShaderInputIndex(&m_shaderInputConstantIndices[5], m_shaderResourceGroups[1], AZ::Name{ShaderInputs::ShaderInputImageDiffuseColor}, sampleName); FindShaderInputIndex(&m_shaderInputImageIndex, m_shaderResourceGroups[1], AZ::Name{ShaderInputs::ShaderInputImageDepthMapTexture}, sampleName); } void MultipleViewsComponent::CreateDepthScope() { const auto prepareFunctionLightView = [this](AZ::RHI::FrameGraphInterface frameGraph, [[maybe_unused]] ScopeData& scopeData) { // Create & Binds DepthStencil image { frameGraph.GetAttachmentDatabase().CreateTransientImage(m_transientImageDescriptor); AZ::RHI::ImageScopeAttachmentDescriptor dsDesc; dsDesc.m_attachmentId = m_depthMapID; dsDesc.m_imageViewDescriptor.m_overrideFormat = AZ::RHI::Format::D32_FLOAT; dsDesc.m_loadStoreAction.m_clearValue = m_depthClearValue; dsDesc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Clear; frameGraph.UseDepthStencilAttachment(dsDesc, AZ::RHI::ScopeAttachmentAccess::ReadWrite); } frameGraph.SetEstimatedItemCount(1); }; AZ::RHI::EmptyCompileFunction compileFunctionLightView; const auto executeFunctionLightView = [this](const AZ::RHI::FrameGraphExecuteContext& context, [[maybe_unused]] const ScopeData& scopeData) { AZ::RHI::CommandList* commandList = context.GetCommandList(); AZ::RHI::Viewport viewport = AZ::RHI::Viewport(0, static_cast(s_shadowMapSize), 0, static_cast(s_shadowMapSize)); AZ::RHI::Scissor scissor = AZ::RHI::Scissor(0, 0, static_cast(s_shadowMapSize), static_cast(s_shadowMapSize)); commandList->SetViewports(&viewport, 1); commandList->SetScissors(&scissor, 1); AZ::RHI::DrawIndexed drawIndexed; drawIndexed.m_indexCount = geometryIndexCount; drawIndexed.m_instanceCount = 1; const AZ::RHI::ShaderResourceGroup* shaderResourceGroups[] = { m_shaderResourceGroups[0]->GetRHIShaderResourceGroup() }; AZ::RHI::DrawItem drawItem; drawItem.m_arguments = drawIndexed; drawItem.m_pipelineState = m_pipelineStates[0].get(); drawItem.m_indexBufferView = &m_indexBufferView; drawItem.m_shaderResourceGroupCount = static_cast(AZ::RHI::ArraySize(shaderResourceGroups)); drawItem.m_shaderResourceGroups = shaderResourceGroups; drawItem.m_streamBufferViewCount = static_cast(m_streamBufferViews.size()); drawItem.m_streamBufferViews = m_streamBufferViews.data(); commandList->Submit(drawItem); }; m_scopeProducers.emplace_back(aznew AZ::RHI::ScopeProducerFunction< ScopeData, decltype(prepareFunctionLightView), decltype(compileFunctionLightView), decltype(executeFunctionLightView)>( AZ::RHI::ScopeId{"MultipleViewsDepth"}, ScopeData{}, prepareFunctionLightView, compileFunctionLightView, executeFunctionLightView)); } void MultipleViewsComponent::CreateMainScope() { const auto prepareFunctionMainView = [this](AZ::RHI::FrameGraphInterface frameGraph, [[maybe_unused]] ScopeData& scopeData) { // Binds the swap chain as a color attachment. Clears it to black. { AZ::RHI::ImageScopeAttachmentDescriptor descriptor; descriptor.m_attachmentId = m_outputAttachmentId; descriptor.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; frameGraph.UseColorAttachment(descriptor); } // Binds depth buffer from depth pass { frameGraph.UseShaderAttachment(AZ::RHI::ImageScopeAttachmentDescriptor(m_transientImageDescriptor.m_attachmentId), AZ::RHI::ScopeAttachmentAccess::Read); } // Create & Binds DepthStencil image { AZ::RHI::Ptr device = Utils::GetRHIDevice(); AZ::RHI::Format depthStencilFormat = device->GetNearestSupportedFormat(AZ::RHI::Format::D24_UNORM_S8_UINT, AZ::RHI::FormatCapabilities::DepthStencil); const AZ::RHI::ImageDescriptor imageDescriptor = AZ::RHI::ImageDescriptor::Create2D( AZ::RHI::ImageBindFlags::DepthStencil, m_outputWidth, m_outputHeight, depthStencilFormat); const AZ::RHI::TransientImageDescriptor transientImageDescriptor(m_depthStencilID, imageDescriptor); frameGraph.GetAttachmentDatabase().CreateTransientImage(transientImageDescriptor); AZ::RHI::ImageScopeAttachmentDescriptor dsDesc; dsDesc.m_attachmentId = m_depthStencilID; dsDesc.m_imageViewDescriptor.m_overrideFormat = depthStencilFormat; dsDesc.m_loadStoreAction.m_clearValue = m_depthClearValue; dsDesc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Clear; frameGraph.UseDepthStencilAttachment(dsDesc, AZ::RHI::ScopeAttachmentAccess::Write); } // We will submit a single draw item. frameGraph.SetEstimatedItemCount(1); }; const auto compileFunctionMainView = [this](const AZ::RHI::FrameGraphCompileContext& context, [[maybe_unused]] const ScopeData& scopeData) { const AZ::RHI::ImageView* imageView = context.GetImageView(m_transientImageDescriptor.m_attachmentId); m_shaderResourceGroups[1]->SetImageView(m_shaderInputImageIndex, imageView); m_shaderResourceGroups[1]->Compile(); }; const auto executeFunctionMainView = [this](const AZ::RHI::FrameGraphExecuteContext& context, [[maybe_unused]] const ScopeData& scopeData) { AZ::RHI::CommandList* commandList = context.GetCommandList(); // Set persistent viewport and scissor state. commandList->SetViewports(&m_viewport, 1); commandList->SetScissors(&m_scissor, 1); AZ::RHI::DrawIndexed drawIndexed; drawIndexed.m_indexCount = geometryIndexCount; drawIndexed.m_instanceCount = 1; const AZ::RHI::ShaderResourceGroup* shaderResourceGroups[] = { m_shaderResourceGroups[1]->GetRHIShaderResourceGroup() }; AZ::RHI::DrawItem drawItem; drawItem.m_arguments = drawIndexed; drawItem.m_pipelineState = m_pipelineStates[1].get(); drawItem.m_indexBufferView = &m_indexBufferView; drawItem.m_shaderResourceGroupCount = static_cast(AZ::RHI::ArraySize(shaderResourceGroups)); drawItem.m_shaderResourceGroups = shaderResourceGroups; drawItem.m_streamBufferViewCount = static_cast(m_streamBufferViews.size()); drawItem.m_streamBufferViews = m_streamBufferViews.data(); commandList->Submit(drawItem); }; m_scopeProducers.emplace_back( aznew AZ::RHI::ScopeProducerFunction< ScopeData, decltype(prepareFunctionMainView), decltype(compileFunctionMainView), decltype(executeFunctionMainView)>( AZ::RHI::ScopeId{"MultipleViewsShadow"}, ScopeData{}, prepareFunctionMainView, compileFunctionMainView, executeFunctionMainView)); } }