From cd6f00a3e58ccb81b94a2d1415da75c212c44389 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 25 Jan 2011 15:08:30 +0000 Subject: [PATCH] DX11 code maintenance, part 6: Move constant buffer management from EmuGfxState to Vertex/PixelShaderCache. Finally remove the EmuGfxState class, cheers! git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6915 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugins/Plugin_VideoDX11/Src/D3DBase.cpp | 2 - Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h | 1 + .../Plugins/Plugin_VideoDX11/Src/GfxState.cpp | 70 ------------------- .../Plugins/Plugin_VideoDX11/Src/GfxState.h | 38 ++-------- .../Plugin_VideoDX11/Src/PixelShaderCache.cpp | 49 ++++++++++--- .../Plugin_VideoDX11/Src/PixelShaderCache.h | 1 + .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 3 + .../Plugin_VideoDX11/Src/VertexManager.cpp | 2 - .../Src/VertexShaderCache.cpp | 50 +++++++++---- .../Plugin_VideoDX11/Src/VertexShaderCache.h | 1 + 10 files changed, 90 insertions(+), 127 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp index 6e95178182..287cf59f2c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp @@ -337,7 +337,6 @@ HRESULT Create(HWND wnd) device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support); bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; - gfxstate = new EmuGfxState; stateman = new StateManager; return S_OK; } @@ -348,7 +347,6 @@ void Close() context->ClearState(); SAFE_RELEASE(backbuf); SAFE_RELEASE(swapchain); - SAFE_DELETE(gfxstate); SAFE_DELETE(stateman); context->Flush(); // immediately destroy device objects diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h index e76617de15..8bb22f238c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h @@ -21,6 +21,7 @@ #include "Common.h" #include "D3DBlob.h" #include "GfxState.h" +#include #define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; } #define SAFE_DELETE(x) { delete (x); (x) = NULL; } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp index f3591ee361..10fc00d3f1 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp @@ -22,78 +22,8 @@ namespace D3D { -EmuGfxState* gfxstate; StateManager* stateman; -EmuGfxState::EmuGfxState() : apply_called(false) -{ - pscbuf = NULL; - vscbuf = NULL; - - pscbufchanged = false; - vscbufchanged = false; -} - -EmuGfxState::~EmuGfxState() -{ - SAFE_RELEASE(pscbuf); - SAFE_RELEASE(vscbuf); -} - -void EmuGfxState::ApplyState() -{ - HRESULT hr; - - // vertex shader - // TODO: divide the global variables of the generated shaders into about 5 constant buffers - // TODO: improve interaction between EmuGfxState and global state management, so that we don't need to set the constant buffers every time - if (!vscbuf) - { - unsigned int size = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16 - D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); - hr = device->CreateBuffer(&cbdesc, NULL, &vscbuf); - CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", size); - SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "a vertex shader constant buffer of EmuGfxState"); - } - if (vscbufchanged) - { - D3D11_MAPPED_SUBRESOURCE map; - context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - memcpy(map.pData, vsconstants, sizeof(vsconstants)); - context->Unmap(vscbuf, 0); - vscbufchanged = false; - } - D3D::context->VSSetConstantBuffers(0, 1, &vscbuf); - - // pixel shader - if (!pscbuf) - { - unsigned int size = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16 - D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(size, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); - device->CreateBuffer(&cbdesc, NULL, &pscbuf); - CHECK(hr==S_OK, "Create pixel shader constant buffer (size=%u)", size); - SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "a pixel shader constant buffer of EmuGfxState"); - } - if (pscbufchanged) - { - D3D11_MAPPED_SUBRESOURCE map; - context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - memcpy(map.pData, psconstants, sizeof(psconstants)); - context->Unmap(pscbuf, 0); - pscbufchanged = false; - } - D3D::context->PSSetConstantBuffers(0, 1, &pscbuf); - - apply_called = true; -} - -void EmuGfxState::Reset() -{ - if (apply_called) - { - apply_called = false; - } -} template AutoState::AutoState(const T* object) : state(object) { diff --git a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h index 35d11189b1..bbdc18f724 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h @@ -17,38 +17,15 @@ #pragma once -#include "D3DBase.h" -#include "VertexShaderGen.h" -#include "PixelShaderGen.h" #include -using std::stack; + +struct ID3D11BlendState; +struct ID3D11DepthStencilState; +struct ID3D11RasterizerState; namespace D3D { -// stores the pipeline state to use when calling VertexManager::Flush() -class EmuGfxState -{ -public: - EmuGfxState(); - ~EmuGfxState(); - - void ApplyState(); // apply current state - void Reset(); - - - float psconstants[C_PENVCONST_END*4]; - float vsconstants[C_VENVCONST_END*4]; - bool vscbufchanged; - bool pscbufchanged; - -private: - ID3D11Buffer* vscbuf; - ID3D11Buffer* pscbuf; - - bool apply_called; -}; - template class AutoState { public: @@ -85,15 +62,14 @@ public: void Apply(); private: - stack blendstates; - stack depthstates; - stack raststates; + std::stack blendstates; + std::stack depthstates; + std::stack raststates; ID3D11BlendState* cur_blendstate; ID3D11DepthStencilState* cur_depthstate; ID3D11RasterizerState* cur_raststate; }; -extern EmuGfxState* gfxstate; extern StateManager* stateman; } // namespace diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp index 23e01af3bf..d4821bc854 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp @@ -46,6 +46,10 @@ ID3D11PixelShader* s_ColorCopyProgram[2] = {NULL}; ID3D11PixelShader* s_DepthMatrixProgram[2] = {NULL}; ID3D11PixelShader* s_ClearProgram = NULL; +float psconstants[C_PENVCONST_END*4]; +bool pscbufchanged = true; +ID3D11Buffer* pscbuf = NULL; + const char clear_program_code[] = { "void main(\n" "out float4 ocol0 : SV_Target,\n" @@ -157,6 +161,7 @@ ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram(bool multisampled) else if (s_ColorCopyProgram[1]) return s_ColorCopyProgram[1]; else { + // TODO: recreate shader on AA mode change! // create MSAA shader for current AA mode char buf[1024]; int l = sprintf_s(buf, 1024, color_copy_program_code_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode)); @@ -173,6 +178,7 @@ ID3D11PixelShader* PixelShaderCache::GetColorMatrixProgram(bool multisampled) else if (s_ColorMatrixProgram[1]) return s_ColorMatrixProgram[1]; else { + // TODO: recreate shader on AA mode change! // create MSAA shader for current AA mode char buf[1024]; int l = sprintf_s(buf, 1024, color_matrix_program_code_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode)); @@ -189,6 +195,7 @@ ID3D11PixelShader* PixelShaderCache::GetDepthMatrixProgram(bool multisampled) else if (s_DepthMatrixProgram[1]) return s_DepthMatrixProgram[1]; else { + // TODO: recreate shader on AA mode change! // create MSAA shader for current AA mode char buf[1024]; int l = sprintf_s(buf, 1024, depth_matrix_program_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode)); @@ -228,23 +235,37 @@ unsigned int ps_constant_offset_table[] = { }; void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { - D3D::gfxstate->psconstants[ps_constant_offset_table[const_number] ] = f1; - D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+1] = f2; - D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+2] = f3; - D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]+3] = f4; - D3D::gfxstate->pscbufchanged = true; + psconstants[ps_constant_offset_table[const_number] ] = f1; + psconstants[ps_constant_offset_table[const_number]+1] = f2; + psconstants[ps_constant_offset_table[const_number]+2] = f3; + psconstants[ps_constant_offset_table[const_number]+3] = f4; + pscbufchanged = true; } void SetPSConstant4fv(unsigned int const_number, const float* f) { - memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4); - D3D::gfxstate->pscbufchanged = true; + memcpy(&psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4); + pscbufchanged = true; } void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float* f) { - memcpy(&D3D::gfxstate->psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4*count); - D3D::gfxstate->pscbufchanged = true; + memcpy(&psconstants[ps_constant_offset_table[const_number]], f, sizeof(float)*4*count); + pscbufchanged = true; +} + +ID3D11Buffer* &PixelShaderCache::GetConstantBuffer() +{ + // TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up + if (pscbufchanged) + { + D3D11_MAPPED_SUBRESOURCE map; + D3D::context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + memcpy(map.pData, psconstants, sizeof(psconstants)); + D3D::context->Unmap(pscbuf, 0); + pscbufchanged = false; + } + return pscbuf; } // this class will load the precompiled shaders into our cache @@ -259,6 +280,12 @@ public: void PixelShaderCache::Init() { + unsigned int cbsize = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16 + D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); + D3D::device->CreateBuffer(&cbdesc, NULL, &pscbuf); + CHECK(pscbuf!=NULL, "Create pixel shader constant buffer"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "pixel shader constant buffer used to emulate the GX pipeline"); + // used when drawing clear quads s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, sizeof(clear_program_code)); CHECK(s_ClearProgram!=NULL, "Create clear pixel shader"); @@ -311,6 +338,8 @@ void PixelShaderCache::InvalidateMSAAShaders() void PixelShaderCache::Shutdown() { + SAFE_RELEASE(pscbuf); + SAFE_RELEASE(s_ClearProgram); for (int i = 0; i < 2; ++i) { @@ -356,7 +385,7 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) const char* code = GeneratePixelShaderCode(dstAlphaMode, API_D3D11, components); D3DBlob* pbytecode; - if (!D3D::CompilePixelShader(code, strlen(code), &pbytecode)) + if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode)) { PanicAlert("Failed to compile Pixel Shader:\n\n%s", code); GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h index 3ff52fc23a..7a1b96288e 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h @@ -36,6 +36,7 @@ public: static bool InsertByteCode(const PIXELSHADERUID &uid, const void* bytecode, unsigned int bytecodelen); static ID3D11PixelShader* GetActiveShader() { return last_entry->shader; } + static ID3D11Buffer* &GetConstantBuffer(); static ID3D11PixelShader* GetColorMatrixProgram(bool multisampled); static ID3D11PixelShader* GetColorCopyProgram(bool multisampled); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index f504e2d94b..ea026ed4ee 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -1233,6 +1233,9 @@ void Renderer::ApplyState(bool bUseDstAlpha) SetLogicOpMode(); } + D3D::context->PSSetConstantBuffers(0, 1, &PixelShaderCache::GetConstantBuffer()); + D3D::context->VSSetConstantBuffers(0, 1, &VertexShaderCache::GetConstantBuffer()); + D3D::context->PSSetShader(PixelShaderCache::GetActiveShader(), NULL, 0); D3D::context->VSSetShader(VertexShaderCache::GetActiveShader(), NULL, 0); } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index d07d4eca38..c2b17c34c8 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -228,7 +228,6 @@ void VertexManager::vFlush() unsigned int stride = g_nativeVertexFmt->GetVertexStride(); g_nativeVertexFmt->SetupVertexPointers(); - D3D::gfxstate->ApplyState(); g_renderer->ApplyState(useDstAlpha); LoadBuffers(); Draw(stride); @@ -236,7 +235,6 @@ void VertexManager::vFlush() GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); g_renderer->RestoreState(); - D3D::gfxstate->Reset(); shader_fail: ResetBuffer(); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp index a5fe2dbaa0..4bbd686e15 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp @@ -48,37 +48,55 @@ ID3D11VertexShader* VertexShaderCache::GetClearVertexShader() { return ClearVert ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout() { return SimpleLayout; } ID3D11InputLayout* VertexShaderCache::GetClearInputLayout() { return ClearLayout; } +float vsconstants[C_VENVCONST_END*4]; +bool vscbufchanged = true; +ID3D11Buffer* vscbuf = NULL; + // maps the constant numbers to float indices in the constant buffer unsigned int vs_constant_offset_table[C_VENVCONST_END]; void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { - D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number] ] = f1; - D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+1] = f2; - D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+2] = f3; - D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]+3] = f4; - D3D::gfxstate->vscbufchanged = true; + vsconstants[vs_constant_offset_table[const_number] ] = f1; + vsconstants[vs_constant_offset_table[const_number]+1] = f2; + vsconstants[vs_constant_offset_table[const_number]+2] = f3; + vsconstants[vs_constant_offset_table[const_number]+3] = f4; + vscbufchanged = true; } void SetVSConstant4fv(unsigned int const_number, const float* f) { - memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4); - D3D::gfxstate->vscbufchanged = true; + memcpy(&vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4); + vscbufchanged = true; } void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float* f) { for (unsigned int i = 0; i < count; i++) { - memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]], f+3*i, sizeof(float)*3); - D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number+i]+3] = 0.f; + memcpy(&vsconstants[vs_constant_offset_table[const_number+i]], f+3*i, sizeof(float)*3); + vsconstants[vs_constant_offset_table[const_number+i]+3] = 0.f; } - D3D::gfxstate->vscbufchanged = true; + vscbufchanged = true; } void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float* f) { - memcpy(&D3D::gfxstate->vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4*count); - D3D::gfxstate->vscbufchanged = true; + memcpy(&vsconstants[vs_constant_offset_table[const_number]], f, sizeof(float)*4*count); + vscbufchanged = true; +} + +ID3D11Buffer* &VertexShaderCache::GetConstantBuffer() +{ + // TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up + if (vscbufchanged) + { + D3D11_MAPPED_SUBRESOURCE map; + D3D::context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + memcpy(map.pData, vsconstants, sizeof(vsconstants)); + D3D::context->Unmap(vscbuf, 0); + vscbufchanged = false; + } + return vscbuf; } // this class will load the precompiled shaders into our cache @@ -140,6 +158,12 @@ void VertexShaderCache::Init() { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; + unsigned int cbsize = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16 + D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); + HRESULT hr = D3D::device->CreateBuffer(&cbdesc, NULL, &vscbuf); + CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", cbsize); + D3D::SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "vertex shader constant buffer used to emulate the GX pipeline"); + D3DBlob* blob; D3D::CompileVertexShader(simple_shader_code, sizeof(simple_shader_code), &blob); D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout); @@ -193,6 +217,8 @@ void VertexShaderCache::Clear() void VertexShaderCache::Shutdown() { + SAFE_RELEASE(vscbuf); + SAFE_RELEASE(SimpleVertexShader); SAFE_RELEASE(ClearVertexShader); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h index a44ccda1df..e52abee815 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.h @@ -32,6 +32,7 @@ public: static ID3D11VertexShader* GetActiveShader() { return last_entry->shader; } static D3DBlob* GetActiveShaderBytecode() { return last_entry->bytecode; } + static ID3D11Buffer* &GetConstantBuffer(); static ID3D11VertexShader* GetSimpleVertexShader(); static ID3D11VertexShader* GetClearVertexShader();