Files
UnrealEngineUWP/Engine/Source/Runtime/RenderCore/Private/ClearQuad.cpp
andrew davidson 57beb335f2 Merging //UE5/Dev-LargeWorldCoordinates [at] 17581892 to //UE5/Main
#ROBOMERGE-AUTHOR: andrew.davidson
#ROBOMERGE-SOURCE: CL 17595295 in //UE5/Main/...
#ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v871-17566257)

[CL 17595306 by andrew davidson in ue5-release-engine-test branch]
2021-09-22 10:01:48 -04:00

168 lines
6.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "ClearQuad.h"
#include "Shader.h"
#include "RHIStaticStates.h"
#include "OneColorShader.h"
#include "PipelineStateCache.h"
#include "ClearReplacementShaders.h"
#include "RendererInterface.h"
#include "Logging/LogMacros.h"
TGlobalResource<FClearVertexBuffer> GClearVertexBuffer;
DEFINE_LOG_CATEGORY_STATIC(LogClearQuad, Log, Log)
static void ClearQuadSetup( FRHICommandList& RHICmdList, bool bClearColor, int32 NumClearColors, const FLinearColor* ClearColorArray, bool bClearDepth, float Depth, bool bClearStencil, uint32 Stencil, TFunction<void(FGraphicsPipelineStateInitializer&)> PSOModifier = nullptr)
{
if (UNLIKELY(!FApp::CanEverRender()))
{
return;
}
// Set new states
FRHIBlendState* BlendStateRHI = bClearColor
? TStaticBlendState<>::GetRHI()
: TStaticBlendStateWriteMask<CW_NONE,CW_NONE,CW_NONE,CW_NONE,CW_NONE,CW_NONE,CW_NONE,CW_NONE>::GetRHI();
FRHIDepthStencilState* DepthStencilStateRHI =
(bClearDepth && bClearStencil)
? TStaticDepthStencilState<
true, CF_Always,
true,CF_Always,SO_Replace,SO_Replace,SO_Replace,
false,CF_Always,SO_Replace,SO_Replace,SO_Replace,
0xff,0xff
>::GetRHI()
: bClearDepth
? TStaticDepthStencilState<true, CF_Always>::GetRHI()
: bClearStencil
? TStaticDepthStencilState<
false, CF_Always,
true,CF_Always,SO_Replace,SO_Replace,SO_Replace,
false,CF_Always,SO_Replace,SO_Replace,SO_Replace,
0xff,0xff
>::GetRHI()
: TStaticDepthStencilState<false, CF_Always>::GetRHI();
FGraphicsPipelineStateInitializer GraphicsPSOInit;
RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
GraphicsPSOInit.RasterizerState = TStaticRasterizerState<FM_Solid, CM_None>::GetRHI();
GraphicsPSOInit.BlendState = BlendStateRHI;
GraphicsPSOInit.DepthStencilState = DepthStencilStateRHI;
auto* ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel);
// Set the new shaders
TShaderMapRef<TOneColorVS<true> > VertexShader(ShaderMap);
// Set the shader to write to the appropriate number of render targets
// On AMD PC hardware, outputting to a color index in the shader without a matching render target set has a significant performance hit
TOneColorPixelShaderMRT::FPermutationDomain PermutationVector;
PermutationVector.Set<TOneColorPixelShaderMRT::TOneColorPixelShaderNumOutputs>(NumClearColors ? NumClearColors : 1);
PermutationVector.Set<TOneColorPixelShaderMRT::TOneColorPixelShader128bitRT>(PlatformRequires128bitRT((EPixelFormat)GraphicsPSOInit.RenderTargetFormats[0]));
TShaderMapRef<TOneColorPixelShaderMRT > PixelShader(ShaderMap, PermutationVector);
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GetVertexDeclarationFVector4();
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
GraphicsPSOInit.PrimitiveType = PT_TriangleStrip;
if (PSOModifier)
{
PSOModifier(GraphicsPSOInit);
}
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, Stencil);
VertexShader->SetDepthParameter(RHICmdList, Depth);
PixelShader->SetColors(RHICmdList, ClearColorArray, NumClearColors);
}
void DrawClearQuadMRT(FRHICommandList& RHICmdList, bool bClearColor, int32 NumClearColors, const FLinearColor* ClearColorArray, bool bClearDepth, float Depth, bool bClearStencil, uint32 Stencil)
{
ClearQuadSetup(RHICmdList, bClearColor, NumClearColors, ClearColorArray, bClearDepth, Depth, bClearStencil, Stencil);
RHICmdList.SetStreamSource(0, GClearVertexBuffer.VertexBufferRHI, 0);
RHICmdList.DrawPrimitive(0, 2, 1);
}
void DrawClearQuadMRT(FRHICommandList& RHICmdList, bool bClearColor, int32 NumClearColors, const FLinearColor* ClearColorArray, bool bClearDepth, float Depth, bool bClearStencil, uint32 Stencil, FClearQuadCallbacks ClearQuadCallbacks)
{
ClearQuadSetup(RHICmdList, bClearColor, NumClearColors, ClearColorArray, bClearDepth, Depth, bClearStencil, Stencil, ClearQuadCallbacks.PSOModifier);
if (ClearQuadCallbacks.PreClear)
{
ClearQuadCallbacks.PreClear(RHICmdList);
}
// Draw a fullscreen quad without a hole
RHICmdList.SetStreamSource(0, GClearVertexBuffer.VertexBufferRHI, 0);
RHICmdList.DrawPrimitive(0, 2, 1);
if (ClearQuadCallbacks.PostClear)
{
ClearQuadCallbacks.PostClear(RHICmdList);
}
}
void DrawClearQuadMRT(FRHICommandList& RHICmdList, bool bClearColor, int32 NumClearColors, const FLinearColor* ClearColorArray, bool bClearDepth, float Depth, bool bClearStencil, uint32 Stencil, FIntPoint ViewSize, FIntRect ExcludeRect)
{
if (ExcludeRect.Min == FIntPoint::ZeroValue && ExcludeRect.Max == ViewSize)
{
// Early out if the entire surface is excluded
return;
}
ClearQuadSetup(RHICmdList, bClearColor, NumClearColors, ClearColorArray, bClearDepth, Depth, bClearStencil, Stencil);
// Draw a fullscreen quad
if (ExcludeRect.Width() > 0 && ExcludeRect.Height() > 0)
{
// with a hole in it
FVector4f OuterVertices[4];
OuterVertices[0].Set(-1.0f, 1.0f, Depth, 1.0f);
OuterVertices[1].Set(1.0f, 1.0f, Depth, 1.0f);
OuterVertices[2].Set(1.0f, -1.0f, Depth, 1.0f);
OuterVertices[3].Set(-1.0f, -1.0f, Depth, 1.0f);
float InvViewWidth = 1.0f / ViewSize.X;
float InvViewHeight = 1.0f / ViewSize.Y;
FVector4f FractionRect = FVector4f(ExcludeRect.Min.X * InvViewWidth, ExcludeRect.Min.Y * InvViewHeight, (ExcludeRect.Max.X - 1) * InvViewWidth, (ExcludeRect.Max.Y - 1) * InvViewHeight);
FVector4f InnerVertices[4];
InnerVertices[0].Set(FMath::Lerp(-1.0f, 1.0f, FractionRect.X), FMath::Lerp(1.0f, -1.0f, FractionRect.Y), Depth, 1.0f);
InnerVertices[1].Set(FMath::Lerp(-1.0f, 1.0f, FractionRect.Z), FMath::Lerp(1.0f, -1.0f, FractionRect.Y), Depth, 1.0f);
InnerVertices[2].Set(FMath::Lerp(-1.0f, 1.0f, FractionRect.Z), FMath::Lerp(1.0f, -1.0f, FractionRect.W), Depth, 1.0f);
InnerVertices[3].Set(FMath::Lerp(-1.0f, 1.0f, FractionRect.X), FMath::Lerp(1.0f, -1.0f, FractionRect.W), Depth, 1.0f);
FRHIResourceCreateInfo CreateInfo(TEXT("DrawClearQuadMRT"));
FBufferRHIRef VertexBufferRHI = RHICreateVertexBuffer(sizeof(FVector4f) * 10, BUF_Volatile, CreateInfo);
void* VoidPtr = RHILockBuffer(VertexBufferRHI, 0, sizeof(FVector4f) * 10, RLM_WriteOnly);
FVector4f* Vertices = reinterpret_cast<FVector4f*>(VoidPtr);
Vertices[0] = OuterVertices[0];
Vertices[1] = InnerVertices[0];
Vertices[2] = OuterVertices[1];
Vertices[3] = InnerVertices[1];
Vertices[4] = OuterVertices[2];
Vertices[5] = InnerVertices[2];
Vertices[6] = OuterVertices[3];
Vertices[7] = InnerVertices[3];
Vertices[8] = OuterVertices[0];
Vertices[9] = InnerVertices[0];
RHIUnlockBuffer(VertexBufferRHI);
RHICmdList.SetStreamSource(0, VertexBufferRHI, 0);
RHICmdList.DrawPrimitive(0, 8, 1);
VertexBufferRHI.SafeRelease();
}
else
{
// without a hole
RHICmdList.SetStreamSource(0, GClearVertexBuffer.VertexBufferRHI, 0);
RHICmdList.DrawPrimitive(0, 2, 1);
}
}