Reenable support for UI Elements that use Render Targets (#2352)
* Re-add support for UI Elements that use Render Targets * Move LyShine pass request from Atom's MainPipeline.pass to project's * Make all dynamic draw contexts in LyShine draw to pass directly without the need of draw list tags * Remove local RPI changes that are no longer needed * Prevent crash if LyShine gem is enabled but its custom pass hasn't been added to the main render pipeline * Revert to default UI pass if the LyShine pass has not been added to project's main render pipeline Signed-off-by: abrmich <abrmich@amazon.com>
This commit is contained in:
@@ -10,6 +10,9 @@
|
||||
#include "UiRenderer.h"
|
||||
|
||||
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
|
||||
#include <AzCore/Math/MatrixUtils.h>
|
||||
|
||||
#ifndef _RELEASE
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
@@ -78,57 +81,28 @@ namespace LyShine
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void PrimitiveListRenderNode::Render(UiRenderer* uiRenderer)
|
||||
void PrimitiveListRenderNode::Render(UiRenderer* uiRenderer
|
||||
, const AZ::Matrix4x4& modelViewProjMat
|
||||
, AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw)
|
||||
{
|
||||
#ifdef LYSHINE_ATOM_TODO // keeping this code for reference for future phase (masks/render targets)
|
||||
for (int i = 0; i < m_numTextures; ++i)
|
||||
{
|
||||
uiRenderer->SetTexture(m_textures[i].m_texture, i, m_textures[i].m_isClampTextureMode);
|
||||
}
|
||||
|
||||
int blendModeState = m_blendModeState;
|
||||
|
||||
IRenderer* renderer = gEnv->pRenderer;
|
||||
renderer->SetState(blendModeState | uiRenderer->GetBaseState());
|
||||
|
||||
if (m_isTextureSRGB)
|
||||
{
|
||||
renderer->SetSrgbWrite(false);
|
||||
}
|
||||
|
||||
// We are using SetColorOp as a way to set flags for the ui.cfx shader by reusing flags
|
||||
// that the FixedPipelineEmu.cfx shader uses. So the names colorOp and alphaOp are used
|
||||
// just because this are the inputs to SetColorOp.
|
||||
uint8 colorOp = m_preMultiplyAlpha ? ColorOp_PreMultiplyAlpha : ColorOp_Normal;
|
||||
uint8 alphaOp = AlphaOp_Normal;
|
||||
switch (m_alphaMaskType)
|
||||
{
|
||||
case AlphaMaskType::None:
|
||||
alphaOp = AlphaOp_Normal;
|
||||
break;
|
||||
case AlphaMaskType::ModulateAlpha:
|
||||
alphaOp = AlphaOp_ModulateAlpha;
|
||||
break;
|
||||
case AlphaMaskType::ModulateAlphaAndColor:
|
||||
alphaOp = AlphaOp_ModulateAlphaAndColor;
|
||||
break;
|
||||
}
|
||||
|
||||
renderer->SetColorOp(colorOp, alphaOp, DEF_TEXARG0, DEF_TEXARG0);
|
||||
|
||||
renderer->DrawDynUiPrimitiveList(m_primitives, m_totalNumVertices, m_totalNumIndices);
|
||||
|
||||
if (m_isTextureSRGB)
|
||||
{
|
||||
renderer->SetSrgbWrite(true);
|
||||
}
|
||||
#endif
|
||||
if (!uiRenderer->IsReady())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = uiRenderer->GetDynamicDrawContext();
|
||||
UiRenderer::BaseState curBaseState = uiRenderer->GetBaseState();
|
||||
UiRenderer::BaseState prevBaseState = curBaseState;
|
||||
if (m_isTextureSRGB)
|
||||
{
|
||||
curBaseState.m_srgbWrite = false;
|
||||
}
|
||||
|
||||
if (m_alphaMaskType == AlphaMaskType::ModulateAlpha)
|
||||
{
|
||||
curBaseState.m_modulateAlpha = true;
|
||||
}
|
||||
uiRenderer->SetBaseState(curBaseState);
|
||||
|
||||
const UiRenderer::UiShaderData& uiShaderData = uiRenderer->GetUiShaderData();
|
||||
|
||||
// Set render state
|
||||
@@ -167,7 +141,7 @@ namespace LyShine
|
||||
drawSrg->SetConstant(uiShaderData.m_isClampInputIndex, isClampTextureMode);
|
||||
|
||||
// Set projection matrix
|
||||
drawSrg->SetConstant(uiShaderData.m_viewProjInputIndex, uiRenderer->GetModelViewProjectionMatrix());
|
||||
drawSrg->SetConstant(uiShaderData.m_viewProjInputIndex, modelViewProjMat);
|
||||
|
||||
drawSrg->Compile();
|
||||
|
||||
@@ -180,6 +154,8 @@ namespace LyShine
|
||||
{
|
||||
dynamicDraw->DrawIndexed(primitive.m_vertices, primitive.m_numVertices, primitive.m_indices, primitive.m_numIndices, AZ::RHI::IndexFormat::Uint16, drawSrg);
|
||||
}
|
||||
|
||||
uiRenderer->SetBaseState(prevBaseState);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -303,33 +279,35 @@ namespace LyShine
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void MaskRenderNode::Render(UiRenderer* uiRenderer)
|
||||
void MaskRenderNode::Render(UiRenderer* uiRenderer
|
||||
, const AZ::Matrix4x4& modelViewProjMat
|
||||
, AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw)
|
||||
{
|
||||
UiRenderer::BaseState priorBaseState = uiRenderer->GetBaseState();
|
||||
|
||||
if (m_isMaskingEnabled || m_drawBehind)
|
||||
{
|
||||
SetupBeforeRenderingMask(uiRenderer, true, priorBaseState);
|
||||
SetupBeforeRenderingMask(uiRenderer, dynamicDraw, true, priorBaseState);
|
||||
for (RenderNode* renderNode : m_maskRenderNodes)
|
||||
{
|
||||
renderNode->Render(uiRenderer);
|
||||
renderNode->Render(uiRenderer, modelViewProjMat, dynamicDraw);
|
||||
}
|
||||
SetupAfterRenderingMask(uiRenderer, true, priorBaseState);
|
||||
SetupAfterRenderingMask(uiRenderer, dynamicDraw, true, priorBaseState);
|
||||
}
|
||||
|
||||
for (RenderNode* renderNode : m_contentRenderNodes)
|
||||
{
|
||||
renderNode->Render(uiRenderer);
|
||||
renderNode->Render(uiRenderer, modelViewProjMat, dynamicDraw);
|
||||
}
|
||||
|
||||
if (m_isMaskingEnabled || m_drawInFront)
|
||||
{
|
||||
SetupBeforeRenderingMask(uiRenderer, false, priorBaseState);
|
||||
SetupBeforeRenderingMask(uiRenderer, dynamicDraw, false, priorBaseState);
|
||||
for (RenderNode* renderNode : m_maskRenderNodes)
|
||||
{
|
||||
renderNode->Render(uiRenderer);
|
||||
renderNode->Render(uiRenderer, modelViewProjMat, dynamicDraw);
|
||||
}
|
||||
SetupAfterRenderingMask(uiRenderer, false, priorBaseState);
|
||||
SetupAfterRenderingMask(uiRenderer, dynamicDraw, false, priorBaseState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +345,9 @@ namespace LyShine
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void MaskRenderNode::SetupBeforeRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState)
|
||||
void MaskRenderNode::SetupBeforeRenderingMask(UiRenderer* uiRenderer,
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw,
|
||||
bool firstPass, UiRenderer::BaseState priorBaseState)
|
||||
{
|
||||
UiRenderer::BaseState curBaseState = priorBaseState;
|
||||
|
||||
@@ -406,7 +386,6 @@ namespace LyShine
|
||||
curBaseState.m_stencilState.m_backFace = stencilOpState;
|
||||
|
||||
// set up for stencil write
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = uiRenderer->GetDynamicDrawContext();
|
||||
dynamicDraw->SetStencilReference(uiRenderer->GetStencilRef());
|
||||
curBaseState.m_stencilState.m_enable = true;
|
||||
curBaseState.m_stencilState.m_writeMask = 0xFF;
|
||||
@@ -421,7 +400,9 @@ namespace LyShine
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void MaskRenderNode::SetupAfterRenderingMask(UiRenderer* uiRenderer, bool firstPass, UiRenderer::BaseState priorBaseState)
|
||||
void MaskRenderNode::SetupAfterRenderingMask(UiRenderer* uiRenderer,
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw,
|
||||
bool firstPass, UiRenderer::BaseState priorBaseState)
|
||||
{
|
||||
if (m_isMaskingEnabled)
|
||||
{
|
||||
@@ -439,7 +420,6 @@ namespace LyShine
|
||||
uiRenderer->DecrementStencilRef();
|
||||
}
|
||||
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = uiRenderer->GetDynamicDrawContext();
|
||||
dynamicDraw->SetStencilReference(uiRenderer->GetStencilRef());
|
||||
|
||||
if (firstPass)
|
||||
@@ -474,16 +454,14 @@ namespace LyShine
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RenderTargetRenderNode::RenderTargetRenderNode(
|
||||
RenderTargetRenderNode* parentRenderTarget,
|
||||
int renderTargetHandle,
|
||||
SDepthTexture* renderTargetDepthSurface,
|
||||
AZ::Data::Instance<AZ::RPI::AttachmentImage> attachmentImage,
|
||||
const AZ::Vector2& viewportTopLeft,
|
||||
const AZ::Vector2& viewportSize,
|
||||
const AZ::Color& clearColor,
|
||||
int nestLevel)
|
||||
: RenderNode(RenderNodeType::RenderTarget)
|
||||
, m_parentRenderTarget(parentRenderTarget)
|
||||
, m_renderTargetHandle(renderTargetHandle)
|
||||
, m_renderTargetDepthSurface(renderTargetDepthSurface)
|
||||
, m_attachmentImage(attachmentImage)
|
||||
, m_viewportX(viewportTopLeft.GetX())
|
||||
, m_viewportY(viewportTopLeft.GetY())
|
||||
, m_viewportWidth(viewportSize.GetX())
|
||||
@@ -491,6 +469,13 @@ namespace LyShine
|
||||
, m_clearColor(clearColor)
|
||||
, m_nestLevel(nestLevel)
|
||||
{
|
||||
AZ::MakeOrthographicMatrixRH(m_modelViewProjMat,
|
||||
m_viewportX,
|
||||
m_viewportX + m_viewportWidth,
|
||||
m_viewportY + m_viewportHeight,
|
||||
m_viewportY,
|
||||
0.0f,
|
||||
1.0f);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -505,9 +490,11 @@ namespace LyShine
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RenderTargetRenderNode::Render(UiRenderer* uiRenderer)
|
||||
void RenderTargetRenderNode::Render(UiRenderer* uiRenderer
|
||||
, [[maybe_unused]] const AZ::Matrix4x4& modelViewProjMat
|
||||
, [[maybe_unused]] AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw)
|
||||
{
|
||||
if (m_renderTargetHandle <= 0)
|
||||
if (!m_attachmentImage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -515,39 +502,52 @@ namespace LyShine
|
||||
ISystem* system = gEnv->pSystem;
|
||||
if (system && !gEnv->IsDedicated())
|
||||
{
|
||||
TransformationMatrices backupMatrices;
|
||||
gEnv->pRenderer->Set2DModeNonZeroTopLeft(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight, backupMatrices);
|
||||
|
||||
// this will change the viewport
|
||||
gEnv->pRenderer->SetRenderTarget(m_renderTargetHandle, m_renderTargetDepthSurface);
|
||||
|
||||
// clear the render target before rendering to it
|
||||
// NOTE: the FRT_CLEAR_IMMEDIATE is required since we will have already set the render target
|
||||
// In theory we could call this before setting the render target without the immediate flag
|
||||
// but that doesn't work. Perhaps because FX_Commit is not called.
|
||||
ColorF viewportBackgroundColor(m_clearColor.GetR(), m_clearColor.GetG(), m_clearColor.GetB(), m_clearColor.GetA());
|
||||
gEnv->pRenderer->ClearTargetsImmediately(FRT_CLEAR, viewportBackgroundColor);
|
||||
|
||||
// we could use SetSrgbWrite to write to a linear texture here. But that gets complicated with
|
||||
// having to affect all decsendant element renders. So we just let it write srgb to the render target and
|
||||
// allow for that when we render using the render target as a source texture.
|
||||
|
||||
for (RenderNode* renderNode : m_childRenderNodes)
|
||||
// Use a dedicated dynamic draw context for rendering to the texture since it can only have one draw list tag
|
||||
if (!m_dynamicDraw)
|
||||
{
|
||||
renderNode->Render(uiRenderer);
|
||||
m_dynamicDraw = uiRenderer->CreateDynamicDrawContextForRTT(GetRenderTargetName());
|
||||
}
|
||||
|
||||
gEnv->pRenderer->SetRenderTarget(0); // restore render target
|
||||
if (m_dynamicDraw)
|
||||
{
|
||||
UiRenderer::BaseState priorBaseState = uiRenderer->GetBaseState();
|
||||
|
||||
gEnv->pRenderer->Unset2DMode(backupMatrices);
|
||||
UiRenderer::BaseState curBaseState = priorBaseState;
|
||||
curBaseState.m_blendState.m_blendAlphaSource = AZ::RHI::BlendFactor::One;
|
||||
curBaseState.m_blendState.m_blendAlphaDest = AZ::RHI::BlendFactor::AlphaSource1Inverse;
|
||||
uiRenderer->SetBaseState(curBaseState);
|
||||
|
||||
for (RenderNode* renderNode : m_childRenderNodes)
|
||||
{
|
||||
renderNode->Render(uiRenderer, m_modelViewProjMat, m_dynamicDraw);
|
||||
}
|
||||
|
||||
uiRenderer->SetBaseState(priorBaseState);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_WarningOnce("UI", false, "Failed to create a Dynamic Draw Context for UI Element's render target. "\
|
||||
"Please ensure that the custom LyShinePass has been added to the project's main render pipeline.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const char* RenderTargetRenderNode::GetRenderTargetName() const
|
||||
{
|
||||
ITexture* texture = gEnv->pRenderer->EF_GetTextureByID(m_renderTargetHandle);
|
||||
return texture->GetName();
|
||||
return m_attachmentImage->GetRHIImage()->GetName().GetCStr();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int RenderTargetRenderNode::GetNestLevel() const
|
||||
{
|
||||
return m_nestLevel;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const AZ::Data::Instance<AZ::RPI::AttachmentImage> RenderTargetRenderNode::GetRenderTarget() const
|
||||
{
|
||||
return m_attachmentImage;
|
||||
}
|
||||
|
||||
#ifndef _RELEASE
|
||||
@@ -671,31 +671,29 @@ namespace LyShine
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RenderGraph::BeginRenderToTexture(int renderTargetHandle, SDepthTexture* renderTargetDepthSurface,
|
||||
void RenderGraph::BeginRenderToTexture([[maybe_unused]] int renderTargetHandle, [[maybe_unused]] SDepthTexture* renderTargetDepthSurface,
|
||||
[[maybe_unused]] const AZ::Vector2& viewportTopLeft, [[maybe_unused]] const AZ::Vector2& viewportSize, [[maybe_unused]] const AZ::Color& clearColor)
|
||||
{
|
||||
// LYSHINE_ATOM_TODO - this function will be removed when all IRenderer references are gone from UI components
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RenderGraph::BeginRenderToTexture(AZ::Data::Instance<AZ::RPI::AttachmentImage> attachmentImage,
|
||||
const AZ::Vector2& viewportTopLeft, const AZ::Vector2& viewportSize, const AZ::Color& clearColor)
|
||||
{
|
||||
#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (masks and render targets)
|
||||
// this uses pool allocator
|
||||
RenderTargetRenderNode* renderTargetRenderNode = new RenderTargetRenderNode(
|
||||
m_currentRenderTarget, renderTargetHandle, renderTargetDepthSurface,
|
||||
m_currentRenderTarget, attachmentImage,
|
||||
viewportTopLeft, viewportSize, clearColor, m_renderTargetNestLevel);
|
||||
|
||||
m_currentRenderTarget = renderTargetRenderNode;
|
||||
m_renderNodeListStack.push(&m_currentRenderTarget->GetChildRenderNodeList());
|
||||
m_renderTargetNestLevel++;
|
||||
#else
|
||||
AZ_UNUSED(clearColor);
|
||||
AZ_UNUSED(viewportSize);
|
||||
AZ_UNUSED(viewportTopLeft);
|
||||
AZ_UNUSED(renderTargetDepthSurface);
|
||||
AZ_UNUSED(renderTargetHandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RenderGraph::EndRenderToTexture()
|
||||
{
|
||||
#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (masks and render targets)
|
||||
AZ_Assert(m_currentRenderTarget, "Calling EndRenderToTexture while not defining a render target node");
|
||||
if (m_currentRenderTarget)
|
||||
{
|
||||
@@ -709,7 +707,6 @@ namespace LyShine
|
||||
m_renderNodeListStack.pop();
|
||||
m_renderTargetNestLevel--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenderGraph::AddPrimitive(
|
||||
@@ -803,11 +800,22 @@ namespace LyShine
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RenderGraph::AddAlphaMaskPrimitive(IRenderer::DynUiPrimitive* primitive,
|
||||
ITexture* texture, ITexture* maskTexture,
|
||||
bool isClampTextureMode, bool isTextureSRGB, bool isTexturePremultipliedAlpha, BlendMode blendMode)
|
||||
void RenderGraph::AddAlphaMaskPrimitive([[maybe_unused]] IRenderer::DynUiPrimitive* primitive,
|
||||
[[maybe_unused]] ITexture* texture, [[maybe_unused]] ITexture* maskTexture,
|
||||
[[maybe_unused]] bool isClampTextureMode, [[maybe_unused]] bool isTextureSRGB, [[maybe_unused]] bool isTexturePremultipliedAlpha, [[maybe_unused]] BlendMode blendMode)
|
||||
{
|
||||
// LYSHINE_ATOM_TODO - this function will be removed when all IRenderer references are gone from UI components
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RenderGraph::AddAlphaMaskPrimitiveAtom(IRenderer::DynUiPrimitive* primitive,
|
||||
AZ::Data::Instance<AZ::RPI::AttachmentImage> contentAttachmentImage,
|
||||
AZ::Data::Instance<AZ::RPI::AttachmentImage> maskAttachmentImage,
|
||||
bool isClampTextureMode,
|
||||
bool isTextureSRGB,
|
||||
bool isTexturePremultipliedAlpha,
|
||||
BlendMode blendMode)
|
||||
{
|
||||
#ifdef LYSHINE_ATOM_TODO // keeping this code for future phase (masks and render targets)
|
||||
AZStd::vector<RenderNode*>* renderNodeList = m_renderNodeListStack.top();
|
||||
|
||||
int texUnit0 = -1;
|
||||
@@ -842,8 +850,8 @@ namespace LyShine
|
||||
{
|
||||
// render state is the same - we can add the primitive to this list if the texture is in
|
||||
// the list or there is space for another texture
|
||||
texUnit0 = primListRenderNode->GetOrAddTexture(texture, true);
|
||||
texUnit1 = primListRenderNode->GetOrAddTexture(maskTexture, true);
|
||||
texUnit0 = primListRenderNode->GetOrAddTexture(contentAttachmentImage, true);
|
||||
texUnit1 = primListRenderNode->GetOrAddTexture(maskAttachmentImage, true);
|
||||
|
||||
if (texUnit0 != -1 && texUnit1 != -1)
|
||||
{
|
||||
@@ -857,7 +865,7 @@ namespace LyShine
|
||||
{
|
||||
// We can't add this primitive to the existing render node, we need to create a new render node
|
||||
// this uses a pool allocator for fast allocation
|
||||
renderNodeToAddTo = new PrimitiveListRenderNode(texture, maskTexture,
|
||||
renderNodeToAddTo = new PrimitiveListRenderNode(contentAttachmentImage, maskAttachmentImage,
|
||||
isClampTextureMode, isTextureSRGB, isPreMultiplyAlpha, alphaMaskType, blendModeState);
|
||||
|
||||
renderNodeList->push_back(renderNodeToAddTo);
|
||||
@@ -881,15 +889,6 @@ namespace LyShine
|
||||
// add this primitive to the render node
|
||||
renderNodeToAddTo->AddPrimitive(primitive);
|
||||
}
|
||||
#else
|
||||
AZ_UNUSED(primitive);
|
||||
AZ_UNUSED(texture);
|
||||
AZ_UNUSED(maskTexture);
|
||||
AZ_UNUSED(isClampTextureMode);
|
||||
AZ_UNUSED(isTextureSRGB);
|
||||
AZ_UNUSED(isTexturePremultipliedAlpha);
|
||||
AZ_UNUSED(blendMode);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -972,11 +971,8 @@ namespace LyShine
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RenderGraph::Render(UiRenderer* uiRenderer, const AZ::Vector2& viewportSize)
|
||||
void RenderGraph::Render(UiRenderer* uiRenderer, [[maybe_unused]] const AZ::Vector2& viewportSize)
|
||||
{
|
||||
// LYSHINE_ATOM_TODO - will probably need to support this when converting UI Editor to use Atom
|
||||
AZ_UNUSED(viewportSize);
|
||||
|
||||
AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw = uiRenderer->GetDynamicDrawContext();
|
||||
|
||||
// Disable stencil and enable blend/color write
|
||||
@@ -984,57 +980,35 @@ namespace LyShine
|
||||
dynamicDraw->SetTarget0BlendState(uiRenderer->GetBaseState().m_blendState);
|
||||
|
||||
// First render the render targets, they are sorted so that more deeply nested ones are rendered first.
|
||||
|
||||
#ifdef LYSHINE_ATOM_TODO // keeping this code for reference for future phase (render targets)
|
||||
// They only need to be rendered the first time that a render graph is rendered after it has been built.
|
||||
// Though there is a special case, if this is the first time a shader variant has been used it can miss
|
||||
// the first render. So to be safe we only stop rendering to render targets after we have rendered to
|
||||
// them twice with no shader compiles initiated.
|
||||
if (m_renderToRenderTargetCount < 2)
|
||||
if (m_renderToRenderTargetCount == 0)
|
||||
{
|
||||
// Enable the Rtt passes to draw onto the render targets
|
||||
SetRttPassesEnabled(uiRenderer, true);
|
||||
}
|
||||
|
||||
// LYSHINE_ATOM_TODO - It is currently necessary to render to the targets twice. Needs investigation
|
||||
constexpr int timesToRenderToRenderTargets = 2;
|
||||
if (m_renderToRenderTargetCount < timesToRenderToRenderTargets)
|
||||
{
|
||||
for (RenderNode* renderNode : m_renderTargetRenderNodes)
|
||||
{
|
||||
renderNode->Render(uiRenderer);
|
||||
}
|
||||
|
||||
// if the render targets render OK we don't need to render them every frame. But if a new shader
|
||||
// variant needed to be compiled then they will not have rendered OK. So we check is there are
|
||||
// any shaders still in the process of compiling. Because they are compiled on the render
|
||||
// thread, we may not know until the next frame that a shader needed to be compiled. So we need
|
||||
// the counter.
|
||||
SShaderCacheStatistics stats;
|
||||
gEnv->pRenderer->EF_Query(EFQ_GetShaderCacheInfo, stats);
|
||||
bool waitingOnShadersToCompile = stats.m_nNumShaderAsyncCompiles > 0 ? true : false;
|
||||
if (!waitingOnShadersToCompile)
|
||||
{
|
||||
m_renderToRenderTargetCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderToRenderTargetCount = 0;
|
||||
renderNode->Render(uiRenderer, uiRenderer->GetModelViewProjectionMatrix(), dynamicDraw);
|
||||
}
|
||||
m_renderToRenderTargetCount++;
|
||||
}
|
||||
#else
|
||||
for (RenderNode* renderNode : m_renderTargetRenderNodes)
|
||||
else if (m_renderToRenderTargetCount < timesToRenderToRenderTargets + 1)
|
||||
{
|
||||
renderNode->Render(uiRenderer);
|
||||
// Disable the rtt render passes since they don't need to be rendered to until the graph becomes invalidated again.
|
||||
// This is also necessary to prevent the render targets' contents getting cleared on load by the pass.
|
||||
SetRttPassesEnabled(uiRenderer, false);
|
||||
m_renderToRenderTargetCount++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LYSHINE_ATOM_TODO // keeping this code for reference for future phase (UI Editor)
|
||||
// Set2DMode defines the viewport so we set it to canvas viewport here (the render target render nodes
|
||||
// above will have set the viewport as they needed).
|
||||
TransformationMatrices backupMatrices;
|
||||
gEnv->pRenderer->Set2DMode(static_cast<uint32>(viewportSize.GetX()), static_cast<uint32>(viewportSize.GetY()), backupMatrices);
|
||||
#endif
|
||||
for (RenderNode* renderNode : m_renderNodes)
|
||||
{
|
||||
renderNode->Render(uiRenderer);
|
||||
renderNode->Render(uiRenderer, uiRenderer->GetModelViewProjectionMatrix(), dynamicDraw);
|
||||
}
|
||||
#ifdef LYSHINE_ATOM_TODO // keeping this code for reference for future phase (UI Editor)
|
||||
// end the 2D mode
|
||||
gEnv->pRenderer->Unset2DMode(backupMatrices);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1072,6 +1046,31 @@ namespace LyShine
|
||||
return m_renderNodes.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RenderGraph::GetRenderTargetsAndDependencies(LyShine::AttachmentImagesAndDependencies& attachmentImagesAndDependencies)
|
||||
{
|
||||
for (RenderNode* renderNode : m_renderTargetRenderNodes)
|
||||
{
|
||||
const RenderTargetRenderNode* renderTargetRenderNode = static_cast<const RenderTargetRenderNode*>(renderNode);
|
||||
|
||||
if (renderTargetRenderNode->GetNestLevel() == 0)
|
||||
{
|
||||
LyShine::AttachmentImages attachmentImages;
|
||||
const AZStd::vector<RenderNode*>& childNodeList = renderTargetRenderNode->GetChildRenderNodeList();
|
||||
for (auto& childNode : childNodeList)
|
||||
{
|
||||
if (childNode->GetType() == RenderNodeType::RenderTarget)
|
||||
{
|
||||
const RenderTargetRenderNode* childRenderTargetRenderNode = static_cast<const RenderTargetRenderNode*>(childNode);
|
||||
attachmentImages.emplace_back(childRenderTargetRenderNode->GetRenderTarget());
|
||||
}
|
||||
}
|
||||
|
||||
attachmentImagesAndDependencies.emplace_back(AttachmentImageAndDependentsPair(renderTargetRenderNode->GetRenderTarget(), attachmentImages));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _RELEASE
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RenderGraph::ValidateGraph()
|
||||
@@ -1540,4 +1539,19 @@ namespace LyShine
|
||||
return flags;
|
||||
}
|
||||
|
||||
void RenderGraph::SetRttPassesEnabled(UiRenderer* uiRenderer, bool enabled)
|
||||
{
|
||||
// Enable or disable the rtt render passes
|
||||
AZ::RPI::SceneId sceneId = uiRenderer->GetViewportContext()->GetRenderScene()->GetId();
|
||||
for (RenderTargetRenderNode* renderTargetRenderNode : m_renderTargetRenderNodes)
|
||||
{
|
||||
// Find the rtt pass to disable
|
||||
AZ::RPI::RasterPass* rttPass = nullptr;
|
||||
LyShinePassRequestBus::EventResult(rttPass, sceneId, &LyShinePassRequestBus::Events::GetRttPass, renderTargetRenderNode->GetRenderTargetName());
|
||||
if (rttPass)
|
||||
{
|
||||
rttPass->SetEnabled(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user