diff --git a/Source/Core/VideoBackends/D3D/D3DState.cpp b/Source/Core/VideoBackends/D3D/D3DState.cpp index 563f94cd9d..b251356e30 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.cpp +++ b/Source/Core/VideoBackends/D3D/D3DState.cpp @@ -33,46 +33,170 @@ template AutoState::~AutoState() state = nullptr; } -StateManager::StateManager() : cur_blendstate(nullptr), cur_depthstate(nullptr), cur_raststate(nullptr) {} +StateManager::StateManager() + : m_currentBlendState(nullptr) + , m_currentDepthState(nullptr) + , m_currentRasterizerState(nullptr) + , m_dirtyFlags(~0u) +{ + memset(&m_pending, 0, sizeof(m_pending)); + memset(&m_current, 0, sizeof(m_current)); +} -void StateManager::PushBlendState(const ID3D11BlendState* state) { blendstates.push(AutoBlendState(state)); } -void StateManager::PushDepthState(const ID3D11DepthStencilState* state) { depthstates.push(AutoDepthStencilState(state)); } -void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) { raststates.push(AutoRasterizerState(state)); } -void StateManager::PopBlendState() { blendstates.pop(); } -void StateManager::PopDepthState() { depthstates.pop(); } -void StateManager::PopRasterizerState() { raststates.pop(); } +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() { - if (!blendstates.empty()) + if (!m_blendStates.empty()) { - if (cur_blendstate != blendstates.top().GetPtr()) + if (m_currentBlendState != m_blendStates.top().GetPtr()) { - cur_blendstate = (ID3D11BlendState*)blendstates.top().GetPtr(); - D3D::context->OMSetBlendState(cur_blendstate, nullptr, 0xFFFFFFFF); + 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 (!depthstates.empty()) + if (!m_depthStates.empty()) { - if (cur_depthstate != depthstates.top().GetPtr()) + if (m_currentDepthState != m_depthStates.top().GetPtr()) { - cur_depthstate = (ID3D11DepthStencilState*)depthstates.top().GetPtr(); - D3D::context->OMSetDepthStencilState(cur_depthstate, 0); + m_currentDepthState = (ID3D11DepthStencilState*)m_depthStates.top().GetPtr(); + D3D::context->OMSetDepthStencilState(m_currentDepthState, 0); } } else ERROR_LOG(VIDEO, "Tried to apply without depth state!"); - if (!raststates.empty()) + if (!m_rasterizerStates.empty()) { - if (cur_raststate != raststates.top().GetPtr()) + if (m_currentRasterizerState != m_rasterizerStates.top().GetPtr()) { - cur_raststate = (ID3D11RasterizerState*)raststates.top().GetPtr(); - D3D::context->RSSetState(cur_raststate); + 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; + } + + const u32 dirtyTextures = DirtyFlag_Texture0 | DirtyFlag_Texture1 | DirtyFlag_Texture2 | DirtyFlag_Texture3 + | DirtyFlag_Texture4 | DirtyFlag_Texture5 | DirtyFlag_Texture6 | DirtyFlag_Texture7; + const u32 dirtySamplers = DirtyFlag_Sampler0 | DirtyFlag_Sampler1 | DirtyFlag_Sampler2 | DirtyFlag_Sampler3 + | DirtyFlag_Sampler4 | DirtyFlag_Sampler5 | DirtyFlag_Sampler6 | DirtyFlag_Sampler7; + const u32 dirtyConstants = DirtyFlag_PixelConstants | DirtyFlag_VertexConstants | DirtyFlag_GeometryConstants; + const u32 dirtyShaders = DirtyFlag_PixelShader | DirtyFlag_VertexShader | DirtyFlag_GeometryShader; + const u32 dirtyBuffers = DirtyFlag_VertexBuffer | DirtyFlag_IndexBuffer; + + if (m_dirtyFlags & dirtyConstants) + { + if (m_current.pixelConstants[0] != m_pending.pixelConstants[0] || + m_current.pixelConstants[1] != m_pending.pixelConstants[1]) + { + D3D::context->PSSetConstantBuffers(0, m_pending.pixelConstants[1] ? 2 : 1, m_pending.pixelConstants); + m_current.pixelConstants[0] = m_pending.pixelConstants[0]; + m_current.pixelConstants[1] = m_pending.pixelConstants[1]; + } + + if (m_current.vertexConstants != m_pending.vertexConstants) + { + D3D::context->VSSetConstantBuffers(0, 1, &m_pending.vertexConstants); + m_current.vertexConstants = m_pending.vertexConstants; + } + + if (m_current.geometryConstants != m_pending.geometryConstants) + { + D3D::context->GSSetConstantBuffers(0, 1, &m_pending.geometryConstants); + m_current.geometryConstants = m_pending.geometryConstants; + } + } + + if (m_dirtyFlags & (dirtyBuffers|DirtyFlag_InputAssembler)) + { + if (m_current.vertexBuffer != m_pending.vertexBuffer || + m_current.vertexBufferStride != m_pending.vertexBufferStride || + m_current.vertexBufferOffset != m_pending.vertexBufferOffset) + { + D3D::context->IASetVertexBuffers(0, 1, &m_pending.vertexBuffer, &m_pending.vertexBufferStride, &m_pending.vertexBufferOffset); + m_current.vertexBuffer = m_pending.vertexBuffer; + m_current.vertexBufferStride = m_pending.vertexBufferStride; + m_current.vertexBufferOffset = m_pending.vertexBufferOffset; + } + + if (m_current.indexBuffer != m_pending.indexBuffer) + { + D3D::context->IASetIndexBuffer(m_pending.indexBuffer, DXGI_FORMAT_R16_UINT, 0); + m_current.indexBuffer = m_pending.indexBuffer; + } + + if (m_current.topology != m_pending.topology) + { + D3D::context->IASetPrimitiveTopology(m_pending.topology); + m_current.topology = m_pending.topology; + } + + if (m_current.inputLayout != m_pending.inputLayout) + { + D3D::context->IASetInputLayout(m_pending.inputLayout); + m_current.inputLayout = m_pending.inputLayout; + } + } + + if (m_dirtyFlags & dirtyTextures) + { + for (int i = 0; i < 8; ++i) + { + // TODO: bit scan through dirty flags + if (m_current.textures[i] != m_pending.textures[i]) + { + D3D::context->PSSetShaderResources(i, 1, &m_pending.textures[i]); + m_current.textures[i] = m_pending.textures[i]; + } + } + } + + if (m_dirtyFlags & dirtySamplers) + { + for (int i = 0; i < 8; ++i) + { + // TODO: bit scan through dirty flags + if (m_current.samplers[i] != m_pending.samplers[i]) + { + D3D::context->PSSetSamplers(i, 1, &m_pending.samplers[i]); + m_current.samplers[i] = m_pending.samplers[i]; + } + } + } + + if (m_dirtyFlags & dirtyShaders) + { + if (m_current.pixelShader != m_pending.pixelShader) + { + D3D::context->PSSetShader(m_pending.pixelShader, nullptr, 0); + m_current.pixelShader = m_pending.pixelShader; + } + + if (m_current.vertexShader != m_pending.vertexShader) + { + D3D::context->VSSetShader(m_pending.vertexShader, nullptr, 0); + m_current.vertexShader = m_pending.vertexShader; + } + + if (m_current.geometryShader != m_pending.geometryShader) + { + D3D::context->GSSetShader(m_pending.geometryShader, nullptr, 0); + m_current.geometryShader = m_pending.geometryShader; + } + } + + m_dirtyFlags = 0; } } // namespace D3D diff --git a/Source/Core/VideoBackends/D3D/D3DState.h b/Source/Core/VideoBackends/D3D/D3DState.h index 8c7ee75776..d39012d9ad 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.h +++ b/Source/Core/VideoBackends/D3D/D3DState.h @@ -73,7 +73,6 @@ private: std::unordered_map m_raster; std::unordered_map m_blend; std::unordered_map 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 blendstates; - std::stack depthstates; - std::stack raststates; - ID3D11BlendState* cur_blendstate; - ID3D11DepthStencilState* cur_depthstate; - ID3D11RasterizerState* cur_raststate; + + 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, + 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; diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.cpp b/Source/Core/VideoBackends/D3D/D3DUtil.cpp index ad37d4f419..d798814a89 100644 --- a/Source/Core/VideoBackends/D3D/D3DUtil.cpp +++ b/Source/Core/VideoBackends/D3D/D3DUtil.cpp @@ -346,14 +346,13 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw // set general pipeline state D3D::stateman->PushBlendState(m_blendstate); D3D::stateman->PushRasterizerState(m_raststate); - D3D::stateman->Apply(); - D3D::context->PSSetShader(m_pshader, nullptr, 0); - D3D::context->VSSetShader(m_vshader, nullptr, 0); + D3D::stateman->setPixelShader(m_pshader); + D3D::stateman->setVertexShader(m_vshader); - D3D::context->IASetInputLayout(m_InputLayout); - D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - D3D::context->PSSetShaderResources(0, 1, &m_pTexture); + D3D::stateman->setInputLayout(m_InputLayout); + D3D::stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + D3D::stateman->setTexture(0, m_pTexture); float fStartX = sx; for (char c : text) @@ -392,7 +391,9 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw { context->Unmap(m_pVB, 0); - D3D::context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset); + D3D::stateman->setVertexBuffer(m_pVB, stride, bufoffset); + + D3D::stateman->Apply(); D3D::context->Draw(3 * dwNumTriangles, 0); dwNumTriangles = 0; @@ -408,7 +409,9 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw context->Unmap(m_pVB, 0); if (dwNumTriangles > 0) { - D3D::context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset); + D3D::stateman->setVertexBuffer(m_pVB, stride, bufoffset); + + D3D::stateman->Apply(); D3D::context->Draw(3 * dwNumTriangles, 0); } D3D::stateman->PopBlendState(); @@ -494,12 +497,12 @@ void ShutdownUtils() void SetPointCopySampler() { - D3D::context->PSSetSamplers(0, 1, &point_copy_sampler); + D3D::stateman->setSampler(0, point_copy_sampler); } void SetLinearCopySampler() { - D3D::context->PSSetSamplers(0, 1, &linear_copy_sampler); + D3D::stateman->setSampler(0, linear_copy_sampler); } void drawShadedTexQuad(ID3D11ShaderResourceView* texture, @@ -543,17 +546,18 @@ void drawShadedTexQuad(ID3D11ShaderResourceView* texture, UINT stride = sizeof(STQVertex); UINT offset = 0; - D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - D3D::context->IASetInputLayout(layout); - D3D::context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset); - D3D::context->PSSetShader(PShader, nullptr, 0); - D3D::context->PSSetShaderResources(0, 1, &texture); - D3D::context->VSSetShader(Vshader, nullptr, 0); + D3D::stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + D3D::stateman->setInputLayout(layout); + D3D::stateman->setVertexBuffer(util_vbuf->GetBuffer(), stride, offset); + D3D::stateman->setPixelShader(PShader); + D3D::stateman->setTexture(0, texture); + D3D::stateman->setVertexShader(Vshader); + D3D::stateman->Apply(); D3D::context->Draw(4, stq_offset); - ID3D11ShaderResourceView* texres = nullptr; - context->PSSetShaderResources(0, 1, &texres); // immediately unbind the texture + D3D::stateman->setTexture(0, nullptr); // immediately unbind the texture + D3D::stateman->Apply(); } void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, @@ -600,17 +604,18 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, UINT stride = sizeof(STSQVertex); UINT offset = 0; - context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset); - context->IASetInputLayout(layout); - context->PSSetShaderResources(0, 1, &texture); - context->PSSetShader(PShader, nullptr, 0); - context->VSSetShader(Vshader, nullptr, 0); + stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + stateman->setVertexBuffer(util_vbuf->GetBuffer(), stride, offset); + stateman->setInputLayout(layout); + stateman->setTexture(0, texture); + stateman->setPixelShader(PShader); + stateman->setVertexShader(Vshader); + stateman->Apply(); context->Draw(4, stsq_offset); - ID3D11ShaderResourceView* texres = nullptr; - context->PSSetShaderResources(0, 1, &texres); // immediately unbind the texture + stateman->setTexture(0, nullptr); // immediately unbind the texture + stateman->Apply(); } // Fills a certain area of the current render target with the specified color @@ -639,14 +644,14 @@ void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2) draw_quad_data.col = Color; } - context->VSSetShader(VertexShaderCache::GetClearVertexShader(), nullptr, 0); - context->PSSetShader(PixelShaderCache::GetClearProgram(), nullptr, 0); - context->IASetInputLayout(VertexShaderCache::GetClearInputLayout()); + stateman->setVertexShader(VertexShaderCache::GetClearVertexShader()); + stateman->setPixelShader(PixelShaderCache::GetClearProgram()); + stateman->setInputLayout(VertexShaderCache::GetClearInputLayout()); UINT stride = sizeof(ColVertex); UINT offset = 0; - context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset); + stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + stateman->setVertexBuffer(util_vbuf->GetBuffer(), stride, offset); stateman->Apply(); context->Draw(4, cq_offset); @@ -669,14 +674,16 @@ void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexS clear_quad_data.col = Color; clear_quad_data.z = z; } - context->VSSetShader(Vshader, nullptr, 0); - context->PSSetShader(PShader, nullptr, 0); - context->IASetInputLayout(layout); + + stateman->setVertexShader(Vshader); + stateman->setPixelShader(PShader); + stateman->setInputLayout(layout); UINT stride = sizeof(ClearVertex); UINT offset = 0; - context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset); + stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + stateman->setVertexBuffer(util_vbuf->GetBuffer(), stride, offset); + stateman->Apply(); context->Draw(4, clearq_offset); } diff --git a/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp b/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp index 9cd3ba6b5a..692f099ab7 100644 --- a/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp +++ b/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp @@ -6,6 +6,7 @@ #include "VideoBackends/D3D/D3DBase.h" #include "VideoBackends/D3D/D3DShader.h" +#include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/LineGeometryShader.h" #include "VideoCommon/VertexShaderGen.h" @@ -223,8 +224,8 @@ bool LineGeometryShader::SetShader(u32 components, float lineWidth, DEBUG_LOG(VIDEO, "Line params: width %f, texOffset %f, vpWidth %f, vpHeight %f", lineWidth, texOffset, vpWidth, vpHeight); - D3D::context->GSSetShader(shaderIt->second, nullptr, 0); - D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer); + D3D::stateman->setGeometryShader(shaderIt->second); + D3D::stateman->setGeometryConstants(m_paramsBuffer); return true; } diff --git a/Source/Core/VideoBackends/D3D/NativeVertexFormat.cpp b/Source/Core/VideoBackends/D3D/NativeVertexFormat.cpp index be59a2ac8c..bb83cba003 100644 --- a/Source/Core/VideoBackends/D3D/NativeVertexFormat.cpp +++ b/Source/Core/VideoBackends/D3D/NativeVertexFormat.cpp @@ -4,6 +4,7 @@ #include "VideoBackends/D3D/D3DBase.h" #include "VideoBackends/D3D/D3DBlob.h" +#include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/VertexManager.h" #include "VideoBackends/D3D/VertexShaderCache.h" #include "VideoCommon/NativeVertexFormat.h" @@ -137,7 +138,7 @@ void D3DVertexFormat::SetupVertexPointers() if (FAILED(hr)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__); DX11::D3D::SetDebugObjectName((ID3D11DeviceChild*)m_layout, "input layout used to emulate the GX pipeline"); } - DX11::D3D::context->IASetInputLayout(m_layout); + DX11::D3D::stateman->setInputLayout(m_layout); } } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index fe1f134635..aa90986bcc 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -1083,21 +1083,20 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, if (SetStaticShader(dstFormat, srcFormat, isIntensity, scaleByHalf)) #endif { - D3D::context->VSSetShader(m_vShader, nullptr, 0); + D3D::stateman->setVertexShader(m_vShader); D3D::stateman->PushBlendState(m_efbEncodeBlendState); D3D::stateman->PushDepthState(m_efbEncodeDepthState); D3D::stateman->PushRasterizerState(m_efbEncodeRastState); - D3D::stateman->Apply(); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(cacheLinesPerRow*2), FLOAT(numBlocksY)); D3D::context->RSSetViewports(1, &vp); - D3D::context->IASetInputLayout(m_quadLayout); - D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + D3D::stateman->setInputLayout(m_quadLayout); + D3D::stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); UINT stride = sizeof(QuadVertex); UINT offset = 0; - D3D::context->IASetVertexBuffers(0, 1, &m_quad, &stride, &offset); + D3D::stateman->setVertexBuffer(m_quad, stride, offset); EFBRectangle fullSrcRect; fullSrcRect.left = 0; @@ -1117,8 +1116,6 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, params.TexBottom = float(targetRect.bottom) / g_renderer->GetTargetHeight(); D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0); - D3D::context->VSSetConstantBuffers(0, 1, &m_encodeParams); - D3D::context->OMSetRenderTargets(1, &m_outRTV, nullptr); ID3D11ShaderResourceView* pEFB = (srcFormat == PEControl::Z24) ? @@ -1128,12 +1125,14 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, // expecting the blurred edges around multisampled shapes. FramebufferManager::GetResolvedEFBColorTexture()->GetSRV(); - D3D::context->PSSetConstantBuffers(0, 1, &m_encodeParams); - D3D::context->PSSetShaderResources(0, 1, &pEFB); - D3D::context->PSSetSamplers(0, 1, &m_efbSampler); + D3D::stateman->setVertexConstants(m_encodeParams); + D3D::stateman->setPixelConstants(m_encodeParams); + D3D::stateman->setTexture(0, pEFB); + D3D::stateman->setSampler(0, m_efbSampler); // Encode! + D3D::stateman->Apply(); D3D::context->Draw(4, 0); // Copy to staging buffer @@ -1143,23 +1142,20 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, // Clean up state - IUnknown* nullDummy = nullptr; - - D3D::context->PSSetSamplers(0, 1, (ID3D11SamplerState**)&nullDummy); - D3D::context->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&nullDummy); - D3D::context->PSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy); - D3D::context->OMSetRenderTargets(0, nullptr, nullptr); - D3D::context->VSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy); + D3D::stateman->setSampler(0, nullptr); + D3D::stateman->setTexture(0, nullptr); + D3D::stateman->setPixelConstants(nullptr); + D3D::stateman->setVertexConstants(nullptr); + + D3D::stateman->setPixelShader(nullptr); + D3D::stateman->setVertexBuffer(nullptr, 0, 0); D3D::stateman->PopRasterizerState(); D3D::stateman->PopDepthState(); D3D::stateman->PopBlendState(); - D3D::context->PSSetShader(nullptr, nullptr, 0); - D3D::context->VSSetShader(nullptr, nullptr, 0); - // Transfer staging buffer to GameCube/Wii RAM D3D11_MAPPED_SUBRESOURCE map = { 0 }; @@ -1276,7 +1272,7 @@ bool PSTextureEncoder::SetStaticShader(unsigned int dstFormat, PEControl::PixelF { if (it->second) { - D3D::context->PSSetShader(it->second, nullptr, 0); + D3D::stateman->setPixelShader(it->second); return true; } else @@ -1436,7 +1432,7 @@ bool PSTextureEncoder::SetDynamicShader(unsigned int dstFormat, if (m_generatorSlot != UINT(-1)) m_linkageArray[m_generatorSlot] = m_generatorClass[generatorNum]; - D3D::context->PSSetShader(m_dynamicShader, + D3D::stateman->setPixelShaderDynamic(m_dynamicShader, m_linkageArray.empty() ? nullptr : &m_linkageArray[0], (UINT)m_linkageArray.size()); diff --git a/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp b/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp index 732ef95749..de2d0cd016 100644 --- a/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp +++ b/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp @@ -6,6 +6,7 @@ #include "VideoBackends/D3D/D3DBase.h" #include "VideoBackends/D3D/D3DShader.h" +#include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/PointGeometryShader.h" #include "VideoCommon/VertexShaderGen.h" @@ -217,8 +218,8 @@ bool PointGeometryShader::SetShader(u32 components, float pointSize, DEBUG_LOG(VIDEO, "Point params: size %f, texOffset %f, vpWidth %f, vpHeight %f", pointSize, texOffset, vpWidth, vpHeight); - D3D::context->GSSetShader(shaderIt->second, nullptr, 0); - D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer); + D3D::stateman->setGeometryShader(shaderIt->second); + D3D::stateman->setGeometryConstants(m_paramsBuffer); return true; } diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 6adf3ac52f..455d34ea57 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -356,7 +356,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) // depth buffers can only be completely CopySubresourceRegion'ed, so we're using drawShadedTexQuad instead D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, 1.f, 1.f); D3D::context->RSSetViewports(1, &vp); - D3D::context->PSSetConstantBuffers(0, 1, &access_efb_cbuf); + D3D::stateman->setPixelConstants(0, access_efb_cbuf); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBDepthReadTexture()->GetRTV(), nullptr); D3D::SetPointCopySampler(); D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(), @@ -1006,15 +1006,12 @@ void Renderer::ApplyState(bool bUseDstAlpha) gx_state.raster.wireframe = g_ActiveConfig.bWireFrame; D3D::stateman->PushRasterizerState(gx_state_cache.Get(gx_state.raster)); - ID3D11SamplerState* samplerstate[8]; for (unsigned int stage = 0; stage < 8; stage++) { + // TODO: cache SamplerState directly, not d3d object gx_state.sampler[stage].max_anisotropy = g_ActiveConfig.iMaxAnisotropy; - samplerstate[stage] = gx_state_cache.Get(gx_state.sampler[stage]); + D3D::stateman->setSampler(stage, gx_state_cache.Get(gx_state.sampler[stage])); } - D3D::context->PSSetSamplers(0, 8, samplerstate); - - D3D::stateman->Apply(); if (bUseDstAlpha) { @@ -1023,12 +1020,14 @@ void Renderer::ApplyState(bool bUseDstAlpha) SetLogicOpMode(); } - ID3D11Buffer* const_buffers[2] = {PixelShaderCache::GetConstantBuffer(), VertexShaderCache::GetConstantBuffer()}; - D3D::context->PSSetConstantBuffers(0, 1 + g_ActiveConfig.bEnablePixelLighting, const_buffers); - D3D::context->VSSetConstantBuffers(0, 1, const_buffers+1); + ID3D11Buffer* vertexConstants = VertexShaderCache::GetConstantBuffer(); + ID3D11Buffer* pixelConstants = PixelShaderCache::GetConstantBuffer(); - D3D::context->PSSetShader(PixelShaderCache::GetActiveShader(), nullptr, 0); - D3D::context->VSSetShader(VertexShaderCache::GetActiveShader(), nullptr, 0); + D3D::stateman->setPixelConstants(pixelConstants, g_ActiveConfig.bEnablePixelLighting ? vertexConstants : nullptr); + D3D::stateman->setVertexConstants(vertexConstants); + + D3D::stateman->setPixelShader(PixelShaderCache::GetActiveShader()); + D3D::stateman->setVertexShader(VertexShaderCache::GetActiveShader()); } void Renderer::RestoreState() @@ -1045,8 +1044,6 @@ void Renderer::ApplyCullDisable() ID3D11RasterizerState* raststate = gx_state_cache.Get(rast); D3D::stateman->PushRasterizerState(raststate); - - D3D::stateman->Apply(); } void Renderer::RestoreCull() diff --git a/Source/Core/VideoBackends/D3D/Television.cpp b/Source/Core/VideoBackends/D3D/Television.cpp index 94904c8e1f..5a3b982645 100644 --- a/Source/Core/VideoBackends/D3D/Television.cpp +++ b/Source/Core/VideoBackends/D3D/Television.cpp @@ -7,6 +7,7 @@ #include "Core/HW/Memmap.h" #include "VideoBackends/D3D/D3DBase.h" #include "VideoBackends/D3D/D3DShader.h" +#include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/D3DUtil.h" #include "VideoBackends/D3D/Television.h" #include "VideoBackends/D3D/VertexShaderCache.h" @@ -150,7 +151,7 @@ void Television::Render() MathUtil::Rectangle sourceRc(0, 0, int(m_curWidth), int(m_curHeight)); MathUtil::Rectangle destRc(-1.f, 1.f, 1.f, -1.f); - D3D::context->PSSetSamplers(0, 1, &m_samplerState); + D3D::stateman->setSampler(0, m_samplerState); D3D::drawShadedTexSubQuad( m_yuyvTextureSRV, &sourceRc, diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index 773833ee18..06317ca66e 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -4,10 +4,11 @@ #include "Core/HW/Memmap.h" #include "VideoBackends/D3D/D3DBase.h" +#include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/D3DUtil.h" #include "VideoBackends/D3D/FramebufferManager.h" -#include "VideoBackends/D3D/PixelShaderCache.h" #include "VideoBackends/D3D/PSTextureEncoder.h" +#include "VideoBackends/D3D/PixelShaderCache.h" #include "VideoBackends/D3D/TextureCache.h" #include "VideoBackends/D3D/TextureEncoder.h" #include "VideoBackends/D3D/VertexShaderCache.h" @@ -29,7 +30,7 @@ TextureCache::TCacheEntry::~TCacheEntry() void TextureCache::TCacheEntry::Bind(unsigned int stage) { - D3D::context->PSSetShaderResources(stage, 1, &texture->GetSRV()); + D3D::stateman->setTexture(stage, texture->GetSRV()); } bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int level) @@ -143,7 +144,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid); D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture"); } - D3D::context->PSSetConstantBuffers(0, 1, &efbcopycbuf[cbufid]); + D3D::stateman->setPixelConstants(efbcopycbuf[cbufid]); const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect); // TODO: try targetSource.asRECT(); diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index a59ea63dea..f42c3a9845 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "VideoBackends/D3D/D3DBase.h" +#include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/PixelShaderCache.h" #include "VideoBackends/D3D/Render.h" #include "VideoBackends/D3D/VertexManager.h" @@ -127,17 +128,19 @@ void VertexManager::Draw(u32 stride) u32 components = VertexLoaderManager::GetCurrentVertexFormat()->m_components; u32 indices = IndexGenerator::GetIndexLen(); - u32 zero = 0; - D3D::context->IASetVertexBuffers(0, 1, &m_buffers[m_currentBuffer], &stride, &zero); - D3D::context->IASetIndexBuffer(m_buffers[m_currentBuffer], DXGI_FORMAT_R16_UINT, 0); + D3D::stateman->setVertexBuffer(m_buffers[m_currentBuffer], stride, 0); + D3D::stateman->setIndexBuffer(m_buffers[m_currentBuffer]); u32 baseVertex = m_vertexDrawOffset / stride; u32 startIndex = m_indexDrawOffset / sizeof(u16); if (current_primitive_type == PRIMITIVE_TRIANGLES) { - D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + D3D::stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + D3D::stateman->Apply(); D3D::context->DrawIndexed(indices, startIndex, baseVertex); + INCSTAT(stats.thisFrame.numDrawCalls); } else if (current_primitive_type == PRIMITIVE_LINES) @@ -156,11 +159,14 @@ void VertexManager::Draw(u32 stride) texOffset, vpWidth, vpHeight, texOffsetEnable)) { ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); // Disable culling for lines and points - D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); + D3D::stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); + + D3D::stateman->Apply(); D3D::context->DrawIndexed(indices, startIndex, baseVertex); + INCSTAT(stats.thisFrame.numDrawCalls); - D3D::context->GSSetShader(nullptr, nullptr, 0); + D3D::stateman->setGeometryShader(nullptr); ((DX11::Renderer*)g_renderer)->RestoreCull(); } } @@ -180,11 +186,15 @@ void VertexManager::Draw(u32 stride) texOffset, vpWidth, vpHeight, texOffsetEnable)) { ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); // Disable culling for lines and points - D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + + D3D::stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + + D3D::stateman->Apply(); D3D::context->DrawIndexed(indices, startIndex, baseVertex); + INCSTAT(stats.thisFrame.numDrawCalls); - D3D::context->GSSetShader(nullptr, nullptr, 0); + D3D::stateman->setGeometryShader(nullptr); ((DX11::Renderer*)g_renderer)->RestoreCull(); } } diff --git a/Source/Core/VideoBackends/D3D/XFBEncoder.cpp b/Source/Core/VideoBackends/D3D/XFBEncoder.cpp index 50524d8a3d..9f805d995c 100644 --- a/Source/Core/VideoBackends/D3D/XFBEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/XFBEncoder.cpp @@ -280,22 +280,21 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR // Set up all the state for XFB encoding - D3D::context->PSSetShader(m_pShader, nullptr, 0); - D3D::context->VSSetShader(m_vShader, nullptr, 0); + D3D::stateman->setPixelShader(m_pShader); + D3D::stateman->setVertexShader(m_vShader); D3D::stateman->PushBlendState(m_xfbEncodeBlendState); D3D::stateman->PushDepthState(m_xfbEncodeDepthState); D3D::stateman->PushRasterizerState(m_xfbEncodeRastState); - D3D::stateman->Apply(); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(width/2), FLOAT(height)); D3D::context->RSSetViewports(1, &vp); - D3D::context->IASetInputLayout(m_quadLayout); - D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + D3D::stateman->setInputLayout(m_quadLayout); + D3D::stateman->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); UINT stride = sizeof(QuadVertex); UINT offset = 0; - D3D::context->IASetVertexBuffers(0, 1, &m_quad, &stride, &offset); + D3D::stateman->setVertexBuffer(m_quad, stride, offset); TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(srcRect); @@ -309,18 +308,18 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR params.Gamma = gamma; D3D::context->UpdateSubresource(m_encodeParams, 0, nullptr, ¶ms, 0, 0); - D3D::context->VSSetConstantBuffers(0, 1, &m_encodeParams); - D3D::context->OMSetRenderTargets(1, &m_outRTV, nullptr); ID3D11ShaderResourceView* pEFB = FramebufferManager::GetEFBColorTexture()->GetSRV(); - D3D::context->PSSetConstantBuffers(0, 1, &m_encodeParams); - D3D::context->PSSetShaderResources(0, 1, &pEFB); - D3D::context->PSSetSamplers(0, 1, &m_efbSampler); + D3D::stateman->setVertexConstants(m_encodeParams); + D3D::stateman->setPixelConstants(m_encodeParams); + D3D::stateman->setTexture(0, pEFB); + D3D::stateman->setSampler(0, m_efbSampler); // Encode! + D3D::stateman->Apply(); D3D::context->Draw(4, 0); // Copy to staging buffer @@ -330,23 +329,20 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR // Clean up state - IUnknown* nullDummy = nullptr; - - D3D::context->PSSetSamplers(0, 1, (ID3D11SamplerState**)&nullDummy); - D3D::context->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&nullDummy); - D3D::context->PSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy); - D3D::context->OMSetRenderTargets(0, nullptr, nullptr); - D3D::context->VSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy); + D3D::stateman->setSampler(0, nullptr); + D3D::stateman->setTexture(0, nullptr); + D3D::stateman->setPixelConstants(nullptr); + D3D::stateman->setVertexConstants(nullptr); + + D3D::stateman->setPixelShader(nullptr); + D3D::stateman->setVertexShader(nullptr); D3D::stateman->PopRasterizerState(); D3D::stateman->PopDepthState(); D3D::stateman->PopBlendState(); - D3D::context->PSSetShader(nullptr, nullptr, 0); - D3D::context->VSSetShader(nullptr, nullptr, 0); - // Transfer staging buffer to GameCube/Wii RAM D3D11_MAPPED_SUBRESOURCE map = { 0 };