From e0b757fe6ab56f95b4d8d884a204aad48d6ac823 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 24 Jan 2011 08:44:32 +0000 Subject: [PATCH] DX11 code maintenance, part 1: Move sampler state/shader resource management from EmuGfxState to Renderer. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6902 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/VideoCommon/Src/RenderBase.h | 3 + .../Plugins/Plugin_VideoDX11/Src/GfxState.cpp | 44 ---------- .../Plugins/Plugin_VideoDX11/Src/GfxState.h | 7 -- .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 81 ++++++++++++++----- Source/Plugins/Plugin_VideoDX11/Src/Render.h | 3 + .../Plugin_VideoDX11/Src/TextureCache.cpp | 2 +- .../Plugin_VideoDX11/Src/VertexManager.cpp | 6 +- Source/Plugins/Plugin_VideoDX9/Src/Render.h | 4 + Source/Plugins/Plugin_VideoOGL/Src/Render.h | 4 + 9 files changed, 79 insertions(+), 75 deletions(-) diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 1d265083d9..d7ddbe5112 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -66,6 +66,9 @@ public: virtual void SetSamplerState(int stage,int texindex) = 0; virtual void SetInterlacingMode() = 0; + virtual void ApplyState() = 0; + virtual void UnsetTextures() = 0; + // Real internal resolution: // D3D doesn't support viewports larger than the target size, so we need to resize the target to the viewport size for those. // OpenGL supports this, so GetFullTargetWidth returns the same as GetTargetWidth there. diff --git a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp index 070793f278..39a09169b0 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp @@ -26,14 +26,6 @@ StateManager* stateman; EmuGfxState::EmuGfxState() : vertexshader(NULL), vsbytecode(NULL), pixelshader(NULL), psbytecode(NULL), apply_called(false) { - for (unsigned int k = 0;k < 8;k++) - { - float border[4] = {0.f, 0.f, 0.f, 0.f}; - shader_resources[k] = NULL; - samplerdesc[k] = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, 0.f, 16, D3D11_COMPARISON_ALWAYS, border, -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX); - if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[k].Filter = D3D11_FILTER_ANISOTROPIC; - } - m_useDstAlpha = false; memset(&blenddesc, 0, sizeof(blenddesc)); @@ -71,9 +63,6 @@ EmuGfxState::EmuGfxState() : vertexshader(NULL), vsbytecode(NULL), pixelshader(N EmuGfxState::~EmuGfxState() { - for (unsigned int k = 0;k < 8;k++) - SAFE_RELEASE(shader_resources[k]); - SAFE_RELEASE(vsbytecode); SAFE_RELEASE(psbytecode); SAFE_RELEASE(vertexshader); @@ -119,13 +108,6 @@ void EmuGfxState::SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT n memcpy(inp_elems, elems, num*sizeof(D3D11_INPUT_ELEMENT_DESC)); } -void EmuGfxState::SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv) -{ - if (shader_resources[stage]) shader_resources[stage]->Release(); - shader_resources[stage] = srv; - if (srv) srv->AddRef(); -} - void EmuGfxState::ApplyState() { HRESULT hr; @@ -181,22 +163,6 @@ void EmuGfxState::ApplyState() } D3D::context->PSSetConstantBuffers(0, 1, &pscbuf); - ID3D11SamplerState* samplerstate[8]; - for (unsigned int stage = 0; stage < 8; stage++) - { - if (shader_resources[stage]) - { - if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[stage].Filter = D3D11_FILTER_ANISOTROPIC; - hr = D3D::device->CreateSamplerState(&samplerdesc[stage], &samplerstate[stage]); - if (FAILED(hr)) PanicAlert("Fail %s %d, stage=%d\n", __FILE__, __LINE__, stage); - else SetDebugObjectName((ID3D11DeviceChild*)samplerstate[stage], "a sampler state of EmuGfxState"); - } - else samplerstate[stage] = NULL; - } - D3D::context->PSSetSamplers(0, 8, samplerstate); - for (unsigned int stage = 0; stage < 8; stage++) - SAFE_RELEASE(samplerstate[stage]); - ID3D11BlendState* blstate; hr = device->CreateBlendState(&blenddesc, &blstate); if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__); @@ -221,7 +187,6 @@ void EmuGfxState::ApplyState() context->PSSetShader(pixelshader, NULL, 0); context->VSSetShader(vertexshader, NULL, 0); - context->PSSetShaderResources(0, 8, shader_resources); stateman->Apply(); apply_called = true; @@ -229,10 +194,6 @@ void EmuGfxState::ApplyState() void EmuGfxState::Reset() { - for (unsigned int k = 0;k < 8;k++) - SAFE_RELEASE(shader_resources[k]); - - context->PSSetShaderResources(0, 8, shader_resources); // unbind all textures if (apply_called) { stateman->PopBlendState(); @@ -345,11 +306,6 @@ void EmuGfxState::SetDstAlpha(bool enable) SetBlendOp(blenddesc.RenderTarget[0].BlendOp); } -void EmuGfxState::SetSamplerFilter(DWORD stage, D3D11_FILTER filter) -{ - samplerdesc[stage].Filter = filter; -} - template AutoState::AutoState(const T* object) : state(object) { ((IUnknown*)state)->AddRef(); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h index 90151a7905..b4f20f3afc 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h @@ -36,7 +36,6 @@ public: void SetVShader(ID3D11VertexShader* shader, D3DBlob* bcode); void SetPShader(ID3D11PixelShader* shader); void SetInputElements(const D3D11_INPUT_ELEMENT_DESC* elems, UINT num); - void SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv); void ApplyState(); // apply current state void Reset(); @@ -50,12 +49,7 @@ public: void SetDstAlpha(bool enable); - // sampler states - void SetSamplerFilter(DWORD stage, D3D11_FILTER filter); - // TODO: add methods for changing the other states instead of modifying them directly - - D3D11_SAMPLER_DESC samplerdesc[8]; D3D11_RASTERIZER_DESC rastdesc; D3D11_DEPTH_STENCIL_DESC depthdesc; @@ -78,7 +72,6 @@ private: D3D11_INPUT_ELEMENT_DESC inp_elems[32]; int num_inp_elems; - ID3D11ShaderResourceView* shader_resources[8]; D3D11_BLEND_DESC blenddesc; bool m_useDstAlpha; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 191ff0b75b..f269b21fbe 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -64,6 +64,12 @@ ID3D11BlendState* resetblendstate = NULL; ID3D11DepthStencilState* resetdepthstate = NULL; ID3D11RasterizerState* resetraststate = NULL; +// GX pipeline state +struct +{ + D3D11_SAMPLER_DESC sampdc[8]; +} gx_state; + bool reset_called = false; // State translation lookup tables @@ -338,9 +344,18 @@ Renderer::Renderer() SetupDeviceObjects(); - for (unsigned int stage = 0; stage < 8; stage++) - D3D::gfxstate->samplerdesc[stage].MaxAnisotropy = g_ActiveConfig.iMaxAnisotropy; + // Setup GX pipeline state + for (unsigned int k = 0;k < 8;k++) + { + float border[4] = {0.f, 0.f, 0.f, 0.f}; + gx_state.sampdc[k] = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, D3D11_TEXTURE_ADDRESS_CLAMP, + 0.f, 1 << g_ActiveConfig.iMaxAnisotropy, + D3D11_COMPARISON_ALWAYS, border, + -D3D11_FLOAT32_MAX, D3D11_FLOAT32_MAX); + if(g_ActiveConfig.iMaxAnisotropy != 0) gx_state.sampdc[k].Filter = D3D11_FILTER_ANISOTROPIC; + } + // Clear EFB textures float ClearColor[4] = { 0.f, 0.f, 0.f, 1.f }; D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), ClearColor); D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0); @@ -1073,6 +1088,32 @@ void Renderer::RestoreAPIState() reset_called = false; } +void Renderer::ApplyState() +{ + ID3D11SamplerState* samplerstate[8]; + for (unsigned int stage = 0; stage < 8; stage++) + { + // TODO: unnecessary state changes, we should store a list of shader resources + //if (shader_resources[stage]) + { + if(g_ActiveConfig.iMaxAnisotropy > 0) gx_state.sampdc[stage].Filter = D3D11_FILTER_ANISOTROPIC; + HRESULT hr = D3D::device->CreateSamplerState(&gx_state.sampdc[stage], &samplerstate[stage]); + if (FAILED(hr)) PanicAlert("Fail %s %d, stage=%d\n", __FILE__, __LINE__, stage); + else D3D::SetDebugObjectName((ID3D11DeviceChild*)samplerstate[stage], "sampler state used to emulate the GX pipeline"); + } + // else samplerstate[stage] = NULL; + } + D3D::context->PSSetSamplers(0, 8, samplerstate); + for (unsigned int stage = 0; stage < 8; stage++) + SAFE_RELEASE(samplerstate[stage]); +} + +void Renderer::UnsetTextures() +{ + ID3D11ShaderResourceView* shader_resources[8] = { NULL }; + D3D::context->PSSetShaderResources(0, 8, shader_resources); +} + void Renderer::SetGenerationMode() { // rastdesc.FrontCounterClockwise must be false for this to work @@ -1137,45 +1178,45 @@ void Renderer::SetSamplerState(int stage, int texindex) // NOTE: since there's no "no filter" in DX11 we're using point filters in these cases if (g_ActiveConfig.bForceFiltering) { - D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_MAG_MIP_LINEAR); + gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; } else if (tm0.min_filter & 4) // linear min filter { if (tm0.mag_filter) // linear mag filter { - if (mip == TEXF_NONE) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT); - else if (mip == TEXF_POINT) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT); - else if (mip == TEXF_LINEAR) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_MAG_MIP_LINEAR); + if (mip == TEXF_NONE) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + else if (mip == TEXF_POINT) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + else if (mip == TEXF_LINEAR) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; } else // point mag filter { - if (mip == TEXF_NONE) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT); - else if (mip == TEXF_POINT) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT); - else if (mip == TEXF_LINEAR) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR); + if (mip == TEXF_NONE) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; + else if (mip == TEXF_POINT) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; + else if (mip == TEXF_LINEAR) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; } } else // point min filter { if (tm0.mag_filter) // linear mag filter { - if (mip == TEXF_NONE) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT); - else if (mip == TEXF_POINT) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT); - else if (mip == TEXF_LINEAR) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR); + if (mip == TEXF_NONE) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; + else if (mip == TEXF_POINT) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; + else if (mip == TEXF_LINEAR) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; } else // point mag filter { - if (mip == TEXF_NONE) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_MAG_MIP_POINT); - else if (mip == TEXF_POINT) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_MAG_MIP_POINT); - else if (mip == TEXF_LINEAR) D3D::gfxstate->SetSamplerFilter(stage, D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR); + if (mip == TEXF_NONE) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + else if (mip == TEXF_POINT) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + else if (mip == TEXF_LINEAR) gx_state.sampdc[stage].Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; } } - D3D::gfxstate->samplerdesc[stage].AddressU = d3dClamps[tm0.wrap_s]; - D3D::gfxstate->samplerdesc[stage].AddressV = d3dClamps[tm0.wrap_t]; + gx_state.sampdc[stage].AddressU = d3dClamps[tm0.wrap_s]; + gx_state.sampdc[stage].AddressV = d3dClamps[tm0.wrap_t]; - D3D::gfxstate->samplerdesc[stage].MipLODBias = (float)tm0.lod_bias/32.0f; - D3D::gfxstate->samplerdesc[stage].MaxLOD = (float)tm1.max_lod/16.f; - D3D::gfxstate->samplerdesc[stage].MinLOD = (float)tm1.min_lod/16.f; + gx_state.sampdc[stage].MipLODBias = (float)tm0.lod_bias/32.0f; + gx_state.sampdc[stage].MaxLOD = (float)tm1.max_lod/16.f; + gx_state.sampdc[stage].MinLOD = (float)tm1.min_lod/16.f; } void Renderer::SetInterlacingMode() diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.h b/Source/Plugins/Plugin_VideoDX11/Src/Render.h index db052b7e59..5ee6f1b4cc 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.h @@ -24,6 +24,9 @@ public: void SetSamplerState(int stage,int texindex); void SetInterlacingMode(); + void ApplyState(); + void UnsetTextures(); + void RenderText(const char* pstr, int left, int top, u32 color); u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index f51512282f..5a1dd79219 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -53,7 +53,7 @@ TextureCache::TCacheEntry::~TCacheEntry() void TextureCache::TCacheEntry::Bind(unsigned int stage) { - D3D::gfxstate->SetShaderResource(stage, texture->GetSRV()); + D3D::context->PSSetShaderResources(stage, 1, &texture->GetSRV()); } bool TextureCache::TCacheEntry::Save(const char filename[]) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index 184cd83958..f49f99a887 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -139,8 +139,6 @@ void VertexManager::LoadBuffers() void VertexManager::Draw(UINT stride) { - D3D::gfxstate->ApplyState(); - D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &m_vertexDrawOffset); D3D::context->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0); @@ -232,9 +230,11 @@ void VertexManager::vFlush() unsigned int stride = g_nativeVertexFmt->GetVertexStride(); g_nativeVertexFmt->SetupVertexPointers(); + D3D::gfxstate->ApplyState(); + g_renderer->ApplyState(); LoadBuffers(); Draw(stride); - + g_renderer->UnsetTextures(); D3D::gfxstate->Reset(); GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.h b/Source/Plugins/Plugin_VideoDX9/Src/Render.h index 967e996634..b13488744e 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.h @@ -24,6 +24,10 @@ public: void SetSamplerState(int stage,int texindex); void SetInterlacingMode(); + // No need to implement these in D3D9 + void ApplyState() {} + void UnsetTextures() {} + void RenderText(const char* pstr, int left, int top, u32 color); u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.h b/Source/Plugins/Plugin_VideoOGL/Src/Render.h index 37bfd28d2e..17e92b473f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.h @@ -24,6 +24,10 @@ public: void SetSamplerState(int stage,int texindex); void SetInterlacingMode(); + // No need to implement these in OGL + void ApplyState() {} + void UnsetTextures() {} + void RenderText(const char* pstr, int left, int top, u32 color); void DrawDebugInfo(); void FlipImageData(u8 *data, int w, int h);