771 lines
28 KiB
C++
771 lines
28 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CanvasTypes.h"
|
|
#include "CommonRenderResources.h"
|
|
#include "GlobalShader.h"
|
|
#include "PipelineStateCache.h"
|
|
#include "RenderGraphBuilder.h"
|
|
#include "RenderGraphUtils.h"
|
|
#include "RHIStaticStates.h"
|
|
#include "SceneView.h"
|
|
|
|
struct FScreenPassTexture;
|
|
struct FScreenPassTextureSlice;
|
|
|
|
// Returns whether a HMD hidden area mask is being used for VR.
|
|
RENDERER_API bool IsHMDHiddenAreaMaskActive();
|
|
|
|
// Returns the global engine mini font texture.
|
|
FRHITexture* GetMiniFontTexture();
|
|
|
|
// Creates and returns an RDG texture for the view family output. Returns null if no RHI texture exists.
|
|
FRDGTextureRef RENDERER_API TryCreateViewFamilyTexture(FRDGBuilder& GraphBuilder, const FSceneViewFamily& ViewFamily);
|
|
FRDGTextureRef RENDERER_API TryCreateViewFamilyDepthTexture(FRDGBuilder& GraphBuilder, const FSceneViewFamily& ViewFamily);
|
|
|
|
// The vertex shader used by DrawScreenPass to draw a rectangle.
|
|
class FScreenPassVS : public FGlobalShader
|
|
{
|
|
public:
|
|
DECLARE_EXPORTED_GLOBAL_SHADER(FScreenPassVS, RENDERER_API);
|
|
|
|
FScreenPassVS() = default;
|
|
FScreenPassVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{}
|
|
};
|
|
|
|
// Describes a texture with a paired viewport rect.
|
|
struct FScreenPassTexture
|
|
{
|
|
FScreenPassTexture() {}
|
|
|
|
explicit FScreenPassTexture(FRDGTextureRef InTexture);
|
|
explicit FScreenPassTexture(const FScreenPassTextureSlice& ScreenTexture);
|
|
|
|
FScreenPassTexture(FRDGTextureRef InTexture, FIntRect InViewRect);
|
|
|
|
// Returns a 2D texture from the input slice. A copy is used if the input is a slice of a 2D texture array, or the override output is active.
|
|
RENDERER_API static FScreenPassTexture CopyFromSlice(FRDGBuilder& GraphBuilder, const FScreenPassTextureSlice& ScreenTextureSlice, FScreenPassTexture OverrideOutput = FScreenPassTexture());
|
|
|
|
bool IsValid() const;
|
|
|
|
bool operator==(FScreenPassTexture Other) const;
|
|
bool operator!=(FScreenPassTexture Other) const;
|
|
|
|
void UpdateVisualizeTextureExtent();
|
|
|
|
FRDGTextureRef Texture = nullptr;
|
|
FIntRect ViewRect;
|
|
};
|
|
|
|
// Describes a Texture2D or a slice within a texture array with a paired viewport rect.
|
|
struct FScreenPassTextureSlice
|
|
{
|
|
FScreenPassTextureSlice() = default;
|
|
|
|
FScreenPassTextureSlice(FRDGTextureSRVRef InTextureSRV, FIntRect InViewRect);
|
|
|
|
RENDERER_API static FScreenPassTextureSlice CreateFromScreenPassTexture(FRDGBuilder& GraphBuilder, const FScreenPassTexture& ScreenTexture);
|
|
|
|
bool IsValid() const;
|
|
|
|
bool operator==(FScreenPassTextureSlice Other) const;
|
|
bool operator!=(FScreenPassTextureSlice Other) const;
|
|
|
|
FRDGTextureSRVRef TextureSRV = nullptr;
|
|
FIntRect ViewRect;
|
|
};
|
|
|
|
// Describes a texture with a load action for usage as a render target.
|
|
struct FScreenPassRenderTarget : public FScreenPassTexture
|
|
{
|
|
RENDERER_API static FScreenPassRenderTarget CreateFromInput(
|
|
FRDGBuilder& GraphBuilder,
|
|
FScreenPassTexture Input,
|
|
ERenderTargetLoadAction OutputLoadAction,
|
|
const TCHAR* OutputName);
|
|
|
|
RENDERER_API static FScreenPassRenderTarget CreateFromInput(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGTexture* InputTexture,
|
|
FIntPoint Extent,
|
|
ERenderTargetLoadAction OutputLoadAction,
|
|
const TCHAR* OutputName);
|
|
|
|
static FScreenPassRenderTarget CreateViewFamilyOutput(FRDGTextureRef ViewFamilyTexture, const FViewInfo& View);
|
|
|
|
FScreenPassRenderTarget() = default;
|
|
|
|
explicit FScreenPassRenderTarget(FScreenPassTexture InTexture)
|
|
: FScreenPassTexture(InTexture)
|
|
{
|
|
// Derive the load action based on whether we are rendering to the entire texture or not.
|
|
if (ViewRect.Min != FIntPoint::ZeroValue || (Texture && Texture->Desc.Extent != ViewRect.Max))
|
|
{
|
|
LoadAction = ERenderTargetLoadAction::ELoad;
|
|
}
|
|
}
|
|
|
|
FScreenPassRenderTarget(FScreenPassTexture InTexture, ERenderTargetLoadAction InLoadAction)
|
|
: FScreenPassTexture(InTexture)
|
|
, LoadAction(InLoadAction)
|
|
{}
|
|
|
|
FScreenPassRenderTarget(FRDGTextureRef InTexture, ERenderTargetLoadAction InLoadAction)
|
|
: FScreenPassTexture(InTexture)
|
|
, LoadAction(InLoadAction)
|
|
{}
|
|
|
|
FScreenPassRenderTarget(FRDGTextureRef InTexture, FIntRect InViewRect, ERenderTargetLoadAction InLoadAction)
|
|
: FScreenPassTexture(InTexture, InViewRect)
|
|
, LoadAction(InLoadAction)
|
|
{}
|
|
|
|
bool operator==(FScreenPassRenderTarget Other) const;
|
|
bool operator!=(FScreenPassRenderTarget Other) const;
|
|
|
|
FRenderTargetBinding GetRenderTargetBinding() const;
|
|
|
|
ERenderTargetLoadAction LoadAction = ERenderTargetLoadAction::ENoAction;
|
|
};
|
|
|
|
// Describes a view rect contained within the extent of a texture. Used to derive texture coordinate transformations.
|
|
class FScreenPassTextureViewport
|
|
{
|
|
public:
|
|
FScreenPassTextureViewport() = default;
|
|
|
|
explicit FScreenPassTextureViewport(FIntRect InRect)
|
|
: Extent(InRect.Max)
|
|
, Rect(InRect)
|
|
{}
|
|
|
|
explicit FScreenPassTextureViewport(FScreenPassTexture InTexture);
|
|
explicit FScreenPassTextureViewport(FScreenPassTextureSlice InTexture);
|
|
|
|
explicit FScreenPassTextureViewport(FRDGTextureRef InTexture)
|
|
: FScreenPassTextureViewport(FScreenPassTexture(InTexture))
|
|
{}
|
|
|
|
explicit FScreenPassTextureViewport(FIntPoint InExtent)
|
|
: Extent(InExtent)
|
|
, Rect(FIntPoint::ZeroValue, InExtent)
|
|
{}
|
|
|
|
FScreenPassTextureViewport(FIntPoint InExtent, FIntRect InRect)
|
|
: Extent(InExtent)
|
|
, Rect(InRect)
|
|
{}
|
|
|
|
FScreenPassTextureViewport(FRDGTextureRef InTexture, FIntRect InRect)
|
|
: FScreenPassTextureViewport(FScreenPassTexture(InTexture, InRect))
|
|
{}
|
|
|
|
bool operator==(const FScreenPassTextureViewport& Other) const;
|
|
bool operator!=(const FScreenPassTextureViewport& Other) const;
|
|
|
|
// Returns whether the viewport contains an empty viewport or extent.
|
|
bool IsEmpty() const;
|
|
|
|
// Returns whether the viewport covers the full extent of the texture.
|
|
bool IsFullscreen() const;
|
|
|
|
// Returns the ratio of rect size to extent along each axis.
|
|
FVector2D GetRectToExtentRatio() const;
|
|
|
|
// The texture extent, in pixels; defines a super-set [0, 0]x(Extent, Extent).
|
|
FIntPoint Extent = FIntPoint::ZeroValue;
|
|
|
|
// The viewport rect, in pixels; defines a sub-set within [0, 0]x(Extent, Extent).
|
|
FIntRect Rect;
|
|
};
|
|
|
|
// Returns an extent downscaled by a multiple of the integer divisor (and clamped to 1).
|
|
FIntPoint GetDownscaledExtent(FIntPoint Extent, FIntPoint Divisor);
|
|
|
|
// Returns an extent scaled by the floating point scale factor.
|
|
FIntPoint GetScaledExtent(FIntPoint Extent, FVector2D Multiplier);
|
|
FIntPoint GetScaledExtent(FIntPoint Extent, float Multiplier);
|
|
|
|
// Returns a rect downscaled by a multiple of the integer divisor.
|
|
FIntRect GetDownscaledRect(FIntRect Rect, FIntPoint Divisor);
|
|
|
|
// Returns a rect scaled by the floating point scale factor.
|
|
FIntRect GetScaledRect(FIntRect Rect, FVector2D Multiplier);
|
|
FIntRect GetScaledRect(FIntRect Rect, float Multiplier);
|
|
|
|
// Returns the texture viewport downscaled by an integer divisor.
|
|
FScreenPassTextureViewport GetDownscaledViewport(FScreenPassTextureViewport Viewport, FIntPoint Divisor);
|
|
|
|
// Returns the texture viewport scaled by a float multiplier.
|
|
FScreenPassTextureViewport GetScaledViewport(FScreenPassTextureViewport Viewport, FVector2D Multiplier);
|
|
|
|
// Returns a rect with the min point at the origin and the max point at Extent.
|
|
FIntRect GetRectFromExtent(FIntPoint Extent);
|
|
|
|
// Describes the set of shader parameters for a screen pass texture viewport.
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, )
|
|
// Texture extent in pixels.
|
|
SHADER_PARAMETER(FVector2f, Extent)
|
|
SHADER_PARAMETER(FVector2f, ExtentInverse)
|
|
|
|
// Scale / Bias factor to convert from [-1, 1] to [ViewportMin, ViewportMax]
|
|
SHADER_PARAMETER(FVector2f, ScreenPosToViewportScale)
|
|
SHADER_PARAMETER(FVector2f, ScreenPosToViewportBias)
|
|
|
|
// Texture viewport min / max in pixels.
|
|
SHADER_PARAMETER(FIntPoint, ViewportMin)
|
|
SHADER_PARAMETER(FIntPoint, ViewportMax)
|
|
|
|
// Texture viewport size in pixels.
|
|
SHADER_PARAMETER(FVector2f, ViewportSize)
|
|
SHADER_PARAMETER(FVector2f, ViewportSizeInverse)
|
|
|
|
// Texture viewport min / max in normalized UV coordinates, with respect to the texture extent.
|
|
SHADER_PARAMETER(FVector2f, UVViewportMin)
|
|
SHADER_PARAMETER(FVector2f, UVViewportMax)
|
|
|
|
// Texture viewport size in normalized UV coordinates, with respect to the texture extent.
|
|
SHADER_PARAMETER(FVector2f, UVViewportSize)
|
|
SHADER_PARAMETER(FVector2f, UVViewportSizeInverse)
|
|
|
|
// Texture viewport min / max in normalized UV coordinates, with respect to the texture extent,
|
|
// adjusted by a half pixel offset for bilinear filtering. Useful for clamping to avoid sampling
|
|
// pixels on viewport edges; e.g. clamp(UV, UVViewportBilinearMin, UVViewportBilinearMax);
|
|
SHADER_PARAMETER(FVector2f, UVViewportBilinearMin)
|
|
SHADER_PARAMETER(FVector2f, UVViewportBilinearMax)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
FScreenPassTextureViewportParameters RENDERER_API GetScreenPassTextureViewportParameters(const FScreenPassTextureViewport& InViewport);
|
|
|
|
/** Generic affine 2D texture coordinate transformation x * S + B.
|
|
*
|
|
* Construct:
|
|
* FVector2f PointInA = ...;
|
|
* FVector2f PointInB = PointInA * Scale0 + Bias0;
|
|
*
|
|
* FScreenTransform AToB(Scale0, Bias0);
|
|
* FVector2f PointInB = PointInA * AToB;
|
|
*
|
|
* Associativity:
|
|
* FVector2f PointInA = ...;
|
|
* FScreenTransform AToB = ...;
|
|
* FScreenTransform BToC = ...;
|
|
* FVector2f PointInC = (PointInA * AToB) * BToC;
|
|
*
|
|
* FScreenTransform AToC = AToB * BToC;
|
|
* FVector2f PointInC = PointInA * AToC;
|
|
*
|
|
* Explicit construction by factorization:
|
|
* FVector2f PointInA = ...;
|
|
* FVector2f PointInB = PointInA * Scale0 + Bias0;
|
|
* FVector2f PointInC = PointInB * Scale1 + Bias1;
|
|
*
|
|
* FScreenTransform AToC = (FScreenTransform::Identity * Scale0 + Bias0) * Scale1 + Bias1;
|
|
* FVector2f PointInC = PointInA * AToC;
|
|
*
|
|
* Shader code:
|
|
* #include "/Engine/Private/ScreenPass.ush"
|
|
*
|
|
* FScreenTransform AToC; // shader parameter in global scope
|
|
*
|
|
* {
|
|
* float2 PointInA = ...;
|
|
* float2 PointInC = ApplyScreenTransform(PointInA, AToC);
|
|
* }
|
|
*
|
|
*/
|
|
struct FScreenTransform
|
|
{
|
|
FVector2f Scale;
|
|
FVector2f Bias;
|
|
|
|
inline FScreenTransform()
|
|
{ }
|
|
|
|
inline FScreenTransform(const FVector2f& InScale, const FVector2f& InBias)
|
|
: Scale(InScale)
|
|
, Bias(InBias)
|
|
{ }
|
|
|
|
|
|
// A * FScreenTransform::Identity = A
|
|
static RENDERER_API const FScreenTransform Identity;
|
|
|
|
// Transforms ScreenPos to/from ViewportUV
|
|
static RENDERER_API const FScreenTransform ScreenPosToViewportUV;
|
|
static RENDERER_API const FScreenTransform ViewportUVToScreenPos;
|
|
|
|
|
|
/** Invert a transformation AToB to BToA. */
|
|
static inline FScreenTransform Invert(const FScreenTransform& AToB);
|
|
|
|
/** Change of coordinate to map from a rectangle to another. */
|
|
static FScreenTransform ChangeRectFromTo(
|
|
FVector2f SourceOffset, FVector2f SourceExtent,
|
|
FVector2f DestinationOffset, FVector2f DestinationExtent);
|
|
static FScreenTransform ChangeRectFromTo(const FIntRect& SrcViewport, const FIntRect& DestViewport);
|
|
|
|
/** Different texture coordinate basis. */
|
|
enum class ETextureBasis
|
|
{
|
|
// Viewport maps [-1.0,1.0] on X, ]1.0, -1.0[ on Y.
|
|
ScreenPosition,
|
|
|
|
// Viewport maps [0.0,1.0]
|
|
ViewportUV,
|
|
|
|
// Viewport maps [Viewport.Min,Viewport.Max] in pixel coordinate in the texture
|
|
// Used for instance for MyTexture[uint(TexelPosition)];
|
|
TexelPosition,
|
|
|
|
// Viewport maps [Viewport.Min / TextureExtent,Viewport.Max / TextureExtent]
|
|
// Used for MyTexture.SampleLevel(MySampler, TextureUV, 0);
|
|
TextureUV,
|
|
};
|
|
|
|
/** Change of basis for texture coordinate. */
|
|
static inline FScreenTransform ChangeTextureBasisFromTo(
|
|
const FIntPoint& TextureExtent, const FIntRect& TextureViewport,
|
|
ETextureBasis SrcBasis, ETextureBasis DestBasis);
|
|
|
|
static inline FScreenTransform ChangeTextureBasisFromTo(
|
|
const FScreenPassTextureViewport& TextureViewport,
|
|
ETextureBasis SrcBasis, ETextureBasis DestBasis)
|
|
{
|
|
return ChangeTextureBasisFromTo(TextureViewport.Extent, TextureViewport.Rect, SrcBasis, DestBasis);
|
|
}
|
|
|
|
static inline FScreenTransform ChangeTextureBasisFromTo(
|
|
const FScreenPassTexture& Texture,
|
|
ETextureBasis SrcBasis, ETextureBasis DestBasis)
|
|
{
|
|
return ChangeTextureBasisFromTo(FScreenPassTextureViewport(Texture.Texture, Texture.ViewRect), SrcBasis, DestBasis);
|
|
}
|
|
|
|
/** Change TextureUV coordinate from one texture to another, taking into account change in texture extent too. */
|
|
static FScreenTransform ChangeTextureUVCoordinateFromTo(
|
|
const FScreenPassTextureViewport& SrcViewport,
|
|
const FScreenPassTextureViewport& DestViewport);
|
|
|
|
static FScreenTransform SvPositionToViewportUV(const FIntRect& SrcViewport);
|
|
static FScreenTransform DispatchThreadIdToViewportUV(const FIntRect& SrcViewport);
|
|
}; // FScreenTransform
|
|
|
|
// A utility shader parameter struct containing the viewport, texture, and sampler for a unique texture input to a shader.
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FScreenPassTextureInput, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FScreenPassTextureViewportParameters, Viewport)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, Texture)
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, Sampler)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FScreenPassTextureSliceInput, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FScreenPassTextureViewportParameters, Viewport)
|
|
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, Texture)
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, Sampler)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
FScreenPassTextureInput GetScreenPassTextureInput(FScreenPassTexture Input, FRHISamplerState* Sampler);
|
|
FScreenPassTextureSliceInput GetScreenPassTextureInput(FScreenPassTextureSlice Input, FRHISamplerState* Sampler);
|
|
|
|
/** Draw information for the more advanced DrawScreenPass variant. Allows customizing the blend / depth stencil state,
|
|
* providing a custom vertex shader, and more fine-grained control of the underlying draw call.
|
|
*/
|
|
struct FScreenPassPipelineState
|
|
{
|
|
using FDefaultBlendState = TStaticBlendState<>;
|
|
using FDefaultDepthStencilState = TStaticDepthStencilState<false, CF_Always>;
|
|
|
|
FScreenPassPipelineState() = default;
|
|
|
|
FScreenPassPipelineState(
|
|
const TShaderRef<FShader>& InVertexShader,
|
|
const TShaderRef<FShader>& InPixelShader,
|
|
FRHIBlendState* InBlendState = FDefaultBlendState::GetRHI(),
|
|
FRHIDepthStencilState* InDepthStencilState = FDefaultDepthStencilState::GetRHI(),
|
|
uint8 InStencilRef = 0,
|
|
FRHIVertexDeclaration* InVertexDeclaration = GFilterVertexDeclaration.VertexDeclarationRHI)
|
|
: VertexShader(InVertexShader)
|
|
, PixelShader(InPixelShader)
|
|
, BlendState(InBlendState)
|
|
, DepthStencilState(InDepthStencilState)
|
|
, VertexDeclaration(InVertexDeclaration)
|
|
, StencilRef(InStencilRef)
|
|
{}
|
|
|
|
void Validate() const
|
|
{
|
|
check(VertexShader.IsValid());
|
|
check(PixelShader.IsValid());
|
|
check(BlendState);
|
|
check(DepthStencilState);
|
|
check(VertexDeclaration);
|
|
}
|
|
|
|
TShaderRef<FShader> VertexShader;
|
|
TShaderRef<FShader> PixelShader;
|
|
FRHIBlendState* BlendState = nullptr;
|
|
FRHIDepthStencilState* DepthStencilState = nullptr;
|
|
FRHIVertexDeclaration* VertexDeclaration = nullptr;
|
|
uint8 StencilRef{};
|
|
};
|
|
|
|
// Helper function which sets the pipeline state object on the command list prior to invoking a screen pass.
|
|
void RENDERER_API SetScreenPassPipelineState(FRHICommandList& RHICmdList, const FScreenPassPipelineState& ScreenPassDraw);
|
|
|
|
enum class EScreenPassDrawFlags : uint8
|
|
{
|
|
None,
|
|
|
|
// Allows the screen pass to use a HMD hidden area mask if one is available. Used for VR.
|
|
AllowHMDHiddenAreaMask = 0x2
|
|
};
|
|
ENUM_CLASS_FLAGS(EScreenPassDrawFlags);
|
|
|
|
/** Type used to carry the limited amount of data we need from a FSceneView. */
|
|
struct FScreenPassViewInfo
|
|
{
|
|
const ERHIFeatureLevel::Type FeatureLevel;
|
|
const int32 StereoViewIndex;
|
|
const int32 InstanceCount;
|
|
const bool bHMDHiddenAreaMaskActive;
|
|
|
|
FScreenPassViewInfo()
|
|
: FScreenPassViewInfo(GMaxRHIFeatureLevel)
|
|
{
|
|
}
|
|
|
|
FScreenPassViewInfo(ERHIFeatureLevel::Type InFeatureLevel)
|
|
: FeatureLevel(InFeatureLevel)
|
|
, StereoViewIndex(INDEX_NONE)
|
|
, InstanceCount(1)
|
|
, bHMDHiddenAreaMaskActive(IsHMDHiddenAreaMaskActive())
|
|
{
|
|
}
|
|
|
|
FScreenPassViewInfo(const FSceneView& View)
|
|
: FeatureLevel(View.FeatureLevel)
|
|
, StereoViewIndex(View.StereoViewIndex)
|
|
, InstanceCount(View.GetStereoPassInstanceFactor())
|
|
, bHMDHiddenAreaMaskActive(View.bHMDHiddenAreaMaskActive)
|
|
{
|
|
}
|
|
|
|
FScreenPassViewInfo(const FSceneView& View, const uint32 OverrideInstanceCount)
|
|
: FeatureLevel(View.FeatureLevel)
|
|
, StereoViewIndex(View.StereoViewIndex)
|
|
, InstanceCount(OverrideInstanceCount)
|
|
, bHMDHiddenAreaMaskActive(View.bHMDHiddenAreaMaskActive)
|
|
{
|
|
}
|
|
};
|
|
|
|
RENDERER_API void DrawScreenPass_PostSetup(
|
|
FRHICommandList& RHICmdList,
|
|
const FScreenPassViewInfo& ViewInfo,
|
|
const FScreenPassTextureViewport& OutputViewport,
|
|
const FScreenPassTextureViewport& InputViewport,
|
|
const FScreenPassPipelineState& PipelineState,
|
|
EScreenPassDrawFlags Flags);
|
|
|
|
/** More advanced variant of screen pass drawing. Supports overriding blend / depth stencil
|
|
* pipeline state, and providing a custom vertex shader. Shader parameters are not bound by
|
|
* this method, instead the user provides a setup function that is called prior to draw, but
|
|
* after setting the PSO. This setup function should assign shader parameters.
|
|
*/
|
|
template<typename TSetupFunction>
|
|
void DrawScreenPass(
|
|
FRHICommandList& RHICmdList,
|
|
FScreenPassViewInfo ViewInfo,
|
|
const FScreenPassTextureViewport& OutputViewport,
|
|
const FScreenPassTextureViewport& InputViewport,
|
|
const FScreenPassPipelineState& PipelineState,
|
|
EScreenPassDrawFlags Flags,
|
|
TSetupFunction SetupFunction)
|
|
{
|
|
PipelineState.Validate();
|
|
|
|
const FIntRect OutputRect = OutputViewport.Rect;
|
|
|
|
RHICmdList.SetViewport(OutputRect.Min.X, OutputRect.Min.Y, 0.0f, OutputRect.Max.X, OutputRect.Max.Y, 1.0f);
|
|
|
|
SetScreenPassPipelineState(RHICmdList, PipelineState);
|
|
|
|
SetupFunction(RHICmdList);
|
|
|
|
DrawScreenPass_PostSetup(RHICmdList, ViewInfo, OutputViewport, InputViewport, PipelineState, Flags);
|
|
}
|
|
|
|
/** Render graph variant of simpler DrawScreenPass function. Clears graph resources unused by the
|
|
* pixel shader prior to adding the pass.
|
|
*/
|
|
template <typename PixelShaderType>
|
|
FORCEINLINE void AddDrawScreenPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
FScreenPassViewInfo ViewInfo,
|
|
const FScreenPassTextureViewport& OutputViewport,
|
|
const FScreenPassTextureViewport& InputViewport,
|
|
const TShaderRef<FShader>& VertexShader,
|
|
const TShaderRef<PixelShaderType>& PixelShader,
|
|
FRHIBlendState* BlendState,
|
|
FRHIDepthStencilState* DepthStencilState,
|
|
typename PixelShaderType::FParameters* PixelShaderParameters,
|
|
EScreenPassDrawFlags Flags = EScreenPassDrawFlags::None)
|
|
{
|
|
check(VertexShader.IsValid());
|
|
check(PixelShader.IsValid());
|
|
check(PixelShaderParameters);
|
|
|
|
ClearUnusedGraphResources(PixelShader, PixelShaderParameters);
|
|
|
|
const FScreenPassPipelineState PipelineState(VertexShader, PixelShader, BlendState, DepthStencilState);
|
|
|
|
GraphBuilder.AddPass(
|
|
Forward<FRDGEventName&&>(PassName),
|
|
PixelShaderParameters,
|
|
ERDGPassFlags::Raster,
|
|
[ViewInfo, OutputViewport, InputViewport, PipelineState, PixelShader, PixelShaderParameters, Flags](FRDGAsyncTask, FRHICommandList& RHICmdList)
|
|
{
|
|
DrawScreenPass(RHICmdList, ViewInfo, OutputViewport, InputViewport, PipelineState, Flags, [&](FRHICommandList&)
|
|
{
|
|
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *PixelShaderParameters);
|
|
});
|
|
});
|
|
}
|
|
|
|
template <typename PixelShaderType>
|
|
FORCEINLINE void AddDrawScreenPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
FScreenPassViewInfo ViewInfo,
|
|
const FScreenPassTextureViewport& OutputViewport,
|
|
const FScreenPassTextureViewport& InputViewport,
|
|
const TShaderRef<FShader>& VertexShader,
|
|
const TShaderRef<PixelShaderType>& PixelShader,
|
|
typename PixelShaderType::FParameters* PixelShaderParameters,
|
|
EScreenPassDrawFlags Flags = EScreenPassDrawFlags::None)
|
|
{
|
|
FRHIBlendState* BlendState = FScreenPassPipelineState::FDefaultBlendState::GetRHI();
|
|
FRHIDepthStencilState* DepthStencilState = FScreenPassPipelineState::FDefaultDepthStencilState::GetRHI();
|
|
AddDrawScreenPass(GraphBuilder, Forward<FRDGEventName&&>(PassName), ViewInfo, OutputViewport, InputViewport, VertexShader, PixelShader, BlendState, DepthStencilState, PixelShaderParameters, Flags);
|
|
}
|
|
|
|
template <typename PixelShaderType>
|
|
FORCEINLINE void AddDrawScreenPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
FScreenPassViewInfo ViewInfo,
|
|
const FScreenPassTextureViewport& OutputViewport,
|
|
const FScreenPassTextureViewport& InputViewport,
|
|
const TShaderRef<FShader>& VertexShader,
|
|
const TShaderRef<PixelShaderType>& PixelShader,
|
|
FRHIBlendState* BlendState,
|
|
typename PixelShaderType::FParameters* PixelShaderParameters,
|
|
EScreenPassDrawFlags Flags = EScreenPassDrawFlags::None)
|
|
{
|
|
FRHIDepthStencilState* DepthStencilState = FScreenPassPipelineState::FDefaultDepthStencilState::GetRHI();
|
|
AddDrawScreenPass(GraphBuilder, Forward<FRDGEventName&&>(PassName), ViewInfo, OutputViewport, InputViewport, VertexShader, PixelShader, BlendState, DepthStencilState, PixelShaderParameters, Flags);
|
|
}
|
|
|
|
template <typename PixelShaderType>
|
|
FORCEINLINE void AddDrawScreenPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
FScreenPassViewInfo ViewInfo,
|
|
const FScreenPassTextureViewport& OutputViewport,
|
|
const FScreenPassTextureViewport& InputViewport,
|
|
const TShaderRef<FShader>& VertexShader,
|
|
const TShaderRef<PixelShaderType>& PixelShader,
|
|
FRHIDepthStencilState* DepthStencilState,
|
|
typename PixelShaderType::FParameters* PixelShaderParameters,
|
|
EScreenPassDrawFlags Flags = EScreenPassDrawFlags::None)
|
|
{
|
|
FRHIBlendState* BlendState = FScreenPassPipelineState::FDefaultBlendState::GetRHI();
|
|
AddDrawScreenPass(GraphBuilder, Forward<FRDGEventName&&>(PassName), ViewInfo, OutputViewport, InputViewport, VertexShader, PixelShader, BlendState, DepthStencilState, PixelShaderParameters, Flags);
|
|
}
|
|
|
|
template <typename PixelShaderType>
|
|
FORCEINLINE void AddDrawScreenPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
FScreenPassViewInfo ViewInfo,
|
|
const FScreenPassTextureViewport& OutputViewport,
|
|
const FScreenPassTextureViewport& InputViewport,
|
|
const TShaderRef<PixelShaderType>& PixelShader,
|
|
typename PixelShaderType::FParameters* PixelShaderParameters,
|
|
EScreenPassDrawFlags Flags = EScreenPassDrawFlags::None)
|
|
{
|
|
FGlobalShaderMap* ShaderMap = GetGlobalShaderMap(ViewInfo.FeatureLevel);
|
|
TShaderMapRef<FScreenPassVS> VertexShader(ShaderMap);
|
|
FRHIBlendState* BlendState = FScreenPassPipelineState::FDefaultBlendState::GetRHI();
|
|
FRHIDepthStencilState* DepthStencilState = FScreenPassPipelineState::FDefaultDepthStencilState::GetRHI();
|
|
AddDrawScreenPass(GraphBuilder, Forward<FRDGEventName&&>(PassName), ViewInfo, OutputViewport, InputViewport, VertexShader, PixelShader, BlendState, DepthStencilState, PixelShaderParameters, Flags);
|
|
}
|
|
|
|
/** Render graph variant of more advanced DrawScreenPass function. Does *not* clear unused graph
|
|
* resources, since the parameters might be shared between the vertex and pixel shaders.
|
|
*/
|
|
template <typename TSetupFunction, typename TPassParameterStruct>
|
|
FORCEINLINE void AddDrawScreenPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
FScreenPassViewInfo ViewInfo,
|
|
const FScreenPassTextureViewport& OutputViewport,
|
|
const FScreenPassTextureViewport& InputViewport,
|
|
const FScreenPassPipelineState& PipelineState,
|
|
TPassParameterStruct* PassParameterStruct,
|
|
EScreenPassDrawFlags Flags,
|
|
TSetupFunction SetupFunction)
|
|
{
|
|
PipelineState.Validate();
|
|
check(PassParameterStruct);
|
|
|
|
GraphBuilder.AddPass(
|
|
Forward<FRDGEventName&&>(PassName),
|
|
PassParameterStruct,
|
|
ERDGPassFlags::Raster,
|
|
[ViewInfo, OutputViewport, InputViewport, PipelineState, SetupFunction, Flags] (FRDGAsyncTask, FRHICommandList& RHICmdList)
|
|
{
|
|
DrawScreenPass(RHICmdList, ViewInfo, OutputViewport, InputViewport, PipelineState, Flags, SetupFunction);
|
|
});
|
|
}
|
|
|
|
template <typename TSetupFunction, typename TPassParameterStruct>
|
|
FORCEINLINE void AddDrawScreenPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
FScreenPassViewInfo ViewInfo,
|
|
const FScreenPassTextureViewport& OutputViewport,
|
|
const FScreenPassTextureViewport& InputViewport,
|
|
const FScreenPassPipelineState& PipelineState,
|
|
TPassParameterStruct* PassParameterStruct,
|
|
TSetupFunction SetupFunction)
|
|
{
|
|
AddDrawScreenPass(GraphBuilder, Forward<FRDGEventName&&>(PassName), ViewInfo, OutputViewport, InputViewport, PipelineState, PassParameterStruct, EScreenPassDrawFlags::None, SetupFunction);
|
|
}
|
|
|
|
/** Helper function which copies a region of an input texture to a region of the output texture,
|
|
* with support for format conversion. If formats match, the method falls back to a simple DMA
|
|
* (CopyTexture); otherwise, it rasterizes using a pixel shader. Use this method if the two
|
|
* textures may have different formats.
|
|
*/
|
|
void RENDERER_API AddDrawTexturePass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FScreenPassViewInfo ViewInfo,
|
|
FRDGTextureRef InputTexture,
|
|
FRDGTextureRef OutputTexture,
|
|
FIntPoint InputPosition = FIntPoint::ZeroValue,
|
|
FIntPoint OutputPosition = FIntPoint::ZeroValue,
|
|
FIntPoint Size = FIntPoint::ZeroValue);
|
|
|
|
void RENDERER_API AddDrawTexturePass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FScreenPassViewInfo ViewInfo,
|
|
FRDGTextureRef InputTexture,
|
|
FRDGTextureRef OutputTexture,
|
|
FIntPoint InputPosition,
|
|
FIntPoint InputSize,
|
|
FIntPoint OutputPosition,
|
|
FIntPoint OutputSize);
|
|
|
|
/** Helper variant which takes a shared viewport instead of unique input / output positions. */
|
|
FORCEINLINE void AddDrawTexturePass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FScreenPassViewInfo ViewInfo,
|
|
FRDGTextureRef InputTexture,
|
|
FRDGTextureRef OutputTexture,
|
|
FIntRect ViewportRect)
|
|
{
|
|
AddDrawTexturePass(GraphBuilder, ViewInfo, InputTexture, OutputTexture, ViewportRect.Min, ViewportRect.Min, ViewportRect.Size());
|
|
}
|
|
|
|
void RENDERER_API AddDrawTexturePass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FScreenPassViewInfo ViewInfo,
|
|
FScreenPassTexture Input,
|
|
FScreenPassRenderTarget Output,
|
|
uint32 RTMultiviewCount = 1);
|
|
|
|
inline void AddDrawTexturePass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FScreenPassViewInfo ViewInfo,
|
|
FScreenPassTexture Input,
|
|
FScreenPassTexture Output)
|
|
{
|
|
ERenderTargetLoadAction LoadAction = ERenderTargetLoadAction::ELoad;
|
|
if (Input.Texture->Desc.Extent == Output.Texture->Desc.Extent && Input.ViewRect == Output.ViewRect)
|
|
{
|
|
LoadAction = ERenderTargetLoadAction::ENoAction;
|
|
}
|
|
AddDrawTexturePass(GraphBuilder, ViewInfo, Input, FScreenPassRenderTarget(Output, LoadAction));
|
|
}
|
|
|
|
/** Variation of above that accepts a slice, which contains a texture SRV instead of a texture */
|
|
void RENDERER_API AddDrawTexturePass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FScreenPassViewInfo ViewInfo,
|
|
FScreenPassTextureSlice Input,
|
|
FScreenPassRenderTarget Output);
|
|
|
|
template <typename TFunction>
|
|
FORCEINLINE void AddRenderTargetPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
FScreenPassRenderTarget Output,
|
|
TFunction&& Function)
|
|
{
|
|
FRenderTargetParameters* PassParameters = GraphBuilder.AllocParameters<FRenderTargetParameters>();
|
|
PassParameters->RenderTargets[0] = Output.GetRenderTargetBinding();
|
|
GraphBuilder.AddPass(MoveTemp(PassName), PassParameters, ERDGPassFlags::Raster, MoveTemp(Function));
|
|
}
|
|
|
|
template <typename TFunction>
|
|
FORCEINLINE void AddDrawCanvasPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
const FSceneView& View,
|
|
FScreenPassRenderTarget Output,
|
|
TFunction Function)
|
|
{
|
|
check(Output.IsValid());
|
|
|
|
const FSceneViewFamily& ViewFamily = *View.Family;
|
|
FCanvas& Canvas = *FCanvas::Create(GraphBuilder, Output.Texture, nullptr, ViewFamily.Time, View.GetFeatureLevel(), ViewFamily.DebugDPIScale);
|
|
Canvas.SetRenderTargetRect(Output.ViewRect);
|
|
|
|
Function(Canvas);
|
|
|
|
const bool bFlush = false;
|
|
Canvas.Flush_RenderThread(GraphBuilder, bFlush);
|
|
}
|
|
|
|
enum class EDownsampleDepthFilter
|
|
{
|
|
// Produces a depth value that is not conservative but has consistent error (i.e. picks the sample).
|
|
Point,
|
|
|
|
// Produces a conservative max depth value.
|
|
Max,
|
|
|
|
// Produces a checkerboarded selection of min and max depth values
|
|
Checkerboard,
|
|
|
|
// Produces a color texture where R=min and G=max DeviceZ
|
|
MinAndMaxDepth,
|
|
|
|
// Produces a color texture where R=min and G=max DeviceZ from a color texture containing R=min and G=max DeviceZ
|
|
MinAndMaxDepthFromMinAndMaxDepth
|
|
};
|
|
|
|
RENDERER_API void AddDownsampleDepthPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FViewInfo& View,
|
|
FScreenPassTexture Input,
|
|
FScreenPassRenderTarget Output,
|
|
EDownsampleDepthFilter DownsampleDepthFilter);
|
|
|
|
#include "ScreenPass.inl" // IWYU pragma: export
|