From 5c9bc8b79c0d1049dc021e4c7c7148fa26b46c05 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 30 Apr 2017 00:54:22 +1000 Subject: [PATCH] D3D11: Use blending state from VideoCommon --- Source/Core/VideoBackends/D3D/D3DState.cpp | 80 ++++------ Source/Core/VideoBackends/D3D/D3DState.h | 16 +- Source/Core/VideoBackends/D3D/Render.cpp | 169 +-------------------- Source/Core/VideoBackends/D3D/Render.h | 2 - 4 files changed, 37 insertions(+), 230 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DState.cpp b/Source/Core/VideoBackends/D3D/D3DState.cpp index f0f583e95b..67536a4fa3 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.cpp +++ b/Source/Core/VideoBackends/D3D/D3DState.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "Common/BitSet.h" #include "Common/CommonTypes.h" @@ -351,72 +352,51 @@ ID3D11SamplerState* StateCache::Get(SamplerState state) return res; } -ID3D11BlendState* StateCache::Get(BlendState state) +ID3D11BlendState* StateCache::Get(BlendingState state) { - if (!state.blend_enable) - { - state.src_blend = D3D11_BLEND_ONE; - state.dst_blend = D3D11_BLEND_ZERO; - state.blend_op = D3D11_BLEND_OP_ADD; - state.use_dst_alpha = false; - } - - auto it = m_blend.find(state.packed); - + auto it = m_blend.find(state.hex); if (it != m_blend.end()) return it->second; - D3D11_BLEND_DESC blenddc = CD3D11_BLEND_DESC(CD3D11_DEFAULT()); + D3D11_BLEND_DESC desc = {}; + desc.AlphaToCoverageEnable = FALSE; + desc.IndependentBlendEnable = FALSE; - blenddc.AlphaToCoverageEnable = FALSE; - blenddc.IndependentBlendEnable = FALSE; - blenddc.RenderTarget[0].BlendEnable = state.blend_enable; - blenddc.RenderTarget[0].RenderTargetWriteMask = (u32)state.write_mask; - blenddc.RenderTarget[0].SrcBlend = state.src_blend; - blenddc.RenderTarget[0].DestBlend = state.dst_blend; - blenddc.RenderTarget[0].BlendOp = state.blend_op; - blenddc.RenderTarget[0].SrcBlendAlpha = state.src_blend; - blenddc.RenderTarget[0].DestBlendAlpha = state.dst_blend; - blenddc.RenderTarget[0].BlendOpAlpha = state.blend_op; + D3D11_RENDER_TARGET_BLEND_DESC& tdesc = desc.RenderTarget[0]; + tdesc.BlendEnable = state.blendenable; - if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_SRC_COLOR) - blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC1_ALPHA; - else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_INV_SRC_COLOR) - blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; - else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_DEST_COLOR) - blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA; - else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_INV_DEST_COLOR) - blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; + if (state.colorupdate) + tdesc.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | + D3D11_COLOR_WRITE_ENABLE_BLUE; else - blenddc.RenderTarget[0].SrcBlendAlpha = blenddc.RenderTarget[0].SrcBlend; + tdesc.RenderTargetWriteMask = 0; + if (state.alphaupdate) + tdesc.RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; - if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_SRC_COLOR) - blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC1_ALPHA; - else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_SRC_COLOR) - blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; - else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_DEST_COLOR) - blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA; - else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_DEST_COLOR) - blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; - else - blenddc.RenderTarget[0].DestBlendAlpha = blenddc.RenderTarget[0].DestBlend; + static constexpr std::array src_factors = { + {D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_INV_DEST_COLOR, + D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_INV_SRC1_ALPHA, D3D11_BLEND_DEST_ALPHA, + D3D11_BLEND_INV_DEST_ALPHA}}; + static constexpr std::array dst_factors = { + {D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_SRC_COLOR, D3D11_BLEND_INV_SRC_COLOR, + D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_INV_SRC1_ALPHA, D3D11_BLEND_DEST_ALPHA, + D3D11_BLEND_INV_DEST_ALPHA}}; - if (state.use_dst_alpha) - { - blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; - blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; - blenddc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - } + tdesc.SrcBlend = src_factors[state.srcfactor]; + tdesc.SrcBlendAlpha = src_factors[state.srcfactoralpha]; + tdesc.DestBlend = dst_factors[state.dstfactor]; + tdesc.DestBlendAlpha = dst_factors[state.dstfactoralpha]; + tdesc.BlendOp = state.subtract ? D3D11_BLEND_OP_REV_SUBTRACT : D3D11_BLEND_OP_ADD; + tdesc.BlendOpAlpha = state.subtractAlpha ? D3D11_BLEND_OP_REV_SUBTRACT : D3D11_BLEND_OP_ADD; ID3D11BlendState* res = nullptr; - HRESULT hr = D3D::device->CreateBlendState(&blenddc, &res); + HRESULT hr = D3D::device->CreateBlendState(&desc, &res); if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__); D3D::SetDebugObjectName(res, "blend state used to emulate the GX pipeline"); - m_blend.emplace(state.packed, res); - + m_blend.emplace(state.hex, res); return res; } diff --git a/Source/Core/VideoBackends/D3D/D3DState.h b/Source/Core/VideoBackends/D3D/D3DState.h index f09bb22bb2..6b3838c661 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.h +++ b/Source/Core/VideoBackends/D3D/D3DState.h @@ -12,7 +12,7 @@ #include "Common/BitField.h" #include "Common/CommonTypes.h" #include "VideoBackends/D3D/D3DBase.h" -#include "VideoCommon/BPMemory.h" +#include "VideoCommon/RenderState.h" struct ID3D11BlendState; struct ID3D11DepthStencilState; @@ -27,18 +27,6 @@ union RasterizerState u32 packed; }; -union BlendState -{ - BitField<0, 1, u32> blend_enable; - BitField<1, 3, D3D11_BLEND_OP> blend_op; - BitField<4, 4, u32> write_mask; - BitField<8, 5, D3D11_BLEND> src_blend; - BitField<13, 5, D3D11_BLEND> dst_blend; - BitField<18, 1, u32> use_dst_alpha; - - u32 packed; -}; - union SamplerState { BitField<0, 3, u64> min_filter; @@ -59,7 +47,7 @@ public: // Get existing or create new render state. // Returned objects is owned by the cache and does not need to be released. ID3D11SamplerState* Get(SamplerState state); - ID3D11BlendState* Get(BlendState state); + ID3D11BlendState* Get(BlendingState state); ID3D11RasterizerState* Get(RasterizerState state); ID3D11DepthStencilState* Get(ZMode state); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 157c2218d7..6551cadf60 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -36,6 +36,7 @@ #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/PixelEngine.h" #include "VideoCommon/PixelShaderManager.h" +#include "VideoCommon/RenderState.h" #include "VideoCommon/SamplerCommon.h" #include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoConfig.h" @@ -58,7 +59,7 @@ typedef struct _Nv_Stereo_Image_Header struct GXPipelineState { std::array samplers; - BlendState blend; + BlendingState blend; ZMode zmode; RasterizerState raster; }; @@ -247,17 +248,8 @@ Renderer::Renderer() : ::Renderer(D3D::GetBackBufferWidth(), D3D::GetBackBufferH SetupDeviceObjects(); // Setup GX pipeline state - s_gx_state.blend.blend_enable = false; - s_gx_state.blend.write_mask = D3D11_COLOR_WRITE_ENABLE_ALL; - s_gx_state.blend.src_blend = D3D11_BLEND_ONE; - s_gx_state.blend.dst_blend = D3D11_BLEND_ZERO; - s_gx_state.blend.blend_op = D3D11_BLEND_OP_ADD; - s_gx_state.blend.use_dst_alpha = false; - for (auto& sampler : s_gx_state.samplers) - { sampler.packed = 0; - } s_gx_state.zmode.testenable = false; s_gx_state.zmode.updateenable = false; @@ -329,21 +321,6 @@ void Renderer::SetScissorRect(const EFBRectangle& rc) D3D::context->RSSetScissorRects(1, trc.AsRECT()); } -void Renderer::SetColorMask() -{ - // Only enable alpha channel if it's supported by the current EFB format - UINT8 color_mask = 0; - if (bpmem.alpha_test.TestResult() != AlphaTest::FAIL) - { - if (bpmem.blendmode.alphaupdate && (bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24)) - color_mask = D3D11_COLOR_WRITE_ENABLE_ALPHA; - if (bpmem.blendmode.colorupdate) - color_mask |= D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | - D3D11_COLOR_WRITE_ENABLE_BLUE; - } - s_gx_state.blend.write_mask = color_mask; -} - // This function allows the CPU to directly access the EFB. // There are EFB peeks (which will read the color or depth of a pixel) // and EFB pokes (which will change the color or depth of a pixel). @@ -665,44 +642,9 @@ void Renderer::ReinterpretPixelData(unsigned int convtype) void Renderer::SetBlendMode(bool forceUpdate) { - // Our render target always uses an alpha channel, so we need to override the blend functions to - // assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel - // Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel - // is assumed to always be 1. - bool target_has_alpha = bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24; - const std::array d3d_src_factors{{ - D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_INV_DEST_COLOR, - D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_INV_SRC1_ALPHA, - (target_has_alpha) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE, - (target_has_alpha) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO, - }}; - const std::array d3d_dest_factors{{ - D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_SRC_COLOR, D3D11_BLEND_INV_SRC_COLOR, - D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_INV_SRC1_ALPHA, - (target_has_alpha) ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_ONE, - (target_has_alpha) ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_ZERO, - }}; - - if (bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable && !forceUpdate) - return; - - if (bpmem.blendmode.subtract) - { - s_gx_state.blend.blend_enable = true; - s_gx_state.blend.blend_op = D3D11_BLEND_OP_REV_SUBTRACT; - s_gx_state.blend.src_blend = D3D11_BLEND_ONE; - s_gx_state.blend.dst_blend = D3D11_BLEND_ONE; - } - else - { - s_gx_state.blend.blend_enable = (u32)bpmem.blendmode.blendenable; - if (bpmem.blendmode.blendenable) - { - s_gx_state.blend.blend_op = D3D11_BLEND_OP_ADD; - s_gx_state.blend.src_blend = d3d_src_factors[bpmem.blendmode.srcfactor]; - s_gx_state.blend.dst_blend = d3d_dest_factors[bpmem.blendmode.dstfactor]; - } - } + BlendingState state; + state.Generate(bpmem); + gx_state.blend.hex = state.hex; } // This function has the final picture. We adjust the aspect ratio here. @@ -930,11 +872,6 @@ void Renderer::RestoreAPIState() void Renderer::ApplyState() { - // TODO: Refactor this logic here. - bool bUseDstAlpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && - bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24; - - s_gx_state.blend.use_dst_alpha = bUseDstAlpha; D3D::stateman->PushBlendState(s_gx_state_cache.Get(s_gx_state.blend)); D3D::stateman->PushDepthState(s_gx_state_cache.Get(s_gx_state.zmode)); D3D::stateman->PushRasterizerState(s_gx_state_cache.Get(s_gx_state.raster)); @@ -946,13 +883,6 @@ void Renderer::ApplyState() D3D::stateman->SetSampler(stage, s_gx_state_cache.Get(s_gx_state.samplers[stage])); } - if (bUseDstAlpha) - { - // restore actual state - SetBlendMode(false); - SetLogicOpMode(); - } - ID3D11Buffer* vertexConstants = VertexShaderCache::GetConstantBuffer(); D3D::stateman->SetPixelConstants(PixelShaderCache::GetConstantBuffer(), @@ -998,95 +928,6 @@ void Renderer::SetDepthMode() s_gx_state.zmode.hex = bpmem.zmode.hex; } -void Renderer::SetLogicOpMode() -{ - // D3D11 doesn't support logic blending, so this is a huge hack - // TODO: Make use of D3D11.1's logic blending support - - // 0 0x00 - // 1 Source & destination - // 2 Source & ~destination - // 3 Source - // 4 ~Source & destination - // 5 Destination - // 6 Source ^ destination = Source & ~destination | ~Source & destination - // 7 Source | destination - // 8 ~(Source | destination) - // 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination - // 10 ~Destination - // 11 Source | ~destination - // 12 ~Source - // 13 ~Source | destination - // 14 ~(Source & destination) - // 15 0xff - constexpr std::array d3d_logic_ops{{ - D3D11_BLEND_OP_ADD, // 0 - D3D11_BLEND_OP_ADD, // 1 - D3D11_BLEND_OP_SUBTRACT, // 2 - D3D11_BLEND_OP_ADD, // 3 - D3D11_BLEND_OP_REV_SUBTRACT, // 4 - D3D11_BLEND_OP_ADD, // 5 - D3D11_BLEND_OP_MAX, // 6 - D3D11_BLEND_OP_ADD, // 7 - D3D11_BLEND_OP_MAX, // 8 - D3D11_BLEND_OP_MAX, // 9 - D3D11_BLEND_OP_ADD, // 10 - D3D11_BLEND_OP_ADD, // 11 - D3D11_BLEND_OP_ADD, // 12 - D3D11_BLEND_OP_ADD, // 13 - D3D11_BLEND_OP_ADD, // 14 - D3D11_BLEND_OP_ADD // 15 - }}; - constexpr std::array d3d_logic_op_src_factors{{ - D3D11_BLEND_ZERO, // 0 - D3D11_BLEND_DEST_COLOR, // 1 - D3D11_BLEND_ONE, // 2 - D3D11_BLEND_ONE, // 3 - D3D11_BLEND_DEST_COLOR, // 4 - D3D11_BLEND_ZERO, // 5 - D3D11_BLEND_INV_DEST_COLOR, // 6 - D3D11_BLEND_INV_DEST_COLOR, // 7 - D3D11_BLEND_INV_SRC_COLOR, // 8 - D3D11_BLEND_INV_SRC_COLOR, // 9 - D3D11_BLEND_INV_DEST_COLOR, // 10 - D3D11_BLEND_ONE, // 11 - D3D11_BLEND_INV_SRC_COLOR, // 12 - D3D11_BLEND_INV_SRC_COLOR, // 13 - D3D11_BLEND_INV_DEST_COLOR, // 14 - D3D11_BLEND_ONE // 15 - }}; - constexpr std::array d3d_logic_op_dest_factors{{ - D3D11_BLEND_ZERO, // 0 - D3D11_BLEND_ZERO, // 1 - D3D11_BLEND_INV_SRC_COLOR, // 2 - D3D11_BLEND_ZERO, // 3 - D3D11_BLEND_ONE, // 4 - D3D11_BLEND_ONE, // 5 - D3D11_BLEND_INV_SRC_COLOR, // 6 - D3D11_BLEND_ONE, // 7 - D3D11_BLEND_INV_DEST_COLOR, // 8 - D3D11_BLEND_SRC_COLOR, // 9 - D3D11_BLEND_INV_DEST_COLOR, // 10 - D3D11_BLEND_INV_DEST_COLOR, // 11 - D3D11_BLEND_INV_SRC_COLOR, // 12 - D3D11_BLEND_ONE, // 13 - D3D11_BLEND_INV_SRC_COLOR, // 14 - D3D11_BLEND_ONE // 15 - }}; - - if (bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable) - { - s_gx_state.blend.blend_enable = true; - s_gx_state.blend.blend_op = d3d_logic_ops[bpmem.blendmode.logicmode]; - s_gx_state.blend.src_blend = d3d_logic_op_src_factors[bpmem.blendmode.logicmode]; - s_gx_state.blend.dst_blend = d3d_logic_op_dest_factors[bpmem.blendmode.logicmode]; - } - else - { - SetBlendMode(true); - } -} - void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex) { const FourTexUnits& tex = bpmem.tex[texindex]; diff --git a/Source/Core/VideoBackends/D3D/Render.h b/Source/Core/VideoBackends/D3D/Render.h index e5b429f2ab..f7e9e08b64 100644 --- a/Source/Core/VideoBackends/D3D/Render.h +++ b/Source/Core/VideoBackends/D3D/Render.h @@ -19,12 +19,10 @@ public: Renderer(); ~Renderer() override; - void SetColorMask() override; void SetBlendMode(bool forceUpdate) override; void SetScissorRect(const EFBRectangle& rc) override; void SetGenerationMode() override; void SetDepthMode() override; - void SetLogicOpMode() override; void SetSamplerState(int stage, int texindex, bool custom_tex) override; void SetInterlacingMode() override; void SetViewport() override;