summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorshuffle2 <godisgovernment@gmail.com>2014-12-18 02:59:51 -0800
committershuffle2 <godisgovernment@gmail.com>2014-12-18 02:59:51 -0800
commit717e155ce16d7bbfa9c2066f41547d99f7907dda (patch)
treee9e9e38793d55446ff14a07c9445cee34e9f05df /Source/Core
parent418e006e88306b6f9f3877f946ac5c17dd7e8751 (diff)
parent5688c27610f2a6d67b62e8f90f689e3c1d90a953 (diff)
Merge pull request #1689 from kayru/d3d_efb_copy_fix
D3D: Fixed D3D validation error during EFB to texture copy
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/VideoBackends/D3D/D3DState.cpp27
-rw-r--r--Source/Core/VideoBackends/D3D/D3DState.h4
-rw-r--r--Source/Core/VideoBackends/D3D/TextureCache.cpp7
3 files changed, 38 insertions, 0 deletions
diff --git a/Source/Core/VideoBackends/D3D/D3DState.cpp b/Source/Core/VideoBackends/D3D/D3DState.cpp
index 33310c9957..d4d98e35b8 100644
--- a/Source/Core/VideoBackends/D3D/D3DState.cpp
+++ b/Source/Core/VideoBackends/D3D/D3DState.cpp
@@ -199,6 +199,33 @@ void StateManager::Apply()
m_dirtyFlags = 0;
}
+u32 StateManager::UnsetTexture(ID3D11ShaderResourceView* srv)
+{
+ u32 mask = 0;
+
+ for (u32 index = 0; index < 8; ++index)
+ {
+ if (m_current.textures[index] == srv)
+ {
+ SetTexture(index, nullptr);
+ mask |= 1 << index;
+ }
+ }
+
+ return mask;
+}
+
+void StateManager::SetTextureByMask(u32 textureSlotMask, ID3D11ShaderResourceView* srv)
+{
+ while (textureSlotMask)
+ {
+ unsigned long index;
+ _BitScanForward(&index, textureSlotMask);
+ SetTexture(index, srv);
+ textureSlotMask &= ~(1 << index);
+ }
+}
+
} // namespace D3D
ID3D11SamplerState* StateCache::Get(SamplerState state)
diff --git a/Source/Core/VideoBackends/D3D/D3DState.h b/Source/Core/VideoBackends/D3D/D3DState.h
index 176da98e8b..2910eb9358 100644
--- a/Source/Core/VideoBackends/D3D/D3DState.h
+++ b/Source/Core/VideoBackends/D3D/D3DState.h
@@ -218,6 +218,10 @@ public:
m_pending.geometryShader = shader;
}
+ // removes currently set texture from all slots, returns mask of previously bound slots
+ u32 UnsetTexture(ID3D11ShaderResourceView* srv);
+ void SetTextureByMask(u32 textureSlotMask, ID3D11ShaderResourceView* srv);
+
// call this immediately before any drawing operation or to explicitly apply pending resource state changes
void Apply();
diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp
index bef632e4fd..b251a30682 100644
--- a/Source/Core/VideoBackends/D3D/TextureCache.cpp
+++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp
@@ -157,6 +157,10 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
else
D3D::SetPointCopySampler();
+ // if texture is currently in use, it needs to be temporarily unset
+ u32 textureSlotMask = D3D::stateman->UnsetTexture(texture->GetSRV());
+ D3D::stateman->Apply();
+
D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), nullptr);
// Create texture copy
@@ -170,6 +174,9 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
g_renderer->RestoreAPIState();
+
+ // Restore old texture in all previously used slots, if any
+ D3D::stateman->SetTextureByMask(textureSlotMask, texture->GetSRV());
}
if (!g_ActiveConfig.bCopyEFBToTexture)