From 31111ef1432bc5d6d653fbef175e8ca3ac2c152d Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 22 Feb 2018 19:40:09 +1000 Subject: [PATCH] D3D: Remove state stack from tracker, set explicitly instead --- Source/Core/VideoBackends/D3D/D3DState.cpp | 104 ++++----------------- Source/Core/VideoBackends/D3D/D3DState.h | 73 +++++++-------- Source/Core/VideoBackends/D3D/D3DUtil.cpp | 6 +- Source/Core/VideoBackends/D3D/Render.cpp | 43 +++------ 4 files changed, 66 insertions(+), 160 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DState.cpp b/Source/Core/VideoBackends/D3D/D3DState.cpp index 41412342cc..b779683fb8 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.cpp +++ b/Source/Core/VideoBackends/D3D/D3DState.cpp @@ -20,97 +20,13 @@ namespace D3D { StateManager* stateman; -template -AutoState::AutoState(const T* object) : state(object) -{ - ((IUnknown*)state)->AddRef(); -} - -template -AutoState::AutoState(const AutoState& source) -{ - state = source.GetPtr(); - ((T*)state)->AddRef(); -} - -template -AutoState::~AutoState() -{ - if (state) - ((T*)state)->Release(); - state = nullptr; -} - -StateManager::StateManager() - : m_currentBlendState(nullptr), m_currentDepthState(nullptr), m_currentRasterizerState(nullptr), - m_dirtyFlags(~0u), m_pending(), m_current() -{ -} - -void StateManager::PushBlendState(const ID3D11BlendState* state) -{ - m_blendStates.push(AutoBlendState(state)); -} -void StateManager::PushDepthState(const ID3D11DepthStencilState* state) -{ - m_depthStates.push(AutoDepthStencilState(state)); -} -void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) -{ - m_rasterizerStates.push(AutoRasterizerState(state)); -} -void StateManager::PopBlendState() -{ - m_blendStates.pop(); -} -void StateManager::PopDepthState() -{ - m_depthStates.pop(); -} -void StateManager::PopRasterizerState() -{ - m_rasterizerStates.pop(); -} +StateManager::StateManager() = default; +StateManager::~StateManager() = default; void StateManager::Apply() { - if (!m_blendStates.empty()) - { - if (m_currentBlendState != m_blendStates.top().GetPtr()) - { - m_currentBlendState = (ID3D11BlendState*)m_blendStates.top().GetPtr(); - D3D::context->OMSetBlendState(m_currentBlendState, nullptr, 0xFFFFFFFF); - } - } - else - ERROR_LOG(VIDEO, "Tried to apply without blend state!"); - - if (!m_depthStates.empty()) - { - if (m_currentDepthState != m_depthStates.top().GetPtr()) - { - m_currentDepthState = (ID3D11DepthStencilState*)m_depthStates.top().GetPtr(); - D3D::context->OMSetDepthStencilState(m_currentDepthState, 0); - } - } - else - ERROR_LOG(VIDEO, "Tried to apply without depth state!"); - - if (!m_rasterizerStates.empty()) - { - if (m_currentRasterizerState != m_rasterizerStates.top().GetPtr()) - { - m_currentRasterizerState = (ID3D11RasterizerState*)m_rasterizerStates.top().GetPtr(); - D3D::context->RSSetState(m_currentRasterizerState); - } - } - else - ERROR_LOG(VIDEO, "Tried to apply without rasterizer state!"); - if (!m_dirtyFlags) - { return; - } int textureMaskShift = LeastSignificantSetBit((u32)DirtyFlag_Texture0); int samplerMaskShift = LeastSignificantSetBit((u32)DirtyFlag_Sampler0); @@ -232,6 +148,22 @@ void StateManager::Apply() } } + if (m_dirtyFlags & DirtyFlag_BlendState) + { + D3D::context->OMSetBlendState(m_pending.blendState, nullptr, 0xFFFFFFFF); + m_current.blendState = m_pending.blendState; + } + if (m_dirtyFlags & DirtyFlag_DepthState) + { + D3D::context->OMSetDepthStencilState(m_pending.depthState, 0); + m_current.depthState = m_pending.depthState; + } + if (m_dirtyFlags & DirtyFlag_RasterizerState) + { + D3D::context->RSSetState(m_pending.rasterizerState); + m_current.rasterizerState = m_pending.rasterizerState; + } + m_dirtyFlags = 0; } diff --git a/Source/Core/VideoBackends/D3D/D3DState.h b/Source/Core/VideoBackends/D3D/D3DState.h index f7565cae45..805ed8996b 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.h +++ b/Source/Core/VideoBackends/D3D/D3DState.h @@ -6,7 +6,6 @@ #include #include -#include #include #include "Common/BitField.h" @@ -14,10 +13,6 @@ #include "VideoBackends/D3D/D3DBase.h" #include "VideoCommon/RenderState.h" -struct ID3D11BlendState; -struct ID3D11DepthStencilState; -struct ID3D11RasterizerState; - namespace DX11 { class StateCache @@ -44,37 +39,35 @@ private: namespace D3D { -template -class AutoState -{ -public: - AutoState(const T* object); - AutoState(const AutoState& source); - ~AutoState(); - - const inline T* GetPtr() const { return state; } -private: - const T* state; -}; - -typedef AutoState AutoBlendState; -typedef AutoState AutoDepthStencilState; -typedef AutoState AutoRasterizerState; - class StateManager { public: StateManager(); + ~StateManager(); - // call any of these to change the affected states - void PushBlendState(const ID3D11BlendState* state); - void PushDepthState(const ID3D11DepthStencilState* state); - void PushRasterizerState(const ID3D11RasterizerState* state); + void SetBlendState(ID3D11BlendState* state) + { + if (m_current.blendState != state) + m_dirtyFlags |= DirtyFlag_BlendState; - // call these after drawing - void PopBlendState(); - void PopDepthState(); - void PopRasterizerState(); + m_pending.blendState = state; + } + + void SetDepthState(ID3D11DepthStencilState* state) + { + if (m_current.depthState != state) + m_dirtyFlags |= DirtyFlag_DepthState; + + m_pending.depthState = state; + } + + void SetRasterizerState(ID3D11RasterizerState* state) + { + if (m_current.rasterizerState != state) + m_dirtyFlags |= DirtyFlag_RasterizerState; + + m_pending.rasterizerState = state; + } void SetTexture(size_t index, ID3D11ShaderResourceView* texture) { @@ -209,14 +202,6 @@ public: void Apply(); private: - std::stack m_blendStates; - std::stack m_depthStates; - std::stack m_rasterizerStates; - - ID3D11BlendState* m_currentBlendState; - ID3D11DepthStencilState* m_currentDepthState; - ID3D11RasterizerState* m_currentRasterizerState; - enum DirtyFlags { DirtyFlag_Texture0 = 1 << 0, @@ -251,9 +236,12 @@ private: DirtyFlag_ComputeShader = 1 << 25, DirtyFlag_InputAssembler = 1 << 26, + DirtyFlag_BlendState = 1 << 27, + DirtyFlag_DepthState = 1 << 28, + DirtyFlag_RasterizerState = 1 << 29, }; - u32 m_dirtyFlags; + u32 m_dirtyFlags = ~0u; struct Resources { @@ -273,10 +261,13 @@ private: ID3D11VertexShader* vertexShader; ID3D11GeometryShader* geometryShader; ID3D11ComputeShader* computeShader; + ID3D11BlendState* blendState; + ID3D11DepthStencilState* depthState; + ID3D11RasterizerState* rasterizerState; }; - Resources m_pending; - Resources m_current; + Resources m_pending = {}; + Resources m_current = {}; }; extern StateManager* stateman; diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.cpp b/Source/Core/VideoBackends/D3D/D3DUtil.cpp index bd95004bfe..138db0554b 100644 --- a/Source/Core/VideoBackends/D3D/D3DUtil.cpp +++ b/Source/Core/VideoBackends/D3D/D3DUtil.cpp @@ -406,8 +406,8 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw pVertices = (D3D::FONT2DVERTEX*)vbmap.pData; // set general pipeline state - D3D::stateman->PushBlendState(m_blendstate); - D3D::stateman->PushRasterizerState(m_raststate); + D3D::stateman->SetBlendState(m_blendstate); + D3D::stateman->SetRasterizerState(m_raststate); D3D::stateman->SetPixelShader(m_pshader); D3D::stateman->SetVertexShader(m_vshader); @@ -478,8 +478,6 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw D3D::stateman->Apply(); D3D::context->Draw(3 * dwNumTriangles, 0); } - D3D::stateman->PopBlendState(); - D3D::stateman->PopRasterizerState(); return S_OK; } diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 0e8c822d23..77281ffa37 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -405,8 +405,8 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num } else // if (type == EFBAccessType::PokeZ) { - D3D::stateman->PushBlendState(m_clear_blend_states[3]); - D3D::stateman->PushDepthState(m_clear_depth_states[1]); + D3D::stateman->SetBlendState(m_clear_blend_states[3]); + D3D::stateman->SetDepthState(m_clear_depth_states[1]); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.0f, 0.0f, (float)GetTargetWidth(), (float)GetTargetHeight()); @@ -417,12 +417,6 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num D3D::DrawEFBPokeQuads(type, points, num_points); - if (type == EFBAccessType::PokeZ) - { - D3D::stateman->PopDepthState(); - D3D::stateman->PopBlendState(); - } - RestoreAPIState(); } @@ -446,21 +440,21 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE ResetAPIState(); if (colorEnable && alphaEnable) - D3D::stateman->PushBlendState(m_clear_blend_states[0]); + D3D::stateman->SetBlendState(m_clear_blend_states[0]); else if (colorEnable) - D3D::stateman->PushBlendState(m_clear_blend_states[1]); + D3D::stateman->SetBlendState(m_clear_blend_states[1]); else if (alphaEnable) - D3D::stateman->PushBlendState(m_clear_blend_states[2]); + D3D::stateman->SetBlendState(m_clear_blend_states[2]); else - D3D::stateman->PushBlendState(m_clear_blend_states[3]); + D3D::stateman->SetBlendState(m_clear_blend_states[3]); // TODO: Should we enable Z testing here? // if (!bpmem.zmode.testenable) D3D::stateman->PushDepthState(s_clear_depth_states[0]); // else if (zEnable) - D3D::stateman->PushDepthState(m_clear_depth_states[1]); + D3D::stateman->SetDepthState(m_clear_depth_states[1]); else /*if (!zEnable)*/ - D3D::stateman->PushDepthState(m_clear_depth_states[2]); + D3D::stateman->SetDepthState(m_clear_depth_states[2]); // Update the view port for clearing the picture TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc); @@ -474,9 +468,6 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE u32 rgbaColor = (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000); D3D::drawClearQuad(rgbaColor, 1.0f - (z & 0xFFFFFF) / 16777216.0f); - D3D::stateman->PopDepthState(); - D3D::stateman->PopBlendState(); - RestoreAPIState(); } @@ -646,26 +637,23 @@ void Renderer::UpdateBackbufferSize() // ALWAYS call RestoreAPIState for each ResetAPIState call you're doing void Renderer::ResetAPIState() { - D3D::stateman->PushBlendState(m_reset_blend_state); - D3D::stateman->PushDepthState(m_reset_depth_state); - D3D::stateman->PushRasterizerState(m_reset_rast_state); + D3D::stateman->SetBlendState(m_reset_blend_state); + D3D::stateman->SetDepthState(m_reset_depth_state); + D3D::stateman->SetRasterizerState(m_reset_rast_state); } void Renderer::RestoreAPIState() { // Gets us back into a more game-like state. - D3D::stateman->PopBlendState(); - D3D::stateman->PopDepthState(); - D3D::stateman->PopRasterizerState(); BPFunctions::SetViewport(); BPFunctions::SetScissor(); } void Renderer::ApplyState() { - D3D::stateman->PushBlendState(m_state_cache.Get(m_gx_state.blend)); - D3D::stateman->PushDepthState(m_state_cache.Get(m_gx_state.zmode)); - D3D::stateman->PushRasterizerState(m_state_cache.Get(m_gx_state.raster)); + D3D::stateman->SetBlendState(m_state_cache.Get(m_gx_state.blend)); + D3D::stateman->SetDepthState(m_state_cache.Get(m_gx_state.zmode)); + D3D::stateman->SetRasterizerState(m_state_cache.Get(m_gx_state.raster)); D3D::stateman->SetPrimitiveTopology( StateCache::GetPrimitiveTopology(m_gx_state.raster.primitive)); FramebufferManager::SetIntegerEFBRenderTarget(m_gx_state.blend.logicopenable); @@ -683,9 +671,6 @@ void Renderer::ApplyState() void Renderer::RestoreState() { - D3D::stateman->PopBlendState(); - D3D::stateman->PopDepthState(); - D3D::stateman->PopRasterizerState(); } void Renderer::SetRasterizationState(const RasterizationState& state)