297 lines
9.7 KiB
C++
297 lines
9.7 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
BoundShaderStateCache.h: Bound shader state cache definition.
|
|
=============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "RHI.h"
|
|
|
|
/**
|
|
* Key used to map a set of unique decl/vs/ps combinations to
|
|
* a vertex shader resource
|
|
*/
|
|
class FBoundShaderStateKey
|
|
{
|
|
public:
|
|
/** Initialization constructor. */
|
|
FBoundShaderStateKey(
|
|
FRHIVertexDeclaration* InVertexDeclaration,
|
|
FRHIVertexShader* InVertexShader,
|
|
FRHIPixelShader* InPixelShader,
|
|
FRHIGeometryShader* InGeometryShader = nullptr
|
|
)
|
|
: VertexDeclaration(InVertexDeclaration)
|
|
, VertexShader(InVertexShader)
|
|
, PixelShader(InPixelShader)
|
|
, GeometryShader(InGeometryShader)
|
|
{}
|
|
|
|
/** Initialization constructor. */
|
|
FBoundShaderStateKey(
|
|
FRHIMeshShader* InMeshShader,
|
|
FRHIAmplificationShader* InAmplificationShader,
|
|
FRHIPixelShader* InPixelShader
|
|
)
|
|
: MeshShader(InMeshShader)
|
|
, AmplificationShader(InAmplificationShader)
|
|
, PixelShader(InPixelShader)
|
|
{}
|
|
|
|
/**
|
|
* Get the RHI shader for the given frequency.
|
|
*/
|
|
FORCEINLINE FRHIVertexShader* GetVertexShader() const { return VertexShader; }
|
|
FORCEINLINE FRHIMeshShader* GetMeshShader() const { return MeshShader; }
|
|
FORCEINLINE FRHIAmplificationShader* GetAmplificationShader() const { return AmplificationShader; }
|
|
FORCEINLINE FRHIPixelShader* GetPixelShader() const { return PixelShader; }
|
|
FORCEINLINE FRHIGeometryShader* GetGeometryShader() const { return GeometryShader; }
|
|
|
|
/**
|
|
* Get the RHI vertex declaration.
|
|
*/
|
|
FORCEINLINE FRHIVertexDeclaration* GetVertexDeclaration() const { return VertexDeclaration; }
|
|
|
|
private:
|
|
/**
|
|
* Note: We intentionally do use ...Ref, not ...ParamRef to get
|
|
* AddRef() for object to prevent and rare issue that happened before.
|
|
* When changing and recompiling a shader it got the same memory
|
|
* pointer and because the caching is happening with pointer comparison
|
|
* the BoundShaderstate cache was holding on to the old pointer
|
|
* it was not creating a new entry.
|
|
*/
|
|
|
|
/** vertex decl for this combination */
|
|
FVertexDeclarationRHIRef VertexDeclaration;
|
|
/** vs for this combination */
|
|
FVertexShaderRHIRef VertexShader;
|
|
/** ms for this combination */
|
|
FMeshShaderRHIRef MeshShader;
|
|
/** as for this combination */
|
|
FAmplificationShaderRHIRef AmplificationShader;
|
|
/** ps for this combination */
|
|
FPixelShaderRHIRef PixelShader;
|
|
/** gs for this combination */
|
|
FGeometryShaderRHIRef GeometryShader;
|
|
|
|
friend class FBoundShaderStateLookupKey;
|
|
};
|
|
|
|
// Non-reference-counted version of shader state key.
|
|
// This structure is used as the actual key type for TMap, which avoids reference counting overhead during lookup.
|
|
// Note that FCachedBoundShaderStateLink contains a full-fat reference-counted FBoundShaderStateKey, ensuring
|
|
// correct lifetime management.
|
|
class FBoundShaderStateLookupKey
|
|
{
|
|
public:
|
|
|
|
// Note: implicit cast is allowed/expected for this constructor
|
|
FBoundShaderStateLookupKey(const FBoundShaderStateKey& Key)
|
|
: VertexDeclaration(Key.VertexDeclaration.GetReference())
|
|
, VertexShader(Key.VertexShader.GetReference())
|
|
, MeshShader(Key.MeshShader.GetReference())
|
|
, AmplificationShader(Key.AmplificationShader.GetReference())
|
|
, PixelShader(Key.PixelShader.GetReference())
|
|
, GeometryShader(Key.GeometryShader.GetReference())
|
|
{}
|
|
|
|
FBoundShaderStateLookupKey(
|
|
FRHIVertexDeclaration* InVertexDeclaration,
|
|
FRHIVertexShader* InVertexShader,
|
|
FRHIPixelShader* InPixelShader,
|
|
FRHIGeometryShader* InGeometryShader = nullptr
|
|
)
|
|
: VertexDeclaration(InVertexDeclaration)
|
|
, VertexShader(InVertexShader)
|
|
, PixelShader(InPixelShader)
|
|
, GeometryShader(InGeometryShader)
|
|
{}
|
|
|
|
FBoundShaderStateLookupKey(
|
|
FRHIMeshShader* InMeshShader,
|
|
FRHIAmplificationShader* InAmplificationShader,
|
|
FRHIPixelShader* InPixelShader
|
|
)
|
|
: MeshShader(InMeshShader)
|
|
, AmplificationShader(InAmplificationShader)
|
|
, PixelShader(InPixelShader)
|
|
{}
|
|
|
|
/**
|
|
* Equality is based on decl, vertex shader and pixel shader
|
|
* @param Other - instance to compare against
|
|
* @return true if equal
|
|
*/
|
|
friend bool operator == (const FBoundShaderStateLookupKey& A, const FBoundShaderStateLookupKey& B)
|
|
{
|
|
return A.VertexDeclaration == B.VertexDeclaration &&
|
|
A.VertexShader == B.VertexShader &&
|
|
A.MeshShader == B.MeshShader &&
|
|
A.AmplificationShader == B.AmplificationShader &&
|
|
A.PixelShader == B.PixelShader &&
|
|
A.GeometryShader == B.GeometryShader;
|
|
}
|
|
|
|
/**
|
|
* Get the hash for this type.
|
|
* @param Key - struct to hash
|
|
* @return dword hash based on type
|
|
*/
|
|
friend uint32 GetTypeHash(const FBoundShaderStateLookupKey& Key)
|
|
{
|
|
return GetTypeHash(Key.VertexDeclaration) ^
|
|
GetTypeHash(Key.VertexShader) ^
|
|
GetTypeHash(Key.MeshShader) ^
|
|
GetTypeHash(Key.AmplificationShader) ^
|
|
GetTypeHash(Key.PixelShader) ^
|
|
GetTypeHash(Key.GeometryShader);
|
|
}
|
|
|
|
private:
|
|
const FRHIVertexDeclaration* VertexDeclaration = nullptr;
|
|
const FRHIVertexShader* VertexShader = nullptr;
|
|
const FRHIMeshShader* MeshShader = nullptr;
|
|
const FRHIAmplificationShader* AmplificationShader = nullptr;
|
|
const FRHIPixelShader* PixelShader = nullptr;
|
|
const FRHIGeometryShader* GeometryShader = nullptr;
|
|
};
|
|
|
|
/**
|
|
* Encapsulates a bound shader state's entry in the cache.
|
|
* Handles removal from the bound shader state cache on destruction.
|
|
* RHIs that use cached bound shader states should create one for each bound shader state.
|
|
*/
|
|
class FCachedBoundShaderStateLink
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* The cached bound shader state. This is not a reference counted pointer because we rely on the RHI to destruct this object
|
|
* when the bound shader state this references is destructed.
|
|
*/
|
|
FRHIBoundShaderState* BoundShaderState;
|
|
|
|
/** Adds the bound shader state to the cache. */
|
|
RHI_API FCachedBoundShaderStateLink(
|
|
FRHIVertexDeclaration* VertexDeclaration,
|
|
FRHIVertexShader* VertexShader,
|
|
FRHIPixelShader* PixelShader,
|
|
FRHIBoundShaderState* InBoundShaderState,
|
|
bool bAddToSingleThreadedCache = true
|
|
);
|
|
|
|
/** Adds the bound shader state to the cache. */
|
|
RHI_API FCachedBoundShaderStateLink(
|
|
FRHIVertexDeclaration* VertexDeclaration,
|
|
FRHIVertexShader* VertexShader,
|
|
FRHIPixelShader* PixelShader,
|
|
FRHIGeometryShader* GeometryShader,
|
|
FRHIBoundShaderState* InBoundShaderState,
|
|
bool bAddToSingleThreadedCache = true
|
|
);
|
|
|
|
/** Adds the bound shader state to the cache. */
|
|
RHI_API FCachedBoundShaderStateLink(
|
|
FRHIMeshShader* MeshShader,
|
|
FRHIAmplificationShader* AmplificationShader,
|
|
FRHIPixelShader* PixelShader,
|
|
FRHIBoundShaderState* InBoundShaderState,
|
|
bool bAddToSingleThreadedCache = true
|
|
);
|
|
|
|
/** Destructor. Removes the bound shader state from the cache. */
|
|
RHI_API ~FCachedBoundShaderStateLink();
|
|
|
|
/**
|
|
* Get the RHI shader for the given frequency.
|
|
*/
|
|
FORCEINLINE FRHIVertexShader* GetVertexShader() const { return Key.GetVertexShader(); }
|
|
FORCEINLINE FRHIMeshShader* GetMeshShader() const { return Key.GetMeshShader(); }
|
|
FORCEINLINE FRHIAmplificationShader* GetAmplificationShader() const { return Key.GetAmplificationShader(); }
|
|
FORCEINLINE FRHIPixelShader* GetPixelShader() const { return Key.GetPixelShader(); }
|
|
FORCEINLINE FRHIGeometryShader* GetGeometryShader() const { return Key.GetGeometryShader(); }
|
|
|
|
/**
|
|
* Get the RHI vertex declaration.
|
|
*/
|
|
FORCEINLINE FRHIVertexDeclaration* GetVertexDeclaration() const { return Key.GetVertexDeclaration(); }
|
|
|
|
protected:
|
|
FBoundShaderStateKey Key;
|
|
bool bAddedToSingleThreadedCache;
|
|
};
|
|
|
|
|
|
/**
|
|
* Searches for a cached bound shader state.
|
|
* @return If a bound shader state matching the parameters is cached, it is returned; otherwise NULL is returned.
|
|
*/
|
|
extern RHI_API FCachedBoundShaderStateLink* GetCachedBoundShaderState(
|
|
FRHIVertexDeclaration* VertexDeclaration,
|
|
FRHIVertexShader* VertexShader,
|
|
FRHIPixelShader* PixelShader,
|
|
FRHIGeometryShader* GeometryShader = nullptr,
|
|
FRHIMeshShader* MeshShader = nullptr,
|
|
FRHIAmplificationShader* AmplificationShader = nullptr
|
|
);
|
|
|
|
extern RHI_API void EmptyCachedBoundShaderStates();
|
|
|
|
class FCachedBoundShaderStateLink_Threadsafe : public FCachedBoundShaderStateLink
|
|
{
|
|
public:
|
|
/** Adds the bound shader state to the cache. */
|
|
FCachedBoundShaderStateLink_Threadsafe(
|
|
FRHIVertexDeclaration* VertexDeclaration,
|
|
FRHIVertexShader* VertexShader,
|
|
FRHIPixelShader* PixelShader,
|
|
FRHIBoundShaderState* InBoundShaderState
|
|
)
|
|
: FCachedBoundShaderStateLink(VertexDeclaration, VertexShader, PixelShader, InBoundShaderState, false)
|
|
{
|
|
}
|
|
|
|
/** Adds the bound shader state to the cache. */
|
|
FCachedBoundShaderStateLink_Threadsafe(
|
|
FRHIVertexDeclaration* VertexDeclaration,
|
|
FRHIVertexShader* VertexShader,
|
|
FRHIPixelShader* PixelShader,
|
|
FRHIGeometryShader* GeometryShader,
|
|
FRHIBoundShaderState* InBoundShaderState
|
|
)
|
|
: FCachedBoundShaderStateLink(VertexDeclaration, VertexShader, PixelShader, GeometryShader, InBoundShaderState, false)
|
|
{
|
|
}
|
|
|
|
/** Adds the bound shader state to the cache. */
|
|
FCachedBoundShaderStateLink_Threadsafe(
|
|
FRHIMeshShader* MeshShader,
|
|
FRHIAmplificationShader* AmplificationShader,
|
|
FRHIPixelShader* PixelShader,
|
|
FRHIBoundShaderState* InBoundShaderState
|
|
)
|
|
: FCachedBoundShaderStateLink(MeshShader, AmplificationShader, PixelShader, InBoundShaderState, false)
|
|
{
|
|
}
|
|
|
|
RHI_API void AddToCache();
|
|
RHI_API void RemoveFromCache();
|
|
};
|
|
|
|
/**
|
|
* Searches for a cached bound shader state. Threadsafe version.
|
|
* @return If a bound shader state matching the parameters is cached, it is returned; otherwise NULL is returned.
|
|
*/
|
|
extern RHI_API FBoundShaderStateRHIRef GetCachedBoundShaderState_Threadsafe(
|
|
FRHIVertexDeclaration* VertexDeclaration,
|
|
FRHIVertexShader* VertexShader,
|
|
FRHIPixelShader* PixelShader,
|
|
FRHIGeometryShader* GeometryShader = nullptr,
|
|
FRHIMeshShader* MeshShader = nullptr,
|
|
FRHIAmplificationShader* AmplificationShader = nullptr
|
|
);
|
|
|