You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
184 lines
6.9 KiB
C++
184 lines
6.9 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "RenderGraphResources.h"
|
|
#include "RenderGraphBuilder.h"
|
|
#include "Shader.h"
|
|
#include "ShaderParameterStruct.h"
|
|
#include "ShaderParameterMacros.h"
|
|
|
|
|
|
/** An empty shader parameter structure ready to be used anywhere. */
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FEmptyShaderParameters, RENDERCORE_API)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
|
|
/** Useful parameter struct that only have render targets.
|
|
*
|
|
* FRenderTargetParameters PassParameters;
|
|
* PassParameters.RenderTargets.DepthStencil = ... ;
|
|
* PassParameters.RenderTargets[0] = ... ;
|
|
*/
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FRenderTargetParameters, RENDERCORE_API)
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
|
|
/**
|
|
* Clears all render graph tracked resources that are not bound by a shader.
|
|
* Excludes any resources on the ExcludeList from being cleared regardless of whether the
|
|
* shader binds them or not. This is needed for resources that are used outside of shader
|
|
* bindings such as indirect arguments buffers.
|
|
*/
|
|
extern RENDERCORE_API void ClearUnusedGraphResourcesImpl(
|
|
const FShaderParameterBindings& ShaderBindings,
|
|
const FShaderParametersMetadata* ParametersMetadata,
|
|
void* InoutParameters,
|
|
std::initializer_list< FRDGResourceRef > ExcludeList);
|
|
|
|
template<typename TShaderClass>
|
|
FORCEINLINE_DEBUGGABLE void ClearUnusedGraphResources(
|
|
const TShaderClass* Shader,
|
|
typename TShaderClass::FParameters* InoutParameters,
|
|
std::initializer_list< FRDGResourceRef > ExcludeList = {})
|
|
{
|
|
const FShaderParametersMetadata* ParametersMetadata = TShaderClass::FParameters::FTypeInfo::GetStructMetadata();
|
|
|
|
// Verify the shader have all the parameters it needs. This is done before the
|
|
// ClearUnusedGraphResourcesImpl() to not misslead user on why some resource are misseing
|
|
// when debugging a validation failure.
|
|
ValidateShaderParameters(Shader, ParametersMetadata, InoutParameters);
|
|
|
|
// Clear the resources the shader won't need.
|
|
return ClearUnusedGraphResourcesImpl(Shader->Bindings, ParametersMetadata, InoutParameters, ExcludeList);
|
|
}
|
|
|
|
|
|
/**
|
|
* Register external texture with fallback if the resource is invalid.
|
|
*
|
|
* CAUTION: use this function very wisely. It may actually remove shader parameter validation
|
|
* failure when a pass is actually trying to access a resource not yet or no longer available.
|
|
*/
|
|
RENDERCORE_API FRDGTextureRef RegisterExternalTextureWithFallback(
|
|
FRDGBuilder& GraphBuilder,
|
|
const TRefCountPtr<IPooledRenderTarget>& ExternalPooledTexture,
|
|
const TRefCountPtr<IPooledRenderTarget>& FallbackPooledTexture,
|
|
const TCHAR* ExternalPooledTextureName = TEXT("External"));
|
|
|
|
|
|
/** All utils for compute shaders.
|
|
*/
|
|
struct RENDERCORE_API FComputeShaderUtils
|
|
{
|
|
/** Ideal size of group size 8x8 to occupy at least an entire wave on GCN, two warp on Nvidia. */
|
|
static constexpr int32 kGolden2DGroupSize = 8;
|
|
|
|
/** Compute the number of group to dispatch. */
|
|
static FIntVector GetGroupCount(const int32 ThreadCount, const int32 GroupSize)
|
|
{
|
|
return FIntVector(
|
|
FMath::DivideAndRoundUp(ThreadCount, GroupSize),
|
|
1,
|
|
1);
|
|
}
|
|
static FIntVector GetGroupCount(const FIntPoint& ThreadCount, const FIntPoint& GroupSize)
|
|
{
|
|
return FIntVector(
|
|
FMath::DivideAndRoundUp(ThreadCount.X, GroupSize.X),
|
|
FMath::DivideAndRoundUp(ThreadCount.Y, GroupSize.Y),
|
|
1);
|
|
}
|
|
static FIntVector GetGroupCount(const FIntPoint& ThreadCount, const int32 GroupSize)
|
|
{
|
|
return FIntVector(
|
|
FMath::DivideAndRoundUp(ThreadCount.X, GroupSize),
|
|
FMath::DivideAndRoundUp(ThreadCount.Y, GroupSize),
|
|
1);
|
|
}
|
|
static FIntVector GetGroupCount(const FIntVector& ThreadCount, const FIntVector& GroupSize)
|
|
{
|
|
return FIntVector(
|
|
FMath::DivideAndRoundUp(ThreadCount.X, GroupSize.X),
|
|
FMath::DivideAndRoundUp(ThreadCount.Y, GroupSize.Y),
|
|
FMath::DivideAndRoundUp(ThreadCount.Z, GroupSize.Z));
|
|
}
|
|
|
|
|
|
/** Dispatch a compute shader to rhi command list with its parameters. */
|
|
template<typename TShaderClass>
|
|
static FORCEINLINE_DEBUGGABLE void Dispatch(FRHICommandList& RHICmdList, const TShaderClass* ComputeShader, const typename TShaderClass::FParameters& Parameters, FIntVector GroupCount)
|
|
{
|
|
FRHIComputeShader* ShaderRHI = ComputeShader->GetComputeShader();
|
|
RHICmdList.SetComputeShader(ShaderRHI);
|
|
SetShaderParameters(RHICmdList, ComputeShader, ShaderRHI, Parameters);
|
|
RHICmdList.DispatchComputeShader(GroupCount.X, GroupCount.Y, GroupCount.Z);
|
|
UnsetShaderUAVs(RHICmdList, ComputeShader, ShaderRHI);
|
|
}
|
|
|
|
/** Indirect dispatch a compute shader to rhi command list with its parameters. */
|
|
template<typename TShaderClass>
|
|
static FORCEINLINE_DEBUGGABLE void DispatchIndirect(
|
|
FRHICommandList& RHICmdList,
|
|
const TShaderClass* ComputeShader,
|
|
const typename TShaderClass::FParameters& Parameters,
|
|
FRHIVertexBuffer* IndirectArgsBuffer,
|
|
uint32 IndirectArgOffset)
|
|
{
|
|
FRHIComputeShader* ShaderRHI = ComputeShader->GetComputeShader();
|
|
RHICmdList.SetComputeShader(ShaderRHI);
|
|
SetShaderParameters(RHICmdList, ComputeShader, ShaderRHI, Parameters);
|
|
RHICmdList.DispatchIndirectComputeShader(IndirectArgsBuffer, IndirectArgOffset);
|
|
UnsetShaderUAVs(RHICmdList, ComputeShader, ShaderRHI);
|
|
}
|
|
|
|
/** Dispatch a compute shader to render graph builder with its parameters. */
|
|
template<typename TShaderClass>
|
|
static FORCEINLINE_DEBUGGABLE void AddPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
const TShaderClass* ComputeShader,
|
|
typename TShaderClass::FParameters* Parameters,
|
|
FIntVector GroupCount)
|
|
{
|
|
ClearUnusedGraphResources(ComputeShader, Parameters);
|
|
|
|
GraphBuilder.AddPass(
|
|
Forward<FRDGEventName>(PassName),
|
|
Parameters,
|
|
ERDGPassFlags::Compute,
|
|
[Parameters, ComputeShader, GroupCount](FRHICommandList& RHICmdList)
|
|
{
|
|
FComputeShaderUtils::Dispatch(RHICmdList, ComputeShader, *Parameters, GroupCount);
|
|
});
|
|
}
|
|
|
|
/** Dispatch a compute shader to render graph builder with its parameters. */
|
|
template<typename TShaderClass>
|
|
static FORCEINLINE_DEBUGGABLE void AddPass(
|
|
FRDGBuilder& GraphBuilder,
|
|
FRDGEventName&& PassName,
|
|
const TShaderClass* ComputeShader,
|
|
typename TShaderClass::FParameters* Parameters,
|
|
FRDGBufferRef IndirectArgsBuffer,
|
|
uint32 IndirectArgOffset)
|
|
{
|
|
checkf(IndirectArgsBuffer->Desc.Usage & BUF_DrawIndirect, TEXT("The buffer %s was not flagged for indirect draw parameters"), IndirectArgsBuffer->Name);
|
|
|
|
ClearUnusedGraphResources(ComputeShader, Parameters, { IndirectArgsBuffer });
|
|
|
|
GraphBuilder.AddPass(
|
|
Forward<FRDGEventName>(PassName),
|
|
Parameters,
|
|
ERDGPassFlags::Compute,
|
|
[Parameters, ComputeShader, IndirectArgsBuffer, IndirectArgOffset](FRHICommandList& RHICmdList)
|
|
{
|
|
// Marks the indirect draw parameter as used by the pass manually, given it can't be bound directly by any of the shader,
|
|
// meaning SetShaderParameters() won't be able to do it.
|
|
IndirectArgsBuffer->MarkResourceAsUsed();
|
|
|
|
FComputeShaderUtils::DispatchIndirect(RHICmdList, ComputeShader, *Parameters, IndirectArgsBuffer->GetIndirectRHICallBuffer(), IndirectArgOffset);
|
|
});
|
|
}
|
|
}; |