892 lines
34 KiB
C++
892 lines
34 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
RHIContext.h: Interface for RHI Contexts
|
|
=============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#include "Misc/AssertionMacros.h"
|
|
#include "Math/Color.h"
|
|
#include "Math/IntPoint.h"
|
|
#include "Math/IntRect.h"
|
|
#include "Math/Box2D.h"
|
|
#include "Math/PerspectiveMatrix.h"
|
|
#include "Math/TranslationMatrix.h"
|
|
#include "Math/ScaleMatrix.h"
|
|
#include "Math/Float16Color.h"
|
|
#include "Modules/ModuleInterface.h"
|
|
#include "RHIBreadcrumbs.h"
|
|
#include "RHIResources.h"
|
|
#include "RHIShaderParameters.h"
|
|
#include "GPUProfiler.h"
|
|
|
|
class FRHIDepthRenderTargetView;
|
|
class FRHIRenderTargetView;
|
|
class FRHISetRenderTargetsInfo;
|
|
class FRHIShaderBindingLayout;
|
|
struct FViewportBounds;
|
|
struct FRayTracingGeometryInstance;
|
|
struct FRayTracingShaderBindings;
|
|
struct FRayTracingGeometrySegment;
|
|
struct FRayTracingGeometryBuildParams;
|
|
struct FRayTracingSceneBuildParams;
|
|
struct FRayTracingLocalShaderBindings;
|
|
enum class ERayTracingBindingType : uint8;
|
|
enum class EAsyncComputeBudget;
|
|
|
|
struct FRHIBufferRange;
|
|
struct FRHIPerCategoryDrawStats;
|
|
struct FRHIDrawStats;
|
|
struct FRHICopyTextureInfo;
|
|
|
|
|
|
#define VALIDATE_UNIFORM_BUFFER_STATIC_BINDINGS (!UE_BUILD_SHIPPING && !UE_BUILD_TEST)
|
|
|
|
/** A list of static uniform buffer bindings. */
|
|
class FUniformBufferStaticBindings
|
|
{
|
|
public:
|
|
FUniformBufferStaticBindings() = default;
|
|
|
|
template <typename... TArgs>
|
|
FUniformBufferStaticBindings(TArgs... Args)
|
|
{
|
|
std::initializer_list<FRHIUniformBuffer*> InitList = { Args... };
|
|
|
|
for (FRHIUniformBuffer* Buffer : InitList)
|
|
{
|
|
AddUniformBuffer(Buffer);
|
|
}
|
|
}
|
|
|
|
RHI_API FUniformBufferStaticBindings(const FRHIShaderBindingLayout* InSRTDesc);
|
|
|
|
RHI_API void AddUniformBuffer(FRHIUniformBuffer* UniformBuffer);
|
|
|
|
inline void TryAddUniformBuffer(FRHIUniformBuffer* UniformBuffer)
|
|
{
|
|
if (UniformBuffer)
|
|
{
|
|
AddUniformBuffer(UniformBuffer);
|
|
}
|
|
}
|
|
|
|
int32 GetUniformBufferCount() const
|
|
{
|
|
return UniformBuffers.Num();
|
|
}
|
|
|
|
FRHIUniformBuffer* GetUniformBuffer(int32 Index) const
|
|
{
|
|
return UniformBuffers[Index];
|
|
}
|
|
|
|
FUniformBufferStaticSlot GetSlot(int32 Index) const
|
|
{
|
|
return Slots[Index];
|
|
}
|
|
|
|
int32 GetSlotCount() const
|
|
{
|
|
return SlotCount;
|
|
}
|
|
|
|
const FRHIShaderBindingLayout* GetShaderBindingLayout() const
|
|
{
|
|
return ShaderBindingLayout;
|
|
}
|
|
|
|
RHI_API void Bind(TArray<FRHIUniformBuffer*>& Bindings) const;
|
|
|
|
private:
|
|
static const uint32 InlineUniformBufferCount = 8;
|
|
TArray<FUniformBufferStaticSlot, TInlineAllocator<InlineUniformBufferCount>> Slots;
|
|
TArray<FRHIUniformBuffer*, TInlineAllocator<InlineUniformBufferCount>> UniformBuffers;
|
|
int32 SlotCount = 0;
|
|
|
|
// Shader binding layout used during shader generation to validate runtime bindings and know where uniform buffers need to be bound
|
|
const FRHIShaderBindingLayout* ShaderBindingLayout = nullptr;
|
|
};
|
|
|
|
struct FTransferResourceFenceData
|
|
{
|
|
TStaticArray<void*, MAX_NUM_GPUS> SyncPoints;
|
|
FRHIGPUMask Mask;
|
|
|
|
FTransferResourceFenceData()
|
|
: SyncPoints(InPlace, nullptr)
|
|
{}
|
|
};
|
|
|
|
struct FCrossGPUTransferFence
|
|
{
|
|
uint32 SignalGPUIndex = 0;
|
|
uint32 WaitGPUIndex = 0;
|
|
void* SyncPoint = nullptr;
|
|
|
|
FCrossGPUTransferFence() = default;
|
|
};
|
|
|
|
FORCEINLINE FTransferResourceFenceData* RHICreateTransferResourceFenceData()
|
|
{
|
|
#if WITH_MGPU
|
|
return new FTransferResourceFenceData;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
FORCEINLINE FCrossGPUTransferFence* RHICreateCrossGPUTransferFence()
|
|
{
|
|
#if WITH_MGPU
|
|
return new FCrossGPUTransferFence;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
/** Parameters for RHITransferResources, used to copy memory between GPUs */
|
|
struct FTransferResourceParams
|
|
{
|
|
FTransferResourceParams() {}
|
|
|
|
FTransferResourceParams(FRHITexture* InTexture, const FIntRect& InRect, uint32 InSrcGPUIndex, uint32 InDestGPUIndex, bool InPullData, bool InLockStepGPUs)
|
|
: Texture(InTexture), Buffer(nullptr), Min(InRect.Min.X, InRect.Min.Y, 0), Max(InRect.Max.X, InRect.Max.Y, 1), SrcGPUIndex(InSrcGPUIndex), DestGPUIndex(InDestGPUIndex), bPullData(InPullData), bLockStepGPUs(InLockStepGPUs)
|
|
{
|
|
check(InTexture);
|
|
}
|
|
|
|
FTransferResourceParams(FRHITexture* InTexture, uint32 InSrcGPUIndex, uint32 InDestGPUIndex, bool InPullData, bool InLockStepGPUs)
|
|
: Texture(InTexture), Buffer(nullptr), Min(0, 0, 0), Max(0, 0, 0), SrcGPUIndex(InSrcGPUIndex), DestGPUIndex(InDestGPUIndex), bPullData(InPullData), bLockStepGPUs(InLockStepGPUs)
|
|
{
|
|
check(InTexture);
|
|
}
|
|
|
|
FTransferResourceParams(FRHIBuffer* InBuffer, uint32 InSrcGPUIndex, uint32 InDestGPUIndex, bool InPullData, bool InLockStepGPUs)
|
|
: Texture(nullptr), Buffer(InBuffer), Min(0, 0, 0), Max(0, 0, 0), SrcGPUIndex(InSrcGPUIndex), DestGPUIndex(InDestGPUIndex), bPullData(InPullData), bLockStepGPUs(InLockStepGPUs)
|
|
{
|
|
check(InBuffer);
|
|
}
|
|
|
|
void SetRect(const FIntRect& Rect)
|
|
{
|
|
// Do nothing if this isn't a texture
|
|
if (!Texture)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Reset the extents to default (zero), if the rect is empty or covers the full extent of the texture. Forces a more efficient full resource copy.
|
|
if (Rect.IsEmpty() || (Rect.Min.X == 0 && Rect.Min.Y == 0 && Rect.Max.X == Texture->GetDesc().Extent.X && Rect.Max.Y == Texture->GetDesc().Extent.Y))
|
|
{
|
|
Min = FIntVector3(0);
|
|
Max = FIntVector3(0);
|
|
return;
|
|
}
|
|
|
|
// Initialize the extent
|
|
Min = FIntVector3(Rect.Min.X, Rect.Min.Y, 0);
|
|
Max = FIntVector3(Rect.Max.X, Rect.Max.Y, 1);
|
|
}
|
|
|
|
// The texture which must be must be allocated on both GPUs
|
|
FTextureRHIRef Texture;
|
|
// Or alternately, a buffer that's allocated on both GPUs
|
|
FBufferRHIRef Buffer;
|
|
// The min rect of the texture region to copy
|
|
FIntVector Min;
|
|
// The max rect of the texture region to copy
|
|
FIntVector Max;
|
|
// The GPU index where the data will be read from.
|
|
uint32 SrcGPUIndex;
|
|
// The GPU index where the data will be written to.
|
|
uint32 DestGPUIndex;
|
|
// Whether the data is read by the dest GPU, or written by the src GPU (not allowed if the texture is a backbuffer)
|
|
bool bPullData = true;
|
|
// Whether the GPUs must handshake before and after the transfer. Required if the texture rect is being written to in several render passes.
|
|
// Otherwise, minimal synchronization will be used.
|
|
bool bLockStepGPUs = true;
|
|
/**
|
|
* Optional pointer where fence data can be written if you want to delay waiting on the GPU fence for a resource transfer.
|
|
* Should be created via "RHICreateTransferResourceFenceData", and must later be consumed via "TransferResourceWait" command.
|
|
* Note that it is valid to consume the fence data, even if you don't end up implementing a transfer that uses it -- it will
|
|
* behave as a nop in that case. That can simplify cases where the transfer may be conditional, and you don't want to worry
|
|
* about whether it occurred or not, but need to reserve the possibility.
|
|
*/
|
|
FTransferResourceFenceData* DelayedFence = nullptr;
|
|
/**
|
|
* Optional pointer to a fence to wait on before starting the transfer. Useful if a resource may be in use on the destination
|
|
* GPU, and you need to wait until it's no longer in use before copying to it from the current GPU. Fences are created via
|
|
* "RHICreateTransferResourceFenceData", then signaled via "TransferResourceSignal" command, before being added to one of the
|
|
* transfers in a batch that's dependent on the signal.
|
|
*/
|
|
FTransferResourceFenceData* PreTransferFence = nullptr;
|
|
};
|
|
|
|
//
|
|
// Type representing a finalized platform GPU command list, which can be submitted to the GPU via RHISubmitCommandLists().
|
|
// This type is intended only for use by RHI command list management. Platform RHIs provide the implementation.
|
|
// Also contains RHI breadcrumb allocators and ranges that platform RHIs must use if they implement GPU crash debugging.
|
|
//
|
|
class IRHIPlatformCommandList
|
|
{
|
|
// Prevent copying
|
|
IRHIPlatformCommandList(IRHIPlatformCommandList const&) = delete;
|
|
IRHIPlatformCommandList& operator = (IRHIPlatformCommandList const&) = delete;
|
|
|
|
protected:
|
|
// Allow moving
|
|
IRHIPlatformCommandList(IRHIPlatformCommandList&&) = default;
|
|
IRHIPlatformCommandList& operator = (IRHIPlatformCommandList&&) = default;
|
|
|
|
// This type is only usable by derived types (platform RHI implementations)
|
|
IRHIPlatformCommandList() = default;
|
|
~IRHIPlatformCommandList() = default;
|
|
|
|
public:
|
|
#if WITH_RHI_BREADCRUMBS
|
|
FRHIBreadcrumbAllocatorArray BreadcrumbAllocators {};
|
|
FRHIBreadcrumbRange BreadcrumbRange {};
|
|
#endif
|
|
};
|
|
|
|
/** Context that is capable of doing Compute work. Can be async or compute on the gfx pipe. */
|
|
class IRHIComputeContext
|
|
{
|
|
public:
|
|
virtual ~IRHIComputeContext()
|
|
{
|
|
}
|
|
|
|
virtual ERHIPipeline GetPipeline() const
|
|
{
|
|
return ERHIPipeline::AsyncCompute;
|
|
}
|
|
|
|
virtual void RHISetComputePipelineState(FRHIComputePipelineState* ComputePipelineState) = 0;
|
|
|
|
virtual void RHIDispatchComputeShader(uint32 ThreadGroupCountX, uint32 ThreadGroupCountY, uint32 ThreadGroupCountZ) = 0;
|
|
|
|
virtual void RHIRayTraceDispatch(FRHIRayTracingPipelineState* RayTracingPipelineState, FRHIRayTracingShader* RayGenShader,
|
|
FRHIShaderBindingTable* SBT, const FRayTracingShaderBindings& GlobalResourceBindings,
|
|
uint32 Width, uint32 Height)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
virtual void RHIRayTraceDispatchIndirect(FRHIRayTracingPipelineState* RayTracingPipelineState, FRHIRayTracingShader* RayGenShader,
|
|
FRHIShaderBindingTable* SBT, const FRayTracingShaderBindings& GlobalResourceBindings,
|
|
FRHIBuffer* ArgumentBuffer, uint32 ArgumentOffset)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
virtual void RHIDispatchIndirectComputeShader(FRHIBuffer* ArgumentBuffer, uint32 ArgumentOffset) = 0;
|
|
|
|
virtual void RHISetAsyncComputeBudget(EAsyncComputeBudget Budget) {}
|
|
virtual void RHISetComputeBudget(ESyncComputeBudget Budget) {}
|
|
|
|
virtual void RHIBeginTransitions(TArrayView<const FRHITransition*> Transitions) = 0;
|
|
|
|
virtual void RHIEndTransitions(TArrayView<const FRHITransition*> Transitions) = 0;
|
|
|
|
/**
|
|
* Clears a UAV to the multi-channel floating point value provided. Should only be called on UAVs with a floating point format, or on structured buffers.
|
|
* Structured buffers are treated as a regular R32_UINT buffer during the clear operation, and the Values.X component is copied directly into the buffer without any format conversion. (Y,Z,W) of Values is ignored.
|
|
* Typed floating point buffers undergo standard format conversion during the write operation. The conversion is determined by the format of the UAV.
|
|
*
|
|
* @param UnorderedAccessViewRHI The UAV to clear.
|
|
* @param Values The values to clear the UAV to, one component per channel (XYZW = RGBA). Channels not supported by the UAV are ignored.
|
|
*
|
|
*/
|
|
virtual void RHIClearUAVFloat(FRHIUnorderedAccessView* UnorderedAccessViewRHI, const FVector4f& Values) = 0;
|
|
|
|
/**
|
|
* Clears a UAV to the multi-component unsigned integer value provided. Should only be called on UAVs with an integer format, or on structured buffers.
|
|
* Structured buffers are treated as a regular R32_UINT buffer during the clear operation, and the Values.X component is copied directly into the buffer without any format conversion. (Y,Z,W) of Values is ignored.
|
|
* Typed integer buffers undergo standard format conversion during the write operation. The conversion is determined by the format of the UAV.
|
|
*
|
|
* @param UnorderedAccessViewRHI The UAV to clear.
|
|
* @param Values The values to clear the UAV to, one component per channel (XYZW = RGBA). Channels not supported by the UAV are ignored.
|
|
*
|
|
*/
|
|
virtual void RHIClearUAVUint(FRHIUnorderedAccessView* UnorderedAccessViewRHI, const FUintVector4& Values) = 0;
|
|
|
|
virtual void RHISetShaderRootConstants(const FUint32Vector4& Constants)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
virtual void RHIDispatchComputeShaderBundle(
|
|
FRHIShaderBundle* ShaderBundle,
|
|
FRHIBuffer* RecordArgBuffer,
|
|
TConstArrayView<FRHIShaderParameterResource> SharedBindlessParameters,
|
|
TConstArrayView<FRHIShaderBundleComputeDispatch> Dispatches,
|
|
bool bEmulated) {}
|
|
|
|
virtual void RHIDispatchGraphicsShaderBundle(
|
|
FRHIShaderBundle* ShaderBundle,
|
|
FRHIBuffer* RecordArgBuffer,
|
|
const FRHIShaderBundleGraphicsState& BundleState,
|
|
TConstArrayView<FRHIShaderParameterResource> SharedBindlessParameters,
|
|
TConstArrayView<FRHIShaderBundleGraphicsDispatch> Dispatches,
|
|
bool bEmulated) {}
|
|
|
|
virtual void RHIBeginUAVOverlap() {}
|
|
virtual void RHIEndUAVOverlap() {}
|
|
|
|
virtual void RHIBeginUAVOverlap(TConstArrayView<FRHIUnorderedAccessView*> UAVs) {}
|
|
virtual void RHIEndUAVOverlap(TConstArrayView<FRHIUnorderedAccessView*> UAVs) {}
|
|
|
|
virtual void RHISetShaderParameters(FRHIComputeShader* ComputeShader, TConstArrayView<uint8> InParametersData, TConstArrayView<FRHIShaderParameter> InParameters, TConstArrayView<FRHIShaderParameterResource> InResourceParameters, TConstArrayView<FRHIShaderParameterResource> InBindlessParameters) = 0;
|
|
|
|
void RHISetBatchedShaderParameters(FRHIComputeShader* InShader, FRHIBatchedShaderParameters& InBatchedParameters)
|
|
{
|
|
RHISetShaderParameters(
|
|
InShader,
|
|
InBatchedParameters.ParametersData,
|
|
InBatchedParameters.Parameters,
|
|
InBatchedParameters.ResourceParameters,
|
|
InBatchedParameters.BindlessParameters);
|
|
|
|
InBatchedParameters.Reset();
|
|
}
|
|
|
|
virtual void RHISetShaderUnbinds(FRHIComputeShader* ComputeShader, TConstArrayView<FRHIShaderParameterUnbind> InUnbinds)
|
|
{
|
|
checkf(false, TEXT("RHISetShaderUnbinds called when the active RHI hasn't overridden it and GRHIGlobals.NeedsShaderUnbinds is set."));
|
|
}
|
|
|
|
virtual void RHISetStaticUniformBuffers(const FUniformBufferStaticBindings& InUniformBuffers) = 0;
|
|
|
|
virtual void RHISetStaticUniformBuffer(FUniformBufferStaticSlot Slot, FRHIUniformBuffer* UniformBuffer) = 0;
|
|
|
|
virtual void RHISetUniformBufferDynamicOffset(FUniformBufferStaticSlot Slot, uint32 Offset)
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
#if WITH_RHI_BREADCRUMBS
|
|
virtual void RHIBeginBreadcrumbGPU(FRHIBreadcrumbNode* Breadcrumb) = 0;
|
|
virtual void RHIEndBreadcrumbGPU (FRHIBreadcrumbNode* Breadcrumb) = 0;
|
|
#endif
|
|
|
|
/**
|
|
* Performs a copy of the data in 'SourceBuffer' to 'DestinationStagingBuffer.' This will occur inline on the GPU timeline. This is a mechanism to perform nonblocking readback of a buffer at a point in time.
|
|
* @param SourceBuffer The source vertex buffer that will be inlined copied.
|
|
* @param DestinationStagingBuffer The the host-visible destination buffer
|
|
* @param Offset The start of the data in 'SourceBuffer'
|
|
* @param NumBytes The number of bytes to copy out of 'SourceBuffer'
|
|
*/
|
|
virtual void RHICopyToStagingBuffer(FRHIBuffer* SourceBufferRHI, FRHIStagingBuffer* DestinationStagingBufferRHI, uint32 InOffset, uint32 InNumBytes)
|
|
{
|
|
check(false);
|
|
}
|
|
|
|
/**
|
|
* Write the fence in the GPU timeline. The fence can then be tested on the CPU to know if the previous GPU commands are completed.
|
|
* @param Fence
|
|
*/
|
|
virtual void RHIWriteGPUFence(FRHIGPUFence* FenceRHI)
|
|
{
|
|
check(false);
|
|
}
|
|
|
|
virtual void RHISetGPUMask(FRHIGPUMask GPUMask)
|
|
{
|
|
ensure(GPUMask == FRHIGPUMask::GPU0());
|
|
}
|
|
|
|
virtual FRHIGPUMask RHIGetGPUMask() const
|
|
{
|
|
return FRHIGPUMask::GPU0();
|
|
}
|
|
|
|
#if WITH_MGPU
|
|
/**
|
|
* Synchronizes the content of a resource between two GPUs using a copy operation.
|
|
* @param Params - the parameters for each resource or texture region copied between GPUs.
|
|
*/
|
|
virtual void RHITransferResources(TConstArrayView<FTransferResourceParams> Params)
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
/*
|
|
* Signal where a cross GPU resource transfer can start. Useful when the destination resource of a copy may still be in use, and
|
|
* the copy from the source GPUs needs to wait until the destination is finished with it. SrcGPUMask must not overlap the current
|
|
* GPU mask of the context (which specifies the destination GPUs), and the number of items in the "FenceDatas" array MUST match the
|
|
* number of bits set in SrcGPUMask.
|
|
*/
|
|
virtual void RHITransferResourceSignal(TConstArrayView<FTransferResourceFenceData*> FenceDatas, FRHIGPUMask SrcGPUMask)
|
|
{
|
|
/* default noop implementation */
|
|
for (FTransferResourceFenceData* FenceData : FenceDatas)
|
|
{
|
|
delete FenceData;
|
|
}
|
|
}
|
|
|
|
virtual void RHITransferResourceWait(TConstArrayView<FTransferResourceFenceData*> FenceDatas)
|
|
{
|
|
/* default noop implementation */
|
|
for (FTransferResourceFenceData* FenceData : FenceDatas)
|
|
{
|
|
delete FenceData;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Synchronizes the content of a resource between two or more GPUs using a copy operation -- variation of above that includes separate arrays of fences.
|
|
* @param Params - the parameters for each resource or texture region copied between GPUs.
|
|
* @param PreTransfer - Fences to wait on before copying the relevant data (initialized with RHITransferResourceSignal before this function)
|
|
* @param PostTransfer - Fences that can be waited on after copy (waited on by RHITransferResourceWait after this function)
|
|
*/
|
|
virtual void RHICrossGPUTransfer(TConstArrayView<FTransferResourceParams> Params, TConstArrayView<FCrossGPUTransferFence*> PreTransfer, TConstArrayView<FCrossGPUTransferFence*> PostTransfer)
|
|
{
|
|
/** empty default implementation. */
|
|
}
|
|
|
|
virtual void RHICrossGPUTransferSignal(TConstArrayView<FTransferResourceParams> Params, TConstArrayView<FCrossGPUTransferFence*> PreTransfer)
|
|
{
|
|
/* default noop implementation */
|
|
for (FCrossGPUTransferFence* SyncPoint : PreTransfer)
|
|
{
|
|
delete SyncPoint;
|
|
}
|
|
}
|
|
|
|
virtual void RHICrossGPUTransferWait(TConstArrayView<FCrossGPUTransferFence*> SyncPoints)
|
|
{
|
|
/* default noop implementation */
|
|
for (FCrossGPUTransferFence* SyncPoint : SyncPoints)
|
|
{
|
|
delete SyncPoint;
|
|
}
|
|
}
|
|
#endif // WITH_MGPU
|
|
|
|
virtual void RHIBuildAccelerationStructures(TConstArrayView<FRayTracingGeometryBuildParams> Params, const FRHIBufferRange& ScratchBufferRange)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
virtual void RHIBuildAccelerationStructures(TConstArrayView<FRayTracingSceneBuildParams> Params)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
virtual void RHIBindAccelerationStructureMemory(FRHIRayTracingScene* Scene, FRHIBuffer* Buffer, uint32 BufferOffset)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
#if ENABLE_RHI_VALIDATION
|
|
|
|
RHIValidation::FTracker* Tracker = nullptr;
|
|
IRHIComputeContext* WrappingContext = nullptr;
|
|
|
|
// Always returns the platform RHI context, even when the validation RHI is active.
|
|
virtual IRHIComputeContext& GetLowestLevelContext() { return *this; }
|
|
|
|
// Returns the validation RHI context if the validation RHI is active, otherwise returns the platform RHI context.
|
|
IRHIComputeContext const& GetHighestLevelContext() const { return WrappingContext ? *WrappingContext : *this; }
|
|
IRHIComputeContext & GetHighestLevelContext() { return WrappingContext ? *WrappingContext : *this; }
|
|
|
|
#else
|
|
|
|
// Fast implementations when the RHI validation layer is disabled.
|
|
IRHIComputeContext& GetLowestLevelContext() { return *this; }
|
|
|
|
IRHIComputeContext const& GetHighestLevelContext() const { return *this; }
|
|
IRHIComputeContext & GetHighestLevelContext() { return *this; }
|
|
|
|
#endif
|
|
|
|
#if ENABLE_RHI_VALIDATION
|
|
virtual
|
|
#endif
|
|
void SetTrackedAccess(const FRHITrackedAccessInfo& Info)
|
|
{
|
|
Info.Resource->SetTrackedAccessFromContext(Info);
|
|
}
|
|
|
|
inline ERHIAccess GetTrackedAccess(const FRHIViewableResource* Resource) const
|
|
{
|
|
check(Resource);
|
|
return Resource->TrackedAccess.Access;
|
|
}
|
|
|
|
inline ERHIPipeline GetTrackedPipelines(const FRHIViewableResource* Resource) const
|
|
{
|
|
check(Resource);
|
|
return Resource->TrackedAccess.Pipelines != ERHIPipeline::None ? Resource->TrackedAccess.Pipelines : GetPipeline();
|
|
}
|
|
|
|
virtual void* RHIGetNativeCommandBuffer() { return nullptr; }
|
|
virtual void RHIPostExternalCommandsReset() { }
|
|
|
|
private:
|
|
// Pointer to the RHI command list that is replaying commands into this context.
|
|
class FRHICommandListBase* ExecutingCmdList = nullptr;
|
|
|
|
public:
|
|
// Returns the RHI command list that is currently replaying commands into this context.
|
|
FRHICommandListBase& GetExecutingCommandList() const
|
|
{
|
|
check(ExecutingCmdList);
|
|
return *ExecutingCmdList;
|
|
}
|
|
|
|
// Used within FRHICommandListBase::ActivatePipeline to setup a context for command execution.
|
|
virtual void SetExecutingCommandList(FRHICommandListBase* InCmdList)
|
|
{
|
|
ExecutingCmdList = InCmdList;
|
|
}
|
|
|
|
#if WITH_RHI_BREADCRUMBS
|
|
//
|
|
// Returns true if RHI breadcrumb strings should be emitted to platform GPU profiling APIs.
|
|
// Platform RHI implementations should check for this inside RHIBeginBreadcrumbGPU and RHIEndBreadcrumbGPU.
|
|
//
|
|
inline bool ShouldEmitBreadcrumbs() const;
|
|
#endif
|
|
|
|
protected:
|
|
#if RHI_NEW_GPU_PROFILER
|
|
// Used to accumulate draw call and primitive counts,
|
|
// via the RHI_DRAW_CALL_INC / RHI_DRAW_CALL_STATS macros.
|
|
UE::RHI::GPUProfiler::FEvent::FStats StatEvent {};
|
|
#endif
|
|
};
|
|
|
|
/** Context that is used to generate Upload commands. */
|
|
class IRHIUploadContext
|
|
{};
|
|
|
|
// Utility function to generate pre-transfer sync points to pass to CrossGPUTransferSignal and CrossGPUTransfer
|
|
RHI_API void RHIGenerateCrossGPUPreTransferFences(TConstArrayView<FTransferResourceParams> Params, TArray<FCrossGPUTransferFence*>& OutPreTransfer);
|
|
|
|
enum class EAccelerationStructureBuildMode
|
|
{
|
|
// Perform a full acceleration structure build.
|
|
Build,
|
|
|
|
// Update existing acceleration structure, based on new vertex positions.
|
|
// Index buffer must not change between initial build and update operations.
|
|
// Only valid when geometry was created with FRayTracingGeometryInitializer::bAllowUpdate = true.
|
|
Update,
|
|
};
|
|
|
|
struct FRayTracingGeometryBuildParams
|
|
{
|
|
FRayTracingGeometryRHIRef Geometry;
|
|
EAccelerationStructureBuildMode BuildMode = EAccelerationStructureBuildMode::Build;
|
|
|
|
// Optional array of geometry segments that can be used to change per-segment vertex buffers.
|
|
// Only fields related to vertex buffer are used. If empty, then geometry vertex buffers are not changed.
|
|
TConstArrayView<FRayTracingGeometrySegment> Segments;
|
|
};
|
|
|
|
struct FRayTracingSceneBuildParams
|
|
{
|
|
// Scene to be built. May be null if explicit instance buffer is provided.
|
|
FRHIRayTracingScene* Scene = nullptr;
|
|
|
|
// Acceleration structure will be written to this buffer. The buffer must be in BVHWrite state.
|
|
FRHIBuffer* ResultBuffer = nullptr;
|
|
uint32 ResultBufferOffset = 0;
|
|
|
|
// Scratch buffer used to build Acceleration structure. Must be in UAV state.
|
|
FRHIBuffer* ScratchBuffer = nullptr;
|
|
uint32 ScratchBufferOffset = 0;
|
|
|
|
// Buffer of native ray tracing instance descriptors. Must be in SRV state.
|
|
FRHIBuffer* InstanceBuffer = nullptr;
|
|
uint32 InstanceBufferOffset = 0;
|
|
|
|
uint32 NumInstances = 0;
|
|
|
|
// Unique list of geometries referenced by all instances in this scene.
|
|
// Any referenced geometry is kept alive while the scene is alive.
|
|
TConstArrayView<FRHIRayTracingGeometry*> ReferencedGeometries;
|
|
|
|
UE_DEPRECATED(5.6, "No longer necessary.")
|
|
TConstArrayView<FRHIRayTracingGeometry*> PerInstanceGeometries;
|
|
|
|
EAccelerationStructureBuildMode BuildMode = EAccelerationStructureBuildMode::Build;
|
|
|
|
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
|
FRayTracingSceneBuildParams() = default;
|
|
FRayTracingSceneBuildParams(const FRayTracingSceneBuildParams&) = default;
|
|
FRayTracingSceneBuildParams& operator=(const FRayTracingSceneBuildParams&) = default;
|
|
FRayTracingSceneBuildParams(FRayTracingSceneBuildParams&&) = default;
|
|
FRayTracingSceneBuildParams& operator=(FRayTracingSceneBuildParams&&) = default;
|
|
~FRayTracingSceneBuildParams() = default;
|
|
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
|
};
|
|
|
|
struct FCopyBufferRegionParams
|
|
{
|
|
FRHIBuffer* DestBuffer;
|
|
uint64 DstOffset;
|
|
FRHIBuffer* SourceBuffer;
|
|
uint64 SrcOffset;
|
|
uint64 NumBytes;
|
|
};
|
|
|
|
/** The interface RHI command context. Sometimes the RHI handles these. On platforms that can processes command lists in parallel, it is a separate object. */
|
|
class IRHICommandContext : public IRHIComputeContext
|
|
{
|
|
public:
|
|
virtual ~IRHICommandContext()
|
|
{
|
|
}
|
|
|
|
virtual ERHIPipeline GetPipeline() const override
|
|
{
|
|
return ERHIPipeline::Graphics;
|
|
}
|
|
|
|
virtual void RHIDispatchComputeShader(uint32 ThreadGroupCountX, uint32 ThreadGroupCountY, uint32 ThreadGroupCountZ) = 0;
|
|
|
|
virtual void RHIDispatchIndirectComputeShader(FRHIBuffer* ArgumentBuffer, uint32 ArgumentOffset) = 0;
|
|
|
|
// Useful when used with geometry shader (emit polygons to different viewports), otherwise SetViewPort() is simpler
|
|
// @param Count >0
|
|
// @param Data must not be 0
|
|
virtual void RHISetMultipleViewports(uint32 Count, const FViewportBounds* Data) = 0;
|
|
|
|
/**
|
|
* Rebuilds the depth target HTILE meta data (on supported platforms).
|
|
* @param DepthTexture - the depth surface to resummarize.
|
|
*/
|
|
virtual void RHIResummarizeHTile(FRHITexture* DepthTexture)
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
virtual void RHIBeginRenderQuery(FRHIRenderQuery* RenderQuery) = 0;
|
|
|
|
virtual void RHIEndRenderQuery(FRHIRenderQuery* RenderQuery) = 0;
|
|
|
|
virtual void RHICalibrateTimers(FRHITimestampCalibrationQuery* CalibrationQuery)
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
// Not all RHIs need this (Mobile specific)
|
|
virtual void RHIDiscardRenderTargets(bool Depth, bool Stencil, uint32 ColorBitMask) {}
|
|
|
|
// This method is queued with an RHIThread, otherwise it will flush after it is queued; without an RHI thread there is no benefit to queuing this frame advance commands
|
|
virtual void RHIBeginDrawingViewport(FRHIViewport* Viewport, FRHITexture* RenderTargetRHI) = 0;
|
|
|
|
// This method is queued with an RHIThread, otherwise it will flush after it is queued; without an RHI thread there is no benefit to queuing this frame advance commands
|
|
virtual void RHIEndDrawingViewport(FRHIViewport* Viewport, bool bPresent, bool bLockToVsync) = 0;
|
|
|
|
virtual void RHISetStreamSource(uint32 StreamIndex, FRHIBuffer* VertexBuffer, uint32 Offset) = 0;
|
|
|
|
// @param MinX including like Win32 RECT
|
|
// @param MinY including like Win32 RECT
|
|
// @param MaxX excluding like Win32 RECT
|
|
// @param MaxY excluding like Win32 RECT
|
|
virtual void RHISetViewport(float MinX, float MinY, float MinZ, float MaxX, float MaxY, float MaxZ) = 0;
|
|
|
|
virtual void RHISetStereoViewport(float LeftMinX, float RightMinX, float LeftMinY, float RightMinY, float MinZ, float LeftMaxX, float RightMaxX, float LeftMaxY, float RightMaxY, float MaxZ)
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
// @param MinX including like Win32 RECT
|
|
// @param MinY including like Win32 RECT
|
|
// @param MaxX excluding like Win32 RECT
|
|
// @param MaxY excluding like Win32 RECT
|
|
virtual void RHISetScissorRect(bool bEnable, uint32 MinX, uint32 MinY, uint32 MaxX, uint32 MaxY) = 0;
|
|
|
|
virtual void RHISetGraphicsPipelineState(FRHIGraphicsPipelineState* GraphicsState, uint32 StencilRef, bool bApplyAdditionalState) = 0;
|
|
|
|
#if PLATFORM_USE_FALLBACK_PSO
|
|
virtual void RHISetGraphicsPipelineState(const FGraphicsPipelineStateInitializer& PsoInit, uint32 StencilRef, bool bApplyAdditionalState) = 0;
|
|
#endif
|
|
|
|
// Inherit the parent context's RHISet functions that take FRHIComputeShader arguments
|
|
// Required to avoid warning C4263 : 'function' : member function does not override any base class virtual member function
|
|
using IRHIComputeContext::RHISetShaderParameters;
|
|
using IRHIComputeContext::RHISetBatchedShaderParameters;
|
|
using IRHIComputeContext::RHISetShaderUnbinds;
|
|
|
|
virtual void RHISetShaderParameters(FRHIGraphicsShader* Shader, TConstArrayView<uint8> InParametersData, TConstArrayView<FRHIShaderParameter> InParameters, TConstArrayView<FRHIShaderParameterResource> InResourceParameters, TConstArrayView<FRHIShaderParameterResource> InBindlessParameters) = 0;
|
|
|
|
void RHISetBatchedShaderParameters(FRHIGraphicsShader* InShader, FRHIBatchedShaderParameters& InBatchedParameters)
|
|
{
|
|
RHISetShaderParameters(
|
|
InShader,
|
|
InBatchedParameters.ParametersData,
|
|
InBatchedParameters.Parameters,
|
|
InBatchedParameters.ResourceParameters,
|
|
InBatchedParameters.BindlessParameters);
|
|
|
|
InBatchedParameters.Reset();
|
|
}
|
|
|
|
virtual void RHISetShaderUnbinds(FRHIGraphicsShader* Shader, TConstArrayView<FRHIShaderParameterUnbind> InUnbinds)
|
|
{
|
|
checkf(false, TEXT("RHISetShaderUnbinds called when the active RHI hasn't overridden it and GRHIGlobals.NeedsShaderUnbinds is set."));
|
|
}
|
|
|
|
virtual void RHISetStencilRef(uint32 StencilRef) {}
|
|
|
|
virtual void RHISetBlendFactor(const FLinearColor& BlendFactor) {}
|
|
|
|
virtual void RHIDrawPrimitive(uint32 BaseVertexIndex, uint32 NumPrimitives, uint32 NumInstances) = 0;
|
|
|
|
virtual void RHIDrawPrimitiveIndirect(FRHIBuffer* ArgumentBuffer, uint32 ArgumentOffset) = 0;
|
|
|
|
virtual void RHIDrawIndexedIndirect(FRHIBuffer* IndexBufferRHI, FRHIBuffer* ArgumentsBufferRHI, int32 DrawArgumentsIndex, uint32 NumInstances) = 0;
|
|
|
|
// @param NumPrimitives need to be >0
|
|
virtual void RHIDrawIndexedPrimitive(FRHIBuffer* IndexBuffer, int32 BaseVertexIndex, uint32 FirstInstance, uint32 NumVertices, uint32 StartIndex, uint32 NumPrimitives, uint32 NumInstances) = 0;
|
|
|
|
virtual void RHIDrawIndexedPrimitiveIndirect(FRHIBuffer* IndexBuffer, FRHIBuffer* ArgumentBuffer, uint32 ArgumentOffset) = 0;
|
|
|
|
/**
|
|
* Similar to RHIDrawIndexedPrimitiveIndirect, but allows many draw arguments to be provided at once.
|
|
* GRHIGlobals.SupportsDrawIndirect must be checked to detect support on the current machine.
|
|
* @ param IndexBuffer Buffer containing primitive indices
|
|
* @ param ArgumentsBuffer Buffer containing FRHIDrawIndexedIndirectParameters structures
|
|
* @ param ArgumentOffset Offset in bytes of the first element in ArgumentsBuffer that will be used for drawing
|
|
* @ param CountBuffer Buffer containing uint32 count of valid draw arguments that should be consumed (may be nullptr, indicating that only MaxDrawArguments value should be used)
|
|
* @ param CountBuffeOffset Offset in bytes for the CountBuffer element that will be used to source the draw argument count
|
|
* @ param MaxDrawArguments How many draw arguments should be processed at most, i.e. NumDrawArguments = min(MaxDrawArguments, ValueFromCountBuffer)
|
|
*/
|
|
virtual void RHIMultiDrawIndexedPrimitiveIndirect(FRHIBuffer* IndexBuffer, FRHIBuffer* ArgumentBuffer, uint32 ArgumentOffset, FRHIBuffer* CountBuffer, uint32 CountBuffeOffset, uint32 MaxDrawArguments)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
virtual void RHIDispatchMeshShader(uint32 ThreadGroupCountX, uint32 ThreadGroupCountY, uint32 ThreadGroupCountZ)
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
virtual void RHIDispatchIndirectMeshShader(FRHIBuffer* ArgumentBuffer, uint32 ArgumentOffset)
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
/**
|
|
* Sets Depth Bounds range with the given min/max depth.
|
|
* @param MinDepth The minimum depth for depth bounds test
|
|
* @param MaxDepth The maximum depth for depth bounds test.
|
|
* The valid values for fMinDepth and fMaxDepth are such that 0 <= fMinDepth <= fMaxDepth <= 1
|
|
*/
|
|
virtual void RHISetDepthBounds(float MinDepth, float MaxDepth) = 0;
|
|
|
|
virtual void RHIGpuHangCommandListCorruption()
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
virtual void RHISetShadingRate(EVRSShadingRate ShadingRate, EVRSRateCombiner Combiner)
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
virtual void RHIBeginParallelRenderPass(TSharedPtr<FRHIParallelRenderPassInfo> InInfo, const TCHAR* InName)
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
virtual void RHIEndParallelRenderPass()
|
|
{
|
|
/* empty default implementation */
|
|
}
|
|
|
|
virtual void RHIBeginRenderPass(const FRHIRenderPassInfo& InInfo, const TCHAR* InName) = 0;
|
|
|
|
virtual void RHIEndRenderPass() = 0;
|
|
|
|
virtual void RHINextSubpass()
|
|
{
|
|
}
|
|
|
|
virtual void RHICopyTexture(FRHITexture* SourceTexture, FRHITexture* DestTexture, const FRHICopyTextureInfo& CopyInfo) = 0;
|
|
|
|
virtual void RHICopyBufferRegion(FRHIBuffer* DestBuffer, uint64 DstOffset, FRHIBuffer* SourceBuffer, uint64 SrcOffset, uint64 NumBytes) = 0;
|
|
|
|
virtual void RHIClearShaderBindingTable(FRHIShaderBindingTable* SBT)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
virtual void RHISetBindingsOnShaderBindingTable(FRHIShaderBindingTable* SBT, FRHIRayTracingPipelineState* Pipeline, uint32 NumBindings, const FRayTracingLocalShaderBindings* Bindings, ERayTracingBindingType BindingType)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
virtual void RHICommitShaderBindingTable(FRHIShaderBindingTable* SBT, FRHIBuffer* InlineBindingDataBuffer)
|
|
{
|
|
checkNoEntry();
|
|
}
|
|
|
|
protected:
|
|
FRHIRenderPassInfo RenderPassInfo;
|
|
};
|
|
|
|
|
|
|
|
FORCEINLINE FBoundShaderStateRHIRef RHICreateBoundShaderState(
|
|
FRHIVertexDeclaration* VertexDeclaration,
|
|
FRHIVertexShader* VertexShader,
|
|
FRHIPixelShader* PixelShader,
|
|
FRHIGeometryShader* GeometryShader
|
|
);
|
|
|
|
FORCEINLINE FBoundShaderStateRHIRef RHICreateBoundShaderState(
|
|
FRHIAmplificationShader* AmplificationShader,
|
|
FRHIMeshShader* MeshShader,
|
|
FRHIPixelShader* PixelShader
|
|
);
|
|
|
|
|
|
// Command Context for RHIs that do not support real Graphics/Compute Pipelines.
|
|
class IRHICommandContextPSOFallback : public IRHICommandContext
|
|
{
|
|
public:
|
|
virtual void RHISetBoundShaderState(FRHIBoundShaderState* BoundShaderState) = 0;
|
|
virtual void RHISetDepthStencilState(FRHIDepthStencilState* NewState, uint32 StencilRef) = 0;
|
|
virtual void RHISetRasterizerState(FRHIRasterizerState* NewState) = 0;
|
|
virtual void RHISetBlendState(FRHIBlendState* NewState, const FLinearColor& BlendFactor) = 0;
|
|
virtual void RHIEnableDepthBoundsTest(bool bEnable) = 0;
|
|
virtual void RHISetComputeShader(FRHIComputeShader* ComputeShader) = 0;
|
|
|
|
/**
|
|
* This will set most relevant pipeline state. Legacy APIs are expected to set corresponding disjoint state as well.
|
|
* @param GraphicsShaderState - the graphics pipeline state
|
|
*/
|
|
virtual void RHISetGraphicsPipelineState(FRHIGraphicsPipelineState* GraphicsState, uint32 StencilRef, bool bApplyAdditionalState) override
|
|
{
|
|
FRHIGraphicsPipelineStateFallBack* FallbackGraphicsState = static_cast<FRHIGraphicsPipelineStateFallBack*>(GraphicsState);
|
|
SetGraphicsPipelineStateFromInitializer(FallbackGraphicsState->Initializer, StencilRef, bApplyAdditionalState);
|
|
}
|
|
|
|
#if PLATFORM_USE_FALLBACK_PSO
|
|
virtual void RHISetGraphicsPipelineState(const FGraphicsPipelineStateInitializer& PsoInit, uint32 StencilRef, bool bApplyAdditionalState) override
|
|
{
|
|
SetGraphicsPipelineStateFromInitializer(PsoInit, StencilRef, bApplyAdditionalState);
|
|
}
|
|
#endif
|
|
|
|
virtual void RHISetComputePipelineState(FRHIComputePipelineState* ComputePipelineState)
|
|
{
|
|
if (FRHIComputePipelineStateFallback* FallbackState = static_cast<FRHIComputePipelineStateFallback*>(ComputePipelineState))
|
|
{
|
|
RHISetComputeShader(FallbackState->GetComputeShader());
|
|
}
|
|
}
|
|
|
|
private:
|
|
RHI_API void SetGraphicsPipelineStateFromInitializer(const FGraphicsPipelineStateInitializer& PsoInit, uint32 StencilRef, bool bApplyAdditionalState);
|
|
};
|