D3D11: Use blending state from VideoCommon

This commit is contained in:
Stenzek
2017-04-30 00:54:22 +10:00
parent c90b0bf532
commit 5c9bc8b79c
4 changed files with 37 additions and 230 deletions

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <algorithm> #include <algorithm>
#include <array>
#include "Common/BitSet.h" #include "Common/BitSet.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -351,72 +352,51 @@ ID3D11SamplerState* StateCache::Get(SamplerState state)
return res; return res;
} }
ID3D11BlendState* StateCache::Get(BlendState state) ID3D11BlendState* StateCache::Get(BlendingState state)
{ {
if (!state.blend_enable) auto it = m_blend.find(state.hex);
{
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);
if (it != m_blend.end()) if (it != m_blend.end())
return it->second; 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; D3D11_RENDER_TARGET_BLEND_DESC& tdesc = desc.RenderTarget[0];
blenddc.IndependentBlendEnable = FALSE; tdesc.BlendEnable = state.blendenable;
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;
if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_SRC_COLOR) if (state.colorupdate)
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC1_ALPHA; tdesc.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN |
else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_INV_SRC_COLOR) D3D11_COLOR_WRITE_ENABLE_BLUE;
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;
else 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) static constexpr std::array<D3D11_BLEND, 8> src_factors = {
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC1_ALPHA; {D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_INV_DEST_COLOR,
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_SRC_COLOR) D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_INV_SRC1_ALPHA, D3D11_BLEND_DEST_ALPHA,
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; D3D11_BLEND_INV_DEST_ALPHA}};
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_DEST_COLOR) static constexpr std::array<D3D11_BLEND, 8> dst_factors = {
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA; {D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_SRC_COLOR, D3D11_BLEND_INV_SRC_COLOR,
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_DEST_COLOR) D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_INV_SRC1_ALPHA, D3D11_BLEND_DEST_ALPHA,
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; D3D11_BLEND_INV_DEST_ALPHA}};
else
blenddc.RenderTarget[0].DestBlendAlpha = blenddc.RenderTarget[0].DestBlend;
if (state.use_dst_alpha) tdesc.SrcBlend = src_factors[state.srcfactor];
{ tdesc.SrcBlendAlpha = src_factors[state.srcfactoralpha];
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; tdesc.DestBlend = dst_factors[state.dstfactor];
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; tdesc.DestBlendAlpha = dst_factors[state.dstfactoralpha];
blenddc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; 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; ID3D11BlendState* res = nullptr;
HRESULT hr = D3D::device->CreateBlendState(&blenddc, &res); HRESULT hr = D3D::device->CreateBlendState(&desc, &res);
if (FAILED(hr)) if (FAILED(hr))
PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__); PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName(res, "blend state used to emulate the GX pipeline"); 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; return res;
} }

View File

