summaryrefslogtreecommitdiff
path: root/Source/Plugins
diff options
context:
space:
mode:
authorNolan Check <Nolan.Check@gmail.com>2010-10-20 03:11:22 +0000
committerNolan Check <Nolan.Check@gmail.com>2010-10-20 03:11:22 +0000
commitcb453a0fb3209bc7753bc0dbbc36d4e07b7964e6 (patch)
tree3e5307b38b72602c6f6c76f6156e7bcef18b995a /Source/Plugins
parent479eea6ad248ecfef83968f84ca1c6659e37fe6b (diff)
DX11 plugin: Do destination-alpha in a single pass. No more drawing the same geometry twice! SMG is faster now because it uses destination-alpha extensively. This uses dual-source color blending, a DirectX 10-level feature. The equivalent OpenGL function comes from the GL_ARB_blend_func_extended extension, which was made core in OpenGL 3.3.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6294 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Plugins')
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp76
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/GfxState.h5
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/Render.cpp8
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp26
-rw-r--r--Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h2
5 files changed, 61 insertions, 56 deletions
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp
index 10d2dd2d3a..b9a3ca4b65 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp
@@ -34,6 +34,8 @@ EmuGfxState::EmuGfxState() : vertexshader(NULL), vsbytecode(NULL), pixelshader(N
if(g_ActiveConfig.iMaxAnisotropy > 1) samplerdesc[k].Filter = D3D11_FILTER_ANISOTROPIC;
}
+ m_useDstAlpha = false;
+
memset(&blenddesc, 0, sizeof(blenddesc));
blenddesc.AlphaToCoverageEnable = FALSE;
blenddesc.IndependentBlendEnable = FALSE;
@@ -70,7 +72,7 @@ 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(shader_resources[k]);
SAFE_RELEASE(vsbytecode);
SAFE_RELEASE(psbytecode);
@@ -224,27 +226,6 @@ void EmuGfxState::ApplyState()
apply_called = true;
}
-void EmuGfxState::AlphaPass()
-{
- if (!apply_called) ERROR_LOG(VIDEO, "EmuGfxState::AlphaPass called without having called ApplyState before!")
- else stateman->PopBlendState();
-
- // pixel shader for alpha pass is different, so update it
- context->PSSetShader(pixelshader, NULL, 0);
-
- ID3D11BlendState* blstate;
- D3D11_BLEND_DESC desc = blenddesc;
- desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA;
- desc.RenderTarget[0].BlendEnable = FALSE;
- HRESULT hr = device->CreateBlendState(&desc, &blstate);
- if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
- SetDebugObjectName((ID3D11DeviceChild*)blstate, "a blend state of EmuGfxState (created during alpha pass)");
- stateman->PushBlendState(blstate);
- blstate->Release();
-
- stateman->Apply();
-}
-
void EmuGfxState::Reset()
{
for (unsigned int k = 0;k < 8;k++)
@@ -274,28 +255,57 @@ void EmuGfxState::SetSrcBlend(D3D11_BLEND val)
{
// TODO: Check whether e.g. the dest color check is needed here
blenddesc.RenderTarget[0].SrcBlend = val;
- if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
- else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
- else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA;
- else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
- else blenddesc.RenderTarget[0].SrcBlendAlpha = val;
+ if (m_useDstAlpha)
+ {
+ blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
+ }
+ else
+ {
+ if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
+ else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
+ else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA;
+ else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
+ else blenddesc.RenderTarget[0].SrcBlendAlpha = val;
+ }
}
void EmuGfxState::SetDestBlend(D3D11_BLEND val)
{
// TODO: Check whether e.g. the source color check is needed here
blenddesc.RenderTarget[0].DestBlend = val;
- if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC_ALPHA;
- else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
- else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
- else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
- else blenddesc.RenderTarget[0].DestBlendAlpha = val;
+ if (m_useDstAlpha)
+ {
+ blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
+ }
+ else
+ {
+ if (val == D3D11_BLEND_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC_ALPHA;
+ else if (val == D3D11_BLEND_INV_SRC_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
+ else if (val == D3D11_BLEND_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
+ else if (val == D3D11_BLEND_INV_DEST_COLOR) blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
+ else blenddesc.RenderTarget[0].DestBlendAlpha = val;
+ }
}
void EmuGfxState::SetBlendOp(D3D11_BLEND_OP val)
{
blenddesc.RenderTarget[0].BlendOp = val;
- blenddesc.RenderTarget[0].BlendOpAlpha = val;
+ if (m_useDstAlpha)
+ {
+ blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ }
+ else
+ {
+ blenddesc.RenderTarget[0].BlendOpAlpha = val;
+ }
+}
+
+void EmuGfxState::SetDstAlpha(bool enable)
+{
+ m_useDstAlpha = enable;
+ SetSrcBlend(blenddesc.RenderTarget[0].SrcBlend);
+ SetDestBlend(blenddesc.RenderTarget[0].DestBlend);
+ SetBlendOp(blenddesc.RenderTarget[0].BlendOp);
}
void EmuGfxState::SetSamplerFilter(DWORD stage, D3D11_FILTER filter)
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h
index 507eb76c34..90151a7905 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h
+++ b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.h
@@ -39,7 +39,6 @@ public:
void SetShaderResource(unsigned int stage, ID3D11ShaderResourceView* srv);
void ApplyState(); // apply current state
- void AlphaPass(); // only modify the current state to enable the alpha pass
void Reset();
// blend state
@@ -49,6 +48,8 @@ public:
void SetDestBlend(D3D11_BLEND val);
void SetBlendOp(D3D11_BLEND_OP val);
+ void SetDstAlpha(bool enable);
+
// sampler states
void SetSamplerFilter(DWORD stage, D3D11_FILTER filter);
@@ -80,6 +81,8 @@ private:
ID3D11ShaderResourceView* shader_resources[8];
D3D11_BLEND_DESC blenddesc;
+ bool m_useDstAlpha;
+
bool apply_called;
};
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
index c06ff9c9de..5ab0290b82 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp
@@ -90,8 +90,8 @@ static const D3D11_BLEND d3dSrcFactors[8] =
D3D11_BLEND_ONE,
D3D11_BLEND_DEST_COLOR,
D3D11_BLEND_INV_DEST_COLOR,
- D3D11_BLEND_SRC_ALPHA,
- D3D11_BLEND_INV_SRC_ALPHA,
+ D3D11_BLEND_SRC1_ALPHA,
+ D3D11_BLEND_INV_SRC1_ALPHA, // Use dual-source color blending for dst alpha
D3D11_BLEND_DEST_ALPHA,
D3D11_BLEND_INV_DEST_ALPHA
};
@@ -102,8 +102,8 @@ static const D3D11_BLEND d3dDestFactors[8] =
D3D11_BLEND_ONE,
D3D11_BLEND_SRC_COLOR,
D3D11_BLEND_INV_SRC_COLOR,
- D3D11_BLEND_SRC_ALPHA,
- D3D11_BLEND_INV_SRC_ALPHA,
+ D3D11_BLEND_SRC1_ALPHA,
+ D3D11_BLEND_INV_SRC1_ALPHA, // Use dual-source color blending for dst alpha
D3D11_BLEND_DEST_ALPHA,
D3D11_BLEND_INV_DEST_ALPHA
};
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp
index ff4571c054..6f9d90feb8 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp
@@ -144,12 +144,9 @@ void VertexManager::LoadBuffers()
m_indexBufferCursor += iCount;
}
-void VertexManager::Draw(UINT stride, bool alphapass)
+void VertexManager::Draw(UINT stride)
{
- if (!alphapass)
- D3D::gfxstate->ApplyState();
- else
- D3D::gfxstate->AlphaPass();
+ D3D::gfxstate->ApplyState();
D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &m_vertexDrawOffset);
D3D::context->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0);
@@ -221,7 +218,12 @@ void VertexManager::vFlush()
VertexShaderManager::SetConstants();
PixelShaderManager::SetConstants();
- if (!PixelShaderCache::SetShader(false,g_nativeVertexFmt->m_components))
+ bool useDstAlpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
+ bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
+
+ D3D::gfxstate->SetDstAlpha(useDstAlpha);
+
+ if (!PixelShaderCache::SetShader(useDstAlpha,g_nativeVertexFmt->m_components))
goto shader_fail;
if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components))
goto shader_fail;
@@ -230,18 +232,8 @@ void VertexManager::vFlush()
g_nativeVertexFmt->SetupVertexPointers();
LoadBuffers();
+ Draw(stride);
- Draw(stride, false);
-
- if (bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate)
- {
- DWORD write = 0;
- if (!PixelShaderCache::SetShader(true,g_nativeVertexFmt->m_components))
- goto shader_fail;
-
- // update alpha only
- Draw(stride, true);
- }
D3D::gfxstate->Reset();
shader_fail:
diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h
index b6e3ebd545..8efc08d373 100644
--- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h
+++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.h
@@ -37,7 +37,7 @@ private:
void CreateDeviceObjects();
void DestroyDeviceObjects();
void LoadBuffers();
- void Draw(UINT stride, bool alphapass);
+ void Draw(UINT stride);
// temp
void vFlush();