Files
UnrealEngine/Engine/Source/Runtime/Windows/D3D11RHI/Private/D3D11StateCachePrivate.h
2025-05-18 13:04:45 +08:00

662 lines
22 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
// Implementation of Device Context State Caching to improve draw
// thread performance by removing redundant device context calls.
#pragma once
#include "RHIDefinitions.h"
#include "Windows/D3D11ThirdParty.h"
//-----------------------------------------------------------------------------
// Configuration
//-----------------------------------------------------------------------------
// If set, enables the D3D11 state caching system.
#define D3D11_ALLOW_STATE_CACHE 1
// If set, includes a runtime toggle console command for debugging D3D11 state caching.
// ("TOGGLESTATECACHE")
#define D3D11_STATE_CACHE_RUNTIME_TOGGLE 0
// If set, includes a cache state verification check.
// After each state set call, the cached state is compared against the actual state of the ID3D11DeviceContext.
// This is *very slow* and should only be enabled to debug the state caching system.
#ifndef D3D11_STATE_CACHE_DEBUG
#define D3D11_STATE_CACHE_DEBUG 0
#endif
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
// Keep set state functions inline to reduce call overhead
#define D3D11_STATE_CACHE_INLINE FORCEINLINE
//#define DO_CHECK 1
//#define D3D11_STATE_CACHE_DEBUG 1
#if D3D11_ALLOW_STATE_CACHE && D3D11_STATE_CACHE_DEBUG && DO_CHECK
#define D3D11_STATE_CACHE_VERIFY(...) VerifyCacheState()
#define D3D11_STATE_CACHE_VERIFY_PRE(...) VerifyCacheStatePre()
#define D3D11_STATE_CACHE_VERIFY_POST(...) VerifyCacheStatePost()
#else
#define D3D11_STATE_CACHE_VERIFY(...)
#define D3D11_STATE_CACHE_VERIFY_PRE(...)
#define D3D11_STATE_CACHE_VERIFY_POST(...)
#endif
#if D3D11_ALLOW_STATE_CACHE && D3D11_STATE_CACHE_RUNTIME_TOGGLE
extern bool GD3D11SkipStateCaching;
#else
static const bool GD3D11SkipStateCaching = false;
#endif
//-----------------------------------------------------------------------------
// FD3D11StateCache Class Definition
//-----------------------------------------------------------------------------
class FD3D11StateCacheBase
{
public:
bool bDepthBoundsEnabled = false;
float DepthBoundsMin = 0.0f;
float DepthBoundsMax = 1.0f;
protected:
ID3D11DeviceContext* Direct3DDeviceIMContext;
#if D3D11_ALLOW_STATE_CACHE
// Shader Resource Views Cache
ID3D11ShaderResourceView* CurrentShaderResourceViews[SF_NumStandardFrequencies][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
// Rasterizer State Cache
ID3D11RasterizerState* CurrentRasterizerState;
// Depth Stencil State Cache
uint32 CurrentReferenceStencil;
ID3D11DepthStencilState* CurrentDepthStencilState;
// Shader Cache
ID3D11VertexShader* CurrentVertexShader;
ID3D11GeometryShader* CurrentGeometryShader;
ID3D11PixelShader* CurrentPixelShader;
ID3D11ComputeShader* CurrentComputeShader;
// Blend State Cache
float CurrentBlendFactor[4];
uint32 CurrentBlendSampleMask;
ID3D11BlendState* CurrentBlendState;
// Viewport
uint32 CurrentNumberOfViewports;
D3D11_VIEWPORT CurrentViewport[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
// Vertex Buffer State
struct FD3D11VertexBufferState
{
ID3D11Buffer* VertexBuffer;
uint32 Stride;
uint32 Offset;
} CurrentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
// Index Buffer State
ID3D11Buffer* CurrentIndexBuffer;
DXGI_FORMAT CurrentIndexFormat;
uint32 CurrentIndexOffset;
// Primitive Topology State
D3D11_PRIMITIVE_TOPOLOGY CurrentPrimitiveTopology;
// Input Layout State
ID3D11InputLayout* CurrentInputLayout;
uint16 StreamStrides[MaxVertexElementCount];
// Sampler State
ID3D11SamplerState* CurrentSamplerStates[SF_NumStandardFrequencies][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
// Constant Buffer State
struct FD3D11ConstantBufferState
{
ID3D11Buffer* Buffer;
uint32 FirstConstant;
uint32 NumConstants;
} CurrentConstantBuffers[SF_NumStandardFrequencies][D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
bool bAlwaysSetIndexBuffers;
#endif
template <EShaderFrequency ShaderFrequency>
D3D11_STATE_CACHE_INLINE void InternalSetShaderResourceView(uint32 ResourceIndex, ID3D11ShaderResourceView*& SRV)
{
// Set the SRV we have been given (or null).
CA_SUPPRESS(6326);
switch (ShaderFrequency)
{
case SF_Vertex: Direct3DDeviceIMContext->VSSetShaderResources(ResourceIndex, 1, &SRV); break;
case SF_Geometry: Direct3DDeviceIMContext->GSSetShaderResources(ResourceIndex, 1, &SRV); break;
case SF_Pixel: Direct3DDeviceIMContext->PSSetShaderResources(ResourceIndex, 1, &SRV); break;
case SF_Compute: Direct3DDeviceIMContext->CSSetShaderResources(ResourceIndex, 1, &SRV); break;
}
}
template <EShaderFrequency ShaderFrequency>
D3D11_STATE_CACHE_INLINE void InternalSetSamplerState(uint32 SamplerIndex, ID3D11SamplerState*& SamplerState)
{
CA_SUPPRESS(6326);
switch (ShaderFrequency)
{
case SF_Vertex: Direct3DDeviceIMContext->VSSetSamplers(SamplerIndex, 1, &SamplerState); break;
case SF_Geometry: Direct3DDeviceIMContext->GSSetSamplers(SamplerIndex, 1, &SamplerState); break;
case SF_Pixel: Direct3DDeviceIMContext->PSSetSamplers(SamplerIndex, 1, &SamplerState); break;
case SF_Compute: Direct3DDeviceIMContext->CSSetSamplers(SamplerIndex, 1, &SamplerState); break;
}
}
template <EShaderFrequency ShaderFrequency>
D3D11_STATE_CACHE_INLINE void InternalSetSetConstantBuffer(uint32 SlotIndex, ID3D11Buffer*& ConstantBuffer)
{
CA_SUPPRESS(6326);
switch (ShaderFrequency)
{
case SF_Vertex: Direct3DDeviceIMContext->VSSetConstantBuffers(SlotIndex, 1, &ConstantBuffer); break;
case SF_Geometry: Direct3DDeviceIMContext->GSSetConstantBuffers(SlotIndex, 1, &ConstantBuffer); break;
case SF_Pixel: Direct3DDeviceIMContext->PSSetConstantBuffers(SlotIndex, 1, &ConstantBuffer); break;
case SF_Compute: Direct3DDeviceIMContext->CSSetConstantBuffers(SlotIndex, 1, &ConstantBuffer); break;
}
}
D3D11_STATE_CACHE_INLINE void InternalSetIndexBuffer(ID3D11Buffer* IndexBuffer, DXGI_FORMAT Format, uint32 Offset)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ( bAlwaysSetIndexBuffers || (CurrentIndexBuffer != IndexBuffer || CurrentIndexFormat != Format || CurrentIndexOffset != Offset) || GD3D11SkipStateCaching)
{
CurrentIndexBuffer = IndexBuffer;
CurrentIndexFormat = Format;
CurrentIndexOffset = Offset;
Direct3DDeviceIMContext->IASetIndexBuffer(IndexBuffer, Format, Offset);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->IASetIndexBuffer(IndexBuffer, Format, Offset);
#endif
}
template <EShaderFrequency ShaderFrequency>
D3D11_STATE_CACHE_INLINE void InternalSetShaderResourceView(ID3D11ShaderResourceView*& SRV, uint32 ResourceIndex)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
check(ResourceIndex < ARRAYSIZE(CurrentShaderResourceViews[ShaderFrequency]));
if ((CurrentShaderResourceViews[ShaderFrequency][ResourceIndex] != SRV) || GD3D11SkipStateCaching)
{
if(SRV)
{
SRV->AddRef();
}
if(CurrentShaderResourceViews[ShaderFrequency][ResourceIndex])
{
CurrentShaderResourceViews[ShaderFrequency][ResourceIndex]->Release();
}
CurrentShaderResourceViews[ShaderFrequency][ResourceIndex] = SRV;
InternalSetShaderResourceView<ShaderFrequency>(ResourceIndex, SRV);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else // !D3D11_ALLOW_STATE_CACHE
InternalSetShaderResourceView<ShaderFrequency>(ResourceIndex, SRV);
#endif
}
D3D11_STATE_CACHE_INLINE void InternalSetStreamSource(ID3D11Buffer* VertexBuffer, uint32 StreamIndex, uint32 Stride, uint32 Offset)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
check(StreamIndex < ARRAYSIZE(CurrentVertexBuffers));
FD3D11VertexBufferState& Slot = CurrentVertexBuffers[StreamIndex];
if ((Slot.VertexBuffer != VertexBuffer || Slot.Offset != Offset || Slot.Stride != Stride) || GD3D11SkipStateCaching)
{
Slot.VertexBuffer = VertexBuffer;
Slot.Offset = Offset;
Slot.Stride = Stride;
Direct3DDeviceIMContext->IASetVertexBuffers(StreamIndex, 1, &VertexBuffer, &Stride, &Offset);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->IASetVertexBuffers(StreamIndex, 1, &VertexBuffer, &Stride, &Offset);
#endif
}
template <EShaderFrequency ShaderFrequency>
D3D11_STATE_CACHE_INLINE void InternalSetSamplerState(ID3D11SamplerState* SamplerState, uint32 SamplerIndex)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
check(SamplerIndex < ARRAYSIZE(CurrentSamplerStates[ShaderFrequency]));
if ((CurrentSamplerStates[ShaderFrequency][SamplerIndex] != SamplerState) || GD3D11SkipStateCaching)
{
CurrentSamplerStates[ShaderFrequency][SamplerIndex] = SamplerState;
InternalSetSamplerState<ShaderFrequency>(SamplerIndex, SamplerState);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
InternalSetSamplerState<ShaderFrequency>(SamplerIndex, SamplerState);
#endif
}
public:
template <EShaderFrequency ShaderFrequency>
D3D11_STATE_CACHE_INLINE void ClearConstantBuffers()
{
#if D3D11_ALLOW_STATE_CACHE
FMemory::Memzero(CurrentConstantBuffers[ShaderFrequency]);
#endif
ID3D11Buffer* Empty[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {0};
CA_SUPPRESS(6326);
switch (ShaderFrequency)
{
case SF_Vertex: Direct3DDeviceIMContext->VSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, Empty); break;
case SF_Geometry: Direct3DDeviceIMContext->GSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, Empty); break;
case SF_Pixel: Direct3DDeviceIMContext->PSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, Empty); break;
case SF_Compute: Direct3DDeviceIMContext->CSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, Empty); break;
}
}
template <EShaderFrequency ShaderFrequency>
D3D11_STATE_CACHE_INLINE void SetShaderResourceView(ID3D11ShaderResourceView* SRV, uint32 ResourceIndex)
{
InternalSetShaderResourceView<ShaderFrequency>(SRV, ResourceIndex);
}
D3D11_STATE_CACHE_INLINE void SetViewport(D3D11_VIEWPORT Viewport)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentNumberOfViewports != 1 || FMemory::Memcmp(&CurrentViewport[0],&Viewport, sizeof(D3D11_VIEWPORT))) || GD3D11SkipStateCaching)
{
FMemory::Memcpy(&CurrentViewport[0], &Viewport, sizeof(D3D11_VIEWPORT));
CurrentNumberOfViewports = 1;
Direct3DDeviceIMContext->RSSetViewports(1,&Viewport);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else // !D3D11_ALLOW_STATE_CACHE
Direct3DDeviceIMContext->RSSetViewports(1,&Viewport);
#endif // D3D11_ALLOW_STATE_CACHE
}
D3D11_STATE_CACHE_INLINE void SetViewports(uint32 Count, D3D11_VIEWPORT* Viewports)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentNumberOfViewports != Count || FMemory::Memcmp(&CurrentViewport[0], Viewports, sizeof(D3D11_VIEWPORT) * Count)) || GD3D11SkipStateCaching)
{
FMemory::Memcpy(&CurrentViewport[0], Viewports, sizeof(D3D11_VIEWPORT) * Count);
CurrentNumberOfViewports = Count;
Direct3DDeviceIMContext->RSSetViewports(Count, Viewports);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else // !D3D11_ALLOW_STATE_CACHE
Direct3DDeviceIMContext->RSSetViewports(Count, Viewports);
#endif // D3D11_ALLOW_STATE_CACHE
}
D3D11_STATE_CACHE_INLINE void GetViewport(D3D11_VIEWPORT *Viewport)
{
#if D3D11_ALLOW_STATE_CACHE
check(Viewport);
FMemory::Memcpy(Viewport,&CurrentViewport,sizeof(D3D11_VIEWPORT));
#else // !D3D11_ALLOW_STATE_CACHE
uint32 one = 1;
Direct3DDeviceIMContext->RSGetViewports(&one,Viewport);
#endif // D3D11_ALLOW_STATE_CACHE
}
D3D11_STATE_CACHE_INLINE void GetViewports(uint32* Count, D3D11_VIEWPORT *Viewports)
{
#if D3D11_ALLOW_STATE_CACHE
check (*Count);
if (Viewports) //NULL is legal if you just want count
{
//as per d3d spec
int32 StorageSizeCount = (int32)(*Count);
int32 CopyCount = FMath::Min(FMath::Min(StorageSizeCount, (int32)CurrentNumberOfViewports), D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE);
if (CopyCount > 0)
{
FMemory::Memcpy(Viewports, &CurrentViewport[0], sizeof(D3D11_VIEWPORT) * CopyCount);
}
//remaining viewports in supplied array must be set to zero
if (StorageSizeCount > CopyCount)
{
FMemory::Memset(&Viewports[CopyCount], 0, sizeof(D3D11_VIEWPORT) * (StorageSizeCount - CopyCount));
}
}
*Count = CurrentNumberOfViewports;
#else // !D3D11_ALLOW_STATE_CACHE
Direct3DDeviceIMContext->RSGetViewports(Count, Viewports);
#endif // D3D11_ALLOW_STATE_CACHE
}
template <EShaderFrequency ShaderFrequency>
D3D11_STATE_CACHE_INLINE void SetSamplerState(ID3D11SamplerState* SamplerState, uint32 SamplerIndex)
{
InternalSetSamplerState<ShaderFrequency>(SamplerState, SamplerIndex);
}
template <EShaderFrequency ShaderFrequency>
D3D11_STATE_CACHE_INLINE void SetConstantBuffer(ID3D11Buffer* ConstantBuffer, uint32 SlotIndex)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
FD3D11ConstantBufferState& Current = CurrentConstantBuffers[ShaderFrequency][SlotIndex];
if ((Current.Buffer != ConstantBuffer || Current.FirstConstant != 0 || Current.NumConstants != D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT) || GD3D11SkipStateCaching)
{
Current.Buffer = ConstantBuffer;
Current.FirstConstant = 0;
Current.NumConstants = D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
InternalSetSetConstantBuffer<ShaderFrequency>(SlotIndex, ConstantBuffer);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
InternalSetSetConstantBuffer<ShaderFrequency>(SlotIndex, ConstantBuffer);
#endif
}
D3D11_STATE_CACHE_INLINE void SetRasterizerState(ID3D11RasterizerState* State)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentRasterizerState != State) || GD3D11SkipStateCaching)
{
CurrentRasterizerState = State;
Direct3DDeviceIMContext->RSSetState(State);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->RSSetState(State);
#endif
}
D3D11_STATE_CACHE_INLINE void SetBlendState(ID3D11BlendState* State, const float BlendFactor[4], uint32 SampleMask)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentBlendState != State || CurrentBlendSampleMask != SampleMask || FMemory::Memcmp(CurrentBlendFactor, BlendFactor, sizeof(CurrentBlendFactor))) || GD3D11SkipStateCaching)
{
CurrentBlendState = State;
CurrentBlendSampleMask = SampleMask;
FMemory::Memcpy(CurrentBlendFactor, BlendFactor, sizeof(CurrentBlendFactor));
Direct3DDeviceIMContext->OMSetBlendState(State, BlendFactor, SampleMask);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->OMSetBlendState(State, BlendFactor, SampleMask);
#endif
}
D3D11_STATE_CACHE_INLINE void SetBlendFactor(const float BlendFactor[4], uint32 SampleMask)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentBlendSampleMask != SampleMask || FMemory::Memcmp(CurrentBlendFactor, BlendFactor, sizeof(CurrentBlendFactor))) || GD3D11SkipStateCaching)
{
CurrentBlendSampleMask = SampleMask;
FMemory::Memcpy(CurrentBlendFactor, BlendFactor, sizeof(CurrentBlendFactor));
Direct3DDeviceIMContext->OMSetBlendState(CurrentBlendState, BlendFactor, SampleMask);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->OMSetBlendState(CurrentBlendState, BlendFactor, SampleMask);
#endif
}
D3D11_STATE_CACHE_INLINE void SetDepthStencilState(ID3D11DepthStencilState* State, uint32 RefStencil)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentDepthStencilState != State || CurrentReferenceStencil != RefStencil) || GD3D11SkipStateCaching)
{
CurrentDepthStencilState = State;
CurrentReferenceStencil = RefStencil;
Direct3DDeviceIMContext->OMSetDepthStencilState(State, RefStencil);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->OMSetDepthStencilState(State, RefStencil);
#endif
}
D3D11_STATE_CACHE_INLINE void SetStencilRef(uint32 RefStencil)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if (CurrentReferenceStencil != RefStencil || GD3D11SkipStateCaching)
{
CurrentReferenceStencil = RefStencil;
Direct3DDeviceIMContext->OMSetDepthStencilState(CurrentDepthStencilState, RefStencil);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->OMSetDepthStencilState(CurrentDepthStencilState, RefStencil);
#endif
}
D3D11_STATE_CACHE_INLINE void SetVertexShader(ID3D11VertexShader* Shader)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentVertexShader != Shader) || GD3D11SkipStateCaching)
{
CurrentVertexShader = Shader;
Direct3DDeviceIMContext->VSSetShader(Shader, nullptr, 0);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->VSSetShader(Shader, nullptr, 0);
#endif
}
D3D11_STATE_CACHE_INLINE void GetVertexShader(ID3D11VertexShader** VertexShader)
{
#if D3D11_ALLOW_STATE_CACHE
*VertexShader = CurrentVertexShader;
if (CurrentVertexShader)
{
CurrentVertexShader->AddRef();
}
#else
Direct3DDeviceIMContext->VSGetShader(VertexShader, nullptr, nullptr);
#endif
}
D3D11_STATE_CACHE_INLINE void SetGeometryShader(ID3D11GeometryShader* Shader)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentGeometryShader != Shader) || GD3D11SkipStateCaching)
{
CurrentGeometryShader = Shader;
Direct3DDeviceIMContext->GSSetShader(Shader, nullptr, 0);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->GSSetShader(Shader, nullptr, 0);
#endif
}
D3D11_STATE_CACHE_INLINE void GetGeometryShader(ID3D11GeometryShader** GeometryShader)
{
#if D3D11_ALLOW_STATE_CACHE
*GeometryShader = CurrentGeometryShader;
if (CurrentGeometryShader)
{
CurrentGeometryShader->AddRef();
}
#else
Direct3DDeviceIMContext->GSGetShader(GeometryShader, nullptr, nullptr);
#endif
}
D3D11_STATE_CACHE_INLINE void SetPixelShader(ID3D11PixelShader* Shader)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentPixelShader != Shader) || GD3D11SkipStateCaching)
{
CurrentPixelShader = Shader;
Direct3DDeviceIMContext->PSSetShader(Shader, nullptr, 0);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->PSSetShader(Shader, nullptr, 0);
#endif
}
D3D11_STATE_CACHE_INLINE void GetPixelShader(ID3D11PixelShader** PixelShader)
{
#if D3D11_ALLOW_STATE_CACHE
*PixelShader = CurrentPixelShader;
if (CurrentPixelShader)
{
CurrentPixelShader->AddRef();
}
#else
Direct3DDeviceIMContext->PSGetShader(PixelShader, nullptr, nullptr);
#endif
}
D3D11_STATE_CACHE_INLINE void SetComputeShader(ID3D11ComputeShader* Shader)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentComputeShader != Shader) || GD3D11SkipStateCaching)
{
CurrentComputeShader = Shader;
Direct3DDeviceIMContext->CSSetShader(Shader, nullptr, 0);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->CSSetShader(Shader, nullptr, 0);
#endif
}
D3D11_STATE_CACHE_INLINE void GetComputeShader(ID3D11ComputeShader** ComputeShader)
{
#if D3D11_ALLOW_STATE_CACHE
*ComputeShader = CurrentComputeShader;
if (CurrentComputeShader)
{
CurrentComputeShader->AddRef();
}
#else
Direct3DDeviceIMContext->CSGetShader(ComputeShader, nullptr, nullptr);
#endif
}
D3D11_STATE_CACHE_INLINE void SetStreamStrides(const uint16* InStreamStrides)
{
FMemory::Memcpy(StreamStrides, InStreamStrides, sizeof(StreamStrides));
}
D3D11_STATE_CACHE_INLINE void SetInputLayout(ID3D11InputLayout* InputLayout)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentInputLayout != InputLayout) || GD3D11SkipStateCaching)
{
CurrentInputLayout = InputLayout;
Direct3DDeviceIMContext->IASetInputLayout(InputLayout);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->IASetInputLayout(InputLayout);
#endif
}
D3D11_STATE_CACHE_INLINE void SetStreamSource(ID3D11Buffer* VertexBuffer, uint32 StreamIndex, uint32 Stride, uint32 Offset)
{
ensure(Stride == StreamStrides[StreamIndex]);
InternalSetStreamSource(VertexBuffer, StreamIndex, Stride, Offset);
}
D3D11_STATE_CACHE_INLINE void SetStreamSource(ID3D11Buffer* VertexBuffer, uint32 StreamIndex, uint32 Offset)
{
InternalSetStreamSource(VertexBuffer, StreamIndex, StreamStrides[StreamIndex], Offset);
}
public:
D3D11_STATE_CACHE_INLINE void SetIndexBuffer(ID3D11Buffer* IndexBuffer, DXGI_FORMAT Format, uint32 Offset)
{
InternalSetIndexBuffer(IndexBuffer, Format, Offset);
}
D3D11_STATE_CACHE_INLINE void SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology)
{
#if D3D11_ALLOW_STATE_CACHE
D3D11_STATE_CACHE_VERIFY_PRE();
if ((CurrentPrimitiveTopology != PrimitiveTopology) || GD3D11SkipStateCaching)
{
CurrentPrimitiveTopology = PrimitiveTopology;
Direct3DDeviceIMContext->IASetPrimitiveTopology(PrimitiveTopology);
}
D3D11_STATE_CACHE_VERIFY_POST();
#else
Direct3DDeviceIMContext->IASetPrimitiveTopology(PrimitiveTopology);
#endif
}
FD3D11StateCacheBase()
: Direct3DDeviceIMContext(nullptr)
{
FMemory::Memzero(CurrentShaderResourceViews, sizeof(CurrentShaderResourceViews));
}
void Init(ID3D11DeviceContext* InDeviceContext, bool bInAlwaysSetIndexBuffers = false )
{
SetContext(InDeviceContext);
#if D3D11_ALLOW_STATE_CACHE
bAlwaysSetIndexBuffers = bInAlwaysSetIndexBuffers;
#endif
}
virtual ~FD3D11StateCacheBase()
{
}
virtual D3D11_STATE_CACHE_INLINE void SetContext(ID3D11DeviceContext* InDeviceContext)
{
Direct3DDeviceIMContext = InDeviceContext;
ClearState();
D3D11_STATE_CACHE_VERIFY();
}
/**
* Clears all D3D11 State, setting all input/output resource slots, shaders, input layouts,
* predications, scissor rectangles, depth-stencil state, rasterizer state, blend state,
* sampler state, and viewports to NULL
*/
virtual void ClearState();
#if D3D11_ALLOW_STATE_CACHE && D3D11_STATE_CACHE_DEBUG
protected:
// Debug helper methods to verify cached state integrity.
template <EShaderFrequency ShaderFrequency>
void VerifySamplerStates();
template <EShaderFrequency ShaderFrequency>
void VerifyConstantBuffers();
template <EShaderFrequency ShaderFrequency>
void VerifyShaderResourceViews();
void VerifyCacheStatePre();
void VerifyCacheStatePost();
void VerifyCacheState();
#endif
};