@ -12,7 +12,7 @@
#include "Common/BitField.h" #include "Common/BitField.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "VideoBackends/D3D/D3DBase.h" #include "VideoBackends/D3D/D3DBase.h"
#include "VideoCommon/BPMemory.h" #include "VideoCommon/RenderState.h"
struct ID3D11BlendState; struct ID3D11BlendState;
struct ID3D11DepthStencilState; struct ID3D11DepthStencilState;
@ -27,18 +27,6 @@ union RasterizerState
u32 packed; 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 union SamplerState
{ {
BitField<0, 3, u64> min_filter; BitField<0, 3, u64> min_filter;
@ -59,7 +47,7 @@ public:
// Get existing or create new render state. // Get existing or create new render state.
// Returned objects is owned by the cache and does not need to be released. // Returned objects is owned by the cache and does not need to be released.
ID3D11SamplerState* Get(SamplerState state); ID3D11SamplerState* Get(SamplerState state);
ID3D11BlendState* Get(BlendState state); ID3D11BlendState* Get(BlendingState state);
ID3D11RasterizerState* Get(RasterizerState state); ID3D11RasterizerState* Get(RasterizerState state);
ID3D11DepthStencilState* Get(ZMode state); ID3D11DepthStencilState* Get(ZMode state);

View File

@ -36,6 +36,7 @@
#include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/PixelEngine.h" #include "VideoCommon/PixelEngine.h"
#include "VideoCommon/PixelShaderManager.h" #include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/RenderState.h"
#include "VideoCommon/SamplerCommon.h" #include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoConfig.h"
@ -58,7 +59,7 @@ typedef struct _Nv_Stereo_Image_Header
struct GXPipelineState struct GXPipelineState
{ {
std::array<SamplerState, 8> samplers; std::array<SamplerState, 8> samplers;
BlendState blend; BlendingState blend;
ZMode zmode; ZMode zmode;
RasterizerState raster; RasterizerState raster;
}; };
@ -247,17 +248,8 @@ Renderer::Renderer() : ::Renderer(D3D::GetBackBufferWidth(), D3D::GetBackBufferH
SetupDeviceObjects(); SetupDeviceObjects();
// Setup GX pipeline state // 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) for (auto& sampler : s_gx_state.samplers)
{
sampler.packed = 0; sampler.packed = 0;
}
s_gx_state.zmode.testenable = false; s_gx_state.zmode.testenable = false;
s_gx_state.zmode.updateenable = false; s_gx_state.zmode.updateenable = false;
@ -329,21 +321,6 @@ void Renderer::SetScissorRect(const EFBRectangle& rc)
D3D::context->RSSetScissorRects(1, trc.AsRECT()); 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. // This function allows the CPU to directly access the EFB.
// There are EFB peeks (which will read the color or depth of a pixel) // 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). // 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) void Renderer::SetBlendMode(bool forceUpdate)
{ {
// Our render target always uses an alpha channel, so we need to override the blend functions to BlendingState state;
// assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel state.Generate(bpmem);
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel gx_state.blend.hex = state.hex;
// is assumed to always be 1.
bool target_has_alpha = bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
const std::array<D3D11_BLEND, 8> 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<D3D11_BLEND, 8> 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];
}
}
} }
// This function has the final picture. We adjust the aspect ratio here. // This function has the final picture. We adjust the aspect ratio here.
@ -930,11 +872,6 @@ void Renderer::RestoreAPIState()
void Renderer::ApplyState() 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->PushBlendState(s_gx_state_cache.Get(s_gx_state.blend));
D3D::stateman->PushDepthState(s_gx_state_cache.Get(s_gx_state.zmode)); D3D::stateman->PushDepthState(s_gx_state_cache.Get(s_gx_state.zmode));
D3D::stateman->PushRasterizerState(s_gx_state_cache.Get(s_gx_state.raster)); 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])); 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(); ID3D11Buffer* vertexConstants = VertexShaderCache::GetConstantBuffer();
D3D::stateman->SetPixelConstants(PixelShaderCache::GetConstantBuffer(), D3D::stateman->SetPixelConstants(PixelShaderCache::GetConstantBuffer(),
@ -998,95 +928,6 @@ void Renderer::SetDepthMode()
s_gx_state.zmode.hex = bpmem.zmode.hex; 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<D3D11_BLEND_OP, 16> 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<D3D11_BLEND, 16> 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<D3D11_BLEND, 16> 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) void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
{ {
const FourTexUnits& tex = bpmem.tex[texindex]; const FourTexUnits& tex = bpmem.tex[texindex];

View File

@ -19,12 +19,10 @@ public:
Renderer(); Renderer();
~Renderer() override; ~Renderer() override;
void SetColorMask() override;
void SetBlendMode(bool forceUpdate) override; void SetBlendMode(bool forceUpdate) override;
void SetScissorRect(const EFBRectangle& rc) override; void SetScissorRect(const EFBRectangle& rc) override;
void SetGenerationMode() override; void SetGenerationMode() override;
void SetDepthMode() override; void SetDepthMode() override;
void SetLogicOpMode() override;
void SetSamplerState(int stage, int texindex, bool custom_tex) override; void SetSamplerState(int stage, int texindex, bool custom_tex) override;
void SetInterlacingMode() override; void SetInterlacingMode() override;
void SetViewport() override; void SetViewport() override;