// 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 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 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 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 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(ResourceIndex, SRV); } D3D11_STATE_CACHE_VERIFY_POST(); #else // !D3D11_ALLOW_STATE_CACHE InternalSetShaderResourceView(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 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(SamplerIndex, SamplerState); } D3D11_STATE_CACHE_VERIFY_POST(); #else InternalSetSamplerState(SamplerIndex, SamplerState); #endif } public: template 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 D3D11_STATE_CACHE_INLINE void SetShaderResourceView(ID3D11ShaderResourceView* SRV, uint32 ResourceIndex) { InternalSetShaderResourceView(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 D3D11_STATE_CACHE_INLINE void SetSamplerState(ID3D11SamplerState* SamplerState, uint32 SamplerIndex) { InternalSetSamplerState(SamplerState, SamplerIndex); } template 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(SlotIndex, ConstantBuffer); } D3D11_STATE_CACHE_VERIFY_POST(); #else InternalSetSetConstantBuffer(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 void VerifySamplerStates(); template void VerifyConstantBuffers(); template void VerifyShaderResourceViews(); void VerifyCacheStatePre(); void VerifyCacheStatePost(); void VerifyCacheState(); #endif };