D3D: Remove state stack from tracker, set explicitly instead

This commit is contained in:
Stenzek 2018-02-22 19:40:09 +10:00
parent e18c7b1c33
commit 31111ef143
4 changed files with 66 additions and 160 deletions

View file

@ -20,97 +20,13 @@ namespace D3D
{
StateManager* stateman;
template <typename T>
AutoState<T>::AutoState(const T* object) : state(object)
{
((IUnknown*)state)->AddRef();
}
template <typename T>
AutoState<T>::AutoState(const AutoState<T>& source)
{
state = source.GetPtr();
((T*)state)->AddRef();
}
template <typename T>
AutoState<T>::~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;
}

View file

@ -6,7 +6,6 @@
#include <array>
#include <cstddef>
#include <stack>
#include <unordered_map>
#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 <typename T>
class AutoState
{
public:
AutoState(const T* object);
AutoState(const AutoState<T>& source);
~AutoState();
const inline T* GetPtr() const { return state; }
private:
const T* state;
};
typedef AutoState<ID3D11BlendState> AutoBlendState;
typedef AutoState<ID3D11DepthStencilState> AutoDepthStencilState;
typedef AutoState<ID3D11RasterizerState> 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<AutoBlendState> m_blendStates;
std::stack<AutoDepthStencilState> m_depthStates;
std::stack<AutoRasterizerState> 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;

View file

@ -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;
}

View file

@ -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)