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; StateManager* stateman;
template <typename T> StateManager::StateManager() = default;
AutoState<T>::AutoState(const T* object) : state(object) StateManager::~StateManager() = default;
{
((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();
}
void StateManager::Apply() 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) if (!m_dirtyFlags)
{
return; return;
}
int textureMaskShift = LeastSignificantSetBit((u32)DirtyFlag_Texture0); int textureMaskShift = LeastSignificantSetBit((u32)DirtyFlag_Texture0);
int samplerMaskShift = LeastSignificantSetBit((u32)DirtyFlag_Sampler0); 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; m_dirtyFlags = 0;
} }

View File

@ -6,7 +6,6 @@
#include <array> #include <array>
#include <cstddef> #include <cstddef>
#include <stack>
#include <unordered_map> #include <unordered_map>
#include "Common/BitField.h" #include "Common/BitField.h"
@ -14,10 +13,6 @@
#include "VideoBackends/D3D/D3DBase.h" #include "VideoBackends/D3D/D3DBase.h"
#include "VideoCommon/RenderState.h" #include "VideoCommon/RenderState.h"
struct ID3D11BlendState;
struct ID3D11DepthStencilState;
struct ID3D11RasterizerState;
namespace DX11 namespace DX11
{ {
class StateCache class StateCache
@ -44,37 +39,35 @@ private:
namespace D3D 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 class StateManager
{ {
public: public:
StateManager(); StateManager();
~StateManager();
// call any of these to change the affected states void SetBlendState(ID3D11BlendState* state)
void PushBlendState(const ID3D11BlendState* state); {
void PushDepthState(const ID3D11DepthStencilState* state); if (m_current.blendState != state)
void PushRasterizerState(const ID3D11RasterizerState* state); m_dirtyFlags |= DirtyFlag_BlendState;
// call these after drawing m_pending.blendState = state;
void PopBlendState(); }
void PopDepthState();
void PopRasterizerState(); 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) void SetTexture(size_t index, ID3D11ShaderResourceView* texture)
{ {
@ -209,14 +202,6 @@ public:
void Apply(); void Apply();
private: 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 enum DirtyFlags
{ {
DirtyFlag_Texture0 = 1 << 0, DirtyFlag_Texture0 = 1 << 0,
@ -251,9 +236,12 @@ private:
DirtyFlag_ComputeShader = 1 << 25, DirtyFlag_ComputeShader = 1 << 25,
DirtyFlag_InputAssembler = 1 << 26, 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 struct Resources
{ {
@ -273,10 +261,13 @@ private:
ID3D11VertexShader* vertexShader; ID3D11VertexShader* vertexShader;
ID3D11GeometryShader* geometryShader; ID3D11GeometryShader* geometryShader;
ID3D11ComputeShader* computeShader; ID3D11ComputeShader* computeShader;
ID3D11BlendState* blendState;
ID3D11DepthStencilState* depthState;
ID3D11RasterizerState* rasterizerState;
}; };
Resources m_pending; Resources m_pending = {};
Resources m_current; Resources m_current = {};
}; };
extern StateManager* stateman; 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; pVertices = (D3D::FONT2DVERTEX*)vbmap.pData;
// set general pipeline state // set general pipeline state
D3D::stateman->PushBlendState(m_blendstate); D3D::stateman->SetBlendState(m_blendstate);
D3D::stateman->PushRasterizerState(m_raststate); D3D::stateman->SetRasterizerState(m_raststate);
D3D::stateman->SetPixelShader(m_pshader); D3D::stateman->SetPixelShader(m_pshader);
D3D::stateman->SetVertexShader(m_vshader); 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::stateman->Apply();
D3D::context->Draw(3 * dwNumTriangles, 0); D3D::context->Draw(3 * dwNumTriangles, 0);
} }
D3D::stateman->PopBlendState();
D3D::stateman->PopRasterizerState();
return S_OK; 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) else // if (type == EFBAccessType::PokeZ)
{ {
D3D::stateman->PushBlendState(m_clear_blend_states[3]); D3D::stateman->SetBlendState(m_clear_blend_states[3]);
D3D::stateman->PushDepthState(m_clear_depth_states[1]); D3D::stateman->SetDepthState(m_clear_depth_states[1]);
D3D11_VIEWPORT vp = D3D11_VIEWPORT vp =
CD3D11_VIEWPORT(0.0f, 0.0f, (float)GetTargetWidth(), (float)GetTargetHeight()); 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); D3D::DrawEFBPokeQuads(type, points, num_points);
if (type == EFBAccessType::PokeZ)
{
D3D::stateman->PopDepthState();
D3D::stateman->PopBlendState();
}
RestoreAPIState(); RestoreAPIState();
} }
@ -446,21 +440,21 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
ResetAPIState(); ResetAPIState();
if (colorEnable && alphaEnable) if (colorEnable && alphaEnable)
D3D::stateman->PushBlendState(m_clear_blend_states[0]); D3D::stateman->SetBlendState(m_clear_blend_states[0]);
else if (colorEnable) else if (colorEnable)
D3D::stateman->PushBlendState(m_clear_blend_states[1]); D3D::stateman->SetBlendState(m_clear_blend_states[1]);
else if (alphaEnable) else if (alphaEnable)
D3D::stateman->PushBlendState(m_clear_blend_states[2]); D3D::stateman->SetBlendState(m_clear_blend_states[2]);
else else
D3D::stateman->PushBlendState(m_clear_blend_states[3]); D3D::stateman->SetBlendState(m_clear_blend_states[3]);
// TODO: Should we enable Z testing here? // TODO: Should we enable Z testing here?
// if (!bpmem.zmode.testenable) D3D::stateman->PushDepthState(s_clear_depth_states[0]); // if (!bpmem.zmode.testenable) D3D::stateman->PushDepthState(s_clear_depth_states[0]);
// else // else
if (zEnable) if (zEnable)
D3D::stateman->PushDepthState(m_clear_depth_states[1]); D3D::stateman->SetDepthState(m_clear_depth_states[1]);
else /*if (!zEnable)*/ 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 // Update the view port for clearing the picture
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc); 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); u32 rgbaColor = (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000);
D3D::drawClearQuad(rgbaColor, 1.0f - (z & 0xFFFFFF) / 16777216.0f); D3D::drawClearQuad(rgbaColor, 1.0f - (z & 0xFFFFFF) / 16777216.0f);
D3D::stateman->PopDepthState();
D3D::stateman->PopBlendState();
RestoreAPIState(); RestoreAPIState();
} }
@ -646,26 +637,23 @@ void Renderer::UpdateBackbufferSize()
// ALWAYS call RestoreAPIState for each ResetAPIState call you're doing // ALWAYS call RestoreAPIState for each ResetAPIState call you're doing
void Renderer::ResetAPIState() void Renderer::ResetAPIState()
{ {
D3D::stateman->PushBlendState(m_reset_blend_state); D3D::stateman->SetBlendState(m_reset_blend_state);
D3D::stateman->PushDepthState(m_reset_depth_state); D3D::stateman->SetDepthState(m_reset_depth_state);
D3D::stateman->PushRasterizerState(m_reset_rast_state); D3D::stateman->SetRasterizerState(m_reset_rast_state);
} }
void Renderer::RestoreAPIState() void Renderer::RestoreAPIState()
{ {
// Gets us back into a more game-like state. // Gets us back into a more game-like state.
D3D::stateman->PopBlendState();
D3D::stateman->PopDepthState();
D3D::stateman->PopRasterizerState();
BPFunctions::SetViewport(); BPFunctions::SetViewport();
BPFunctions::SetScissor(); BPFunctions::SetScissor();
} }
void Renderer::ApplyState() void Renderer::ApplyState()
{ {
D3D::stateman->PushBlendState(m_state_cache.Get(m_gx_state.blend)); D3D::stateman->SetBlendState(m_state_cache.Get(m_gx_state.blend));
D3D::stateman->PushDepthState(m_state_cache.Get(m_gx_state.zmode)); D3D::stateman->SetDepthState(m_state_cache.Get(m_gx_state.zmode));
D3D::stateman->PushRasterizerState(m_state_cache.Get(m_gx_state.raster)); D3D::stateman->SetRasterizerState(m_state_cache.Get(m_gx_state.raster));
D3D::stateman->SetPrimitiveTopology( D3D::stateman->SetPrimitiveTopology(
StateCache::GetPrimitiveTopology(m_gx_state.raster.primitive)); StateCache::GetPrimitiveTopology(m_gx_state.raster.primitive));
FramebufferManager::SetIntegerEFBRenderTarget(m_gx_state.blend.logicopenable); FramebufferManager::SetIntegerEFBRenderTarget(m_gx_state.blend.logicopenable);
@ -683,9 +671,6 @@ void Renderer::ApplyState()
void Renderer::RestoreState() void Renderer::RestoreState()
{ {
D3D::stateman->PopBlendState();
D3D::stateman->PopDepthState();
D3D::stateman->PopRasterizerState();
} }
void Renderer::SetRasterizationState(const RasterizationState& state) void Renderer::SetRasterizationState(const RasterizationState& state)