mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
D3D: Implemented context state caching
This avoids most of the redundant API calls.
This commit is contained in:
@ -73,7 +73,6 @@ private:
|
||||
std::unordered_map<u32, ID3D11RasterizerState*> m_raster;
|
||||
std::unordered_map<u32, ID3D11BlendState*> m_blend;
|
||||
std::unordered_map<u64, ID3D11SamplerState*> m_sampler;
|
||||
|
||||
};
|
||||
|
||||
namespace D3D
|
||||
@ -111,16 +110,199 @@ public:
|
||||
void PopDepthState();
|
||||
void PopRasterizerState();
|
||||
|
||||
// call this before any drawing operation if states could have changed meanwhile
|
||||
void setTexture(u32 index, ID3D11ShaderResourceView* texture)
|
||||
{
|
||||
if (m_current.textures[index] != texture)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_Texture0 << index;
|
||||
m_pending.textures[index] = texture;
|
||||
}
|
||||
}
|
||||
|
||||
void setSampler(u32 index, ID3D11SamplerState* sampler)
|
||||
{
|
||||
if (m_current.samplers[index] != sampler)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_Sampler0 << index;
|
||||
m_pending.samplers[index] = sampler;
|
||||
}
|
||||
}
|
||||
|
||||
void setPixelConstants(ID3D11Buffer* buffer0, ID3D11Buffer* buffer1 = nullptr)
|
||||
{
|
||||
if (m_current.pixelConstants[0] != buffer0)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_PixelConstants;
|
||||
m_pending.pixelConstants[0] = buffer0;
|
||||
}
|
||||
|
||||
if (m_current.pixelConstants[1] != buffer1)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_PixelConstants;
|
||||
m_pending.pixelConstants[1] = buffer1;
|
||||
}
|
||||
}
|
||||
|
||||
void setVertexConstants(ID3D11Buffer* buffer)
|
||||
{
|
||||
if (m_current.vertexConstants != buffer)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_VertexConstants;
|
||||
m_pending.vertexConstants = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void setGeometryConstants(ID3D11Buffer* buffer)
|
||||
{
|
||||
if (m_current.geometryConstants != buffer)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_GeometryConstants;
|
||||
m_pending.geometryConstants = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void setVertexBuffer(ID3D11Buffer* buffer, u32 stride, u32 offset)
|
||||
{
|
||||
if (m_current.vertexBuffer != buffer ||
|
||||
m_current.vertexBufferStride != stride ||
|
||||
m_current.vertexBufferOffset != offset)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_VertexBuffer;
|
||||
m_pending.vertexBuffer = buffer;
|
||||
m_pending.vertexBufferStride = stride;
|
||||
m_pending.vertexBufferOffset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
void setIndexBuffer(ID3D11Buffer* buffer)
|
||||
{
|
||||
if (m_current.indexBuffer != buffer)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_IndexBuffer;
|
||||
m_pending.indexBuffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY topology)
|
||||
{
|
||||
if (m_current.topology != topology)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_InputAssembler;
|
||||
m_pending.topology = topology;
|
||||
}
|
||||
}
|
||||
|
||||
void setInputLayout(ID3D11InputLayout* layout)
|
||||
{
|
||||
if (m_current.inputLayout != layout)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_InputAssembler;
|
||||
m_pending.inputLayout = layout;
|
||||
}
|
||||
}
|
||||
|
||||
void setPixelShader(ID3D11PixelShader* shader)
|
||||
{
|
||||
if (m_current.pixelShader != shader)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_PixelShader;
|
||||
m_pending.pixelShader = shader;
|
||||
}
|
||||
}
|
||||
|
||||
void setPixelShaderDynamic(ID3D11PixelShader* shader, ID3D11ClassInstance * const * classInstances, u32 classInstancesCount)
|
||||
{
|
||||
D3D::context->PSSetShader(shader, classInstances, classInstancesCount);
|
||||
m_pending.pixelShader = shader;
|
||||
}
|
||||
|
||||
void setVertexShader(ID3D11VertexShader* shader)
|
||||
{
|
||||
if (m_current.vertexShader != shader)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_VertexShader;
|
||||
m_pending.vertexShader = shader;
|
||||
}
|
||||
}
|
||||
|
||||
void setGeometryShader(ID3D11GeometryShader* shader)
|
||||
{
|
||||
if (m_current.geometryShader != shader)
|
||||
{
|
||||
m_dirtyFlags |= DirtyFlag_GeometryShader;
|
||||
m_pending.geometryShader = shader;
|
||||
}
|
||||
}
|
||||
|
||||
// call this immediately before any drawing operation or to explicitly apply pending resource state changes
|
||||
void Apply();
|
||||
|
||||
private:
|
||||
std::stack<AutoBlendState> blendstates;
|
||||
std::stack<AutoDepthStencilState> depthstates;
|
||||
std::stack<AutoRasterizerState> raststates;
|
||||
ID3D11BlendState* cur_blendstate;
|
||||
ID3D11DepthStencilState* cur_depthstate;
|
||||
ID3D11RasterizerState* cur_raststate;
|
||||
|
||||
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,
|
||||
DirtyFlag_Texture1 = 1 << 1,
|
||||
DirtyFlag_Texture2 = 1 << 2,
|
||||
DirtyFlag_Texture3 = 1 << 3,
|
||||
DirtyFlag_Texture4 = 1 << 4,
|
||||
DirtyFlag_Texture5 = 1 << 5,
|
||||
DirtyFlag_Texture6 = 1 << 6,
|
||||
DirtyFlag_Texture7 = 1 << 7,
|
||||
|
||||
DirtyFlag_Sampler0 = 1 << 8,
|
||||
DirtyFlag_Sampler1 = 1 << 9,
|
||||
DirtyFlag_Sampler2 = 1 << 10,
|
||||
DirtyFlag_Sampler3 = 1 << 11,
|
||||
DirtyFlag_Sampler4 = 1 << 12,
|
||||
DirtyFlag_Sampler5 = 1 << 13,
|
||||
DirtyFlag_Sampler6 = 1 << 14,
|
||||
DirtyFlag_Sampler7 = 1 << 15,
|
||||
|
||||
DirtyFlag_PixelConstants = 1 << 16,
|
||||
DirtyFlag_VertexConstants = 1 << 17,
|
||||
DirtyFlag_GeometryConstants = 1 << 18,
|
||||
|
||||
DirtyFlag_VertexBuffer = 1 << 19,
|
||||
DirtyFlag_IndexBuffer = 1 << 20,
|
||||
|
||||
DirtyFlag_PixelShader = 1 << 21,
|
||||
DirtyFlag_VertexShader = 1 << 22,
|
||||
DirtyFlag_GeometryShader = 1 << 23,
|
||||
|
||||
DirtyFlag_InputAssembler = 1 << 24,
|
||||
};
|
||||
|
||||
u32 m_dirtyFlags;
|
||||
|
||||
struct Resources
|
||||
{
|
||||
ID3D11ShaderResourceView* textures[8];
|
||||
ID3D11SamplerState* samplers[8];
|
||||
ID3D11Buffer* pixelConstants[2];
|
||||
ID3D11Buffer* vertexConstants;
|
||||
ID3D11Buffer* geometryConstants;
|
||||
ID3D11Buffer* vertexBuffer;
|
||||
ID3D11Buffer* indexBuffer;
|
||||
u32 vertexBufferStride;
|
||||
u32 vertexBufferOffset;
|
||||
D3D11_PRIMITIVE_TOPOLOGY topology;
|
||||
ID3D11InputLayout* inputLayout;
|
||||
ID3D11PixelShader* pixelShader;
|
||||
ID3D11VertexShader* vertexShader;
|
||||
ID3D11GeometryShader* geometryShader;
|
||||
};
|
||||
|
||||
Resources m_pending;
|
||||
Resources m_current;
|
||||
};
|
||||
|
||||
extern StateManager* stateman;
|
||||
|
Reference in New Issue
Block a user