summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D11
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-08-19 14:47:39 +0000
committerazhirnov <zh1dron@gmail.com>2020-08-19 14:47:39 +0000
commitc7c51b0f61b9427ed9cf56c163ee451fdda0ff02 (patch)
tree613255cd5020831d3c96be0fd06ce6b8a88ec35b /Graphics/GraphicsEngineD3D11
parentAdded mesh shader (diff)
downloadDiligentCore-c7c51b0f61b9427ed9cf56c163ee451fdda0ff02.tar.gz
DiligentCore-c7c51b0f61b9427ed9cf56c163ee451fdda0ff02.zip
formatting
Diffstat (limited to 'Graphics/GraphicsEngineD3D11')
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp4622
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp6
2 files changed, 2314 insertions, 2314 deletions
diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
index d936b247..78814200 100755
--- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
@@ -1,875 +1,875 @@
-/*
- * Copyright 2019-2020 Diligent Graphics LLC
- * Copyright 2015-2019 Egor Yusov
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * In no event and under no legal theory, whether in tort (including negligence),
- * contract, or otherwise, unless required by applicable law (such as deliberate
- * and grossly negligent acts) or agreed to in writing, shall any Contributor be
- * liable for any damages, including any direct, indirect, special, incidental,
- * or consequential damages of any character arising as a result of this License or
- * out of the use or inability to use the software (including but not limited to damages
- * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
- * all other commercial damages or losses), even if such Contributor has been advised
- * of the possibility of such damages.
- */
-
-#include "pch.h"
-#include "DeviceContextD3D11Impl.hpp"
-#include "BufferD3D11Impl.hpp"
-#include "ShaderD3D11Impl.hpp"
-#include "Texture1D_D3D11.hpp"
-#include "Texture2D_D3D11.hpp"
-#include "Texture3D_D3D11.hpp"
-#include "SamplerD3D11Impl.hpp"
-#include "D3D11TypeConversions.hpp"
-#include "TextureViewD3D11Impl.hpp"
-#include "PipelineStateD3D11Impl.hpp"
-#include "ShaderResourceBindingD3D11Impl.hpp"
-#include "EngineD3D11Defines.h"
-#include "CommandListD3D11Impl.hpp"
-#include "RenderDeviceD3D11Impl.hpp"
-#include "FenceD3D11Impl.hpp"
-#include "QueryD3D11Impl.hpp"
-
-namespace Diligent
-{
-DeviceContextD3D11Impl::DeviceContextD3D11Impl(IReferenceCounters* pRefCounters,
- IMemoryAllocator& Allocator,
- RenderDeviceD3D11Impl* pDevice,
- ID3D11DeviceContext* pd3d11DeviceContext,
- const struct EngineD3D11CreateInfo& EngineAttribs,
- bool bIsDeferred) :
- // clang-format off
- TDeviceContextBase
- {
- pRefCounters,
- pDevice,
- bIsDeferred
- },
- m_pd3d11DeviceContext{pd3d11DeviceContext },
- m_DebugFlags {EngineAttribs.DebugFlags },
- m_CmdListAllocator {GetRawAllocator(), sizeof(CommandListD3D11Impl), 64}
-// clang-format on
-{
-}
-
-IMPLEMENT_QUERY_INTERFACE(DeviceContextD3D11Impl, IID_DeviceContextD3D11, TDeviceContextBase)
-
-void DeviceContextD3D11Impl::SetPipelineState(IPipelineState* pPipelineState)
-{
- auto* pPipelineStateD3D11 = ValidatedCast<PipelineStateD3D11Impl>(pPipelineState);
- if (PipelineStateD3D11Impl::IsSameObject(m_pPipelineState, pPipelineStateD3D11))
- return;
-
- TDeviceContextBase::SetPipelineState(pPipelineStateD3D11, 0 /*Dummy*/);
- auto& Desc = pPipelineStateD3D11->GetDesc();
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "DeviceContextD3D11Impl.hpp"
+#include "BufferD3D11Impl.hpp"
+#include "ShaderD3D11Impl.hpp"
+#include "Texture1D_D3D11.hpp"
+#include "Texture2D_D3D11.hpp"
+#include "Texture3D_D3D11.hpp"
+#include "SamplerD3D11Impl.hpp"
+#include "D3D11TypeConversions.hpp"
+#include "TextureViewD3D11Impl.hpp"
+#include "PipelineStateD3D11Impl.hpp"
+#include "ShaderResourceBindingD3D11Impl.hpp"
+#include "EngineD3D11Defines.h"
+#include "CommandListD3D11Impl.hpp"
+#include "RenderDeviceD3D11Impl.hpp"
+#include "FenceD3D11Impl.hpp"
+#include "QueryD3D11Impl.hpp"
+
+namespace Diligent
+{
+DeviceContextD3D11Impl::DeviceContextD3D11Impl(IReferenceCounters* pRefCounters,
+ IMemoryAllocator& Allocator,
+ RenderDeviceD3D11Impl* pDevice,
+ ID3D11DeviceContext* pd3d11DeviceContext,
+ const struct EngineD3D11CreateInfo& EngineAttribs,
+ bool bIsDeferred) :
+ // clang-format off
+ TDeviceContextBase
+ {
+ pRefCounters,
+ pDevice,
+ bIsDeferred
+ },
+ m_pd3d11DeviceContext{pd3d11DeviceContext },
+ m_DebugFlags {EngineAttribs.DebugFlags },
+ m_CmdListAllocator {GetRawAllocator(), sizeof(CommandListD3D11Impl), 64}
+// clang-format on
+{
+}
+
+IMPLEMENT_QUERY_INTERFACE(DeviceContextD3D11Impl, IID_DeviceContextD3D11, TDeviceContextBase)
+
+void DeviceContextD3D11Impl::SetPipelineState(IPipelineState* pPipelineState)
+{
+ auto* pPipelineStateD3D11 = ValidatedCast<PipelineStateD3D11Impl>(pPipelineState);
+ if (PipelineStateD3D11Impl::IsSameObject(m_pPipelineState, pPipelineStateD3D11))
+ return;
+
+ TDeviceContextBase::SetPipelineState(pPipelineStateD3D11, 0 /*Dummy*/);
+ auto& Desc = pPipelineStateD3D11->GetDesc();
if (Desc.IsComputePipeline())
- {
- auto* pd3d11CS = pPipelineStateD3D11->GetD3D11ComputeShader();
- if (pd3d11CS == nullptr)
- {
- LOG_ERROR("Compute shader is not set in the pipeline");
- return;
- }
-
-#define COMMIT_SHADER(SN, ShaderName) \
- do \
- { \
- auto* pd3d11Shader = pPipelineStateD3D11->GetD3D11##ShaderName(); \
- if (m_CommittedD3DShaders[SN##Ind] != pd3d11Shader) \
- { \
- m_CommittedD3DShaders[SN##Ind] = pd3d11Shader; \
- m_pd3d11DeviceContext->SN##SetShader(pd3d11Shader, nullptr, 0); \
- } \
- } while (false)
-
- COMMIT_SHADER(CS, ComputeShader);
- }
- else
- {
- COMMIT_SHADER(VS, VertexShader);
- COMMIT_SHADER(PS, PixelShader);
- COMMIT_SHADER(GS, GeometryShader);
- COMMIT_SHADER(HS, HullShader);
- COMMIT_SHADER(DS, DomainShader);
-#undef COMMIT_SHADER
-
- m_pd3d11DeviceContext->OMSetBlendState(pPipelineStateD3D11->GetD3D11BlendState(), m_BlendFactors, Desc.GraphicsPipeline.SampleMask);
- m_pd3d11DeviceContext->RSSetState(pPipelineStateD3D11->GetD3D11RasterizerState());
- m_pd3d11DeviceContext->OMSetDepthStencilState(pPipelineStateD3D11->GetD3D11DepthStencilState(), m_StencilRef);
-
- auto* pd3d11InputLayout = pPipelineStateD3D11->GetD3D11InputLayout();
- // It is safe to perform raw pointer comparison as the device context
- // keeps bound input layout alive
- if (m_CommittedD3D11InputLayout != pd3d11InputLayout)
- {
- m_pd3d11DeviceContext->IASetInputLayout(pd3d11InputLayout);
- m_CommittedD3D11InputLayout = pd3d11InputLayout;
- }
-
- auto PrimTopology = Desc.GraphicsPipeline.PrimitiveTopology;
- if (m_CommittedPrimitiveTopology != PrimTopology)
- {
- m_CommittedPrimitiveTopology = PrimTopology;
- m_CommittedD3D11PrimTopology = TopologyToD3D11Topology(PrimTopology);
- m_pd3d11DeviceContext->IASetPrimitiveTopology(m_CommittedD3D11PrimTopology);
- }
- }
-}
-
-// clang-format off
-
-/// Helper macro used to create an array of device context methods to
-/// set particular resource for every shader stage
-#define DEFINE_D3D11CTX_FUNC_POINTERS(ArrayName, FuncName) \
- typedef decltype (&ID3D11DeviceContext::VS##FuncName) T##FuncName##Type; \
- static const T##FuncName##Type ArrayName[] = \
- { \
- &ID3D11DeviceContext::VS##FuncName, \
- &ID3D11DeviceContext::PS##FuncName, \
- &ID3D11DeviceContext::GS##FuncName, \
- &ID3D11DeviceContext::HS##FuncName, \
- &ID3D11DeviceContext::DS##FuncName, \
- &ID3D11DeviceContext::CS##FuncName \
- };
-
- DEFINE_D3D11CTX_FUNC_POINTERS(SetCBMethods, SetConstantBuffers)
- DEFINE_D3D11CTX_FUNC_POINTERS(SetSRVMethods, SetShaderResources)
- DEFINE_D3D11CTX_FUNC_POINTERS(SetSamplerMethods, SetSamplers)
-
- typedef decltype (&ID3D11DeviceContext::CSSetUnorderedAccessViews) TSetUnorderedAccessViewsType;
- static const TSetUnorderedAccessViewsType SetUAVMethods[] =
- {
- nullptr, // VS
- reinterpret_cast<TSetUnorderedAccessViewsType>(&ID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews), // Little hack for PS
- nullptr, // GS
- nullptr, // HS
- nullptr, // DS
- &ID3D11DeviceContext::CSSetUnorderedAccessViews // CS
- };
-
-// clang-format on
-
-// http://diligentgraphics.com/diligent-engine/architecture/d3d11/committing-shader-resources-to-the-gpu-pipeline/
-template <bool TransitionResources, bool CommitResources>
-void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* pPSO, IShaderResourceBinding* pShaderResourceBinding, bool VerifyStates)
-{
- VERIFY_EXPR(pPSO != nullptr);
- static_assert(TransitionResources || CommitResources, "At least one of TransitionResources or CommitResources flags is expected to be true");
-
- auto* pPipelineStateD3D11 = ValidatedCast<PipelineStateD3D11Impl>(pPSO);
-
- if (pShaderResourceBinding == nullptr)
- {
-#ifdef DILIGENT_DEVELOPMENT
- bool ResourcesPresent = false;
- for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaders(); ++s)
- {
- auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
- if (pShaderD3D11->GetD3D11Resources()->GetTotalResources() > 0)
- ResourcesPresent = true;
- }
-
- if (ResourcesPresent)
- {
- LOG_ERROR_MESSAGE("Pipeline state '", pPSO->GetDesc().Name, "' requires shader resource binding object to ",
- (CommitResources ? "commit" : "transition"), " resources, but none is provided.");
- }
-#endif
- return;
- }
-
-
- auto pShaderResBindingD3D11 = ValidatedCast<ShaderResourceBindingD3D11Impl>(pShaderResourceBinding);
-#ifdef DILIGENT_DEVELOPMENT
- if (pPipelineStateD3D11->IsIncompatibleWith(pShaderResourceBinding->GetPipelineState()))
- {
- LOG_ERROR_MESSAGE("Shader resource binding does not match Pipeline State");
- return;
- }
-#endif
-
- auto NumShaders = pShaderResBindingD3D11->GetNumActiveShaders();
- VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaders(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state");
-
-#ifdef DILIGENT_DEVELOPMENT
- {
- bool StaticResourcesPresent = false;
- for (Uint32 s = 0; s < NumShaders; ++s)
- {
- const auto& StaticResLayout = pPipelineStateD3D11->GetStaticResourceLayout(s);
- if (StaticResLayout.GetTotalResourceCount() > 0)
- StaticResourcesPresent = true;
- }
- // Static resource bindings are verified in BindStaticShaderResources()
- if (StaticResourcesPresent && !pShaderResBindingD3D11->IsStaticResourcesBound())
- {
- LOG_ERROR_MESSAGE("Static resources have not been initialized in the shader resource binding object being committed for PSO '", pPSO->GetDesc().Name, "'. Please call IShaderResourceBinding::InitializeStaticResources().");
- }
- }
-#endif
-
- bool ClearPixelShaderUAVs = m_NumCommittedUAVs[PSInd] > 0;
- // First, commit all UAVs for all shader stages. This will unbind them from input
- for (Uint32 s = 0; s < NumShaders; ++s)
- {
- auto ShaderTypeInd = pShaderResBindingD3D11->GetActiveShaderTypeIndex(s);
-
-#ifdef DILIGENT_DEVELOPMENT
- auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
- VERIFY_EXPR(ShaderTypeInd == static_cast<Int32>(GetShaderTypeIndex(pShaderD3D11->GetDesc().ShaderType)));
-#endif
-
- auto& Cache = pShaderResBindingD3D11->GetResourceCache(s);
- auto NumUAVs = Cache.GetUAVCount();
- if (NumUAVs)
- {
- ShaderResourceCacheD3D11::CachedResource* CachedUAVResources;
- ID3D11UnorderedAccessView** d3d11UAVs;
- Cache.GetUAVArrays(CachedUAVResources, d3d11UAVs);
-
- auto* CommittedD3D11UAVs = m_CommittedD3D11UAVs[ShaderTypeInd];
- auto* CommittedD3D11UAVRes = m_CommittedD3D11UAVResources[ShaderTypeInd];
-
- if (ShaderTypeInd == PSInd)
- ClearPixelShaderUAVs = false;
-
- UINT MinSlot = UINT_MAX;
- UINT MaxSlot = 0;
-
- for (Uint32 uav = 0; uav < NumUAVs; ++uav)
- {
- VERIFY_EXPR(uav < Cache.GetUAVCount());
- auto& UAVRes = CachedUAVResources[uav];
- // WARNING! This code is not thread-safe. It is up to the application to make
- // sure that multiple threads do not modify the texture state simultaneously.
- if (TransitionResources)
- {
- if (auto* pTexture = ValidatedCast<TextureBaseD3D11>(UAVRes.pTexture))
- {
- if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- if (pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
- UnbindTextureFromInput(pTexture, UAVRes.pd3d11Resource);
- pTexture->SetState(RESOURCE_STATE_UNORDERED_ACCESS);
- }
- }
- else if (auto* pBuffer = ValidatedCast<BufferD3D11Impl>(UAVRes.pBuffer))
- {
- if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- if ((pBuffer->GetState() & RESOURCE_STATE_GENERIC_READ) != 0)
- UnbindBufferFromInput(pBuffer, UAVRes.pd3d11Resource);
- pBuffer->SetState(RESOURCE_STATE_UNORDERED_ACCESS);
- }
- }
- }
-#ifdef DILIGENT_DEVELOPMENT
- else if (VerifyStates)
- {
- if (const auto* pTexture = ValidatedCast<TextureBaseD3D11>(UAVRes.pTexture))
- {
- if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("Texture '", pTexture->GetDesc().Name, "' has not been transitioned to Unordered Access state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the texture to required state.");
- }
- }
- else if (const auto* pBuffer = ValidatedCast<BufferD3D11Impl>(UAVRes.pBuffer))
- {
- if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("Buffer '", pBuffer->GetDesc().Name, "' has not been transitioned to Unordered Access state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state.");
- }
- }
- }
-#endif
- if (CommitResources)
- {
- bool IsNewUAV = CommittedD3D11UAVs[uav] != d3d11UAVs[uav];
- MinSlot = IsNewUAV ? std::min(MinSlot, uav) : MinSlot;
- MaxSlot = IsNewUAV ? uav : MaxSlot;
-
- CommittedD3D11UAVRes[uav] = UAVRes.pd3d11Resource;
- CommittedD3D11UAVs[uav] = d3d11UAVs[uav];
- }
- }
-
- if (CommitResources)
- {
- if (MinSlot != UINT_MAX || ShaderTypeInd == PSInd && m_NumCommittedUAVs[PSInd] != NumUAVs)
- {
- // Something has changed
- if (ShaderTypeInd == PSInd)
- {
- // Pixel shader UAVs cannot be set independently; they all need to be set at the same time.
- // https://docs.microsoft.com/en-us/windows/desktop/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews#remarks
- auto StartUAVSlot = m_NumBoundRenderTargets;
- VERIFY(NumUAVs > StartUAVSlot, "Number of UAVs must be greater than the render target count");
- m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
- D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
- StartUAVSlot, NumUAVs - StartUAVSlot, CommittedD3D11UAVs + StartUAVSlot, nullptr);
- // Clear previously bound UAVs, but do not clear lower slots as if
- // render target count reduces, we will bind these UAVs in CommitRenderTargets()
- for (Uint32 uav = NumUAVs; uav < m_NumCommittedUAVs[ShaderTypeInd]; ++uav)
- {
- CommittedD3D11UAVRes[uav] = nullptr;
- CommittedD3D11UAVs[uav] = nullptr;
- }
- m_NumCommittedUAVs[ShaderTypeInd] = static_cast<Uint8>(NumUAVs);
- }
- else
- {
- // This can only be CS
- auto SetUAVMethod = SetUAVMethods[ShaderTypeInd];
- (m_pd3d11DeviceContext->*SetUAVMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11UAVs + MinSlot, nullptr);
- m_NumCommittedUAVs[ShaderTypeInd] = std::max(m_NumCommittedUAVs[ShaderTypeInd], static_cast<Uint8>(NumUAVs));
- }
- }
-
-#ifdef DILIGENT_DEVELOPMENT
- if ((m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) != 0 && ShaderTypeInd == CSInd)
- {
- dbgVerifyCommittedUAVs(pShaderD3D11->GetDesc().ShaderType);
- }
-#endif
- }
- }
- }
-
- if (ClearPixelShaderUAVs)
- {
- // If pixel shader stage is inactive or does not use UAVs, unbind all committed UAVs.
- // This is important as UnbindPixelShaderUAV<> function may need to rebind
- // existing UAVs and the UAVs pointed to by CommittedD3D11UAVRes must be alive
- // (we do not keep strong references to d3d11 UAVs)
- auto* CommittedD3D11UAVs = m_CommittedD3D11UAVs[PSInd];
- auto* CommittedD3D11UAVRes = m_CommittedD3D11UAVResources[PSInd];
- auto& NumCommittedPixelShaderUAVs = m_NumCommittedUAVs[PSInd];
- for (Uint32 uav = 0; uav < NumCommittedPixelShaderUAVs; ++uav)
- {
- CommittedD3D11UAVRes[uav] = nullptr;
- CommittedD3D11UAVs[uav] = nullptr;
- }
- m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
- D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
- 0, 0, nullptr, nullptr);
- NumCommittedPixelShaderUAVs = 0;
- }
-
- // Commit input resources (CBs, SRVs and Samplers)
- for (Uint32 s = 0; s < NumShaders; ++s)
- {
- auto ShaderTypeInd = pShaderResBindingD3D11->GetActiveShaderTypeIndex(s);
-
-#ifdef DILIGENT_DEVELOPMENT
- auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
- VERIFY_EXPR(ShaderTypeInd == static_cast<Int32>(GetShaderTypeIndex(pShaderD3D11->GetDesc().ShaderType)));
-#endif
-
- auto& Cache = pShaderResBindingD3D11->GetResourceCache(s);
-
- // Transition and commit Constant Buffers
- auto NumCBs = Cache.GetCBCount();
- if (NumCBs)
- {
- ShaderResourceCacheD3D11::CachedCB* CachedCBs;
- ID3D11Buffer** d3d11CBs;
- Cache.GetCBArrays(CachedCBs, d3d11CBs);
-
- auto* CommittedD3D11CBs = m_CommittedD3D11CBs[ShaderTypeInd];
- UINT MinSlot = UINT_MAX;
- UINT MaxSlot = 0;
- for (Uint32 cb = 0; cb < NumCBs; ++cb)
- {
- VERIFY_EXPR(cb < Cache.GetCBCount());
-
- if (TransitionResources)
- {
- auto& CB = CachedCBs[cb];
- if (auto* pBuff = CB.pBuff.RawPtr<BufferD3D11Impl>())
- {
- // WARNING! This code is not thread-safe. It is up to the application to make
- // sure that multiple threads do not modify the buffer state simultaneously.
- if (pBuff->IsInKnownState() && !pBuff->CheckState(RESOURCE_STATE_CONSTANT_BUFFER))
- {
- if (pBuff->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- // Even though we have unbound resources from UAV, we only checked shader
- // stages active in current PSO, so we still may need to unbind the resource
- // from UAV (for instance, unbind resource from CS UAV when running draw command).
- UnbindResourceFromUAV(pBuff, d3d11CBs[cb]);
- pBuff->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
- }
- pBuff->AddState(RESOURCE_STATE_CONSTANT_BUFFER);
- }
- }
- }
-#ifdef DILIGENT_DEVELOPMENT
- else if (VerifyStates)
- {
- VERIFY_EXPR(CommitResources);
- const auto& CB = CachedCBs[cb];
- if (auto* pBuff = CB.pBuff.RawPtr<const BufferD3D11Impl>())
- {
- if (pBuff->IsInKnownState() && !pBuff->CheckState(RESOURCE_STATE_CONSTANT_BUFFER))
- {
- LOG_ERROR_MESSAGE("Buffer '", pBuff->GetDesc().Name, "' has not been transitioned to Constant Buffer state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state.");
- }
- }
- }
-#endif
-
- if (CommitResources)
- {
- bool IsNewCB = CommittedD3D11CBs[cb] != d3d11CBs[cb];
- MinSlot = IsNewCB ? std::min(MinSlot, cb) : MinSlot;
- MaxSlot = IsNewCB ? cb : MaxSlot;
- CommittedD3D11CBs[cb] = d3d11CBs[cb];
- }
- }
-
- if (CommitResources)
- {
- if (MinSlot != UINT_MAX)
- {
- auto SetCBMethod = SetCBMethods[ShaderTypeInd];
- (m_pd3d11DeviceContext->*SetCBMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11CBs + MinSlot);
- m_NumCommittedCBs[ShaderTypeInd] = std::max(m_NumCommittedCBs[ShaderTypeInd], static_cast<Uint8>(NumCBs));
- }
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- dbgVerifyCommittedCBs(pShaderD3D11->GetDesc().ShaderType);
- }
-#endif
- }
- }
-
-
- // Transition and commit Shader Resource Views
- auto NumSRVs = Cache.GetSRVCount();
- if (NumSRVs)
- {
- ShaderResourceCacheD3D11::CachedResource* CachedSRVResources;
- ID3D11ShaderResourceView** d3d11SRVs;
- Cache.GetSRVArrays(CachedSRVResources, d3d11SRVs);
-
- auto* CommittedD3D11SRVs = m_CommittedD3D11SRVs[ShaderTypeInd];
- auto* CommittedD3D11SRVRes = m_CommittedD3D11SRVResources[ShaderTypeInd];
-
- UINT MinSlot = UINT_MAX;
- UINT MaxSlot = 0;
-
- for (Uint32 srv = 0; srv < NumSRVs; ++srv)
- {
- VERIFY_EXPR(srv < Cache.GetSRVCount());
- auto& SRVRes = CachedSRVResources[srv];
- // WARNING! This code is not thread-safe. It is up to the application to make
- // sure that multiple threads do not modify the texture state simultaneously.
- if (TransitionResources)
- {
- if (auto* pTexture = ValidatedCast<TextureBaseD3D11>(SRVRes.pTexture))
- {
- if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
- {
- if (pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- // Even though we have unbound resources from UAV, we only checked shader
- // stages active in current PSO, so we still may need to unbind the resource
- // from UAV (for instance, unbind resource from CS UAV when running draw command).
- UnbindResourceFromUAV(pTexture, SRVRes.pd3d11Resource);
- pTexture->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
- }
-
- if (pTexture->CheckState(RESOURCE_STATE_RENDER_TARGET))
- UnbindTextureFromRenderTarget(pTexture);
-
- if (pTexture->CheckState(RESOURCE_STATE_DEPTH_WRITE))
- UnbindTextureFromDepthStencil(pTexture);
-
- pTexture->SetState(RESOURCE_STATE_SHADER_RESOURCE);
- }
- }
- else if (auto* pBuffer = ValidatedCast<BufferD3D11Impl>(SRVRes.pBuffer))
- {
- if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
- {
- if (pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- UnbindResourceFromUAV(pBuffer, SRVRes.pd3d11Resource);
- pBuffer->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
- }
- pBuffer->AddState(RESOURCE_STATE_SHADER_RESOURCE);
- }
- }
- }
-#ifdef DILIGENT_DEVELOPMENT
- else if (VerifyStates)
- {
- VERIFY_EXPR(CommitResources);
- if (const auto* pTexture = ValidatedCast<TextureBaseD3D11>(SRVRes.pTexture))
- {
- if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
- {
- LOG_ERROR_MESSAGE("Texture '", pTexture->GetDesc().Name, "' has not been transitioned to Shader Resource state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the texture to required state.");
- }
- }
- else if (const auto* pBuffer = ValidatedCast<BufferD3D11Impl>(SRVRes.pBuffer))
- {
- if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
- {
- LOG_ERROR_MESSAGE("Buffer '", pBuffer->GetDesc().Name, "' has not been transitioned to Shader Resource state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state.");
- }
- }
- }
-#endif
-
- if (CommitResources)
- {
- bool IsNewSRV = CommittedD3D11SRVs[srv] != d3d11SRVs[srv];
- MinSlot = IsNewSRV ? std::min(MinSlot, srv) : MinSlot;
- MaxSlot = IsNewSRV ? srv : MaxSlot;
-
- CommittedD3D11SRVRes[srv] = SRVRes.pd3d11Resource;
- CommittedD3D11SRVs[srv] = d3d11SRVs[srv];
- }
- }
-
- if (CommitResources)
- {
- if (MinSlot != UINT_MAX)
- {
- auto SetSRVMethod = SetSRVMethods[ShaderTypeInd];
- (m_pd3d11DeviceContext->*SetSRVMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11SRVs + MinSlot);
- m_NumCommittedSRVs[ShaderTypeInd] = std::max(m_NumCommittedSRVs[ShaderTypeInd], static_cast<Uint8>(NumSRVs));
- }
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- dbgVerifyCommittedSRVs(pShaderD3D11->GetDesc().ShaderType);
- }
-#endif
- }
- }
-
-
- // Commit samplers (no transitions for samplers)
- if (CommitResources)
- {
- auto NumSamplers = Cache.GetSamplerCount();
- if (NumSamplers)
- {
- ShaderResourceCacheD3D11::CachedSampler* CachedSamplers;
- ID3D11SamplerState** d3d11Samplers;
- Cache.GetSamplerArrays(CachedSamplers, d3d11Samplers);
-
- auto* CommittedD3D11Samplers = m_CommittedD3D11Samplers[ShaderTypeInd];
- UINT MinSlot = std::numeric_limits<UINT>::max();
- UINT MaxSlot = 0;
- for (Uint32 sam = 0; sam < NumSamplers; ++sam)
- {
- VERIFY_EXPR(sam < Cache.GetSamplerCount());
-
- bool IsNewSam = CommittedD3D11Samplers[sam] != d3d11Samplers[sam];
- MinSlot = IsNewSam ? std::min(MinSlot, sam) : MinSlot;
- MaxSlot = IsNewSam ? sam : MaxSlot;
-
- CommittedD3D11Samplers[sam] = d3d11Samplers[sam];
- }
-
- if (MinSlot != UINT_MAX)
- {
- auto SetSamplerMethod = SetSamplerMethods[ShaderTypeInd];
- (m_pd3d11DeviceContext->*SetSamplerMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11Samplers + MinSlot);
- m_NumCommittedSamplers[ShaderTypeInd] = std::max(m_NumCommittedSamplers[ShaderTypeInd], static_cast<Uint8>(NumSamplers));
- }
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- dbgVerifyCommittedSamplers(pShaderD3D11->GetDesc().ShaderType);
- }
-#endif
- }
- }
-
-
-
-#ifdef DILIGENT_DEVELOPMENT
- if (CommitResources && (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_SHADER_RESOURCES) != 0)
- {
- // Use full resource layout to verify that all required resources are committed
- pShaderD3D11->GetD3D11Resources()->dvpVerifyCommittedResources(
- m_CommittedD3D11CBs[ShaderTypeInd],
- m_CommittedD3D11SRVs[ShaderTypeInd],
- m_CommittedD3D11SRVResources[ShaderTypeInd],
- m_CommittedD3D11Samplers[ShaderTypeInd],
- m_CommittedD3D11UAVs[ShaderTypeInd],
- m_CommittedD3D11UAVResources[ShaderTypeInd],
- Cache);
- }
-#endif
- }
-}
-
-void DeviceContextD3D11Impl::TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding)
-{
- DEV_CHECK_ERR(pPipelineState != nullptr, "Pipeline state must not be null");
- DEV_CHECK_ERR(pShaderResourceBinding != nullptr, "Shader resource binding must not be null");
- TransitionAndCommitShaderResources<true, false>(pPipelineState, pShaderResourceBinding, false);
-}
-
-void DeviceContextD3D11Impl::CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
-{
- if (!DeviceContextBase::CommitShaderResources(pShaderResourceBinding, StateTransitionMode, 0 /*Dummy*/))
- return;
-
- if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
- TransitionAndCommitShaderResources<true, true>(m_pPipelineState, pShaderResourceBinding, false);
- else
- TransitionAndCommitShaderResources<false, true>(m_pPipelineState, pShaderResourceBinding, StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY);
-}
-
-void DeviceContextD3D11Impl::SetStencilRef(Uint32 StencilRef)
-{
- if (TDeviceContextBase::SetStencilRef(StencilRef, 0))
- {
- ID3D11DepthStencilState* pd3d11DSS =
- m_pPipelineState ? m_pPipelineState->GetD3D11DepthStencilState() : nullptr;
- m_pd3d11DeviceContext->OMSetDepthStencilState(pd3d11DSS, m_StencilRef);
- }
-}
-
-
-void DeviceContextD3D11Impl::SetBlendFactors(const float* pBlendFactors)
-{
- if (TDeviceContextBase::SetBlendFactors(pBlendFactors, 0))
- {
- Uint32 SampleMask = 0xFFFFFFFF;
- ID3D11BlendState* pd3d11BS = nullptr;
- if (m_pPipelineState)
- {
- SampleMask = m_pPipelineState->GetDesc().GraphicsPipeline.SampleMask;
- pd3d11BS = m_pPipelineState->GetD3D11BlendState();
- }
- m_pd3d11DeviceContext->OMSetBlendState(pd3d11BS, m_BlendFactors, SampleMask);
- }
-}
-
-void DeviceContextD3D11Impl::CommitD3D11IndexBuffer(VALUE_TYPE IndexType)
-{
- if (!m_pIndexBuffer)
- {
- LOG_ERROR_MESSAGE("Index buffer is not set up for indexed draw command");
- return;
- }
-
- BufferD3D11Impl* pBuffD3D11 = m_pIndexBuffer.RawPtr<BufferD3D11Impl>();
- if (m_CommittedD3D11IndexBuffer != pBuffD3D11->m_pd3d11Buffer ||
- m_CommittedIBFormat != IndexType ||
- m_CommittedD3D11IndexDataStartOffset != m_IndexDataStartOffset)
- {
- DXGI_FORMAT D3D11IndexFmt = DXGI_FORMAT_UNKNOWN;
- if (IndexType == VT_UINT32)
- D3D11IndexFmt = DXGI_FORMAT_R32_UINT;
- else if (IndexType == VT_UINT16)
- D3D11IndexFmt = DXGI_FORMAT_R16_UINT;
- else
- {
- LOG_ERROR_MESSAGE("Unsupported index format. Only R16_UINT and R32_UINT are allowed.");
- return;
- }
-
- m_CommittedD3D11IndexBuffer = pBuffD3D11->m_pd3d11Buffer;
- m_CommittedIBFormat = IndexType;
- m_CommittedD3D11IndexDataStartOffset = m_IndexDataStartOffset;
- m_pd3d11DeviceContext->IASetIndexBuffer(pBuffD3D11->m_pd3d11Buffer, D3D11IndexFmt, m_IndexDataStartOffset);
- }
-
- pBuffD3D11->AddState(RESOURCE_STATE_INDEX_BUFFER);
- m_bCommittedD3D11IBUpToDate = true;
-}
-
-void DeviceContextD3D11Impl::CommitD3D11VertexBuffers(PipelineStateD3D11Impl* pPipelineStateD3D11)
-{
- VERIFY(m_NumVertexStreams <= MAX_BUFFER_SLOTS, "Too many buffers are being set");
- UINT NumBuffersToSet = std::max(m_NumVertexStreams, m_NumCommittedD3D11VBs);
-
- bool BindVBs = m_NumVertexStreams != m_NumCommittedD3D11VBs;
-
- for (UINT Slot = 0; Slot < m_NumVertexStreams; ++Slot)
- {
- auto& CurrStream = m_VertexStreams[Slot];
- auto* pBuffD3D11Impl = CurrStream.pBuffer.RawPtr();
- ID3D11Buffer* pd3d11Buffer = pBuffD3D11Impl ? pBuffD3D11Impl->m_pd3d11Buffer : nullptr;
- auto Stride = pPipelineStateD3D11->GetBufferStride(Slot);
- auto Offset = CurrStream.Offset;
-
- // It is safe to perform raw pointer check because device context keeps
- // all buffers alive.
- if (m_CommittedD3D11VertexBuffers[Slot] != pd3d11Buffer ||
- m_CommittedD3D11VBStrides[Slot] != Stride ||
- m_CommittedD3D11VBOffsets[Slot] != Offset)
- {
- BindVBs = true;
-
- m_CommittedD3D11VertexBuffers[Slot] = pd3d11Buffer;
- m_CommittedD3D11VBStrides[Slot] = Stride;
- m_CommittedD3D11VBOffsets[Slot] = Offset;
-
- if (pBuffD3D11Impl)
- pBuffD3D11Impl->AddState(RESOURCE_STATE_VERTEX_BUFFER);
- }
- }
-
- // Unbind all buffers at the end
- for (Uint32 Slot = m_NumVertexStreams; Slot < m_NumCommittedD3D11VBs; ++Slot)
- {
- m_CommittedD3D11VertexBuffers[Slot] = nullptr;
- m_CommittedD3D11VBStrides[Slot] = 0;
- m_CommittedD3D11VBOffsets[Slot] = 0;
- }
-
- m_NumCommittedD3D11VBs = m_NumVertexStreams;
-
- if (BindVBs)
- {
- m_pd3d11DeviceContext->IASetVertexBuffers(0, NumBuffersToSet, m_CommittedD3D11VertexBuffers, m_CommittedD3D11VBStrides, m_CommittedD3D11VBOffsets);
- }
-
- m_bCommittedD3D11VBsUpToDate = true;
-}
-
-void DeviceContextD3D11Impl::PrepareForDraw(DRAW_FLAGS Flags)
-{
-#ifdef DILIGENT_DEVELOPMENT
- if ((Flags & DRAW_FLAG_VERIFY_RENDER_TARGETS) != 0)
- DvpVerifyRenderTargets();
-#endif
-
- auto* pd3d11InputLayout = m_pPipelineState->GetD3D11InputLayout();
- if (pd3d11InputLayout != nullptr && !m_bCommittedD3D11VBsUpToDate)
- {
- DEV_CHECK_ERR(m_NumVertexStreams >= m_pPipelineState->GetNumBufferSlotsUsed(), "Currently bound pipeline state '", m_pPipelineState->GetDesc().Name, "' expects ", m_pPipelineState->GetNumBufferSlotsUsed(), " input buffer slots, but only ", m_NumVertexStreams, " is bound");
- CommitD3D11VertexBuffers(m_pPipelineState);
- }
-
-#ifdef DILIGENT_DEVELOPMENT
- if ((Flags & DRAW_FLAG_VERIFY_STATES) != 0)
- {
- for (UINT Slot = 0; Slot < m_NumVertexStreams; ++Slot)
- {
- if (auto* pBuffD3D11Impl = m_VertexStreams[Slot].pBuffer.RawPtr())
- {
- if (pBuffD3D11Impl->IsInKnownState() && pBuffD3D11Impl->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("Buffer '", pBuffD3D11Impl->GetDesc().Name, "' used as vertex buffer at slot ", Slot, " is in RESOURCE_STATE_UNORDERED_ACCESS state. "
- "Use appropriate transition mode or explicitly transition the buffer to RESOURCE_STATE_VERTEX_BUFFER state.");
- }
- }
- }
- }
-
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- // Verify bindings after all resources are set
- dbgVerifyCommittedSRVs();
- dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
- dbgVerifyCommittedSamplers();
- dbgVerifyCommittedCBs();
- dbgVerifyCommittedVertexBuffers();
- dbgVerifyCommittedIndexBuffer();
- dbgVerifyCommittedShaders();
- }
-#endif
-}
-
-void DeviceContextD3D11Impl::PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType)
-{
- if (m_CommittedIBFormat != IndexType)
- m_bCommittedD3D11IBUpToDate = false;
- if (!m_bCommittedD3D11IBUpToDate)
- {
- CommitD3D11IndexBuffer(IndexType);
- }
-#ifdef DILIGENT_DEVELOPMENT
- if (Flags & DRAW_FLAG_VERIFY_STATES)
- {
- if (m_pIndexBuffer->IsInKnownState() && m_pIndexBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("Buffer '", m_pIndexBuffer->GetDesc().Name,
- "' used as index buffer is in RESOURCE_STATE_UNORDERED_ACCESS state."
- " Use appropriate state transition mode or explicitly transition the buffer to RESOURCE_STATE_INDEX_BUFFER state.");
- }
- }
-#endif
- // We need to commit index buffer first because PrepareForDraw
- // may verify committed resources.
- PrepareForDraw(Flags);
-}
-
-void DeviceContextD3D11Impl::Draw(const DrawAttribs& Attribs)
-{
- if (!DvpVerifyDrawArguments(Attribs))
- return;
-
- PrepareForDraw(Attribs.Flags);
-
- if (Attribs.NumInstances > 1 || Attribs.FirstInstanceLocation != 0)
- m_pd3d11DeviceContext->DrawInstanced(Attribs.NumVertices, Attribs.NumInstances, Attribs.StartVertexLocation, Attribs.FirstInstanceLocation);
- else
- m_pd3d11DeviceContext->Draw(Attribs.NumVertices, Attribs.StartVertexLocation);
-}
-
-void DeviceContextD3D11Impl::DrawIndexed(const DrawIndexedAttribs& Attribs)
-{
- if (!DvpVerifyDrawIndexedArguments(Attribs))
- return;
-
- PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType);
-
- if (Attribs.NumInstances > 1 || Attribs.FirstInstanceLocation != 0)
- m_pd3d11DeviceContext->DrawIndexedInstanced(Attribs.NumIndices, Attribs.NumInstances, Attribs.FirstIndexLocation, Attribs.BaseVertex, Attribs.FirstInstanceLocation);
- else
- m_pd3d11DeviceContext->DrawIndexed(Attribs.NumIndices, Attribs.FirstIndexLocation, Attribs.BaseVertex);
-}
-
-void DeviceContextD3D11Impl::DrawIndirect(const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
-{
- if (!DvpVerifyDrawIndirectArguments(Attribs, pAttribsBuffer))
- return;
-
- PrepareForDraw(Attribs.Flags);
-
- auto* pIndirectDrawAttribsD3D11 = ValidatedCast<BufferD3D11Impl>(pAttribsBuffer);
- ID3D11Buffer* pd3d11ArgsBuff = pIndirectDrawAttribsD3D11->m_pd3d11Buffer;
- m_pd3d11DeviceContext->DrawInstancedIndirect(pd3d11ArgsBuff, Attribs.IndirectDrawArgsOffset);
-}
-
-
-void DeviceContextD3D11Impl::DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
-{
- if (!DvpVerifyDrawIndexedIndirectArguments(Attribs, pAttribsBuffer))
- return;
-
- PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType);
-
- auto* pIndirectDrawAttribsD3D11 = ValidatedCast<BufferD3D11Impl>(pAttribsBuffer);
- ID3D11Buffer* pd3d11ArgsBuff = pIndirectDrawAttribsD3D11->m_pd3d11Buffer;
- m_pd3d11DeviceContext->DrawIndexedInstancedIndirect(pd3d11ArgsBuff, Attribs.IndirectDrawArgsOffset);
-}
-
+ {
+ auto* pd3d11CS = pPipelineStateD3D11->GetD3D11ComputeShader();
+ if (pd3d11CS == nullptr)
+ {
+ LOG_ERROR("Compute shader is not set in the pipeline");
+ return;
+ }
+
+#define COMMIT_SHADER(SN, ShaderName) \
+ do \
+ { \
+ auto* pd3d11Shader = pPipelineStateD3D11->GetD3D11##ShaderName(); \
+ if (m_CommittedD3DShaders[SN##Ind] != pd3d11Shader) \
+ { \
+ m_CommittedD3DShaders[SN##Ind] = pd3d11Shader; \
+ m_pd3d11DeviceContext->SN##SetShader(pd3d11Shader, nullptr, 0); \
+ } \
+ } while (false)
+
+ COMMIT_SHADER(CS, ComputeShader);
+ }
+ else
+ {
+ COMMIT_SHADER(VS, VertexShader);
+ COMMIT_SHADER(PS, PixelShader);
+ COMMIT_SHADER(GS, GeometryShader);
+ COMMIT_SHADER(HS, HullShader);
+ COMMIT_SHADER(DS, DomainShader);
+#undef COMMIT_SHADER
+
+ m_pd3d11DeviceContext->OMSetBlendState(pPipelineStateD3D11->GetD3D11BlendState(), m_BlendFactors, Desc.GraphicsPipeline.SampleMask);
+ m_pd3d11DeviceContext->RSSetState(pPipelineStateD3D11->GetD3D11RasterizerState());
+ m_pd3d11DeviceContext->OMSetDepthStencilState(pPipelineStateD3D11->GetD3D11DepthStencilState(), m_StencilRef);
+
+ auto* pd3d11InputLayout = pPipelineStateD3D11->GetD3D11InputLayout();
+ // It is safe to perform raw pointer comparison as the device context
+ // keeps bound input layout alive
+ if (m_CommittedD3D11InputLayout != pd3d11InputLayout)
+ {
+ m_pd3d11DeviceContext->IASetInputLayout(pd3d11InputLayout);
+ m_CommittedD3D11InputLayout = pd3d11InputLayout;
+ }
+
+ auto PrimTopology = Desc.GraphicsPipeline.PrimitiveTopology;
+ if (m_CommittedPrimitiveTopology != PrimTopology)
+ {
+ m_CommittedPrimitiveTopology = PrimTopology;
+ m_CommittedD3D11PrimTopology = TopologyToD3D11Topology(PrimTopology);
+ m_pd3d11DeviceContext->IASetPrimitiveTopology(m_CommittedD3D11PrimTopology);
+ }
+ }
+}
+
+// clang-format off
+
+/// Helper macro used to create an array of device context methods to
+/// set particular resource for every shader stage
+#define DEFINE_D3D11CTX_FUNC_POINTERS(ArrayName, FuncName) \
+ typedef decltype (&ID3D11DeviceContext::VS##FuncName) T##FuncName##Type; \
+ static const T##FuncName##Type ArrayName[] = \
+ { \
+ &ID3D11DeviceContext::VS##FuncName, \
+ &ID3D11DeviceContext::PS##FuncName, \
+ &ID3D11DeviceContext::GS##FuncName, \
+ &ID3D11DeviceContext::HS##FuncName, \
+ &ID3D11DeviceContext::DS##FuncName, \
+ &ID3D11DeviceContext::CS##FuncName \
+ };
+
+ DEFINE_D3D11CTX_FUNC_POINTERS(SetCBMethods, SetConstantBuffers)
+ DEFINE_D3D11CTX_FUNC_POINTERS(SetSRVMethods, SetShaderResources)
+ DEFINE_D3D11CTX_FUNC_POINTERS(SetSamplerMethods, SetSamplers)
+
+ typedef decltype (&ID3D11DeviceContext::CSSetUnorderedAccessViews) TSetUnorderedAccessViewsType;
+ static const TSetUnorderedAccessViewsType SetUAVMethods[] =
+ {
+ nullptr, // VS
+ reinterpret_cast<TSetUnorderedAccessViewsType>(&ID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews), // Little hack for PS
+ nullptr, // GS
+ nullptr, // HS
+ nullptr, // DS
+ &ID3D11DeviceContext::CSSetUnorderedAccessViews // CS
+ };
+
+// clang-format on
+
+// http://diligentgraphics.com/diligent-engine/architecture/d3d11/committing-shader-resources-to-the-gpu-pipeline/
+template <bool TransitionResources, bool CommitResources>
+void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* pPSO, IShaderResourceBinding* pShaderResourceBinding, bool VerifyStates)
+{
+ VERIFY_EXPR(pPSO != nullptr);
+ static_assert(TransitionResources || CommitResources, "At least one of TransitionResources or CommitResources flags is expected to be true");
+
+ auto* pPipelineStateD3D11 = ValidatedCast<PipelineStateD3D11Impl>(pPSO);
+
+ if (pShaderResourceBinding == nullptr)
+ {
+#ifdef DILIGENT_DEVELOPMENT
+ bool ResourcesPresent = false;
+ for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaders(); ++s)
+ {
+ auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
+ if (pShaderD3D11->GetD3D11Resources()->GetTotalResources() > 0)
+ ResourcesPresent = true;
+ }
+
+ if (ResourcesPresent)
+ {
+ LOG_ERROR_MESSAGE("Pipeline state '", pPSO->GetDesc().Name, "' requires shader resource binding object to ",
+ (CommitResources ? "commit" : "transition"), " resources, but none is provided.");
+ }
+#endif
+ return;
+ }
+
+
+ auto pShaderResBindingD3D11 = ValidatedCast<ShaderResourceBindingD3D11Impl>(pShaderResourceBinding);
+#ifdef DILIGENT_DEVELOPMENT
+ if (pPipelineStateD3D11->IsIncompatibleWith(pShaderResourceBinding->GetPipelineState()))
+ {
+ LOG_ERROR_MESSAGE("Shader resource binding does not match Pipeline State");
+ return;
+ }
+#endif
+
+ auto NumShaders = pShaderResBindingD3D11->GetNumActiveShaders();
+ VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaders(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state");
+
+#ifdef DILIGENT_DEVELOPMENT
+ {
+ bool StaticResourcesPresent = false;
+ for (Uint32 s = 0; s < NumShaders; ++s)
+ {
+ const auto& StaticResLayout = pPipelineStateD3D11->GetStaticResourceLayout(s);
+ if (StaticResLayout.GetTotalResourceCount() > 0)
+ StaticResourcesPresent = true;
+ }
+ // Static resource bindings are verified in BindStaticShaderResources()
+ if (StaticResourcesPresent && !pShaderResBindingD3D11->IsStaticResourcesBound())
+ {
+ LOG_ERROR_MESSAGE("Static resources have not been initialized in the shader resource binding object being committed for PSO '", pPSO->GetDesc().Name, "'. Please call IShaderResourceBinding::InitializeStaticResources().");
+ }
+ }
+#endif
+
+ bool ClearPixelShaderUAVs = m_NumCommittedUAVs[PSInd] > 0;
+ // First, commit all UAVs for all shader stages. This will unbind them from input
+ for (Uint32 s = 0; s < NumShaders; ++s)
+ {
+ auto ShaderTypeInd = pShaderResBindingD3D11->GetActiveShaderTypeIndex(s);
+
+#ifdef DILIGENT_DEVELOPMENT
+ auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
+ VERIFY_EXPR(ShaderTypeInd == static_cast<Int32>(GetShaderTypeIndex(pShaderD3D11->GetDesc().ShaderType)));
+#endif
+
+ auto& Cache = pShaderResBindingD3D11->GetResourceCache(s);
+ auto NumUAVs = Cache.GetUAVCount();
+ if (NumUAVs)
+ {
+ ShaderResourceCacheD3D11::CachedResource* CachedUAVResources;
+ ID3D11UnorderedAccessView** d3d11UAVs;
+ Cache.GetUAVArrays(CachedUAVResources, d3d11UAVs);
+
+ auto* CommittedD3D11UAVs = m_CommittedD3D11UAVs[ShaderTypeInd];
+ auto* CommittedD3D11UAVRes = m_CommittedD3D11UAVResources[ShaderTypeInd];
+
+ if (ShaderTypeInd == PSInd)
+ ClearPixelShaderUAVs = false;
+
+ UINT MinSlot = UINT_MAX;
+ UINT MaxSlot = 0;
+
+ for (Uint32 uav = 0; uav < NumUAVs; ++uav)
+ {
+ VERIFY_EXPR(uav < Cache.GetUAVCount());
+ auto& UAVRes = CachedUAVResources[uav];
+ // WARNING! This code is not thread-safe. It is up to the application to make
+ // sure that multiple threads do not modify the texture state simultaneously.
+ if (TransitionResources)
+ {
+ if (auto* pTexture = ValidatedCast<TextureBaseD3D11>(UAVRes.pTexture))
+ {
+ if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ if (pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
+ UnbindTextureFromInput(pTexture, UAVRes.pd3d11Resource);
+ pTexture->SetState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+ }
+ else if (auto* pBuffer = ValidatedCast<BufferD3D11Impl>(UAVRes.pBuffer))
+ {
+ if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ if ((pBuffer->GetState() & RESOURCE_STATE_GENERIC_READ) != 0)
+ UnbindBufferFromInput(pBuffer, UAVRes.pd3d11Resource);
+ pBuffer->SetState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (VerifyStates)
+ {
+ if (const auto* pTexture = ValidatedCast<TextureBaseD3D11>(UAVRes.pTexture))
+ {
+ if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("Texture '", pTexture->GetDesc().Name, "' has not been transitioned to Unordered Access state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the texture to required state.");
+ }
+ }
+ else if (const auto* pBuffer = ValidatedCast<BufferD3D11Impl>(UAVRes.pBuffer))
+ {
+ if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", pBuffer->GetDesc().Name, "' has not been transitioned to Unordered Access state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state.");
+ }
+ }
+ }
+#endif
+ if (CommitResources)
+ {
+ bool IsNewUAV = CommittedD3D11UAVs[uav] != d3d11UAVs[uav];
+ MinSlot = IsNewUAV ? std::min(MinSlot, uav) : MinSlot;
+ MaxSlot = IsNewUAV ? uav : MaxSlot;
+
+ CommittedD3D11UAVRes[uav] = UAVRes.pd3d11Resource;
+ CommittedD3D11UAVs[uav] = d3d11UAVs[uav];
+ }
+ }
+
+ if (CommitResources)
+ {
+ if (MinSlot != UINT_MAX || ShaderTypeInd == PSInd && m_NumCommittedUAVs[PSInd] != NumUAVs)
+ {
+ // Something has changed
+ if (ShaderTypeInd == PSInd)
+ {
+ // Pixel shader UAVs cannot be set independently; they all need to be set at the same time.
+ // https://docs.microsoft.com/en-us/windows/desktop/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews#remarks
+ auto StartUAVSlot = m_NumBoundRenderTargets;
+ VERIFY(NumUAVs > StartUAVSlot, "Number of UAVs must be greater than the render target count");
+ m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
+ D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
+ StartUAVSlot, NumUAVs - StartUAVSlot, CommittedD3D11UAVs + StartUAVSlot, nullptr);
+ // Clear previously bound UAVs, but do not clear lower slots as if
+ // render target count reduces, we will bind these UAVs in CommitRenderTargets()
+ for (Uint32 uav = NumUAVs; uav < m_NumCommittedUAVs[ShaderTypeInd]; ++uav)
+ {
+ CommittedD3D11UAVRes[uav] = nullptr;
+ CommittedD3D11UAVs[uav] = nullptr;
+ }
+ m_NumCommittedUAVs[ShaderTypeInd] = static_cast<Uint8>(NumUAVs);
+ }
+ else
+ {
+ // This can only be CS
+ auto SetUAVMethod = SetUAVMethods[ShaderTypeInd];
+ (m_pd3d11DeviceContext->*SetUAVMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11UAVs + MinSlot, nullptr);
+ m_NumCommittedUAVs[ShaderTypeInd] = std::max(m_NumCommittedUAVs[ShaderTypeInd], static_cast<Uint8>(NumUAVs));
+ }
+ }
+
+#ifdef DILIGENT_DEVELOPMENT
+ if ((m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) != 0 && ShaderTypeInd == CSInd)
+ {
+ dbgVerifyCommittedUAVs(pShaderD3D11->GetDesc().ShaderType);
+ }
+#endif
+ }
+ }
+ }
+
+ if (ClearPixelShaderUAVs)
+ {
+ // If pixel shader stage is inactive or does not use UAVs, unbind all committed UAVs.
+ // This is important as UnbindPixelShaderUAV<> function may need to rebind
+ // existing UAVs and the UAVs pointed to by CommittedD3D11UAVRes must be alive
+ // (we do not keep strong references to d3d11 UAVs)
+ auto* CommittedD3D11UAVs = m_CommittedD3D11UAVs[PSInd];
+ auto* CommittedD3D11UAVRes = m_CommittedD3D11UAVResources[PSInd];
+ auto& NumCommittedPixelShaderUAVs = m_NumCommittedUAVs[PSInd];
+ for (Uint32 uav = 0; uav < NumCommittedPixelShaderUAVs; ++uav)
+ {
+ CommittedD3D11UAVRes[uav] = nullptr;
+ CommittedD3D11UAVs[uav] = nullptr;
+ }
+ m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
+ D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
+ 0, 0, nullptr, nullptr);
+ NumCommittedPixelShaderUAVs = 0;
+ }
+
+ // Commit input resources (CBs, SRVs and Samplers)
+ for (Uint32 s = 0; s < NumShaders; ++s)
+ {
+ auto ShaderTypeInd = pShaderResBindingD3D11->GetActiveShaderTypeIndex(s);
+
+#ifdef DILIGENT_DEVELOPMENT
+ auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
+ VERIFY_EXPR(ShaderTypeInd == static_cast<Int32>(GetShaderTypeIndex(pShaderD3D11->GetDesc().ShaderType)));
+#endif
+
+ auto& Cache = pShaderResBindingD3D11->GetResourceCache(s);
+
+ // Transition and commit Constant Buffers
+ auto NumCBs = Cache.GetCBCount();
+ if (NumCBs)
+ {
+ ShaderResourceCacheD3D11::CachedCB* CachedCBs;
+ ID3D11Buffer** d3d11CBs;
+ Cache.GetCBArrays(CachedCBs, d3d11CBs);
+
+ auto* CommittedD3D11CBs = m_CommittedD3D11CBs[ShaderTypeInd];
+ UINT MinSlot = UINT_MAX;
+ UINT MaxSlot = 0;
+ for (Uint32 cb = 0; cb < NumCBs; ++cb)
+ {
+ VERIFY_EXPR(cb < Cache.GetCBCount());
+
+ if (TransitionResources)
+ {
+ auto& CB = CachedCBs[cb];
+ if (auto* pBuff = CB.pBuff.RawPtr<BufferD3D11Impl>())
+ {
+ // WARNING! This code is not thread-safe. It is up to the application to make
+ // sure that multiple threads do not modify the buffer state simultaneously.
+ if (pBuff->IsInKnownState() && !pBuff->CheckState(RESOURCE_STATE_CONSTANT_BUFFER))
+ {
+ if (pBuff->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ // Even though we have unbound resources from UAV, we only checked shader
+ // stages active in current PSO, so we still may need to unbind the resource
+ // from UAV (for instance, unbind resource from CS UAV when running draw command).
+ UnbindResourceFromUAV(pBuff, d3d11CBs[cb]);
+ pBuff->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+ pBuff->AddState(RESOURCE_STATE_CONSTANT_BUFFER);
+ }
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (VerifyStates)
+ {
+ VERIFY_EXPR(CommitResources);
+ const auto& CB = CachedCBs[cb];
+ if (auto* pBuff = CB.pBuff.RawPtr<const BufferD3D11Impl>())
+ {
+ if (pBuff->IsInKnownState() && !pBuff->CheckState(RESOURCE_STATE_CONSTANT_BUFFER))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", pBuff->GetDesc().Name, "' has not been transitioned to Constant Buffer state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state.");
+ }
+ }
+ }
+#endif
+
+ if (CommitResources)
+ {
+ bool IsNewCB = CommittedD3D11CBs[cb] != d3d11CBs[cb];
+ MinSlot = IsNewCB ? std::min(MinSlot, cb) : MinSlot;
+ MaxSlot = IsNewCB ? cb : MaxSlot;
+ CommittedD3D11CBs[cb] = d3d11CBs[cb];
+ }
+ }
+
+ if (CommitResources)
+ {
+ if (MinSlot != UINT_MAX)
+ {
+ auto SetCBMethod = SetCBMethods[ShaderTypeInd];
+ (m_pd3d11DeviceContext->*SetCBMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11CBs + MinSlot);
+ m_NumCommittedCBs[ShaderTypeInd] = std::max(m_NumCommittedCBs[ShaderTypeInd], static_cast<Uint8>(NumCBs));
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ dbgVerifyCommittedCBs(pShaderD3D11->GetDesc().ShaderType);
+ }
+#endif
+ }
+ }
+
+
+ // Transition and commit Shader Resource Views
+ auto NumSRVs = Cache.GetSRVCount();
+ if (NumSRVs)
+ {
+ ShaderResourceCacheD3D11::CachedResource* CachedSRVResources;
+ ID3D11ShaderResourceView** d3d11SRVs;
+ Cache.GetSRVArrays(CachedSRVResources, d3d11SRVs);
+
+ auto* CommittedD3D11SRVs = m_CommittedD3D11SRVs[ShaderTypeInd];
+ auto* CommittedD3D11SRVRes = m_CommittedD3D11SRVResources[ShaderTypeInd];
+
+ UINT MinSlot = UINT_MAX;
+ UINT MaxSlot = 0;
+
+ for (Uint32 srv = 0; srv < NumSRVs; ++srv)
+ {
+ VERIFY_EXPR(srv < Cache.GetSRVCount());
+ auto& SRVRes = CachedSRVResources[srv];
+ // WARNING! This code is not thread-safe. It is up to the application to make
+ // sure that multiple threads do not modify the texture state simultaneously.
+ if (TransitionResources)
+ {
+ if (auto* pTexture = ValidatedCast<TextureBaseD3D11>(SRVRes.pTexture))
+ {
+ if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
+ {
+ if (pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ // Even though we have unbound resources from UAV, we only checked shader
+ // stages active in current PSO, so we still may need to unbind the resource
+ // from UAV (for instance, unbind resource from CS UAV when running draw command).
+ UnbindResourceFromUAV(pTexture, SRVRes.pd3d11Resource);
+ pTexture->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+
+ if (pTexture->CheckState(RESOURCE_STATE_RENDER_TARGET))
+ UnbindTextureFromRenderTarget(pTexture);
+
+ if (pTexture->CheckState(RESOURCE_STATE_DEPTH_WRITE))
+ UnbindTextureFromDepthStencil(pTexture);
+
+ pTexture->SetState(RESOURCE_STATE_SHADER_RESOURCE);
+ }
+ }
+ else if (auto* pBuffer = ValidatedCast<BufferD3D11Impl>(SRVRes.pBuffer))
+ {
+ if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
+ {
+ if (pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ UnbindResourceFromUAV(pBuffer, SRVRes.pd3d11Resource);
+ pBuffer->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+ pBuffer->AddState(RESOURCE_STATE_SHADER_RESOURCE);
+ }
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (VerifyStates)
+ {
+ VERIFY_EXPR(CommitResources);
+ if (const auto* pTexture = ValidatedCast<TextureBaseD3D11>(SRVRes.pTexture))
+ {
+ if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
+ {
+ LOG_ERROR_MESSAGE("Texture '", pTexture->GetDesc().Name, "' has not been transitioned to Shader Resource state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the texture to required state.");
+ }
+ }
+ else if (const auto* pBuffer = ValidatedCast<BufferD3D11Impl>(SRVRes.pBuffer))
+ {
+ if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", pBuffer->GetDesc().Name, "' has not been transitioned to Shader Resource state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state.");
+ }
+ }
+ }
+#endif
+
+ if (CommitResources)
+ {
+ bool IsNewSRV = CommittedD3D11SRVs[srv] != d3d11SRVs[srv];
+ MinSlot = IsNewSRV ? std::min(MinSlot, srv) : MinSlot;
+ MaxSlot = IsNewSRV ? srv : MaxSlot;
+
+ CommittedD3D11SRVRes[srv] = SRVRes.pd3d11Resource;
+ CommittedD3D11SRVs[srv] = d3d11SRVs[srv];
+ }
+ }
+
+ if (CommitResources)
+ {
+ if (MinSlot != UINT_MAX)
+ {
+ auto SetSRVMethod = SetSRVMethods[ShaderTypeInd];
+ (m_pd3d11DeviceContext->*SetSRVMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11SRVs + MinSlot);
+ m_NumCommittedSRVs[ShaderTypeInd] = std::max(m_NumCommittedSRVs[ShaderTypeInd], static_cast<Uint8>(NumSRVs));
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ dbgVerifyCommittedSRVs(pShaderD3D11->GetDesc().ShaderType);
+ }
+#endif
+ }
+ }
+
+
+ // Commit samplers (no transitions for samplers)
+ if (CommitResources)
+ {
+ auto NumSamplers = Cache.GetSamplerCount();
+ if (NumSamplers)
+ {
+ ShaderResourceCacheD3D11::CachedSampler* CachedSamplers;
+ ID3D11SamplerState** d3d11Samplers;
+ Cache.GetSamplerArrays(CachedSamplers, d3d11Samplers);
+
+ auto* CommittedD3D11Samplers = m_CommittedD3D11Samplers[ShaderTypeInd];
+ UINT MinSlot = std::numeric_limits<UINT>::max();
+ UINT MaxSlot = 0;
+ for (Uint32 sam = 0; sam < NumSamplers; ++sam)
+ {
+ VERIFY_EXPR(sam < Cache.GetSamplerCount());
+
+ bool IsNewSam = CommittedD3D11Samplers[sam] != d3d11Samplers[sam];
+ MinSlot = IsNewSam ? std::min(MinSlot, sam) : MinSlot;
+ MaxSlot = IsNewSam ? sam : MaxSlot;
+
+ CommittedD3D11Samplers[sam] = d3d11Samplers[sam];
+ }
+
+ if (MinSlot != UINT_MAX)
+ {
+ auto SetSamplerMethod = SetSamplerMethods[ShaderTypeInd];
+ (m_pd3d11DeviceContext->*SetSamplerMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11Samplers + MinSlot);
+ m_NumCommittedSamplers[ShaderTypeInd] = std::max(m_NumCommittedSamplers[ShaderTypeInd], static_cast<Uint8>(NumSamplers));
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ dbgVerifyCommittedSamplers(pShaderD3D11->GetDesc().ShaderType);
+ }
+#endif
+ }
+ }
+
+
+
+#ifdef DILIGENT_DEVELOPMENT
+ if (CommitResources && (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_SHADER_RESOURCES) != 0)
+ {
+ // Use full resource layout to verify that all required resources are committed
+ pShaderD3D11->GetD3D11Resources()->dvpVerifyCommittedResources(
+ m_CommittedD3D11CBs[ShaderTypeInd],
+ m_CommittedD3D11SRVs[ShaderTypeInd],
+ m_CommittedD3D11SRVResources[ShaderTypeInd],
+ m_CommittedD3D11Samplers[ShaderTypeInd],
+ m_CommittedD3D11UAVs[ShaderTypeInd],
+ m_CommittedD3D11UAVResources[ShaderTypeInd],
+ Cache);
+ }
+#endif
+ }
+}
+
+void DeviceContextD3D11Impl::TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding)
+{
+ DEV_CHECK_ERR(pPipelineState != nullptr, "Pipeline state must not be null");
+ DEV_CHECK_ERR(pShaderResourceBinding != nullptr, "Shader resource binding must not be null");
+ TransitionAndCommitShaderResources<true, false>(pPipelineState, pShaderResourceBinding, false);
+}
+
+void DeviceContextD3D11Impl::CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ if (!DeviceContextBase::CommitShaderResources(pShaderResourceBinding, StateTransitionMode, 0 /*Dummy*/))
+ return;
+
+ if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ TransitionAndCommitShaderResources<true, true>(m_pPipelineState, pShaderResourceBinding, false);
+ else
+ TransitionAndCommitShaderResources<false, true>(m_pPipelineState, pShaderResourceBinding, StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY);
+}
+
+void DeviceContextD3D11Impl::SetStencilRef(Uint32 StencilRef)
+{
+ if (TDeviceContextBase::SetStencilRef(StencilRef, 0))
+ {
+ ID3D11DepthStencilState* pd3d11DSS =
+ m_pPipelineState ? m_pPipelineState->GetD3D11DepthStencilState() : nullptr;
+ m_pd3d11DeviceContext->OMSetDepthStencilState(pd3d11DSS, m_StencilRef);
+ }
+}
+
+
+void DeviceContextD3D11Impl::SetBlendFactors(const float* pBlendFactors)
+{
+ if (TDeviceContextBase::SetBlendFactors(pBlendFactors, 0))
+ {
+ Uint32 SampleMask = 0xFFFFFFFF;
+ ID3D11BlendState* pd3d11BS = nullptr;
+ if (m_pPipelineState)
+ {
+ SampleMask = m_pPipelineState->GetDesc().GraphicsPipeline.SampleMask;
+ pd3d11BS = m_pPipelineState->GetD3D11BlendState();
+ }
+ m_pd3d11DeviceContext->OMSetBlendState(pd3d11BS, m_BlendFactors, SampleMask);
+ }
+}
+
+void DeviceContextD3D11Impl::CommitD3D11IndexBuffer(VALUE_TYPE IndexType)
+{
+ if (!m_pIndexBuffer)
+ {
+ LOG_ERROR_MESSAGE("Index buffer is not set up for indexed draw command");
+ return;
+ }
+
+ BufferD3D11Impl* pBuffD3D11 = m_pIndexBuffer.RawPtr<BufferD3D11Impl>();
+ if (m_CommittedD3D11IndexBuffer != pBuffD3D11->m_pd3d11Buffer ||
+ m_CommittedIBFormat != IndexType ||
+ m_CommittedD3D11IndexDataStartOffset != m_IndexDataStartOffset)
+ {
+ DXGI_FORMAT D3D11IndexFmt = DXGI_FORMAT_UNKNOWN;
+ if (IndexType == VT_UINT32)
+ D3D11IndexFmt = DXGI_FORMAT_R32_UINT;
+ else if (IndexType == VT_UINT16)
+ D3D11IndexFmt = DXGI_FORMAT_R16_UINT;
+ else
+ {
+ LOG_ERROR_MESSAGE("Unsupported index format. Only R16_UINT and R32_UINT are allowed.");
+ return;
+ }
+
+ m_CommittedD3D11IndexBuffer = pBuffD3D11->m_pd3d11Buffer;
+ m_CommittedIBFormat = IndexType;
+ m_CommittedD3D11IndexDataStartOffset = m_IndexDataStartOffset;
+ m_pd3d11DeviceContext->IASetIndexBuffer(pBuffD3D11->m_pd3d11Buffer, D3D11IndexFmt, m_IndexDataStartOffset);
+ }
+
+ pBuffD3D11->AddState(RESOURCE_STATE_INDEX_BUFFER);
+ m_bCommittedD3D11IBUpToDate = true;
+}
+
+void DeviceContextD3D11Impl::CommitD3D11VertexBuffers(PipelineStateD3D11Impl* pPipelineStateD3D11)
+{
+ VERIFY(m_NumVertexStreams <= MAX_BUFFER_SLOTS, "Too many buffers are being set");
+ UINT NumBuffersToSet = std::max(m_NumVertexStreams, m_NumCommittedD3D11VBs);
+
+ bool BindVBs = m_NumVertexStreams != m_NumCommittedD3D11VBs;
+
+ for (UINT Slot = 0; Slot < m_NumVertexStreams; ++Slot)
+ {
+ auto& CurrStream = m_VertexStreams[Slot];
+ auto* pBuffD3D11Impl = CurrStream.pBuffer.RawPtr();
+ ID3D11Buffer* pd3d11Buffer = pBuffD3D11Impl ? pBuffD3D11Impl->m_pd3d11Buffer : nullptr;
+ auto Stride = pPipelineStateD3D11->GetBufferStride(Slot);
+ auto Offset = CurrStream.Offset;
+
+ // It is safe to perform raw pointer check because device context keeps
+ // all buffers alive.
+ if (m_CommittedD3D11VertexBuffers[Slot] != pd3d11Buffer ||
+ m_CommittedD3D11VBStrides[Slot] != Stride ||
+ m_CommittedD3D11VBOffsets[Slot] != Offset)
+ {
+ BindVBs = true;
+
+ m_CommittedD3D11VertexBuffers[Slot] = pd3d11Buffer;
+ m_CommittedD3D11VBStrides[Slot] = Stride;
+ m_CommittedD3D11VBOffsets[Slot] = Offset;
+
+ if (pBuffD3D11Impl)
+ pBuffD3D11Impl->AddState(RESOURCE_STATE_VERTEX_BUFFER);
+ }
+ }
+
+ // Unbind all buffers at the end
+ for (Uint32 Slot = m_NumVertexStreams; Slot < m_NumCommittedD3D11VBs; ++Slot)
+ {
+ m_CommittedD3D11VertexBuffers[Slot] = nullptr;
+ m_CommittedD3D11VBStrides[Slot] = 0;
+ m_CommittedD3D11VBOffsets[Slot] = 0;
+ }
+
+ m_NumCommittedD3D11VBs = m_NumVertexStreams;
+
+ if (BindVBs)
+ {
+ m_pd3d11DeviceContext->IASetVertexBuffers(0, NumBuffersToSet, m_CommittedD3D11VertexBuffers, m_CommittedD3D11VBStrides, m_CommittedD3D11VBOffsets);
+ }
+
+ m_bCommittedD3D11VBsUpToDate = true;
+}
+
+void DeviceContextD3D11Impl::PrepareForDraw(DRAW_FLAGS Flags)
+{
+#ifdef DILIGENT_DEVELOPMENT
+ if ((Flags & DRAW_FLAG_VERIFY_RENDER_TARGETS) != 0)
+ DvpVerifyRenderTargets();
+#endif
+
+ auto* pd3d11InputLayout = m_pPipelineState->GetD3D11InputLayout();
+ if (pd3d11InputLayout != nullptr && !m_bCommittedD3D11VBsUpToDate)
+ {
+ DEV_CHECK_ERR(m_NumVertexStreams >= m_pPipelineState->GetNumBufferSlotsUsed(), "Currently bound pipeline state '", m_pPipelineState->GetDesc().Name, "' expects ", m_pPipelineState->GetNumBufferSlotsUsed(), " input buffer slots, but only ", m_NumVertexStreams, " is bound");
+ CommitD3D11VertexBuffers(m_pPipelineState);
+ }
+
+#ifdef DILIGENT_DEVELOPMENT
+ if ((Flags & DRAW_FLAG_VERIFY_STATES) != 0)
+ {
+ for (UINT Slot = 0; Slot < m_NumVertexStreams; ++Slot)
+ {
+ if (auto* pBuffD3D11Impl = m_VertexStreams[Slot].pBuffer.RawPtr())
+ {
+ if (pBuffD3D11Impl->IsInKnownState() && pBuffD3D11Impl->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", pBuffD3D11Impl->GetDesc().Name, "' used as vertex buffer at slot ", Slot, " is in RESOURCE_STATE_UNORDERED_ACCESS state. "
+ "Use appropriate transition mode or explicitly transition the buffer to RESOURCE_STATE_VERTEX_BUFFER state.");
+ }
+ }
+ }
+ }
+
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ // Verify bindings after all resources are set
+ dbgVerifyCommittedSRVs();
+ dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
+ dbgVerifyCommittedSamplers();
+ dbgVerifyCommittedCBs();
+ dbgVerifyCommittedVertexBuffers();
+ dbgVerifyCommittedIndexBuffer();
+ dbgVerifyCommittedShaders();
+ }
+#endif
+}
+
+void DeviceContextD3D11Impl::PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType)
+{
+ if (m_CommittedIBFormat != IndexType)
+ m_bCommittedD3D11IBUpToDate = false;
+ if (!m_bCommittedD3D11IBUpToDate)
+ {
+ CommitD3D11IndexBuffer(IndexType);
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ if (Flags & DRAW_FLAG_VERIFY_STATES)
+ {
+ if (m_pIndexBuffer->IsInKnownState() && m_pIndexBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", m_pIndexBuffer->GetDesc().Name,
+ "' used as index buffer is in RESOURCE_STATE_UNORDERED_ACCESS state."
+ " Use appropriate state transition mode or explicitly transition the buffer to RESOURCE_STATE_INDEX_BUFFER state.");
+ }
+ }
+#endif
+ // We need to commit index buffer first because PrepareForDraw
+ // may verify committed resources.
+ PrepareForDraw(Flags);
+}
+
+void DeviceContextD3D11Impl::Draw(const DrawAttribs& Attribs)
+{
+ if (!DvpVerifyDrawArguments(Attribs))
+ return;
+
+ PrepareForDraw(Attribs.Flags);
+
+ if (Attribs.NumInstances > 1 || Attribs.FirstInstanceLocation != 0)
+ m_pd3d11DeviceContext->DrawInstanced(Attribs.NumVertices, Attribs.NumInstances, Attribs.StartVertexLocation, Attribs.FirstInstanceLocation);
+ else
+ m_pd3d11DeviceContext->Draw(Attribs.NumVertices, Attribs.StartVertexLocation);
+}
+
+void DeviceContextD3D11Impl::DrawIndexed(const DrawIndexedAttribs& Attribs)
+{
+ if (!DvpVerifyDrawIndexedArguments(Attribs))
+ return;
+
+ PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType);
+
+ if (Attribs.NumInstances > 1 || Attribs.FirstInstanceLocation != 0)
+ m_pd3d11DeviceContext->DrawIndexedInstanced(Attribs.NumIndices, Attribs.NumInstances, Attribs.FirstIndexLocation, Attribs.BaseVertex, Attribs.FirstInstanceLocation);
+ else
+ m_pd3d11DeviceContext->DrawIndexed(Attribs.NumIndices, Attribs.FirstIndexLocation, Attribs.BaseVertex);
+}
+
+void DeviceContextD3D11Impl::DrawIndirect(const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
+{
+ if (!DvpVerifyDrawIndirectArguments(Attribs, pAttribsBuffer))
+ return;
+
+ PrepareForDraw(Attribs.Flags);
+
+ auto* pIndirectDrawAttribsD3D11 = ValidatedCast<BufferD3D11Impl>(pAttribsBuffer);
+ ID3D11Buffer* pd3d11ArgsBuff = pIndirectDrawAttribsD3D11->m_pd3d11Buffer;
+ m_pd3d11DeviceContext->DrawInstancedIndirect(pd3d11ArgsBuff, Attribs.IndirectDrawArgsOffset);
+}
+
+
+void DeviceContextD3D11Impl::DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
+{
+ if (!DvpVerifyDrawIndexedIndirectArguments(Attribs, pAttribsBuffer))
+ return;
+
+ PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType);
+
+ auto* pIndirectDrawAttribsD3D11 = ValidatedCast<BufferD3D11Impl>(pAttribsBuffer);
+ ID3D11Buffer* pd3d11ArgsBuff = pIndirectDrawAttribsD3D11->m_pd3d11Buffer;
+ m_pd3d11DeviceContext->DrawIndexedInstancedIndirect(pd3d11ArgsBuff, Attribs.IndirectDrawArgsOffset);
+}
+
void DeviceContextD3D11Impl::DrawMesh(const DrawMeshAttribs& Attribs)
{
UNSUPPORTED("DrawMesh is not supported in DirectX 11");
@@ -880,1443 +880,1443 @@ void DeviceContextD3D11Impl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Att
UNSUPPORTED("DrawMeshIndirect is not supported in DirectX 11");
}
-void DeviceContextD3D11Impl::DispatchCompute(const DispatchComputeAttribs& Attribs)
-{
- if (!DvpVerifyDispatchArguments(Attribs))
- return;
-
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- // Verify bindings
- dbgVerifyCommittedSRVs();
- dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
- dbgVerifyCommittedSamplers();
- dbgVerifyCommittedCBs();
- dbgVerifyCommittedShaders();
- }
-#endif
-
- m_pd3d11DeviceContext->Dispatch(Attribs.ThreadGroupCountX, Attribs.ThreadGroupCountY, Attribs.ThreadGroupCountZ);
-}
-
-void DeviceContextD3D11Impl::DispatchComputeIndirect(const DispatchComputeIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
-{
- if (!DvpVerifyDispatchIndirectArguments(Attribs, pAttribsBuffer))
- return;
-
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- // Verify bindings
- dbgVerifyCommittedSRVs();
- dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
- dbgVerifyCommittedSamplers();
- dbgVerifyCommittedCBs();
- dbgVerifyCommittedShaders();
- }
-#endif
-
- auto* pd3d11Buff = ValidatedCast<BufferD3D11Impl>(pAttribsBuffer)->GetD3D11Buffer();
- m_pd3d11DeviceContext->DispatchIndirect(pd3d11Buff, Attribs.DispatchArgsByteOffset);
-}
-
-
-void DeviceContextD3D11Impl::ClearDepthStencil(ITextureView* pView,
- CLEAR_DEPTH_STENCIL_FLAGS ClearFlags,
- float fDepth,
- Uint8 Stencil,
- RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
-{
- if (!TDeviceContextBase::ClearDepthStencil(pView))
- return;
-
- VERIFY_EXPR(pView != nullptr);
-
- auto* pViewD3D11 = ValidatedCast<TextureViewD3D11Impl>(pView);
- auto* pd3d11DSV = static_cast<ID3D11DepthStencilView*>(pViewD3D11->GetD3D11View());
-
- UINT32 d3d11ClearFlags = 0;
- if (ClearFlags & CLEAR_DEPTH_FLAG) d3d11ClearFlags |= D3D11_CLEAR_DEPTH;
- if (ClearFlags & CLEAR_STENCIL_FLAG) d3d11ClearFlags |= D3D11_CLEAR_STENCIL;
- // The full extent of the resource view is always cleared.
- // Viewport and scissor settings are not applied.
- m_pd3d11DeviceContext->ClearDepthStencilView(pd3d11DSV, d3d11ClearFlags, fDepth, Stencil);
-}
-
-void DeviceContextD3D11Impl::ClearRenderTarget(ITextureView* pView, const float* RGBA, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
-{
- if (!TDeviceContextBase::ClearRenderTarget(pView))
- return;
-
- VERIFY_EXPR(pView != nullptr);
-
- auto* pViewD3D11 = ValidatedCast<TextureViewD3D11Impl>(pView);
- auto* pd3d11RTV = static_cast<ID3D11RenderTargetView*>(pViewD3D11->GetD3D11View());
-
- static const float Zero[4] = {0.f, 0.f, 0.f, 0.f};
- if (RGBA == nullptr)
- RGBA = Zero;
-
- // The full extent of the resource view is always cleared.
- // Viewport and scissor settings are not applied.
- m_pd3d11DeviceContext->ClearRenderTargetView(pd3d11RTV, RGBA);
-}
-
-void DeviceContextD3D11Impl::Flush()
-{
- m_pd3d11DeviceContext->Flush();
-}
-
-void DeviceContextD3D11Impl::UpdateBuffer(IBuffer* pBuffer,
- Uint32 Offset,
- Uint32 Size,
- const void* pData,
- RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
-{
- TDeviceContextBase::UpdateBuffer(pBuffer, Offset, Size, pData, StateTransitionMode);
-
- auto* pBufferD3D11Impl = ValidatedCast<BufferD3D11Impl>(pBuffer);
-
- D3D11_BOX DstBox;
- DstBox.left = Offset;
- DstBox.right = Offset + Size;
- DstBox.top = 0;
- DstBox.bottom = 1;
- DstBox.front = 0;
- DstBox.back = 1;
- auto* pDstBox = (Offset == 0 && Size == pBufferD3D11Impl->GetDesc().uiSizeInBytes) ? nullptr : &DstBox;
- m_pd3d11DeviceContext->UpdateSubresource(pBufferD3D11Impl->m_pd3d11Buffer, 0, pDstBox, pData, 0, 0);
-}
-
-void DeviceContextD3D11Impl::CopyBuffer(IBuffer* pSrcBuffer,
- Uint32 SrcOffset,
- RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
- IBuffer* pDstBuffer,
- Uint32 DstOffset,
- Uint32 Size,
- RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode)
-{
- TDeviceContextBase::CopyBuffer(pSrcBuffer, SrcOffset, SrcBufferTransitionMode, pDstBuffer, DstOffset, Size, DstBufferTransitionMode);
-
- auto* pSrcBufferD3D11Impl = ValidatedCast<BufferD3D11Impl>(pSrcBuffer);
- auto* pDstBufferD3D11Impl = ValidatedCast<BufferD3D11Impl>(pDstBuffer);
-
- D3D11_BOX SrcBox;
- SrcBox.left = SrcOffset;
- SrcBox.right = SrcOffset + Size;
- SrcBox.top = 0;
- SrcBox.bottom = 1;
- SrcBox.front = 0;
- SrcBox.back = 1;
- m_pd3d11DeviceContext->CopySubresourceRegion(pDstBufferD3D11Impl->m_pd3d11Buffer, 0, DstOffset, 0, 0, pSrcBufferD3D11Impl->m_pd3d11Buffer, 0, &SrcBox);
-}
-
-
-void DeviceContextD3D11Impl::MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData)
-{
- TDeviceContextBase::MapBuffer(pBuffer, MapType, MapFlags, pMappedData);
-
- auto* pBufferD3D11 = ValidatedCast<BufferD3D11Impl>(pBuffer);
- D3D11_MAP d3d11MapType = static_cast<D3D11_MAP>(0);
- UINT d3d11MapFlags = 0;
- MapParamsToD3D11MapParams(MapType, MapFlags, d3d11MapType, d3d11MapFlags);
-
- D3D11_MAPPED_SUBRESOURCE MappedBuff;
-
- HRESULT hr = m_pd3d11DeviceContext->Map(pBufferD3D11->m_pd3d11Buffer, 0, d3d11MapType, d3d11MapFlags, &MappedBuff);
- if ((d3d11MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) == 0)
- {
- DEV_CHECK_ERR(SUCCEEDED(hr), "Failed to map buffer '", pBufferD3D11->GetDesc().Name, "'");
- }
- pMappedData = SUCCEEDED(hr) ? MappedBuff.pData : nullptr;
-}
-
-void DeviceContextD3D11Impl::UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType)
-{
- TDeviceContextBase::UnmapBuffer(pBuffer, MapType);
- auto* pBufferD3D11 = ValidatedCast<BufferD3D11Impl>(pBuffer);
- m_pd3d11DeviceContext->Unmap(pBufferD3D11->m_pd3d11Buffer, 0);
-}
-
-void DeviceContextD3D11Impl::UpdateTexture(ITexture* pTexture,
- Uint32 MipLevel,
- Uint32 Slice,
- const Box& DstBox,
- const TextureSubResData& SubresData,
- RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
- RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode)
-{
- TDeviceContextBase::UpdateTexture(pTexture, MipLevel, Slice, DstBox, SubresData, SrcBufferTransitionMode, DstTextureTransitionMode);
-
- auto* pTexD3D11 = ValidatedCast<TextureBaseD3D11>(pTexture);
- const auto& Desc = pTexD3D11->GetDesc();
-
- // OpenGL backend uses UpdateData() to initialize textures, so we can't check the usage in ValidateUpdateTextureParams()
- DEV_CHECK_ERR(Desc.Usage == USAGE_DEFAULT, "Only USAGE_DEFAULT textures should be updated with UpdateData()");
-
- if (SubresData.pSrcBuffer != nullptr)
- {
- LOG_ERROR("D3D11 does not support updating texture subresource from a GPU buffer");
- return;
- }
-
- D3D11_BOX D3D11Box;
- D3D11Box.left = DstBox.MinX;
- D3D11Box.right = DstBox.MaxX;
- D3D11Box.top = DstBox.MinY;
- D3D11Box.bottom = DstBox.MaxY;
- D3D11Box.front = DstBox.MinZ;
- D3D11Box.back = DstBox.MaxZ;
- const auto& FmtAttribs = GetTextureFormatAttribs(Desc.Format);
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
- {
- // Align update region by the compressed block size
- VERIFY((D3D11Box.left % FmtAttribs.BlockWidth) == 0, "Update region min X coordinate (", D3D11Box.left, ") must be multiple of a compressed block width (", Uint32{FmtAttribs.BlockWidth}, ")");
- VERIFY((FmtAttribs.BlockWidth & (FmtAttribs.BlockWidth - 1)) == 0, "Compressed block width (", Uint32{FmtAttribs.BlockWidth}, ") is expected to be power of 2");
- D3D11Box.right = (D3D11Box.right + FmtAttribs.BlockWidth - 1) & ~(FmtAttribs.BlockWidth - 1);
-
- VERIFY((D3D11Box.top % FmtAttribs.BlockHeight) == 0, "Update region min Y coordinate (", D3D11Box.top, ") must be multiple of a compressed block height (", Uint32{FmtAttribs.BlockHeight}, ")");
- VERIFY((FmtAttribs.BlockHeight & (FmtAttribs.BlockHeight - 1)) == 0, "Compressed block height (", Uint32{FmtAttribs.BlockHeight}, ") is expected to be power of 2");
- D3D11Box.bottom = (D3D11Box.bottom + FmtAttribs.BlockHeight - 1) & ~(FmtAttribs.BlockHeight - 1);
- }
- auto SubresIndex = D3D11CalcSubresource(MipLevel, Slice, Desc.MipLevels);
- m_pd3d11DeviceContext->UpdateSubresource(pTexD3D11->GetD3D11Texture(), SubresIndex, &D3D11Box, SubresData.pData, SubresData.Stride, SubresData.DepthStride);
-}
-
-void DeviceContextD3D11Impl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
-{
- TDeviceContextBase::CopyTexture(CopyAttribs);
-
- auto* pSrcTexD3D11 = ValidatedCast<TextureBaseD3D11>(CopyAttribs.pSrcTexture);
- auto* pDstTexD3D11 = ValidatedCast<TextureBaseD3D11>(CopyAttribs.pDstTexture);
-
- D3D11_BOX D3D11SrcBox, *pD3D11SrcBox = nullptr;
- if (const auto* pSrcBox = CopyAttribs.pSrcBox)
- {
- D3D11SrcBox.left = pSrcBox->MinX;
- D3D11SrcBox.right = pSrcBox->MaxX;
- D3D11SrcBox.top = pSrcBox->MinY;
- D3D11SrcBox.bottom = pSrcBox->MaxY;
- D3D11SrcBox.front = pSrcBox->MinZ;
- D3D11SrcBox.back = pSrcBox->MaxZ;
- pD3D11SrcBox = &D3D11SrcBox;
- }
- auto SrcSubRes = D3D11CalcSubresource(CopyAttribs.SrcMipLevel, CopyAttribs.SrcSlice, pSrcTexD3D11->GetDesc().MipLevels);
- auto DstSubRes = D3D11CalcSubresource(CopyAttribs.DstMipLevel, CopyAttribs.DstSlice, pDstTexD3D11->GetDesc().MipLevels);
- m_pd3d11DeviceContext->CopySubresourceRegion(pDstTexD3D11->GetD3D11Texture(), DstSubRes, CopyAttribs.DstX, CopyAttribs.DstY, CopyAttribs.DstZ,
- pSrcTexD3D11->GetD3D11Texture(), SrcSubRes, pD3D11SrcBox);
-}
-
-
-void DeviceContextD3D11Impl::MapTextureSubresource(ITexture* pTexture,
- Uint32 MipLevel,
- Uint32 ArraySlice,
- MAP_TYPE MapType,
- MAP_FLAGS MapFlags,
- const Box* pMapRegion,
- MappedTextureSubresource& MappedData)
-{
- TDeviceContextBase::MapTextureSubresource(pTexture, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion, MappedData);
-
- auto* pTexD3D11 = ValidatedCast<TextureBaseD3D11>(pTexture);
- const auto& TexDesc = pTexD3D11->GetDesc();
- D3D11_MAP d3d11MapType = static_cast<D3D11_MAP>(0);
- UINT d3d11MapFlags = 0;
- MapParamsToD3D11MapParams(MapType, MapFlags, d3d11MapType, d3d11MapFlags);
-
- auto Subresource = D3D11CalcSubresource(MipLevel, ArraySlice, TexDesc.MipLevels);
- D3D11_MAPPED_SUBRESOURCE MappedTex;
- auto hr = m_pd3d11DeviceContext->Map(pTexD3D11->GetD3D11Texture(), Subresource, d3d11MapType, d3d11MapFlags, &MappedTex);
- if (FAILED(hr))
- {
- VERIFY_EXPR(hr == DXGI_ERROR_WAS_STILL_DRAWING);
- MappedData = MappedTextureSubresource();
- }
- else
- {
- MappedData.pData = MappedTex.pData;
- MappedData.Stride = MappedTex.RowPitch;
- MappedData.DepthStride = MappedTex.DepthPitch;
- }
-}
-
-void DeviceContextD3D11Impl::UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice)
-{
- TDeviceContextBase::UnmapTextureSubresource(pTexture, MipLevel, ArraySlice);
-
- auto* pTexD3D11 = ValidatedCast<TextureBaseD3D11>(pTexture);
- const auto& TexDesc = pTexD3D11->GetDesc();
- auto Subresource = D3D11CalcSubresource(MipLevel, ArraySlice, TexDesc.MipLevels);
- m_pd3d11DeviceContext->Unmap(pTexD3D11->GetD3D11Texture(), Subresource);
-}
-
-void DeviceContextD3D11Impl::GenerateMips(ITextureView* pTextureView)
-{
- TDeviceContextBase::GenerateMips(pTextureView);
- auto& TexViewD3D11 = *ValidatedCast<TextureViewD3D11Impl>(pTextureView);
- auto* pd3d11SRV = static_cast<ID3D11ShaderResourceView*>(TexViewD3D11.GetD3D11View());
- m_pd3d11DeviceContext->GenerateMips(pd3d11SRV);
-}
-
-void DeviceContextD3D11Impl::FinishFrame()
-{
- if (m_ActiveDisjointQuery)
- {
- m_pd3d11DeviceContext->End(m_ActiveDisjointQuery->pd3d11Query);
- m_ActiveDisjointQuery->IsEnded = true;
- m_ActiveDisjointQuery.reset();
- }
-}
-
-void DeviceContextD3D11Impl::SetVertexBuffers(Uint32 StartSlot,
- Uint32 NumBuffersSet,
- IBuffer** ppBuffers,
- Uint32* pOffsets,
- RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
- SET_VERTEX_BUFFERS_FLAGS Flags)
-{
- TDeviceContextBase::SetVertexBuffers(StartSlot, NumBuffersSet, ppBuffers, pOffsets, StateTransitionMode, Flags);
- for (Uint32 Slot = 0; Slot < m_NumVertexStreams; ++Slot)
- {
- auto& CurrStream = m_VertexStreams[Slot];
- if (auto* pBuffD3D11Impl = CurrStream.pBuffer.RawPtr())
- {
- if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
- {
- if (pBuffD3D11Impl->IsInKnownState() && pBuffD3D11Impl->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- UnbindResourceFromUAV(pBuffD3D11Impl, pBuffD3D11Impl->m_pd3d11Buffer);
- pBuffD3D11Impl->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
- }
- }
-#ifdef DILIGENT_DEVELOPMENT
- else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
- {
- if (pBuffD3D11Impl->IsInKnownState() && pBuffD3D11Impl->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("Buffer '", pBuffD3D11Impl->GetDesc().Name, "' used as vertex buffer at slot ", Slot, " is in RESOURCE_STATE_UNORDERED_ACCESS state. "
- "Use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to RESOURCE_STATE_VERTEX_BUFFER state.");
- }
- }
-#endif
- }
- }
-
- m_bCommittedD3D11VBsUpToDate = false;
-}
-
-void DeviceContextD3D11Impl::SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
-{
- TDeviceContextBase::SetIndexBuffer(pIndexBuffer, ByteOffset, StateTransitionMode);
-
- if (m_pIndexBuffer)
- {
- if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
- {
- if (m_pIndexBuffer->IsInKnownState() && m_pIndexBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- UnbindResourceFromUAV(m_pIndexBuffer, m_pIndexBuffer->m_pd3d11Buffer);
- m_pIndexBuffer->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
- }
- }
-#ifdef DILIGENT_DEVELOPMENT
- else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
- {
- if (m_pIndexBuffer->IsInKnownState() && m_pIndexBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("Buffer '", m_pIndexBuffer->GetDesc().Name, "' used as index buffer is in RESOURCE_STATE_UNORDERED_ACCESS state."
- " Use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to RESOURCE_STATE_INDEX_BUFFER state.");
- }
- }
-#endif
- }
-
- m_bCommittedD3D11IBUpToDate = false;
-}
-
-void DeviceContextD3D11Impl::SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32 RTWidth, Uint32 RTHeight)
-{
- static_assert(MAX_VIEWPORTS >= D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, "MaxViewports constant must be greater than D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE");
- TDeviceContextBase::SetViewports(NumViewports, pViewports, RTWidth, RTHeight);
-
- D3D11_VIEWPORT d3d11Viewports[MAX_VIEWPORTS];
- VERIFY(NumViewports == m_NumViewports, "Unexpected number of viewports");
- for (Uint32 vp = 0; vp < m_NumViewports; ++vp)
- {
- d3d11Viewports[vp].TopLeftX = m_Viewports[vp].TopLeftX;
- d3d11Viewports[vp].TopLeftY = m_Viewports[vp].TopLeftY;
- d3d11Viewports[vp].Width = m_Viewports[vp].Width;
- d3d11Viewports[vp].Height = m_Viewports[vp].Height;
- d3d11Viewports[vp].MinDepth = m_Viewports[vp].MinDepth;
- d3d11Viewports[vp].MaxDepth = m_Viewports[vp].MaxDepth;
- }
- // All viewports must be set atomically as one operation.
- // Any viewports not defined by the call are disabled.
- m_pd3d11DeviceContext->RSSetViewports(NumViewports, d3d11Viewports);
-}
-
-void DeviceContextD3D11Impl::SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32 RTWidth, Uint32 RTHeight)
-{
- static_assert(MAX_VIEWPORTS >= D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, "MaxViewports constant must be greater than D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE");
- TDeviceContextBase::SetScissorRects(NumRects, pRects, RTWidth, RTHeight);
-
- D3D11_RECT d3d11ScissorRects[MAX_VIEWPORTS];
- VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects");
- for (Uint32 sr = 0; sr < NumRects; ++sr)
- {
- d3d11ScissorRects[sr].left = m_ScissorRects[sr].left;
- d3d11ScissorRects[sr].top = m_ScissorRects[sr].top;
- d3d11ScissorRects[sr].right = m_ScissorRects[sr].right;
- d3d11ScissorRects[sr].bottom = m_ScissorRects[sr].bottom;
- }
-
- // All scissor rects must be set atomically as one operation.
- // Any scissor rects not defined by the call are disabled.
- m_pd3d11DeviceContext->RSSetScissorRects(NumRects, d3d11ScissorRects);
-}
-
-void DeviceContextD3D11Impl::CommitRenderTargets()
-{
- const Uint32 MaxD3D11RTs = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
- Uint32 NumRenderTargets = m_NumBoundRenderTargets;
- VERIFY(NumRenderTargets <= MaxD3D11RTs, "D3D11 only allows 8 simultaneous render targets");
- NumRenderTargets = std::min(MaxD3D11RTs, NumRenderTargets);
-
- // Do not waste time setting RTVs to null
- ID3D11RenderTargetView* pd3d11RTs[MaxD3D11RTs];
- ID3D11DepthStencilView* pd3d11DSV = nullptr;
-
- for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
- {
- auto* pViewD3D11 = m_pBoundRenderTargets[rt].RawPtr();
- pd3d11RTs[rt] = pViewD3D11 != nullptr ? static_cast<ID3D11RenderTargetView*>(pViewD3D11->GetD3D11View()) : nullptr;
- }
-
- if (m_pBoundDepthStencil != nullptr)
- {
- pd3d11DSV = static_cast<ID3D11DepthStencilView*>(m_pBoundDepthStencil->GetD3D11View());
- }
-
- auto& NumCommittedPixelShaderUAVs = m_NumCommittedUAVs[PSInd];
- if (NumCommittedPixelShaderUAVs > 0)
- {
- m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(NumRenderTargets, NumRenderTargets > 0 ? pd3d11RTs : nullptr, pd3d11DSV,
- 0, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, nullptr, nullptr);
-
- auto CommittedD3D11UAVs = m_CommittedD3D11UAVs[PSInd];
- auto CommittedD3D11UAVRes = m_CommittedD3D11UAVResources[PSInd];
- for (Uint32 slot = 0; slot < NumRenderTargets; ++slot)
- {
- CommittedD3D11UAVs[slot] = nullptr;
- CommittedD3D11UAVRes[slot] = nullptr;
- }
- if (NumRenderTargets >= NumCommittedPixelShaderUAVs)
- NumCommittedPixelShaderUAVs = 0;
- }
- else
- {
- m_pd3d11DeviceContext->OMSetRenderTargets(NumRenderTargets, NumRenderTargets > 0 ? pd3d11RTs : nullptr, pd3d11DSV);
- }
-}
-
-
-void UnbindView(ID3D11DeviceContext* pContext, TSetShaderResourcesType SetSRVMethod, UINT Slot)
-{
- ID3D11ShaderResourceView* ppNullView[] = {nullptr};
- (pContext->*SetSRVMethod)(Slot, 1, ppNullView);
-}
-
-void UnbindView(ID3D11DeviceContext* pContext, TSetUnorderedAccessViewsType SetUAVMethod, UINT Slot)
-{
- ID3D11UnorderedAccessView* ppNullView[] = {nullptr};
- (pContext->*SetUAVMethod)(Slot, 1, ppNullView, nullptr);
-}
-
-template <typename TD3D11ResourceViewType, typename TSetD3D11View>
-bool UnbindPixelShaderUAV(ID3D11DeviceContext* pDeviceCtx,
- TD3D11ResourceViewType* CommittedD3D11Resources[],
- Uint32 NumCommittedSlots,
- Uint32 NumCommittedRenderTargets,
- TSetD3D11View SetD3D11ViewMethod)
-{
- // For other resource view types do nothing
- return false;
-}
-
-template <>
-bool UnbindPixelShaderUAV<ID3D11UnorderedAccessView, TSetUnorderedAccessViewsType>(
- ID3D11DeviceContext* pDeviceCtx,
- ID3D11UnorderedAccessView* CommittedD3D11UAVs[],
- Uint32 NumCommittedUAVs,
- Uint32 NumCommittedRenderTargets,
- TSetUnorderedAccessViewsType SetD3D11UAVMethod)
-{
- if (SetD3D11UAVMethod == reinterpret_cast<TSetUnorderedAccessViewsType>(&ID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews))
- {
- // Pixel shader UAVs are bound in a special way simulatneously with the render targets
- auto UAVStartSlot = NumCommittedRenderTargets;
- // UAVs cannot be set independently; they all need to be set at the same time.
- // https://docs.microsoft.com/en-us/windows/desktop/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews#remarks
-
- // There is potential problem here: since device context does not keep strong references to
- // UAVs, there is no guarantee the objects are alive
- pDeviceCtx->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
- UAVStartSlot, NumCommittedUAVs - UAVStartSlot,
- CommittedD3D11UAVs + UAVStartSlot, nullptr);
- return true;
- }
-
- return false;
-}
-
-
-
-/// \tparam TD3D11ResourceViewType - Type of the D3D11 resource view (ID3D11ShaderResourceView or ID3D11UnorderedAccessView)
-/// \tparam TSetD3D11View - Type of the D3D11 device context method used to set the D3D11 view
-/// \param CommittedResourcesArr - Pointer to the array of strong references to currently bound
-/// shader resources, for each shader stage
-/// \param CommittedD3D11ResourcesArr - Pointer to the array of currently bound D3D11
-/// shader resources, for each shader stage
-/// \param pd3d11ResToUndind - D3D11 resource to unbind
-/// \param SetD3D11ViewMethods - Array of pointers to device context methods used to set the view,
-/// for every shader stage
-template <typename TD3D11ResourceViewType,
- typename TSetD3D11View,
- size_t NumSlots>
-void DeviceContextD3D11Impl::UnbindResourceView(TD3D11ResourceViewType CommittedD3D11ViewsArr[][NumSlots],
- ID3D11Resource* CommittedD3D11ResourcesArr[][NumSlots],
- Uint8 NumCommittedResourcesArr[],
- ID3D11Resource* pd3d11ResToUndind,
- TSetD3D11View SetD3D11ViewMethods[])
-{
- for (Int32 ShaderTypeInd = 0; ShaderTypeInd < NumShaderTypes; ++ShaderTypeInd)
- {
- auto* CommittedD3D11Views = CommittedD3D11ViewsArr[ShaderTypeInd];
- auto* CommittedD3D11Resources = CommittedD3D11ResourcesArr[ShaderTypeInd];
- auto& NumCommittedSlots = NumCommittedResourcesArr[ShaderTypeInd];
-
- for (Uint32 Slot = 0; Slot < NumCommittedSlots; ++Slot)
- {
- if (CommittedD3D11Resources[Slot] == pd3d11ResToUndind)
- {
- CommittedD3D11Resources[Slot] = nullptr;
- CommittedD3D11Views[Slot] = nullptr;
-
- auto SetViewMethod = SetD3D11ViewMethods[ShaderTypeInd];
- VERIFY(SetViewMethod != nullptr, "No appropriate ID3D11DeviceContext method");
-
- // Pixel shader UAVs require special handling
- if (!UnbindPixelShaderUAV(m_pd3d11DeviceContext, CommittedD3D11Views, NumCommittedSlots, m_NumBoundRenderTargets, SetViewMethod))
- {
- UnbindView(m_pd3d11DeviceContext, SetViewMethod, Slot);
- }
- }
- }
-
- // Pop null resources from the end of arrays
- while (NumCommittedSlots > 0 && CommittedD3D11Resources[NumCommittedSlots - 1] == nullptr)
- {
- VERIFY(CommittedD3D11Views[NumSlots - 1] == nullptr, "Unexpected non-null resource view");
- --NumCommittedSlots;
- }
- }
-}
-
-void DeviceContextD3D11Impl::UnbindTextureFromInput(TextureBaseD3D11* pTexture, ID3D11Resource* pd3d11Resource)
-{
- VERIFY(pTexture, "Null texture provided");
- if (!pTexture) return;
-
- UnbindResourceView(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, pd3d11Resource, SetSRVMethods);
- pTexture->ClearState(RESOURCE_STATE_SHADER_RESOURCE);
-}
-
-void DeviceContextD3D11Impl::UnbindBufferFromInput(BufferD3D11Impl* pBuffer, ID3D11Resource* pd3d11Buffer)
-{
- VERIFY(pBuffer, "Null buffer provided");
- if (!pBuffer || !pBuffer->IsInKnownState()) return;
-
- if (pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
- {
- UnbindResourceView(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, pd3d11Buffer, SetSRVMethods);
- pBuffer->ClearState(RESOURCE_STATE_SHADER_RESOURCE);
- }
-
- if (pBuffer->CheckState(RESOURCE_STATE_INDEX_BUFFER))
- {
- auto pd3d11IndBuffer = ValidatedCast<BufferD3D11Impl>(pBuffer)->GetD3D11Buffer();
- if (pd3d11IndBuffer == m_CommittedD3D11IndexBuffer)
- {
- // Only unbind D3D11 buffer from the context!
- // m_pIndexBuffer.Release();
- m_CommittedD3D11IndexBuffer.Release();
- m_CommittedIBFormat = VT_UNDEFINED;
- m_CommittedD3D11IndexDataStartOffset = 0;
- m_bCommittedD3D11IBUpToDate = false;
- m_pd3d11DeviceContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_R32_UINT, m_CommittedD3D11IndexDataStartOffset);
- }
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- dbgVerifyCommittedIndexBuffer();
- }
-#endif
- pBuffer->ClearState(RESOURCE_STATE_INDEX_BUFFER);
- }
-
- if (pBuffer->CheckState(RESOURCE_STATE_VERTEX_BUFFER))
- {
- auto pd3d11VB = ValidatedCast<BufferD3D11Impl>(pBuffer)->GetD3D11Buffer();
- for (Uint32 Slot = 0; Slot < m_NumCommittedD3D11VBs; ++Slot)
- {
- auto& CommittedD3D11VB = m_CommittedD3D11VertexBuffers[Slot];
- if (CommittedD3D11VB == pd3d11VB)
- {
- // Unbind only D3D11 buffer
- //*VertStream = VertexStreamInfo();
- ID3D11Buffer* ppNullBuffer[] = {nullptr};
- const UINT Zero[] = {0};
- m_CommittedD3D11VertexBuffers[Slot] = nullptr;
- m_CommittedD3D11VBStrides[Slot] = 0;
- m_CommittedD3D11VBOffsets[Slot] = 0;
- m_bCommittedD3D11VBsUpToDate = false;
- m_pd3d11DeviceContext->IASetVertexBuffers(Slot, _countof(ppNullBuffer), ppNullBuffer, Zero, Zero);
- }
- }
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- dbgVerifyCommittedVertexBuffers();
- }
-#endif
- pBuffer->ClearState(RESOURCE_STATE_VERTEX_BUFFER);
- }
-
- if (pBuffer->CheckState(RESOURCE_STATE_CONSTANT_BUFFER))
- {
- for (Int32 ShaderTypeInd = 0; ShaderTypeInd < NumShaderTypes; ++ShaderTypeInd)
- {
- auto* CommittedD3D11CBs = m_CommittedD3D11CBs[ShaderTypeInd];
- auto NumSlots = m_NumCommittedCBs[ShaderTypeInd];
- for (Uint32 Slot = 0; Slot < NumSlots; ++Slot)
- {
- if (CommittedD3D11CBs[Slot] == pd3d11Buffer)
- {
- CommittedD3D11CBs[Slot] = nullptr;
- auto SetCBMethod = SetCBMethods[ShaderTypeInd];
- ID3D11Buffer* ppNullBuffer[] = {nullptr};
- (m_pd3d11DeviceContext->*SetCBMethod)(Slot, 1, ppNullBuffer);
- }
- }
- }
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- dbgVerifyCommittedCBs();
- }
-#endif
- pBuffer->ClearState(RESOURCE_STATE_CONSTANT_BUFFER);
- }
-}
-
-void DeviceContextD3D11Impl::UnbindResourceFromUAV(IDeviceObject* pResource, ID3D11Resource* pd3d11Resource)
-{
- VERIFY(pResource, "Null resource provided");
- if (!pResource) return;
-
- UnbindResourceView(m_CommittedD3D11UAVs, m_CommittedD3D11UAVResources, m_NumCommittedUAVs, pd3d11Resource, SetUAVMethods);
-}
-
-void DeviceContextD3D11Impl::UnbindTextureFromRenderTarget(TextureBaseD3D11* pTexture)
-{
- VERIFY(pTexture, "Null resource provided");
- if (!pTexture) return;
-
- bool bCommitRenderTargets = false;
- for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
- {
- if (auto* pTexView = m_pBoundRenderTargets[rt].RawPtr())
- {
- if (pTexView->GetTexture() == pTexture)
- {
- m_pBoundRenderTargets[rt].Release();
- bCommitRenderTargets = true;
- }
- }
- }
-
- if (bCommitRenderTargets)
- {
- while (m_NumBoundRenderTargets > 0 && !m_pBoundRenderTargets[m_NumBoundRenderTargets - 1])
- --m_NumBoundRenderTargets;
-
- CommitRenderTargets();
- }
-
- pTexture->ClearState(RESOURCE_STATE_RENDER_TARGET);
-}
-
-void DeviceContextD3D11Impl::UnbindTextureFromDepthStencil(TextureBaseD3D11* pTexD3D11)
-{
- VERIFY(pTexD3D11, "Null resource provided");
- if (!pTexD3D11) return;
-
- if (m_pBoundDepthStencil && m_pBoundDepthStencil->GetTexture() == pTexD3D11)
- {
- m_pBoundDepthStencil.Release();
- CommitRenderTargets();
- }
- pTexD3D11->ClearState(RESOURCE_STATE_DEPTH_WRITE);
-}
-
-void DeviceContextD3D11Impl::ResetRenderTargets()
-{
- TDeviceContextBase::ResetRenderTargets();
- m_pd3d11DeviceContext->OMSetRenderTargets(0, nullptr, nullptr);
-}
-
-void DeviceContextD3D11Impl::SetRenderTargets(Uint32 NumRenderTargets,
- ITextureView* ppRenderTargets[],
- ITextureView* pDepthStencil,
- RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
-{
- if (TDeviceContextBase::SetRenderTargets(NumRenderTargets, ppRenderTargets, pDepthStencil))
- {
- for (Uint32 RT = 0; RT < NumRenderTargets; ++RT)
- {
- if (ppRenderTargets[RT])
- {
- auto* pTex = ValidatedCast<TextureBaseD3D11>(ppRenderTargets[RT]->GetTexture());
- if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
- {
- UnbindTextureFromInput(pTex, pTex->GetD3D11Texture());
- if (pTex->IsInKnownState())
- pTex->SetState(RESOURCE_STATE_RENDER_TARGET);
- }
-#ifdef DILIGENT_DEVELOPMENT
- else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
- {
- DvpVerifyTextureState(*pTex, RESOURCE_STATE_RENDER_TARGET, "Setting render targets (DeviceContextD3D11Impl::SetRenderTargets)");
- }
-#endif
- }
- }
-
- if (pDepthStencil)
- {
- auto* pTex = ValidatedCast<TextureBaseD3D11>(pDepthStencil->GetTexture());
- if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
- {
- UnbindTextureFromInput(pTex, pTex->GetD3D11Texture());
- if (pTex->IsInKnownState())
- pTex->SetState(RESOURCE_STATE_DEPTH_WRITE);
- }
-#ifdef DILIGENT_DEVELOPMENT
- else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
- {
- DvpVerifyTextureState(*pTex, RESOURCE_STATE_DEPTH_WRITE, "Setting depth-stencil buffer (DeviceContextD3D11Impl::SetRenderTargets)");
- }
-#endif
- }
-
- CommitRenderTargets();
-
- // Set the viewport to match the render target size
- SetViewports(1, nullptr, 0, 0);
- }
-}
-
-template <typename TD3D11ResourceType, typename TSetD3D11ResMethodType>
-void SetD3D11ResourcesHelper(ID3D11DeviceContext* pDeviceCtx,
- TSetD3D11ResMethodType SetD3D11ResMethod,
- UINT StartSlot,
- UINT NumSlots,
- TD3D11ResourceType** ppResources)
-{
- (pDeviceCtx->*SetD3D11ResMethod)(StartSlot, NumSlots, ppResources);
-}
-
-template <>
-void SetD3D11ResourcesHelper(ID3D11DeviceContext* pDeviceCtx,
- TSetUnorderedAccessViewsType SetD3D11UAVMethod,
- UINT StartSlot,
- UINT NumSlots,
- ID3D11UnorderedAccessView** ppUAVs)
-{
- (pDeviceCtx->*SetD3D11UAVMethod)(StartSlot, NumSlots, ppUAVs, nullptr);
-}
-
-template <typename TD3D11ResourceType, typename TSetD3D11ResMethodType>
-void ReleaseCommittedShaderResourcesHelper(TD3D11ResourceType CommittedD3D11Res[],
- Uint8 NumCommittedResources,
- TSetD3D11ResMethodType SetD3D11ResMethod,
- ID3D11DeviceContext* pDeviceCtx)
-{
- if (NumCommittedResources > 0)
- {
- memset(CommittedD3D11Res, 0, NumCommittedResources * sizeof(CommittedD3D11Res[0]));
- SetD3D11ResourcesHelper(pDeviceCtx, SetD3D11ResMethod, 0, NumCommittedResources, CommittedD3D11Res);
- }
-}
-
-void ReleaseCommittedPSUAVs(ID3D11UnorderedAccessView* CommittedD3D11UAVs[],
- Uint8 NumCommittedResources,
- ID3D11DeviceContext* pDeviceCtx)
-{
- if (NumCommittedResources > 0)
- {
- memset(CommittedD3D11UAVs, 0, NumCommittedResources * sizeof(CommittedD3D11UAVs[0]));
- pDeviceCtx->OMSetRenderTargetsAndUnorderedAccessViews(
- D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
- 0, 0, nullptr, nullptr);
- }
-}
-
-void DeviceContextD3D11Impl::ReleaseCommittedShaderResources()
-{
- for (int ShaderType = 0; ShaderType < NumShaderTypes; ++ShaderType)
- {
- // clang-format off
- ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11CBs[ShaderType], m_NumCommittedCBs[ShaderType], SetCBMethods[ShaderType], m_pd3d11DeviceContext);
- ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11SRVs[ShaderType], m_NumCommittedSRVs[ShaderType], SetSRVMethods[ShaderType], m_pd3d11DeviceContext);
- ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11Samplers[ShaderType], m_NumCommittedSamplers[ShaderType], SetSamplerMethods[ShaderType], m_pd3d11DeviceContext);
- // clang-format on
-
- if (ShaderType == PSInd)
- ReleaseCommittedPSUAVs(m_CommittedD3D11UAVs[ShaderType], m_NumCommittedUAVs[ShaderType], m_pd3d11DeviceContext);
- else
- ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11UAVs[ShaderType], m_NumCommittedUAVs[ShaderType], SetUAVMethods[ShaderType], m_pd3d11DeviceContext);
-
- memset(m_CommittedD3D11SRVResources[ShaderType], 0, sizeof(m_CommittedD3D11SRVResources[ShaderType][0]) * m_NumCommittedSRVs[ShaderType]);
- memset(m_CommittedD3D11UAVResources[ShaderType], 0, sizeof(m_CommittedD3D11UAVResources[ShaderType][0]) * m_NumCommittedUAVs[ShaderType]);
- m_NumCommittedCBs[ShaderType] = 0;
- m_NumCommittedSRVs[ShaderType] = 0;
- m_NumCommittedSamplers[ShaderType] = 0;
- m_NumCommittedUAVs[ShaderType] = 0;
- }
-
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- dbgVerifyCommittedSRVs();
- dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
- dbgVerifyCommittedSamplers();
- dbgVerifyCommittedCBs();
- }
-#endif
- // We do not unbind vertex buffers and index buffer as this can explicitly
- // be done by the user
-}
-
-
-void DeviceContextD3D11Impl::FinishCommandList(ICommandList** ppCommandList)
-{
- CComPtr<ID3D11CommandList> pd3d11CmdList;
- m_pd3d11DeviceContext->FinishCommandList(
- FALSE, // A Boolean flag that determines whether the runtime saves deferred context state before it
- // executes FinishCommandList and restores it afterwards.
- // * TRUE indicates that the runtime needs to save and restore the state.
- // * FALSE indicates that the runtime will not save or restore any state.
- // In this case, the deferred context will return to its default state
- // after the call to FinishCommandList() completes as if
- // ID3D11DeviceContext::ClearState() was called.
- &pd3d11CmdList);
-
- CommandListD3D11Impl* pCmdListD3D11(NEW_RC_OBJ(m_CmdListAllocator, "CommandListD3D11Impl instance", CommandListD3D11Impl)(m_pDevice, pd3d11CmdList));
- pCmdListD3D11->QueryInterface(IID_CommandList, reinterpret_cast<IObject**>(ppCommandList));
-
- // Device context is now in default state
- InvalidateState();
-
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- // Verify bindings
- dbgVerifyCommittedSRVs();
- dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
- dbgVerifyCommittedSamplers();
- dbgVerifyCommittedCBs();
- dbgVerifyCommittedVertexBuffers();
- dbgVerifyCommittedIndexBuffer();
- dbgVerifyCommittedShaders();
- }
-#endif
-}
-
-void DeviceContextD3D11Impl::ExecuteCommandList(ICommandList* pCommandList)
-{
- if (m_bIsDeferred)
- {
- LOG_ERROR("Only immediate context can execute command list");
- return;
- }
-
- CommandListD3D11Impl* pCmdListD3D11 = ValidatedCast<CommandListD3D11Impl>(pCommandList);
- auto* pd3d11CmdList = pCmdListD3D11->GetD3D11CommandList();
- m_pd3d11DeviceContext->ExecuteCommandList(pd3d11CmdList,
- FALSE // A Boolean flag that determines whether the target context state is
- // saved prior to and restored after the execution of a command list.
- // * TRUE indicates that the runtime needs to save and restore the state.
- // * FALSE indicate that no state shall be saved or restored, which causes the
- // target context to return to its default state after the command list executes as if
- // ID3D11DeviceContext::ClearState() was called.
- );
-
- // Device context is now in default state
- InvalidateState();
-
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
- {
- // Verify bindings
- dbgVerifyCommittedSRVs();
- dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
- dbgVerifyCommittedSamplers();
- dbgVerifyCommittedCBs();
- dbgVerifyCommittedVertexBuffers();
- dbgVerifyCommittedIndexBuffer();
- dbgVerifyCommittedShaders();
- }
-#endif
-}
-
-
-static CComPtr<ID3D11Query> CreateD3D11QueryEvent(ID3D11Device* pd3d11Device)
-{
- D3D11_QUERY_DESC QueryDesc = {};
- QueryDesc.Query = D3D11_QUERY_EVENT; // Determines whether or not the GPU is finished processing commands.
- // When the GPU is finished processing commands ID3D11DeviceContext::GetData will
- // return S_OK, and pData will point to a BOOL with a value of TRUE. When using this
- // type of query, ID3D11DeviceContext::Begin is disabled.
- QueryDesc.MiscFlags = 0;
-
- CComPtr<ID3D11Query> pd3d11Query;
- auto hr = pd3d11Device->CreateQuery(&QueryDesc, &pd3d11Query);
- DEV_CHECK_ERR(SUCCEEDED(hr), "Failed to create D3D11 query");
- VERIFY_EXPR(pd3d11Query);
- return pd3d11Query;
-}
-
-void DeviceContextD3D11Impl::SignalFence(IFence* pFence, Uint64 Value)
-{
- VERIFY(!m_bIsDeferred, "Fence can only be signaled from immediate context");
- auto* pd3d11Device = m_pDevice->GetD3D11Device();
- CComPtr<ID3D11Query> pd3d11Query = CreateD3D11QueryEvent(pd3d11Device);
- m_pd3d11DeviceContext->End(pd3d11Query);
- auto* pFenceD3D11Impl = ValidatedCast<FenceD3D11Impl>(pFence);
- pFenceD3D11Impl->AddPendingQuery(m_pd3d11DeviceContext, std::move(pd3d11Query), Value);
-}
-
-void DeviceContextD3D11Impl::WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext)
-{
- VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
- if (FlushContext)
- Flush();
- auto* pFenceD3D11Impl = ValidatedCast<FenceD3D11Impl>(pFence);
- pFenceD3D11Impl->Wait(Value, FlushContext);
-}
-
-void DeviceContextD3D11Impl::WaitForIdle()
-{
- VERIFY(!m_bIsDeferred, "Only immediate contexts can be idled");
- Flush();
- auto* pd3d11Device = m_pDevice->GetD3D11Device();
- CComPtr<ID3D11Query> pd3d11Query = CreateD3D11QueryEvent(pd3d11Device);
- m_pd3d11DeviceContext->End(pd3d11Query);
- BOOL Data;
- while (m_pd3d11DeviceContext->GetData(pd3d11Query, &Data, sizeof(Data), 0) != S_OK)
- std::this_thread::yield();
-}
-
-void DeviceContextD3D11Impl::BeginQuery(IQuery* pQuery)
-{
- if (!TDeviceContextBase::BeginQuery(pQuery, 0))
- return;
-
- auto* pQueryD3D11Impl = ValidatedCast<QueryD3D11Impl>(pQuery);
- m_pd3d11DeviceContext->Begin(pQueryD3D11Impl->GetD3D11Query());
-}
-
-void DeviceContextD3D11Impl::EndQuery(IQuery* pQuery)
-{
- if (!TDeviceContextBase::EndQuery(pQuery, 0))
- return;
-
- auto* pQueryD3D11Impl = ValidatedCast<QueryD3D11Impl>(pQuery);
- if (pQueryD3D11Impl->GetDesc().Type == QUERY_TYPE_TIMESTAMP)
- {
- if (!m_ActiveDisjointQuery)
- {
- m_ActiveDisjointQuery = m_DisjointQueryPool.GetDisjointQuery(m_pDevice->GetD3D11Device());
- // Disjoint timestamp queries should only be invoked once per frame or less.
- m_pd3d11DeviceContext->Begin(m_ActiveDisjointQuery->pd3d11Query);
- m_ActiveDisjointQuery->IsEnded = false;
- }
- pQueryD3D11Impl->SetDisjointQuery(m_ActiveDisjointQuery);
- }
-
- m_pd3d11DeviceContext->End(pQueryD3D11Impl->GetD3D11Query());
-}
-
-void DeviceContextD3D11Impl::ClearStateCache()
-{
- TDeviceContextBase::ClearStateCache();
-
- for (int ShaderType = 0; ShaderType < NumShaderTypes; ++ShaderType)
- {
- // clang-format off
- memset(m_CommittedD3D11CBs[ShaderType], 0, sizeof(m_CommittedD3D11CBs[ShaderType][0]) * m_NumCommittedCBs[ShaderType]);
- memset(m_CommittedD3D11SRVs[ShaderType], 0, sizeof(m_CommittedD3D11SRVs[ShaderType][0]) * m_NumCommittedSRVs[ShaderType]);
- memset(m_CommittedD3D11Samplers[ShaderType], 0, sizeof(m_CommittedD3D11Samplers[ShaderType][0]) * m_NumCommittedSamplers[ShaderType]);
- memset(m_CommittedD3D11UAVs[ShaderType], 0, sizeof(m_CommittedD3D11UAVs[ShaderType][0]) * m_NumCommittedUAVs[ShaderType]);
- memset(m_CommittedD3D11SRVResources[ShaderType], 0, sizeof(m_CommittedD3D11SRVResources[ShaderType][0]) * m_NumCommittedSRVs[ShaderType]);
- memset(m_CommittedD3D11UAVResources[ShaderType], 0, sizeof(m_CommittedD3D11UAVResources[ShaderType][0]) * m_NumCommittedUAVs[ShaderType]);
- // clang-format on
-
- m_NumCommittedCBs[ShaderType] = 0;
- m_NumCommittedSRVs[ShaderType] = 0;
- m_NumCommittedSamplers[ShaderType] = 0;
- m_NumCommittedUAVs[ShaderType] = 0;
-
- m_CommittedD3DShaders[ShaderType].Release();
- }
-
- for (Uint32 vb = 0; vb < m_NumCommittedD3D11VBs; ++vb)
- {
- m_CommittedD3D11VertexBuffers[vb] = nullptr;
- m_CommittedD3D11VBStrides[vb] = 0;
- m_CommittedD3D11VBOffsets[vb] = 0;
- }
- m_NumCommittedD3D11VBs = 0;
- m_bCommittedD3D11VBsUpToDate = false;
-
- m_CommittedD3D11InputLayout = nullptr;
-
- m_CommittedD3D11IndexBuffer.Release();
- m_CommittedIBFormat = VT_UNDEFINED;
- m_CommittedD3D11IndexDataStartOffset = 0;
- m_bCommittedD3D11IBUpToDate = false;
-
- m_CommittedD3D11PrimTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
- m_CommittedPrimitiveTopology = PRIMITIVE_TOPOLOGY_UNDEFINED;
-}
-
-void DeviceContextD3D11Impl::InvalidateState()
-{
- TDeviceContextBase::InvalidateState();
-
- ReleaseCommittedShaderResources();
- for (int ShaderType = 0; ShaderType < NumShaderTypes; ++ShaderType)
- m_CommittedD3DShaders[ShaderType].Release();
- m_pd3d11DeviceContext->VSSetShader(nullptr, nullptr, 0);
- m_pd3d11DeviceContext->GSSetShader(nullptr, nullptr, 0);
- m_pd3d11DeviceContext->PSSetShader(nullptr, nullptr, 0);
- m_pd3d11DeviceContext->HSSetShader(nullptr, nullptr, 0);
- m_pd3d11DeviceContext->DSSetShader(nullptr, nullptr, 0);
- m_pd3d11DeviceContext->CSSetShader(nullptr, nullptr, 0);
- ID3D11RenderTargetView* d3d11NullRTV[] = {nullptr};
- m_pd3d11DeviceContext->OMSetRenderTargets(1, d3d11NullRTV, nullptr);
-
- if (m_NumCommittedD3D11VBs > 0)
- {
- for (Uint32 vb = 0; vb < m_NumCommittedD3D11VBs; ++vb)
- {
- m_CommittedD3D11VertexBuffers[vb] = nullptr;
- m_CommittedD3D11VBStrides[vb] = 0;
- m_CommittedD3D11VBOffsets[vb] = 0;
- }
- m_pd3d11DeviceContext->IASetVertexBuffers(0, m_NumCommittedD3D11VBs, m_CommittedD3D11VertexBuffers, m_CommittedD3D11VBStrides, m_CommittedD3D11VBOffsets);
- m_NumCommittedD3D11VBs = 0;
- }
-
- m_bCommittedD3D11VBsUpToDate = false;
-
- if (m_CommittedD3D11InputLayout != nullptr)
- {
- m_pd3d11DeviceContext->IASetInputLayout(nullptr);
- m_CommittedD3D11InputLayout = nullptr;
- }
-
- if (m_CommittedD3D11IndexBuffer)
- {
- m_pd3d11DeviceContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_R32_UINT, 0);
- m_CommittedD3D11IndexBuffer.Release();
- }
-
- m_CommittedIBFormat = VT_UNDEFINED;
- m_CommittedD3D11IndexDataStartOffset = 0;
- m_bCommittedD3D11IBUpToDate = false;
-
- m_CommittedD3D11PrimTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
- m_CommittedPrimitiveTopology = PRIMITIVE_TOPOLOGY_UNDEFINED;
-}
-
-void DeviceContextD3D11Impl::TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers)
-{
- for (Uint32 i = 0; i < BarrierCount; ++i)
- {
- const auto& Barrier = pResourceBarriers[i];
-#ifdef DILIGENT_DEVELOPMENT
- DvpVerifyStateTransitionDesc(Barrier);
-#endif
- DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer must not be null");
- DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown");
-
- if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
- {
- // Skip begin-split barriers
- VERIFY(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier");
- continue;
- }
- VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type");
-
- if (Barrier.pTexture)
- {
- auto* pTextureD3D11Impl = ValidatedCast<TextureBaseD3D11>(Barrier.pTexture);
- auto OldState = Barrier.OldState;
- if (OldState == RESOURCE_STATE_UNKNOWN)
- {
- if (pTextureD3D11Impl->IsInKnownState())
- {
- OldState = pTextureD3D11Impl->GetState();
- }
- else
- {
- LOG_ERROR_MESSAGE("Failed to transition the state of texture '", pTextureD3D11Impl->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
- continue;
- }
- }
- else
- {
- if (pTextureD3D11Impl->IsInKnownState() && pTextureD3D11Impl->GetState() != OldState)
- {
- LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pTextureD3D11Impl->GetState()), " of texture '",
- pTextureD3D11Impl->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
- " specified by the barrier");
- }
- }
-
- if ((Barrier.NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0)
- {
- DEV_CHECK_ERR((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) == 0, "Unordered access state is not compatible with any input state");
- UnbindTextureFromInput(pTextureD3D11Impl, pTextureD3D11Impl->GetD3D11Texture());
- }
-
- if ((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) != 0)
- {
- if ((OldState & RESOURCE_STATE_RENDER_TARGET) != 0)
- UnbindTextureFromRenderTarget(pTextureD3D11Impl);
-
- if ((OldState & RESOURCE_STATE_DEPTH_WRITE) != 0)
- UnbindTextureFromDepthStencil(pTextureD3D11Impl);
-
- if ((OldState & RESOURCE_STATE_UNORDERED_ACCESS) != 0)
- {
- UnbindResourceFromUAV(pTextureD3D11Impl, pTextureD3D11Impl->GetD3D11Texture());
- pTextureD3D11Impl->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
- }
- }
-
- if (Barrier.UpdateResourceState)
- {
- pTextureD3D11Impl->SetState(Barrier.NewState);
- }
- }
- else
- {
- VERIFY_EXPR(Barrier.pBuffer);
- auto* pBufferD3D11Impl = ValidatedCast<BufferD3D11Impl>(Barrier.pBuffer);
- auto OldState = Barrier.OldState;
- if (OldState == RESOURCE_STATE_UNKNOWN)
- {
- if (pBufferD3D11Impl->IsInKnownState())
- {
- OldState = pBufferD3D11Impl->GetState();
- }
- else
- {
- LOG_ERROR_MESSAGE("Failed to transition the state of buffer '", pBufferD3D11Impl->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
- continue;
- }
- }
- else
- {
- if (pBufferD3D11Impl->IsInKnownState() && pBufferD3D11Impl->GetState() != OldState)
- {
- LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pBufferD3D11Impl->GetState()), " of buffer '",
- pBufferD3D11Impl->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
- " specified by the barrier");
- }
- }
-
- if ((Barrier.NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0)
- {
- DEV_CHECK_ERR((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) == 0, "Unordered access state is not compatible with any input state");
- UnbindBufferFromInput(pBufferD3D11Impl, pBufferD3D11Impl->m_pd3d11Buffer);
- }
-
- if ((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) != 0)
- {
- UnbindResourceFromUAV(pBufferD3D11Impl, pBufferD3D11Impl->m_pd3d11Buffer);
- }
-
- if (Barrier.UpdateResourceState)
- {
- pBufferD3D11Impl->SetState(Barrier.NewState);
- }
- }
- }
-}
-
-void DeviceContextD3D11Impl::ResolveTextureSubresource(ITexture* pSrcTexture,
- ITexture* pDstTexture,
- const ResolveTextureSubresourceAttribs& ResolveAttribs)
-{
- TDeviceContextBase::ResolveTextureSubresource(pSrcTexture, pDstTexture, ResolveAttribs);
-
- auto* pSrcTexD3D11 = ValidatedCast<TextureBaseD3D11>(pSrcTexture);
- auto* pDstTexD3D11 = ValidatedCast<TextureBaseD3D11>(pDstTexture);
- const auto& SrcTexDesc = pSrcTexD3D11->GetDesc();
- const auto& DstTexDesc = pDstTexD3D11->GetDesc();
-
- auto Format = ResolveAttribs.Format;
- if (Format == TEX_FORMAT_UNKNOWN)
- {
- const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
- if (!SrcFmtAttribs.IsTypeless)
- {
- Format = SrcTexDesc.Format;
- }
- else
- {
- const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
- DEV_CHECK_ERR(!DstFmtAttribs.IsTypeless, "Resolve operation format can't be typeless when both source and destination textures are typeless");
- Format = DstFmtAttribs.Format;
- }
- }
-
- auto DXGIFmt = TexFormatToDXGI_Format(Format);
- auto SrcSubresIndex = D3D11CalcSubresource(ResolveAttribs.SrcMipLevel, ResolveAttribs.SrcSlice, SrcTexDesc.MipLevels);
- auto DstSubresIndex = D3D11CalcSubresource(ResolveAttribs.DstMipLevel, ResolveAttribs.DstSlice, DstTexDesc.MipLevels);
- m_pd3d11DeviceContext->ResolveSubresource(pDstTexD3D11->GetD3D11Texture(), DstSubresIndex, pSrcTexD3D11->GetD3D11Texture(), SrcSubresIndex, DXGIFmt);
-}
-
-// clang-format off
-#ifdef VERIFY_CONTEXT_BINDINGS
- DEFINE_D3D11CTX_FUNC_POINTERS(GetCBMethods, GetConstantBuffers)
- DEFINE_D3D11CTX_FUNC_POINTERS(GetSRVMethods, GetShaderResources)
- DEFINE_D3D11CTX_FUNC_POINTERS(GetSamplerMethods, GetSamplers)
-
- typedef decltype (&ID3D11DeviceContext::CSGetUnorderedAccessViews) TGetUnorderedAccessViewsType;
- static const TGetUnorderedAccessViewsType GetUAVMethods[] =
- {
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- &ID3D11DeviceContext::CSGetUnorderedAccessViews
- };
-// clang-format on
-
-/// \tparam MaxResources - Maximum number of resources that can be bound to D3D11 context
-/// \tparam TD3D11ResourceType - Type of D3D11 resource being checked (ID3D11ShaderResourceView,
-/// ID3D11UnorderedAccessView, ID3D11Buffer or ID3D11SamplerState).
-/// \tparam TGetD3D11ResourcesType - Type of the device context method used to get the bound
-/// resources
-/// \param CommittedD3D11ResourcesArr - Pointer to the array of currently bound D3D11
-/// resources, for each shader stage
-/// \param GetD3D11ResMethods - Pointer to the array of device context methods to get the bound
-/// resources, for each shader stage
-/// \param ResourceName - Resource name
-/// \param ShaderType - Shader type for which to check the resources. If Diligent::SHADER_TYPE_UNKNOWN
-/// is provided, all shader stages will be checked
-template <UINT MaxResources,
- typename TD3D11ResourceType,
- typename TGetD3D11ResourcesType>
-void DeviceContextD3D11Impl::dbgVerifyCommittedResources(TD3D11ResourceType CommittedD3D11ResourcesArr[][MaxResources],
- Uint8 NumCommittedResourcesArr[],
- TGetD3D11ResourcesType GetD3D11ResMethods[],
- const Char* ResourceName,
- SHADER_TYPE ShaderType)
-{
- int iStartInd = 0, iEndInd = NumShaderTypes;
- if (ShaderType != SHADER_TYPE_UNKNOWN)
- {
- iStartInd = GetShaderTypeIndex(ShaderType);
- iEndInd = iStartInd + 1;
- }
- for (int iShaderTypeInd = iStartInd; iShaderTypeInd < iEndInd; ++iShaderTypeInd)
- {
- const auto ShaderName = GetShaderTypeLiteralName(GetShaderTypeFromIndex(iShaderTypeInd));
- TD3D11ResourceType pctxResources[MaxResources] = {};
- auto GetResMethod = GetD3D11ResMethods[iShaderTypeInd];
- if (GetResMethod)
- {
- (m_pd3d11DeviceContext->*GetResMethod)(0, _countof(pctxResources), pctxResources);
- }
- const auto* CommittedResources = CommittedD3D11ResourcesArr[iShaderTypeInd];
- auto NumCommittedResources = NumCommittedResourcesArr[iShaderTypeInd];
- for (Uint32 Slot = 0; Slot < _countof(pctxResources); ++Slot)
- {
- if (Slot < NumCommittedResources)
- {
- VERIFY(CommittedResources[Slot] == pctxResources[Slot], ResourceName, " binding mismatch found for ", ShaderName, " shader type at slot ", Slot);
- }
- else
- {
- VERIFY(pctxResources[Slot] == nullptr, ResourceName, " binding mismatch found for ", ShaderName, " shader type at slot ", Slot);
- VERIFY(CommittedResources[Slot] == nullptr, ResourceName, " unexpected non-null resource found for ", ShaderName, " shader type at slot ", Slot);
- }
-
- if (pctxResources[Slot])
- pctxResources[Slot]->Release();
- }
- }
-}
-
-template <UINT MaxResources, typename TD3D11ViewType>
-void DeviceContextD3D11Impl::dbgVerifyViewConsistency(TD3D11ViewType CommittedD3D11ViewArr[][MaxResources],
- ID3D11Resource* CommittedD3D11ResourcesArr[][MaxResources],
- Uint8 NumCommittedResourcesArr[],
- const Char* ResourceName,
- SHADER_TYPE ShaderType)
-{
- int iStartInd = 0, iEndInd = NumShaderTypes;
- if (ShaderType != SHADER_TYPE_UNKNOWN)
- {
- iStartInd = GetShaderTypeIndex(ShaderType);
- iEndInd = iStartInd + 1;
- }
- for (int iShaderTypeInd = iStartInd; iShaderTypeInd < iEndInd; ++iShaderTypeInd)
- {
- const auto ShaderName = GetShaderTypeLiteralName(GetShaderTypeFromIndex(iShaderTypeInd));
- auto* Views = CommittedD3D11ViewArr[iShaderTypeInd];
- auto* Resources = CommittedD3D11ResourcesArr[iShaderTypeInd];
- auto NumCommittedResources = NumCommittedResourcesArr[iShaderTypeInd];
- for (Uint32 Slot = 0; Slot < NumCommittedResources; ++Slot)
- {
- if (Views[Slot] != nullptr)
- {
- CComPtr<ID3D11Resource> pRefRes;
- Views[Slot]->GetResource(&pRefRes);
- VERIFY(pRefRes == Resources[Slot], "Inconsistent ", ResourceName, " detected at slot ", Slot, " in shader ", ShaderName, ". The resource in the view does not match cached D3D11 resource");
- }
- }
- }
-}
-
-void DeviceContextD3D11Impl::dbgVerifyCommittedSRVs(SHADER_TYPE ShaderType)
-{
- dbgVerifyCommittedResources<D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT>(m_CommittedD3D11SRVs, m_NumCommittedSRVs, GetSRVMethods, "SRV", ShaderType);
- dbgVerifyViewConsistency<D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT>(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, "SRV", ShaderType);
-}
-
-void DeviceContextD3D11Impl::dbgVerifyCommittedUAVs(SHADER_TYPE ShaderType)
-{
- dbgVerifyCommittedResources<D3D11_PS_CS_UAV_REGISTER_COUNT>(m_CommittedD3D11UAVs, m_NumCommittedUAVs, GetUAVMethods, "UAV", ShaderType);
- dbgVerifyViewConsistency<D3D11_PS_CS_UAV_REGISTER_COUNT>(m_CommittedD3D11UAVs, m_CommittedD3D11UAVResources, m_NumCommittedUAVs, "UAV", ShaderType);
-}
-
-void DeviceContextD3D11Impl::dbgVerifyCommittedSamplers(SHADER_TYPE ShaderType)
-{
- dbgVerifyCommittedResources<D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT>(m_CommittedD3D11Samplers, m_NumCommittedSamplers, GetSamplerMethods, "Sampler", ShaderType);
-}
-
-void DeviceContextD3D11Impl::dbgVerifyCommittedCBs(SHADER_TYPE ShaderType)
-{
- dbgVerifyCommittedResources<D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT>(m_CommittedD3D11CBs, m_NumCommittedCBs, GetCBMethods, "Constant buffer", ShaderType);
-}
-
-void DeviceContextD3D11Impl::dbgVerifyCommittedIndexBuffer()
-{
- RefCntAutoPtr<ID3D11Buffer> pctxIndexBuffer;
- DXGI_FORMAT Fmt = DXGI_FORMAT_UNKNOWN;
- UINT Offset = 0;
- m_pd3d11DeviceContext->IAGetIndexBuffer(&pctxIndexBuffer, &Fmt, &Offset);
- if (m_CommittedD3D11IndexBuffer && !pctxIndexBuffer)
- UNEXPECTED("D3D11 index buffer is not bound to the context");
- if (!m_CommittedD3D11IndexBuffer && pctxIndexBuffer)
- UNEXPECTED("Unexpected D3D11 index buffer is bound to the context");
-
- if (m_CommittedD3D11IndexBuffer && pctxIndexBuffer)
- {
- VERIFY(m_CommittedD3D11IndexBuffer == pctxIndexBuffer, "Index buffer binding mismatch detected");
- if (Fmt == DXGI_FORMAT_R32_UINT)
- {
- VERIFY(m_CommittedIBFormat == VT_UINT32, "Index buffer format mismatch detected");
- }
- else if (Fmt == DXGI_FORMAT_R16_UINT)
- {
- VERIFY(m_CommittedIBFormat == VT_UINT16, "Index buffer format mismatch detected");
- }
- VERIFY(m_CommittedD3D11IndexDataStartOffset == Offset, "Index buffer offset mismatch detected");
- }
-}
-
-void DeviceContextD3D11Impl::dbgVerifyCommittedVertexBuffers()
-{
- CComPtr<ID3D11InputLayout> pInputLayout;
- m_pd3d11DeviceContext->IAGetInputLayout(&pInputLayout);
- VERIFY(pInputLayout == m_CommittedD3D11InputLayout, "Inconsistent input layout");
-
- const Uint32 MaxVBs = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT;
- ID3D11Buffer* pVBs[MaxVBs];
- UINT Strides[MaxVBs];
- UINT Offsets[MaxVBs];
- m_pd3d11DeviceContext->IAGetVertexBuffers(0, MaxVBs, pVBs, Strides, Offsets);
- auto NumBoundVBs = m_NumCommittedD3D11VBs;
- for (Uint32 Slot = 0; Slot < MaxVBs; ++Slot)
- {
- if (Slot < NumBoundVBs)
- {
- const auto& BoundD3D11VB = m_CommittedD3D11VertexBuffers[Slot];
- auto BoundVBStride = m_CommittedD3D11VBStrides[Slot];
- auto BoundVBOffset = m_CommittedD3D11VBOffsets[Slot];
- if (BoundD3D11VB && !pVBs[Slot])
- VERIFY(pVBs[Slot] == nullptr, "Missing D3D11 buffer detected at slot ", Slot);
- if (!BoundD3D11VB && pVBs[Slot])
- VERIFY(pVBs[Slot] == nullptr, "Unexpected D3D11 buffer detected at slot ", Slot);
- if (BoundD3D11VB && pVBs[Slot])
- {
- VERIFY(BoundD3D11VB == pVBs[Slot], "Vertex buffer mismatch detected at slot ", Slot);
- VERIFY(BoundVBOffset == Offsets[Slot], "Offset mismatch detected at slot ", Slot);
- VERIFY(BoundVBStride == Strides[Slot], "Stride mismatch detected at slot ", Slot);
- }
- }
- else
- {
- VERIFY(pVBs[Slot] == nullptr, "Unexpected D3D11 buffer detected at slot ", Slot);
- }
-
- if (pVBs[Slot])
- pVBs[Slot]->Release();
- }
-}
-
-template <typename TD3D11ShaderType, typename TGetShaderMethodType>
-void dbgVerifyCommittedShadersHelper(SHADER_TYPE ShaderType,
- const CComPtr<ID3D11DeviceChild> BoundD3DShaders[],
- ID3D11DeviceContext* pCtx,
- TGetShaderMethodType GetShaderMethod)
-{
- RefCntAutoPtr<TD3D11ShaderType> pctxShader;
- (pCtx->*GetShaderMethod)(&pctxShader, nullptr, nullptr);
- const auto& BoundShader = BoundD3DShaders[GetShaderTypeIndex(ShaderType)];
- VERIFY(BoundShader == pctxShader, GetShaderTypeLiteralName(ShaderType), " binding mismatch detected");
-}
-void DeviceContextD3D11Impl::dbgVerifyCommittedShaders()
-{
-# define VERIFY_SHADER(NAME, Name, N) dbgVerifyCommittedShadersHelper<ID3D11##Name##Shader>(SHADER_TYPE_##NAME, m_CommittedD3DShaders, m_pd3d11DeviceContext, &ID3D11DeviceContext::N##SGetShader)
- // These shaders which are not set will be unbound from the D3D11 device context
- VERIFY_SHADER(VERTEX, Vertex, V);
- VERIFY_SHADER(PIXEL, Pixel, P);
- VERIFY_SHADER(GEOMETRY, Geometry, G);
- VERIFY_SHADER(DOMAIN, Domain, D);
- VERIFY_SHADER(HULL, Hull, H);
- VERIFY_SHADER(COMPUTE, Compute, C);
-}
-
-#endif // VERIFY_CONTEXT_BINDINGS
-} // namespace Diligent
+void DeviceContextD3D11Impl::DispatchCompute(const DispatchComputeAttribs& Attribs)
+{
+ if (!DvpVerifyDispatchArguments(Attribs))
+ return;
+
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ // Verify bindings
+ dbgVerifyCommittedSRVs();
+ dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
+ dbgVerifyCommittedSamplers();
+ dbgVerifyCommittedCBs();
+ dbgVerifyCommittedShaders();
+ }
+#endif
+
+ m_pd3d11DeviceContext->Dispatch(Attribs.ThreadGroupCountX, Attribs.ThreadGroupCountY, Attribs.ThreadGroupCountZ);
+}
+
+void DeviceContextD3D11Impl::DispatchComputeIndirect(const DispatchComputeIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
+{
+ if (!DvpVerifyDispatchIndirectArguments(Attribs, pAttribsBuffer))
+ return;
+
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ // Verify bindings
+ dbgVerifyCommittedSRVs();
+ dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
+ dbgVerifyCommittedSamplers();
+ dbgVerifyCommittedCBs();
+ dbgVerifyCommittedShaders();
+ }
+#endif
+
+ auto* pd3d11Buff = ValidatedCast<BufferD3D11Impl>(pAttribsBuffer)->GetD3D11Buffer();
+ m_pd3d11DeviceContext->DispatchIndirect(pd3d11Buff, Attribs.DispatchArgsByteOffset);
+}
+
+
+void DeviceContextD3D11Impl::ClearDepthStencil(ITextureView* pView,
+ CLEAR_DEPTH_STENCIL_FLAGS ClearFlags,
+ float fDepth,
+ Uint8 Stencil,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ if (!TDeviceContextBase::ClearDepthStencil(pView))
+ return;
+
+ VERIFY_EXPR(pView != nullptr);
+
+ auto* pViewD3D11 = ValidatedCast<TextureViewD3D11Impl>(pView);
+ auto* pd3d11DSV = static_cast<ID3D11DepthStencilView*>(pViewD3D11->GetD3D11View());
+
+ UINT32 d3d11ClearFlags = 0;
+ if (ClearFlags & CLEAR_DEPTH_FLAG) d3d11ClearFlags |= D3D11_CLEAR_DEPTH;
+ if (ClearFlags & CLEAR_STENCIL_FLAG) d3d11ClearFlags |= D3D11_CLEAR_STENCIL;
+ // The full extent of the resource view is always cleared.
+ // Viewport and scissor settings are not applied.
+ m_pd3d11DeviceContext->ClearDepthStencilView(pd3d11DSV, d3d11ClearFlags, fDepth, Stencil);
+}
+
+void DeviceContextD3D11Impl::ClearRenderTarget(ITextureView* pView, const float* RGBA, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ if (!TDeviceContextBase::ClearRenderTarget(pView))
+ return;
+
+ VERIFY_EXPR(pView != nullptr);
+
+ auto* pViewD3D11 = ValidatedCast<TextureViewD3D11Impl>(pView);
+ auto* pd3d11RTV = static_cast<ID3D11RenderTargetView*>(pViewD3D11->GetD3D11View());
+
+ static const float Zero[4] = {0.f, 0.f, 0.f, 0.f};
+ if (RGBA == nullptr)
+ RGBA = Zero;
+
+ // The full extent of the resource view is always cleared.
+ // Viewport and scissor settings are not applied.
+ m_pd3d11DeviceContext->ClearRenderTargetView(pd3d11RTV, RGBA);
+}
+
+void DeviceContextD3D11Impl::Flush()
+{
+ m_pd3d11DeviceContext->Flush();
+}
+
+void DeviceContextD3D11Impl::UpdateBuffer(IBuffer* pBuffer,
+ Uint32 Offset,
+ Uint32 Size,
+ const void* pData,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ TDeviceContextBase::UpdateBuffer(pBuffer, Offset, Size, pData, StateTransitionMode);
+
+ auto* pBufferD3D11Impl = ValidatedCast<BufferD3D11Impl>(pBuffer);
+
+ D3D11_BOX DstBox;
+ DstBox.left = Offset;
+ DstBox.right = Offset + Size;
+ DstBox.top = 0;
+ DstBox.bottom = 1;
+ DstBox.front = 0;
+ DstBox.back = 1;
+ auto* pDstBox = (Offset == 0 && Size == pBufferD3D11Impl->GetDesc().uiSizeInBytes) ? nullptr : &DstBox;
+ m_pd3d11DeviceContext->UpdateSubresource(pBufferD3D11Impl->m_pd3d11Buffer, 0, pDstBox, pData, 0, 0);
+}
+
+void DeviceContextD3D11Impl::CopyBuffer(IBuffer* pSrcBuffer,
+ Uint32 SrcOffset,
+ RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
+ IBuffer* pDstBuffer,
+ Uint32 DstOffset,
+ Uint32 Size,
+ RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode)
+{
+ TDeviceContextBase::CopyBuffer(pSrcBuffer, SrcOffset, SrcBufferTransitionMode, pDstBuffer, DstOffset, Size, DstBufferTransitionMode);
+
+ auto* pSrcBufferD3D11Impl = ValidatedCast<BufferD3D11Impl>(pSrcBuffer);
+ auto* pDstBufferD3D11Impl = ValidatedCast<BufferD3D11Impl>(pDstBuffer);
+
+ D3D11_BOX SrcBox;
+ SrcBox.left = SrcOffset;
+ SrcBox.right = SrcOffset + Size;
+ SrcBox.top = 0;
+ SrcBox.bottom = 1;
+ SrcBox.front = 0;
+ SrcBox.back = 1;
+ m_pd3d11DeviceContext->CopySubresourceRegion(pDstBufferD3D11Impl->m_pd3d11Buffer, 0, DstOffset, 0, 0, pSrcBufferD3D11Impl->m_pd3d11Buffer, 0, &SrcBox);
+}
+
+
+void DeviceContextD3D11Impl::MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData)
+{
+ TDeviceContextBase::MapBuffer(pBuffer, MapType, MapFlags, pMappedData);
+
+ auto* pBufferD3D11 = ValidatedCast<BufferD3D11Impl>(pBuffer);
+ D3D11_MAP d3d11MapType = static_cast<D3D11_MAP>(0);
+ UINT d3d11MapFlags = 0;
+ MapParamsToD3D11MapParams(MapType, MapFlags, d3d11MapType, d3d11MapFlags);
+
+ D3D11_MAPPED_SUBRESOURCE MappedBuff;
+
+ HRESULT hr = m_pd3d11DeviceContext->Map(pBufferD3D11->m_pd3d11Buffer, 0, d3d11MapType, d3d11MapFlags, &MappedBuff);
+ if ((d3d11MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) == 0)
+ {
+ DEV_CHECK_ERR(SUCCEEDED(hr), "Failed to map buffer '", pBufferD3D11->GetDesc().Name, "'");
+ }
+ pMappedData = SUCCEEDED(hr) ? MappedBuff.pData : nullptr;
+}
+
+void DeviceContextD3D11Impl::UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType)
+{
+ TDeviceContextBase::UnmapBuffer(pBuffer, MapType);
+ auto* pBufferD3D11 = ValidatedCast<BufferD3D11Impl>(pBuffer);
+ m_pd3d11DeviceContext->Unmap(pBufferD3D11->m_pd3d11Buffer, 0);
+}
+
+void DeviceContextD3D11Impl::UpdateTexture(ITexture* pTexture,
+ Uint32 MipLevel,
+ Uint32 Slice,
+ const Box& DstBox,
+ const TextureSubResData& SubresData,
+ RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
+ RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode)
+{
+ TDeviceContextBase::UpdateTexture(pTexture, MipLevel, Slice, DstBox, SubresData, SrcBufferTransitionMode, DstTextureTransitionMode);
+
+ auto* pTexD3D11 = ValidatedCast<TextureBaseD3D11>(pTexture);
+ const auto& Desc = pTexD3D11->GetDesc();
+
+ // OpenGL backend uses UpdateData() to initialize textures, so we can't check the usage in ValidateUpdateTextureParams()
+ DEV_CHECK_ERR(Desc.Usage == USAGE_DEFAULT, "Only USAGE_DEFAULT textures should be updated with UpdateData()");
+
+ if (SubresData.pSrcBuffer != nullptr)
+ {
+ LOG_ERROR("D3D11 does not support updating texture subresource from a GPU buffer");
+ return;
+ }
+
+ D3D11_BOX D3D11Box;
+ D3D11Box.left = DstBox.MinX;
+ D3D11Box.right = DstBox.MaxX;
+ D3D11Box.top = DstBox.MinY;
+ D3D11Box.bottom = DstBox.MaxY;
+ D3D11Box.front = DstBox.MinZ;
+ D3D11Box.back = DstBox.MaxZ;
+ const auto& FmtAttribs = GetTextureFormatAttribs(Desc.Format);
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
+ {
+ // Align update region by the compressed block size
+ VERIFY((D3D11Box.left % FmtAttribs.BlockWidth) == 0, "Update region min X coordinate (", D3D11Box.left, ") must be multiple of a compressed block width (", Uint32{FmtAttribs.BlockWidth}, ")");
+ VERIFY((FmtAttribs.BlockWidth & (FmtAttribs.BlockWidth - 1)) == 0, "Compressed block width (", Uint32{FmtAttribs.BlockWidth}, ") is expected to be power of 2");
+ D3D11Box.right = (D3D11Box.right + FmtAttribs.BlockWidth - 1) & ~(FmtAttribs.BlockWidth - 1);
+
+ VERIFY((D3D11Box.top % FmtAttribs.BlockHeight) == 0, "Update region min Y coordinate (", D3D11Box.top, ") must be multiple of a compressed block height (", Uint32{FmtAttribs.BlockHeight}, ")");
+ VERIFY((FmtAttribs.BlockHeight & (FmtAttribs.BlockHeight - 1)) == 0, "Compressed block height (", Uint32{FmtAttribs.BlockHeight}, ") is expected to be power of 2");
+ D3D11Box.bottom = (D3D11Box.bottom + FmtAttribs.BlockHeight - 1) & ~(FmtAttribs.BlockHeight - 1);
+ }
+ auto SubresIndex = D3D11CalcSubresource(MipLevel, Slice, Desc.MipLevels);
+ m_pd3d11DeviceContext->UpdateSubresource(pTexD3D11->GetD3D11Texture(), SubresIndex, &D3D11Box, SubresData.pData, SubresData.Stride, SubresData.DepthStride);
+}
+
+void DeviceContextD3D11Impl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
+{
+ TDeviceContextBase::CopyTexture(CopyAttribs);
+
+ auto* pSrcTexD3D11 = ValidatedCast<TextureBaseD3D11>(CopyAttribs.pSrcTexture);
+ auto* pDstTexD3D11 = ValidatedCast<TextureBaseD3D11>(CopyAttribs.pDstTexture);
+
+ D3D11_BOX D3D11SrcBox, *pD3D11SrcBox = nullptr;
+ if (const auto* pSrcBox = CopyAttribs.pSrcBox)
+ {
+ D3D11SrcBox.left = pSrcBox->MinX;
+ D3D11SrcBox.right = pSrcBox->MaxX;
+ D3D11SrcBox.top = pSrcBox->MinY;
+ D3D11SrcBox.bottom = pSrcBox->MaxY;
+ D3D11SrcBox.front = pSrcBox->MinZ;
+ D3D11SrcBox.back = pSrcBox->MaxZ;
+ pD3D11SrcBox = &D3D11SrcBox;
+ }
+ auto SrcSubRes = D3D11CalcSubresource(CopyAttribs.SrcMipLevel, CopyAttribs.SrcSlice, pSrcTexD3D11->GetDesc().MipLevels);
+ auto DstSubRes = D3D11CalcSubresource(CopyAttribs.DstMipLevel, CopyAttribs.DstSlice, pDstTexD3D11->GetDesc().MipLevels);
+ m_pd3d11DeviceContext->CopySubresourceRegion(pDstTexD3D11->GetD3D11Texture(), DstSubRes, CopyAttribs.DstX, CopyAttribs.DstY, CopyAttribs.DstZ,
+ pSrcTexD3D11->GetD3D11Texture(), SrcSubRes, pD3D11SrcBox);
+}
+
+
+void DeviceContextD3D11Impl::MapTextureSubresource(ITexture* pTexture,
+ Uint32 MipLevel,
+ Uint32 ArraySlice,
+ MAP_TYPE MapType,
+ MAP_FLAGS MapFlags,
+ const Box* pMapRegion,
+ MappedTextureSubresource& MappedData)
+{
+ TDeviceContextBase::MapTextureSubresource(pTexture, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion, MappedData);
+
+ auto* pTexD3D11 = ValidatedCast<TextureBaseD3D11>(pTexture);
+ const auto& TexDesc = pTexD3D11->GetDesc();
+ D3D11_MAP d3d11MapType = static_cast<D3D11_MAP>(0);
+ UINT d3d11MapFlags = 0;
+ MapParamsToD3D11MapParams(MapType, MapFlags, d3d11MapType, d3d11MapFlags);
+
+ auto Subresource = D3D11CalcSubresource(MipLevel, ArraySlice, TexDesc.MipLevels);
+ D3D11_MAPPED_SUBRESOURCE MappedTex;
+ auto hr = m_pd3d11DeviceContext->Map(pTexD3D11->GetD3D11Texture(), Subresource, d3d11MapType, d3d11MapFlags, &MappedTex);
+ if (FAILED(hr))
+ {
+ VERIFY_EXPR(hr == DXGI_ERROR_WAS_STILL_DRAWING);
+ MappedData = MappedTextureSubresource();
+ }
+ else
+ {
+ MappedData.pData = MappedTex.pData;
+ MappedData.Stride = MappedTex.RowPitch;
+ MappedData.DepthStride = MappedTex.DepthPitch;
+ }
+}
+
+void DeviceContextD3D11Impl::UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice)
+{
+ TDeviceContextBase::UnmapTextureSubresource(pTexture, MipLevel, ArraySlice);
+
+ auto* pTexD3D11 = ValidatedCast<TextureBaseD3D11>(pTexture);
+ const auto& TexDesc = pTexD3D11->GetDesc();
+ auto Subresource = D3D11CalcSubresource(MipLevel, ArraySlice, TexDesc.MipLevels);
+ m_pd3d11DeviceContext->Unmap(pTexD3D11->GetD3D11Texture(), Subresource);
+}
+
+void DeviceContextD3D11Impl::GenerateMips(ITextureView* pTextureView)
+{
+ TDeviceContextBase::GenerateMips(pTextureView);
+ auto& TexViewD3D11 = *ValidatedCast<TextureViewD3D11Impl>(pTextureView);
+ auto* pd3d11SRV = static_cast<ID3D11ShaderResourceView*>(TexViewD3D11.GetD3D11View());
+ m_pd3d11DeviceContext->GenerateMips(pd3d11SRV);
+}
+
+void DeviceContextD3D11Impl::FinishFrame()
+{
+ if (m_ActiveDisjointQuery)
+ {
+ m_pd3d11DeviceContext->End(m_ActiveDisjointQuery->pd3d11Query);
+ m_ActiveDisjointQuery->IsEnded = true;
+ m_ActiveDisjointQuery.reset();
+ }
+}
+
+void DeviceContextD3D11Impl::SetVertexBuffers(Uint32 StartSlot,
+ Uint32 NumBuffersSet,
+ IBuffer** ppBuffers,
+ Uint32* pOffsets,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
+ SET_VERTEX_BUFFERS_FLAGS Flags)
+{
+ TDeviceContextBase::SetVertexBuffers(StartSlot, NumBuffersSet, ppBuffers, pOffsets, StateTransitionMode, Flags);
+ for (Uint32 Slot = 0; Slot < m_NumVertexStreams; ++Slot)
+ {
+ auto& CurrStream = m_VertexStreams[Slot];
+ if (auto* pBuffD3D11Impl = CurrStream.pBuffer.RawPtr())
+ {
+ if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ if (pBuffD3D11Impl->IsInKnownState() && pBuffD3D11Impl->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ UnbindResourceFromUAV(pBuffD3D11Impl, pBuffD3D11Impl->m_pd3d11Buffer);
+ pBuffD3D11Impl->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ if (pBuffD3D11Impl->IsInKnownState() && pBuffD3D11Impl->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", pBuffD3D11Impl->GetDesc().Name, "' used as vertex buffer at slot ", Slot, " is in RESOURCE_STATE_UNORDERED_ACCESS state. "
+ "Use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to RESOURCE_STATE_VERTEX_BUFFER state.");
+ }
+ }
+#endif
+ }
+ }
+
+ m_bCommittedD3D11VBsUpToDate = false;
+}
+
+void DeviceContextD3D11Impl::SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ TDeviceContextBase::SetIndexBuffer(pIndexBuffer, ByteOffset, StateTransitionMode);
+
+ if (m_pIndexBuffer)
+ {
+ if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ if (m_pIndexBuffer->IsInKnownState() && m_pIndexBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ UnbindResourceFromUAV(m_pIndexBuffer, m_pIndexBuffer->m_pd3d11Buffer);
+ m_pIndexBuffer->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ if (m_pIndexBuffer->IsInKnownState() && m_pIndexBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", m_pIndexBuffer->GetDesc().Name, "' used as index buffer is in RESOURCE_STATE_UNORDERED_ACCESS state."
+ " Use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to RESOURCE_STATE_INDEX_BUFFER state.");
+ }
+ }
+#endif
+ }
+
+ m_bCommittedD3D11IBUpToDate = false;
+}
+
+void DeviceContextD3D11Impl::SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32 RTWidth, Uint32 RTHeight)
+{
+ static_assert(MAX_VIEWPORTS >= D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, "MaxViewports constant must be greater than D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE");
+ TDeviceContextBase::SetViewports(NumViewports, pViewports, RTWidth, RTHeight);
+
+ D3D11_VIEWPORT d3d11Viewports[MAX_VIEWPORTS];
+ VERIFY(NumViewports == m_NumViewports, "Unexpected number of viewports");
+ for (Uint32 vp = 0; vp < m_NumViewports; ++vp)
+ {
+ d3d11Viewports[vp].TopLeftX = m_Viewports[vp].TopLeftX;
+ d3d11Viewports[vp].TopLeftY = m_Viewports[vp].TopLeftY;
+ d3d11Viewports[vp].Width = m_Viewports[vp].Width;
+ d3d11Viewports[vp].Height = m_Viewports[vp].Height;
+ d3d11Viewports[vp].MinDepth = m_Viewports[vp].MinDepth;
+ d3d11Viewports[vp].MaxDepth = m_Viewports[vp].MaxDepth;
+ }
+ // All viewports must be set atomically as one operation.
+ // Any viewports not defined by the call are disabled.
+ m_pd3d11DeviceContext->RSSetViewports(NumViewports, d3d11Viewports);
+}
+
+void DeviceContextD3D11Impl::SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32 RTWidth, Uint32 RTHeight)
+{
+ static_assert(MAX_VIEWPORTS >= D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE, "MaxViewports constant must be greater than D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE");
+ TDeviceContextBase::SetScissorRects(NumRects, pRects, RTWidth, RTHeight);
+
+ D3D11_RECT d3d11ScissorRects[MAX_VIEWPORTS];
+ VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects");
+ for (Uint32 sr = 0; sr < NumRects; ++sr)
+ {
+ d3d11ScissorRects[sr].left = m_ScissorRects[sr].left;
+ d3d11ScissorRects[sr].top = m_ScissorRects[sr].top;
+ d3d11ScissorRects[sr].right = m_ScissorRects[sr].right;
+ d3d11ScissorRects[sr].bottom = m_ScissorRects[sr].bottom;
+ }
+
+ // All scissor rects must be set atomically as one operation.
+ // Any scissor rects not defined by the call are disabled.
+ m_pd3d11DeviceContext->RSSetScissorRects(NumRects, d3d11ScissorRects);
+}
+
+void DeviceContextD3D11Impl::CommitRenderTargets()
+{
+ const Uint32 MaxD3D11RTs = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
+ Uint32 NumRenderTargets = m_NumBoundRenderTargets;
+ VERIFY(NumRenderTargets <= MaxD3D11RTs, "D3D11 only allows 8 simultaneous render targets");
+ NumRenderTargets = std::min(MaxD3D11RTs, NumRenderTargets);
+
+ // Do not waste time setting RTVs to null
+ ID3D11RenderTargetView* pd3d11RTs[MaxD3D11RTs];
+ ID3D11DepthStencilView* pd3d11DSV = nullptr;
+
+ for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
+ {
+ auto* pViewD3D11 = m_pBoundRenderTargets[rt].RawPtr();
+ pd3d11RTs[rt] = pViewD3D11 != nullptr ? static_cast<ID3D11RenderTargetView*>(pViewD3D11->GetD3D11View()) : nullptr;
+ }
+
+ if (m_pBoundDepthStencil != nullptr)
+ {
+ pd3d11DSV = static_cast<ID3D11DepthStencilView*>(m_pBoundDepthStencil->GetD3D11View());
+ }
+
+ auto& NumCommittedPixelShaderUAVs = m_NumCommittedUAVs[PSInd];
+ if (NumCommittedPixelShaderUAVs > 0)
+ {
+ m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(NumRenderTargets, NumRenderTargets > 0 ? pd3d11RTs : nullptr, pd3d11DSV,
+ 0, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, nullptr, nullptr);
+
+ auto CommittedD3D11UAVs = m_CommittedD3D11UAVs[PSInd];
+ auto CommittedD3D11UAVRes = m_CommittedD3D11UAVResources[PSInd];
+ for (Uint32 slot = 0; slot < NumRenderTargets; ++slot)
+ {
+ CommittedD3D11UAVs[slot] = nullptr;
+ CommittedD3D11UAVRes[slot] = nullptr;
+ }
+ if (NumRenderTargets >= NumCommittedPixelShaderUAVs)
+ NumCommittedPixelShaderUAVs = 0;
+ }
+ else
+ {
+ m_pd3d11DeviceContext->OMSetRenderTargets(NumRenderTargets, NumRenderTargets > 0 ? pd3d11RTs : nullptr, pd3d11DSV);
+ }
+}
+
+
+void UnbindView(ID3D11DeviceContext* pContext, TSetShaderResourcesType SetSRVMethod, UINT Slot)
+{
+ ID3D11ShaderResourceView* ppNullView[] = {nullptr};
+ (pContext->*SetSRVMethod)(Slot, 1, ppNullView);
+}
+
+void UnbindView(ID3D11DeviceContext* pContext, TSetUnorderedAccessViewsType SetUAVMethod, UINT Slot)
+{
+ ID3D11UnorderedAccessView* ppNullView[] = {nullptr};
+ (pContext->*SetUAVMethod)(Slot, 1, ppNullView, nullptr);
+}
+
+template <typename TD3D11ResourceViewType, typename TSetD3D11View>
+bool UnbindPixelShaderUAV(ID3D11DeviceContext* pDeviceCtx,
+ TD3D11ResourceViewType* CommittedD3D11Resources[],
+ Uint32 NumCommittedSlots,
+ Uint32 NumCommittedRenderTargets,
+ TSetD3D11View SetD3D11ViewMethod)
+{
+ // For other resource view types do nothing
+ return false;
+}
+
+template <>
+bool UnbindPixelShaderUAV<ID3D11UnorderedAccessView, TSetUnorderedAccessViewsType>(
+ ID3D11DeviceContext* pDeviceCtx,
+ ID3D11UnorderedAccessView* CommittedD3D11UAVs[],
+ Uint32 NumCommittedUAVs,
+ Uint32 NumCommittedRenderTargets,
+ TSetUnorderedAccessViewsType SetD3D11UAVMethod)
+{
+ if (SetD3D11UAVMethod == reinterpret_cast<TSetUnorderedAccessViewsType>(&ID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews))
+ {
+ // Pixel shader UAVs are bound in a special way simulatneously with the render targets
+ auto UAVStartSlot = NumCommittedRenderTargets;
+ // UAVs cannot be set independently; they all need to be set at the same time.
+ // https://docs.microsoft.com/en-us/windows/desktop/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews#remarks
+
+ // There is potential problem here: since device context does not keep strong references to
+ // UAVs, there is no guarantee the objects are alive
+ pDeviceCtx->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
+ UAVStartSlot, NumCommittedUAVs - UAVStartSlot,
+ CommittedD3D11UAVs + UAVStartSlot, nullptr);
+ return true;
+ }
+
+ return false;
+}
+
+
+
+/// \tparam TD3D11ResourceViewType - Type of the D3D11 resource view (ID3D11ShaderResourceView or ID3D11UnorderedAccessView)
+/// \tparam TSetD3D11View - Type of the D3D11 device context method used to set the D3D11 view
+/// \param CommittedResourcesArr - Pointer to the array of strong references to currently bound
+/// shader resources, for each shader stage
+/// \param CommittedD3D11ResourcesArr - Pointer to the array of currently bound D3D11
+/// shader resources, for each shader stage
+/// \param pd3d11ResToUndind - D3D11 resource to unbind
+/// \param SetD3D11ViewMethods - Array of pointers to device context methods used to set the view,
+/// for every shader stage
+template <typename TD3D11ResourceViewType,
+ typename TSetD3D11View,
+ size_t NumSlots>
+void DeviceContextD3D11Impl::UnbindResourceView(TD3D11ResourceViewType CommittedD3D11ViewsArr[][NumSlots],
+ ID3D11Resource* CommittedD3D11ResourcesArr[][NumSlots],
+ Uint8 NumCommittedResourcesArr[],
+ ID3D11Resource* pd3d11ResToUndind,
+ TSetD3D11View SetD3D11ViewMethods[])
+{
+ for (Int32 ShaderTypeInd = 0; ShaderTypeInd < NumShaderTypes; ++ShaderTypeInd)
+ {
+ auto* CommittedD3D11Views = CommittedD3D11ViewsArr[ShaderTypeInd];
+ auto* CommittedD3D11Resources = CommittedD3D11ResourcesArr[ShaderTypeInd];
+ auto& NumCommittedSlots = NumCommittedResourcesArr[ShaderTypeInd];
+
+ for (Uint32 Slot = 0; Slot < NumCommittedSlots; ++Slot)
+ {
+ if (CommittedD3D11Resources[Slot] == pd3d11ResToUndind)
+ {
+ CommittedD3D11Resources[Slot] = nullptr;
+ CommittedD3D11Views[Slot] = nullptr;
+
+ auto SetViewMethod = SetD3D11ViewMethods[ShaderTypeInd];
+ VERIFY(SetViewMethod != nullptr, "No appropriate ID3D11DeviceContext method");
+
+ // Pixel shader UAVs require special handling
+ if (!UnbindPixelShaderUAV(m_pd3d11DeviceContext, CommittedD3D11Views, NumCommittedSlots, m_NumBoundRenderTargets, SetViewMethod))
+ {
+ UnbindView(m_pd3d11DeviceContext, SetViewMethod, Slot);
+ }
+ }
+ }
+
+ // Pop null resources from the end of arrays
+ while (NumCommittedSlots > 0 && CommittedD3D11Resources[NumCommittedSlots - 1] == nullptr)
+ {
+ VERIFY(CommittedD3D11Views[NumSlots - 1] == nullptr, "Unexpected non-null resource view");
+ --NumCommittedSlots;
+ }
+ }
+}
+
+void DeviceContextD3D11Impl::UnbindTextureFromInput(TextureBaseD3D11* pTexture, ID3D11Resource* pd3d11Resource)
+{
+ VERIFY(pTexture, "Null texture provided");
+ if (!pTexture) return;
+
+ UnbindResourceView(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, pd3d11Resource, SetSRVMethods);
+ pTexture->ClearState(RESOURCE_STATE_SHADER_RESOURCE);
+}
+
+void DeviceContextD3D11Impl::UnbindBufferFromInput(BufferD3D11Impl* pBuffer, ID3D11Resource* pd3d11Buffer)
+{
+ VERIFY(pBuffer, "Null buffer provided");
+ if (!pBuffer || !pBuffer->IsInKnownState()) return;
+
+ if (pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
+ {
+ UnbindResourceView(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, pd3d11Buffer, SetSRVMethods);
+ pBuffer->ClearState(RESOURCE_STATE_SHADER_RESOURCE);
+ }
+
+ if (pBuffer->CheckState(RESOURCE_STATE_INDEX_BUFFER))
+ {
+ auto pd3d11IndBuffer = ValidatedCast<BufferD3D11Impl>(pBuffer)->GetD3D11Buffer();
+ if (pd3d11IndBuffer == m_CommittedD3D11IndexBuffer)
+ {
+ // Only unbind D3D11 buffer from the context!
+ // m_pIndexBuffer.Release();
+ m_CommittedD3D11IndexBuffer.Release();
+ m_CommittedIBFormat = VT_UNDEFINED;
+ m_CommittedD3D11IndexDataStartOffset = 0;
+ m_bCommittedD3D11IBUpToDate = false;
+ m_pd3d11DeviceContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_R32_UINT, m_CommittedD3D11IndexDataStartOffset);
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ dbgVerifyCommittedIndexBuffer();
+ }
+#endif
+ pBuffer->ClearState(RESOURCE_STATE_INDEX_BUFFER);
+ }
+
+ if (pBuffer->CheckState(RESOURCE_STATE_VERTEX_BUFFER))
+ {
+ auto pd3d11VB = ValidatedCast<BufferD3D11Impl>(pBuffer)->GetD3D11Buffer();
+ for (Uint32 Slot = 0; Slot < m_NumCommittedD3D11VBs; ++Slot)
+ {
+ auto& CommittedD3D11VB = m_CommittedD3D11VertexBuffers[Slot];
+ if (CommittedD3D11VB == pd3d11VB)
+ {
+ // Unbind only D3D11 buffer
+ //*VertStream = VertexStreamInfo();
+ ID3D11Buffer* ppNullBuffer[] = {nullptr};
+ const UINT Zero[] = {0};
+ m_CommittedD3D11VertexBuffers[Slot] = nullptr;
+ m_CommittedD3D11VBStrides[Slot] = 0;
+ m_CommittedD3D11VBOffsets[Slot] = 0;
+ m_bCommittedD3D11VBsUpToDate = false;
+ m_pd3d11DeviceContext->IASetVertexBuffers(Slot, _countof(ppNullBuffer), ppNullBuffer, Zero, Zero);
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ dbgVerifyCommittedVertexBuffers();
+ }
+#endif
+ pBuffer->ClearState(RESOURCE_STATE_VERTEX_BUFFER);
+ }
+
+ if (pBuffer->CheckState(RESOURCE_STATE_CONSTANT_BUFFER))
+ {
+ for (Int32 ShaderTypeInd = 0; ShaderTypeInd < NumShaderTypes; ++ShaderTypeInd)
+ {
+ auto* CommittedD3D11CBs = m_CommittedD3D11CBs[ShaderTypeInd];
+ auto NumSlots = m_NumCommittedCBs[ShaderTypeInd];
+ for (Uint32 Slot = 0; Slot < NumSlots; ++Slot)
+ {
+ if (CommittedD3D11CBs[Slot] == pd3d11Buffer)
+ {
+ CommittedD3D11CBs[Slot] = nullptr;
+ auto SetCBMethod = SetCBMethods[ShaderTypeInd];
+ ID3D11Buffer* ppNullBuffer[] = {nullptr};
+ (m_pd3d11DeviceContext->*SetCBMethod)(Slot, 1, ppNullBuffer);
+ }
+ }
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ dbgVerifyCommittedCBs();
+ }
+#endif
+ pBuffer->ClearState(RESOURCE_STATE_CONSTANT_BUFFER);
+ }
+}
+
+void DeviceContextD3D11Impl::UnbindResourceFromUAV(IDeviceObject* pResource, ID3D11Resource* pd3d11Resource)
+{
+ VERIFY(pResource, "Null resource provided");
+ if (!pResource) return;
+
+ UnbindResourceView(m_CommittedD3D11UAVs, m_CommittedD3D11UAVResources, m_NumCommittedUAVs, pd3d11Resource, SetUAVMethods);
+}
+
+void DeviceContextD3D11Impl::UnbindTextureFromRenderTarget(TextureBaseD3D11* pTexture)
+{
+ VERIFY(pTexture, "Null resource provided");
+ if (!pTexture) return;
+
+ bool bCommitRenderTargets = false;
+ for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
+ {
+ if (auto* pTexView = m_pBoundRenderTargets[rt].RawPtr())
+ {
+ if (pTexView->GetTexture() == pTexture)
+ {
+ m_pBoundRenderTargets[rt].Release();
+ bCommitRenderTargets = true;
+ }
+ }
+ }
+
+ if (bCommitRenderTargets)
+ {
+ while (m_NumBoundRenderTargets > 0 && !m_pBoundRenderTargets[m_NumBoundRenderTargets - 1])
+ --m_NumBoundRenderTargets;
+
+ CommitRenderTargets();
+ }
+
+ pTexture->ClearState(RESOURCE_STATE_RENDER_TARGET);
+}
+
+void DeviceContextD3D11Impl::UnbindTextureFromDepthStencil(TextureBaseD3D11* pTexD3D11)
+{
+ VERIFY(pTexD3D11, "Null resource provided");
+ if (!pTexD3D11) return;
+
+ if (m_pBoundDepthStencil && m_pBoundDepthStencil->GetTexture() == pTexD3D11)
+ {
+ m_pBoundDepthStencil.Release();
+ CommitRenderTargets();
+ }
+ pTexD3D11->ClearState(RESOURCE_STATE_DEPTH_WRITE);
+}
+
+void DeviceContextD3D11Impl::ResetRenderTargets()
+{
+ TDeviceContextBase::ResetRenderTargets();
+ m_pd3d11DeviceContext->OMSetRenderTargets(0, nullptr, nullptr);
+}
+
+void DeviceContextD3D11Impl::SetRenderTargets(Uint32 NumRenderTargets,
+ ITextureView* ppRenderTargets[],
+ ITextureView* pDepthStencil,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ if (TDeviceContextBase::SetRenderTargets(NumRenderTargets, ppRenderTargets, pDepthStencil))
+ {
+ for (Uint32 RT = 0; RT < NumRenderTargets; ++RT)
+ {
+ if (ppRenderTargets[RT])
+ {
+ auto* pTex = ValidatedCast<TextureBaseD3D11>(ppRenderTargets[RT]->GetTexture());
+ if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ UnbindTextureFromInput(pTex, pTex->GetD3D11Texture());
+ if (pTex->IsInKnownState())
+ pTex->SetState(RESOURCE_STATE_RENDER_TARGET);
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyTextureState(*pTex, RESOURCE_STATE_RENDER_TARGET, "Setting render targets (DeviceContextD3D11Impl::SetRenderTargets)");
+ }
+#endif
+ }
+ }
+
+ if (pDepthStencil)
+ {
+ auto* pTex = ValidatedCast<TextureBaseD3D11>(pDepthStencil->GetTexture());
+ if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ UnbindTextureFromInput(pTex, pTex->GetD3D11Texture());
+ if (pTex->IsInKnownState())
+ pTex->SetState(RESOURCE_STATE_DEPTH_WRITE);
+ }
+#ifdef DILIGENT_DEVELOPMENT
+ else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyTextureState(*pTex, RESOURCE_STATE_DEPTH_WRITE, "Setting depth-stencil buffer (DeviceContextD3D11Impl::SetRenderTargets)");
+ }
+#endif
+ }
+
+ CommitRenderTargets();
+
+ // Set the viewport to match the render target size
+ SetViewports(1, nullptr, 0, 0);
+ }
+}
+
+template <typename TD3D11ResourceType, typename TSetD3D11ResMethodType>
+void SetD3D11ResourcesHelper(ID3D11DeviceContext* pDeviceCtx,
+ TSetD3D11ResMethodType SetD3D11ResMethod,
+ UINT StartSlot,
+ UINT NumSlots,
+ TD3D11ResourceType** ppResources)
+{
+ (pDeviceCtx->*SetD3D11ResMethod)(StartSlot, NumSlots, ppResources);
+}
+
+template <>
+void SetD3D11ResourcesHelper(ID3D11DeviceContext* pDeviceCtx,
+ TSetUnorderedAccessViewsType SetD3D11UAVMethod,
+ UINT StartSlot,
+ UINT NumSlots,
+ ID3D11UnorderedAccessView** ppUAVs)
+{
+ (pDeviceCtx->*SetD3D11UAVMethod)(StartSlot, NumSlots, ppUAVs, nullptr);
+}
+
+template <typename TD3D11ResourceType, typename TSetD3D11ResMethodType>
+void ReleaseCommittedShaderResourcesHelper(TD3D11ResourceType CommittedD3D11Res[],
+ Uint8 NumCommittedResources,
+ TSetD3D11ResMethodType SetD3D11ResMethod,
+ ID3D11DeviceContext* pDeviceCtx)
+{
+ if (NumCommittedResources > 0)
+ {
+ memset(CommittedD3D11Res, 0, NumCommittedResources * sizeof(CommittedD3D11Res[0]));
+ SetD3D11ResourcesHelper(pDeviceCtx, SetD3D11ResMethod, 0, NumCommittedResources, CommittedD3D11Res);
+ }
+}
+
+void ReleaseCommittedPSUAVs(ID3D11UnorderedAccessView* CommittedD3D11UAVs[],
+ Uint8 NumCommittedResources,
+ ID3D11DeviceContext* pDeviceCtx)
+{
+ if (NumCommittedResources > 0)
+ {
+ memset(CommittedD3D11UAVs, 0, NumCommittedResources * sizeof(CommittedD3D11UAVs[0]));
+ pDeviceCtx->OMSetRenderTargetsAndUnorderedAccessViews(
+ D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr,
+ 0, 0, nullptr, nullptr);
+ }
+}
+
+void DeviceContextD3D11Impl::ReleaseCommittedShaderResources()
+{
+ for (int ShaderType = 0; ShaderType < NumShaderTypes; ++ShaderType)
+ {
+ // clang-format off
+ ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11CBs[ShaderType], m_NumCommittedCBs[ShaderType], SetCBMethods[ShaderType], m_pd3d11DeviceContext);
+ ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11SRVs[ShaderType], m_NumCommittedSRVs[ShaderType], SetSRVMethods[ShaderType], m_pd3d11DeviceContext);
+ ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11Samplers[ShaderType], m_NumCommittedSamplers[ShaderType], SetSamplerMethods[ShaderType], m_pd3d11DeviceContext);
+ // clang-format on
+
+ if (ShaderType == PSInd)
+ ReleaseCommittedPSUAVs(m_CommittedD3D11UAVs[ShaderType], m_NumCommittedUAVs[ShaderType], m_pd3d11DeviceContext);
+ else
+ ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11UAVs[ShaderType], m_NumCommittedUAVs[ShaderType], SetUAVMethods[ShaderType], m_pd3d11DeviceContext);
+
+ memset(m_CommittedD3D11SRVResources[ShaderType], 0, sizeof(m_CommittedD3D11SRVResources[ShaderType][0]) * m_NumCommittedSRVs[ShaderType]);
+ memset(m_CommittedD3D11UAVResources[ShaderType], 0, sizeof(m_CommittedD3D11UAVResources[ShaderType][0]) * m_NumCommittedUAVs[ShaderType]);
+ m_NumCommittedCBs[ShaderType] = 0;
+ m_NumCommittedSRVs[ShaderType] = 0;
+ m_NumCommittedSamplers[ShaderType] = 0;
+ m_NumCommittedUAVs[ShaderType] = 0;
+ }
+
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ dbgVerifyCommittedSRVs();
+ dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
+ dbgVerifyCommittedSamplers();
+ dbgVerifyCommittedCBs();
+ }
+#endif
+ // We do not unbind vertex buffers and index buffer as this can explicitly
+ // be done by the user
+}
+
+
+void DeviceContextD3D11Impl::FinishCommandList(ICommandList** ppCommandList)
+{
+ CComPtr<ID3D11CommandList> pd3d11CmdList;
+ m_pd3d11DeviceContext->FinishCommandList(
+ FALSE, // A Boolean flag that determines whether the runtime saves deferred context state before it
+ // executes FinishCommandList and restores it afterwards.
+ // * TRUE indicates that the runtime needs to save and restore the state.
+ // * FALSE indicates that the runtime will not save or restore any state.
+ // In this case, the deferred context will return to its default state
+ // after the call to FinishCommandList() completes as if
+ // ID3D11DeviceContext::ClearState() was called.
+ &pd3d11CmdList);
+
+ CommandListD3D11Impl* pCmdListD3D11(NEW_RC_OBJ(m_CmdListAllocator, "CommandListD3D11Impl instance", CommandListD3D11Impl)(m_pDevice, pd3d11CmdList));
+ pCmdListD3D11->QueryInterface(IID_CommandList, reinterpret_cast<IObject**>(ppCommandList));
+
+ // Device context is now in default state
+ InvalidateState();
+
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ // Verify bindings
+ dbgVerifyCommittedSRVs();
+ dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
+ dbgVerifyCommittedSamplers();
+ dbgVerifyCommittedCBs();
+ dbgVerifyCommittedVertexBuffers();
+ dbgVerifyCommittedIndexBuffer();
+ dbgVerifyCommittedShaders();
+ }
+#endif
+}
+
+void DeviceContextD3D11Impl::ExecuteCommandList(ICommandList* pCommandList)
+{
+ if (m_bIsDeferred)
+ {
+ LOG_ERROR("Only immediate context can execute command list");
+ return;
+ }
+
+ CommandListD3D11Impl* pCmdListD3D11 = ValidatedCast<CommandListD3D11Impl>(pCommandList);
+ auto* pd3d11CmdList = pCmdListD3D11->GetD3D11CommandList();
+ m_pd3d11DeviceContext->ExecuteCommandList(pd3d11CmdList,
+ FALSE // A Boolean flag that determines whether the target context state is
+ // saved prior to and restored after the execution of a command list.
+ // * TRUE indicates that the runtime needs to save and restore the state.
+ // * FALSE indicate that no state shall be saved or restored, which causes the
+ // target context to return to its default state after the command list executes as if
+ // ID3D11DeviceContext::ClearState() was called.
+ );
+
+ // Device context is now in default state
+ InvalidateState();
+
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE)
+ {
+ // Verify bindings
+ dbgVerifyCommittedSRVs();
+ dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE);
+ dbgVerifyCommittedSamplers();
+ dbgVerifyCommittedCBs();
+ dbgVerifyCommittedVertexBuffers();
+ dbgVerifyCommittedIndexBuffer();
+ dbgVerifyCommittedShaders();
+ }
+#endif
+}
+
+
+static CComPtr<ID3D11Query> CreateD3D11QueryEvent(ID3D11Device* pd3d11Device)
+{
+ D3D11_QUERY_DESC QueryDesc = {};
+ QueryDesc.Query = D3D11_QUERY_EVENT; // Determines whether or not the GPU is finished processing commands.
+ // When the GPU is finished processing commands ID3D11DeviceContext::GetData will
+ // return S_OK, and pData will point to a BOOL with a value of TRUE. When using this
+ // type of query, ID3D11DeviceContext::Begin is disabled.
+ QueryDesc.MiscFlags = 0;
+
+ CComPtr<ID3D11Query> pd3d11Query;
+ auto hr = pd3d11Device->CreateQuery(&QueryDesc, &pd3d11Query);
+ DEV_CHECK_ERR(SUCCEEDED(hr), "Failed to create D3D11 query");
+ VERIFY_EXPR(pd3d11Query);
+ return pd3d11Query;
+}
+
+void DeviceContextD3D11Impl::SignalFence(IFence* pFence, Uint64 Value)
+{
+ VERIFY(!m_bIsDeferred, "Fence can only be signaled from immediate context");
+ auto* pd3d11Device = m_pDevice->GetD3D11Device();
+ CComPtr<ID3D11Query> pd3d11Query = CreateD3D11QueryEvent(pd3d11Device);
+ m_pd3d11DeviceContext->End(pd3d11Query);
+ auto* pFenceD3D11Impl = ValidatedCast<FenceD3D11Impl>(pFence);
+ pFenceD3D11Impl->AddPendingQuery(m_pd3d11DeviceContext, std::move(pd3d11Query), Value);
+}
+
+void DeviceContextD3D11Impl::WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext)
+{
+ VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
+ if (FlushContext)
+ Flush();
+ auto* pFenceD3D11Impl = ValidatedCast<FenceD3D11Impl>(pFence);
+ pFenceD3D11Impl->Wait(Value, FlushContext);
+}
+
+void DeviceContextD3D11Impl::WaitForIdle()
+{
+ VERIFY(!m_bIsDeferred, "Only immediate contexts can be idled");
+ Flush();
+ auto* pd3d11Device = m_pDevice->GetD3D11Device();
+ CComPtr<ID3D11Query> pd3d11Query = CreateD3D11QueryEvent(pd3d11Device);
+ m_pd3d11DeviceContext->End(pd3d11Query);
+ BOOL Data;
+ while (m_pd3d11DeviceContext->GetData(pd3d11Query, &Data, sizeof(Data), 0) != S_OK)
+ std::this_thread::yield();
+}
+
+void DeviceContextD3D11Impl::BeginQuery(IQuery* pQuery)
+{
+ if (!TDeviceContextBase::BeginQuery(pQuery, 0))
+ return;
+
+ auto* pQueryD3D11Impl = ValidatedCast<QueryD3D11Impl>(pQuery);
+ m_pd3d11DeviceContext->Begin(pQueryD3D11Impl->GetD3D11Query());
+}
+
+void DeviceContextD3D11Impl::EndQuery(IQuery* pQuery)
+{
+ if (!TDeviceContextBase::EndQuery(pQuery, 0))
+ return;
+
+ auto* pQueryD3D11Impl = ValidatedCast<QueryD3D11Impl>(pQuery);
+ if (pQueryD3D11Impl->GetDesc().Type == QUERY_TYPE_TIMESTAMP)
+ {
+ if (!m_ActiveDisjointQuery)
+ {
+ m_ActiveDisjointQuery = m_DisjointQueryPool.GetDisjointQuery(m_pDevice->GetD3D11Device());
+ // Disjoint timestamp queries should only be invoked once per frame or less.
+ m_pd3d11DeviceContext->Begin(m_ActiveDisjointQuery->pd3d11Query);
+ m_ActiveDisjointQuery->IsEnded = false;
+ }
+ pQueryD3D11Impl->SetDisjointQuery(m_ActiveDisjointQuery);
+ }
+
+ m_pd3d11DeviceContext->End(pQueryD3D11Impl->GetD3D11Query());
+}
+
+void DeviceContextD3D11Impl::ClearStateCache()
+{
+ TDeviceContextBase::ClearStateCache();
+
+ for (int ShaderType = 0; ShaderType < NumShaderTypes; ++ShaderType)
+ {
+ // clang-format off
+ memset(m_CommittedD3D11CBs[ShaderType], 0, sizeof(m_CommittedD3D11CBs[ShaderType][0]) * m_NumCommittedCBs[ShaderType]);
+ memset(m_CommittedD3D11SRVs[ShaderType], 0, sizeof(m_CommittedD3D11SRVs[ShaderType][0]) * m_NumCommittedSRVs[ShaderType]);
+ memset(m_CommittedD3D11Samplers[ShaderType], 0, sizeof(m_CommittedD3D11Samplers[ShaderType][0]) * m_NumCommittedSamplers[ShaderType]);
+ memset(m_CommittedD3D11UAVs[ShaderType], 0, sizeof(m_CommittedD3D11UAVs[ShaderType][0]) * m_NumCommittedUAVs[ShaderType]);
+ memset(m_CommittedD3D11SRVResources[ShaderType], 0, sizeof(m_CommittedD3D11SRVResources[ShaderType][0]) * m_NumCommittedSRVs[ShaderType]);
+ memset(m_CommittedD3D11UAVResources[ShaderType], 0, sizeof(m_CommittedD3D11UAVResources[ShaderType][0]) * m_NumCommittedUAVs[ShaderType]);
+ // clang-format on
+
+ m_NumCommittedCBs[ShaderType] = 0;
+ m_NumCommittedSRVs[ShaderType] = 0;
+ m_NumCommittedSamplers[ShaderType] = 0;
+ m_NumCommittedUAVs[ShaderType] = 0;
+
+ m_CommittedD3DShaders[ShaderType].Release();
+ }
+
+ for (Uint32 vb = 0; vb < m_NumCommittedD3D11VBs; ++vb)
+ {
+ m_CommittedD3D11VertexBuffers[vb] = nullptr;
+ m_CommittedD3D11VBStrides[vb] = 0;
+ m_CommittedD3D11VBOffsets[vb] = 0;
+ }
+ m_NumCommittedD3D11VBs = 0;
+ m_bCommittedD3D11VBsUpToDate = false;
+
+ m_CommittedD3D11InputLayout = nullptr;
+
+ m_CommittedD3D11IndexBuffer.Release();
+ m_CommittedIBFormat = VT_UNDEFINED;
+ m_CommittedD3D11IndexDataStartOffset = 0;
+ m_bCommittedD3D11IBUpToDate = false;
+
+ m_CommittedD3D11PrimTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+ m_CommittedPrimitiveTopology = PRIMITIVE_TOPOLOGY_UNDEFINED;
+}
+
+void DeviceContextD3D11Impl::InvalidateState()
+{
+ TDeviceContextBase::InvalidateState();
+
+ ReleaseCommittedShaderResources();
+ for (int ShaderType = 0; ShaderType < NumShaderTypes; ++ShaderType)
+ m_CommittedD3DShaders[ShaderType].Release();
+ m_pd3d11DeviceContext->VSSetShader(nullptr, nullptr, 0);
+ m_pd3d11DeviceContext->GSSetShader(nullptr, nullptr, 0);
+ m_pd3d11DeviceContext->PSSetShader(nullptr, nullptr, 0);
+ m_pd3d11DeviceContext->HSSetShader(nullptr, nullptr, 0);
+ m_pd3d11DeviceContext->DSSetShader(nullptr, nullptr, 0);
+ m_pd3d11DeviceContext->CSSetShader(nullptr, nullptr, 0);
+ ID3D11RenderTargetView* d3d11NullRTV[] = {nullptr};
+ m_pd3d11DeviceContext->OMSetRenderTargets(1, d3d11NullRTV, nullptr);
+
+ if (m_NumCommittedD3D11VBs > 0)
+ {
+ for (Uint32 vb = 0; vb < m_NumCommittedD3D11VBs; ++vb)
+ {
+ m_CommittedD3D11VertexBuffers[vb] = nullptr;
+ m_CommittedD3D11VBStrides[vb] = 0;
+ m_CommittedD3D11VBOffsets[vb] = 0;
+ }
+ m_pd3d11DeviceContext->IASetVertexBuffers(0, m_NumCommittedD3D11VBs, m_CommittedD3D11VertexBuffers, m_CommittedD3D11VBStrides, m_CommittedD3D11VBOffsets);
+ m_NumCommittedD3D11VBs = 0;
+ }
+
+ m_bCommittedD3D11VBsUpToDate = false;
+
+ if (m_CommittedD3D11InputLayout != nullptr)
+ {
+ m_pd3d11DeviceContext->IASetInputLayout(nullptr);
+ m_CommittedD3D11InputLayout = nullptr;
+ }
+
+ if (m_CommittedD3D11IndexBuffer)
+ {
+ m_pd3d11DeviceContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_R32_UINT, 0);
+ m_CommittedD3D11IndexBuffer.Release();
+ }
+
+ m_CommittedIBFormat = VT_UNDEFINED;
+ m_CommittedD3D11IndexDataStartOffset = 0;
+ m_bCommittedD3D11IBUpToDate = false;
+
+ m_CommittedD3D11PrimTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+ m_CommittedPrimitiveTopology = PRIMITIVE_TOPOLOGY_UNDEFINED;
+}
+
+void DeviceContextD3D11Impl::TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers)
+{
+ for (Uint32 i = 0; i < BarrierCount; ++i)
+ {
+ const auto& Barrier = pResourceBarriers[i];
+#ifdef DILIGENT_DEVELOPMENT
+ DvpVerifyStateTransitionDesc(Barrier);
+#endif
+ DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer must not be null");
+ DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown");
+
+ if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
+ {
+ // Skip begin-split barriers
+ VERIFY(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier");
+ continue;
+ }
+ VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type");
+
+ if (Barrier.pTexture)
+ {
+ auto* pTextureD3D11Impl = ValidatedCast<TextureBaseD3D11>(Barrier.pTexture);
+ auto OldState = Barrier.OldState;
+ if (OldState == RESOURCE_STATE_UNKNOWN)
+ {
+ if (pTextureD3D11Impl->IsInKnownState())
+ {
+ OldState = pTextureD3D11Impl->GetState();
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Failed to transition the state of texture '", pTextureD3D11Impl->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
+ continue;
+ }
+ }
+ else
+ {
+ if (pTextureD3D11Impl->IsInKnownState() && pTextureD3D11Impl->GetState() != OldState)
+ {
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pTextureD3D11Impl->GetState()), " of texture '",
+ pTextureD3D11Impl->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ " specified by the barrier");
+ }
+ }
+
+ if ((Barrier.NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0)
+ {
+ DEV_CHECK_ERR((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) == 0, "Unordered access state is not compatible with any input state");
+ UnbindTextureFromInput(pTextureD3D11Impl, pTextureD3D11Impl->GetD3D11Texture());
+ }
+
+ if ((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) != 0)
+ {
+ if ((OldState & RESOURCE_STATE_RENDER_TARGET) != 0)
+ UnbindTextureFromRenderTarget(pTextureD3D11Impl);
+
+ if ((OldState & RESOURCE_STATE_DEPTH_WRITE) != 0)
+ UnbindTextureFromDepthStencil(pTextureD3D11Impl);
+
+ if ((OldState & RESOURCE_STATE_UNORDERED_ACCESS) != 0)
+ {
+ UnbindResourceFromUAV(pTextureD3D11Impl, pTextureD3D11Impl->GetD3D11Texture());
+ pTextureD3D11Impl->ClearState(RESOURCE_STATE_UNORDERED_ACCESS);
+ }
+ }
+
+ if (Barrier.UpdateResourceState)
+ {
+ pTextureD3D11Impl->SetState(Barrier.NewState);
+ }
+ }
+ else
+ {
+ VERIFY_EXPR(Barrier.pBuffer);
+ auto* pBufferD3D11Impl = ValidatedCast<BufferD3D11Impl>(Barrier.pBuffer);
+ auto OldState = Barrier.OldState;
+ if (OldState == RESOURCE_STATE_UNKNOWN)
+ {
+ if (pBufferD3D11Impl->IsInKnownState())
+ {
+ OldState = pBufferD3D11Impl->GetState();
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Failed to transition the state of buffer '", pBufferD3D11Impl->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
+ continue;
+ }
+ }
+ else
+ {
+ if (pBufferD3D11Impl->IsInKnownState() && pBufferD3D11Impl->GetState() != OldState)
+ {
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pBufferD3D11Impl->GetState()), " of buffer '",
+ pBufferD3D11Impl->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ " specified by the barrier");
+ }
+ }
+
+ if ((Barrier.NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0)
+ {
+ DEV_CHECK_ERR((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) == 0, "Unordered access state is not compatible with any input state");
+ UnbindBufferFromInput(pBufferD3D11Impl, pBufferD3D11Impl->m_pd3d11Buffer);
+ }
+
+ if ((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) != 0)
+ {
+ UnbindResourceFromUAV(pBufferD3D11Impl, pBufferD3D11Impl->m_pd3d11Buffer);
+ }
+
+ if (Barrier.UpdateResourceState)
+ {
+ pBufferD3D11Impl->SetState(Barrier.NewState);
+ }
+ }
+ }
+}
+
+void DeviceContextD3D11Impl::ResolveTextureSubresource(ITexture* pSrcTexture,
+ ITexture* pDstTexture,
+ const ResolveTextureSubresourceAttribs& ResolveAttribs)
+{
+ TDeviceContextBase::ResolveTextureSubresource(pSrcTexture, pDstTexture, ResolveAttribs);
+
+ auto* pSrcTexD3D11 = ValidatedCast<TextureBaseD3D11>(pSrcTexture);
+ auto* pDstTexD3D11 = ValidatedCast<TextureBaseD3D11>(pDstTexture);
+ const auto& SrcTexDesc = pSrcTexD3D11->GetDesc();
+ const auto& DstTexDesc = pDstTexD3D11->GetDesc();
+
+ auto Format = ResolveAttribs.Format;
+ if (Format == TEX_FORMAT_UNKNOWN)
+ {
+ const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
+ if (!SrcFmtAttribs.IsTypeless)
+ {
+ Format = SrcTexDesc.Format;
+ }
+ else
+ {
+ const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
+ DEV_CHECK_ERR(!DstFmtAttribs.IsTypeless, "Resolve operation format can't be typeless when both source and destination textures are typeless");
+ Format = DstFmtAttribs.Format;
+ }
+ }
+
+ auto DXGIFmt = TexFormatToDXGI_Format(Format);
+ auto SrcSubresIndex = D3D11CalcSubresource(ResolveAttribs.SrcMipLevel, ResolveAttribs.SrcSlice, SrcTexDesc.MipLevels);
+ auto DstSubresIndex = D3D11CalcSubresource(ResolveAttribs.DstMipLevel, ResolveAttribs.DstSlice, DstTexDesc.MipLevels);
+ m_pd3d11DeviceContext->ResolveSubresource(pDstTexD3D11->GetD3D11Texture(), DstSubresIndex, pSrcTexD3D11->GetD3D11Texture(), SrcSubresIndex, DXGIFmt);
+}
+
+// clang-format off
+#ifdef VERIFY_CONTEXT_BINDINGS
+ DEFINE_D3D11CTX_FUNC_POINTERS(GetCBMethods, GetConstantBuffers)
+ DEFINE_D3D11CTX_FUNC_POINTERS(GetSRVMethods, GetShaderResources)
+ DEFINE_D3D11CTX_FUNC_POINTERS(GetSamplerMethods, GetSamplers)
+
+ typedef decltype (&ID3D11DeviceContext::CSGetUnorderedAccessViews) TGetUnorderedAccessViewsType;
+ static const TGetUnorderedAccessViewsType GetUAVMethods[] =
+ {
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &ID3D11DeviceContext::CSGetUnorderedAccessViews
+ };
+// clang-format on
+
+/// \tparam MaxResources - Maximum number of resources that can be bound to D3D11 context
+/// \tparam TD3D11ResourceType - Type of D3D11 resource being checked (ID3D11ShaderResourceView,
+/// ID3D11UnorderedAccessView, ID3D11Buffer or ID3D11SamplerState).
+/// \tparam TGetD3D11ResourcesType - Type of the device context method used to get the bound
+/// resources
+/// \param CommittedD3D11ResourcesArr - Pointer to the array of currently bound D3D11
+/// resources, for each shader stage
+/// \param GetD3D11ResMethods - Pointer to the array of device context methods to get the bound
+/// resources, for each shader stage
+/// \param ResourceName - Resource name
+/// \param ShaderType - Shader type for which to check the resources. If Diligent::SHADER_TYPE_UNKNOWN
+/// is provided, all shader stages will be checked
+template <UINT MaxResources,
+ typename TD3D11ResourceType,
+ typename TGetD3D11ResourcesType>
+void DeviceContextD3D11Impl::dbgVerifyCommittedResources(TD3D11ResourceType CommittedD3D11ResourcesArr[][MaxResources],
+ Uint8 NumCommittedResourcesArr[],
+ TGetD3D11ResourcesType GetD3D11ResMethods[],
+ const Char* ResourceName,
+ SHADER_TYPE ShaderType)
+{
+ int iStartInd = 0, iEndInd = NumShaderTypes;
+ if (ShaderType != SHADER_TYPE_UNKNOWN)
+ {
+ iStartInd = GetShaderTypeIndex(ShaderType);
+ iEndInd = iStartInd + 1;
+ }
+ for (int iShaderTypeInd = iStartInd; iShaderTypeInd < iEndInd; ++iShaderTypeInd)
+ {
+ const auto ShaderName = GetShaderTypeLiteralName(GetShaderTypeFromIndex(iShaderTypeInd));
+ TD3D11ResourceType pctxResources[MaxResources] = {};
+ auto GetResMethod = GetD3D11ResMethods[iShaderTypeInd];
+ if (GetResMethod)
+ {
+ (m_pd3d11DeviceContext->*GetResMethod)(0, _countof(pctxResources), pctxResources);
+ }
+ const auto* CommittedResources = CommittedD3D11ResourcesArr[iShaderTypeInd];
+ auto NumCommittedResources = NumCommittedResourcesArr[iShaderTypeInd];
+ for (Uint32 Slot = 0; Slot < _countof(pctxResources); ++Slot)
+ {
+ if (Slot < NumCommittedResources)
+ {
+ VERIFY(CommittedResources[Slot] == pctxResources[Slot], ResourceName, " binding mismatch found for ", ShaderName, " shader type at slot ", Slot);
+ }
+ else
+ {
+ VERIFY(pctxResources[Slot] == nullptr, ResourceName, " binding mismatch found for ", ShaderName, " shader type at slot ", Slot);
+ VERIFY(CommittedResources[Slot] == nullptr, ResourceName, " unexpected non-null resource found for ", ShaderName, " shader type at slot ", Slot);
+ }
+
+ if (pctxResources[Slot])
+ pctxResources[Slot]->Release();
+ }
+ }
+}
+
+template <UINT MaxResources, typename TD3D11ViewType>
+void DeviceContextD3D11Impl::dbgVerifyViewConsistency(TD3D11ViewType CommittedD3D11ViewArr[][MaxResources],
+ ID3D11Resource* CommittedD3D11ResourcesArr[][MaxResources],
+ Uint8 NumCommittedResourcesArr[],
+ const Char* ResourceName,
+ SHADER_TYPE ShaderType)
+{
+ int iStartInd = 0, iEndInd = NumShaderTypes;
+ if (ShaderType != SHADER_TYPE_UNKNOWN)
+ {
+ iStartInd = GetShaderTypeIndex(ShaderType);
+ iEndInd = iStartInd + 1;
+ }
+ for (int iShaderTypeInd = iStartInd; iShaderTypeInd < iEndInd; ++iShaderTypeInd)
+ {
+ const auto ShaderName = GetShaderTypeLiteralName(GetShaderTypeFromIndex(iShaderTypeInd));
+ auto* Views = CommittedD3D11ViewArr[iShaderTypeInd];
+ auto* Resources = CommittedD3D11ResourcesArr[iShaderTypeInd];
+ auto NumCommittedResources = NumCommittedResourcesArr[iShaderTypeInd];
+ for (Uint32 Slot = 0; Slot < NumCommittedResources; ++Slot)
+ {
+ if (Views[Slot] != nullptr)
+ {
+ CComPtr<ID3D11Resource> pRefRes;
+ Views[Slot]->GetResource(&pRefRes);
+ VERIFY(pRefRes == Resources[Slot], "Inconsistent ", ResourceName, " detected at slot ", Slot, " in shader ", ShaderName, ". The resource in the view does not match cached D3D11 resource");
+ }
+ }
+ }
+}
+
+void DeviceContextD3D11Impl::dbgVerifyCommittedSRVs(SHADER_TYPE ShaderType)
+{
+ dbgVerifyCommittedResources<D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT>(m_CommittedD3D11SRVs, m_NumCommittedSRVs, GetSRVMethods, "SRV", ShaderType);
+ dbgVerifyViewConsistency<D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT>(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, "SRV", ShaderType);
+}
+
+void DeviceContextD3D11Impl::dbgVerifyCommittedUAVs(SHADER_TYPE ShaderType)
+{
+ dbgVerifyCommittedResources<D3D11_PS_CS_UAV_REGISTER_COUNT>(m_CommittedD3D11UAVs, m_NumCommittedUAVs, GetUAVMethods, "UAV", ShaderType);
+ dbgVerifyViewConsistency<D3D11_PS_CS_UAV_REGISTER_COUNT>(m_CommittedD3D11UAVs, m_CommittedD3D11UAVResources, m_NumCommittedUAVs, "UAV", ShaderType);
+}
+
+void DeviceContextD3D11Impl::dbgVerifyCommittedSamplers(SHADER_TYPE ShaderType)
+{
+ dbgVerifyCommittedResources<D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT>(m_CommittedD3D11Samplers, m_NumCommittedSamplers, GetSamplerMethods, "Sampler", ShaderType);
+}
+
+void DeviceContextD3D11Impl::dbgVerifyCommittedCBs(SHADER_TYPE ShaderType)
+{
+ dbgVerifyCommittedResources<D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT>(m_CommittedD3D11CBs, m_NumCommittedCBs, GetCBMethods, "Constant buffer", ShaderType);
+}
+
+void DeviceContextD3D11Impl::dbgVerifyCommittedIndexBuffer()
+{
+ RefCntAutoPtr<ID3D11Buffer> pctxIndexBuffer;
+ DXGI_FORMAT Fmt = DXGI_FORMAT_UNKNOWN;
+ UINT Offset = 0;
+ m_pd3d11DeviceContext->IAGetIndexBuffer(&pctxIndexBuffer, &Fmt, &Offset);
+ if (m_CommittedD3D11IndexBuffer && !pctxIndexBuffer)
+ UNEXPECTED("D3D11 index buffer is not bound to the context");
+ if (!m_CommittedD3D11IndexBuffer && pctxIndexBuffer)
+ UNEXPECTED("Unexpected D3D11 index buffer is bound to the context");
+
+ if (m_CommittedD3D11IndexBuffer && pctxIndexBuffer)
+ {
+ VERIFY(m_CommittedD3D11IndexBuffer == pctxIndexBuffer, "Index buffer binding mismatch detected");
+ if (Fmt == DXGI_FORMAT_R32_UINT)
+ {
+ VERIFY(m_CommittedIBFormat == VT_UINT32, "Index buffer format mismatch detected");
+ }
+ else if (Fmt == DXGI_FORMAT_R16_UINT)
+ {
+ VERIFY(m_CommittedIBFormat == VT_UINT16, "Index buffer format mismatch detected");
+ }
+ VERIFY(m_CommittedD3D11IndexDataStartOffset == Offset, "Index buffer offset mismatch detected");
+ }
+}
+
+void DeviceContextD3D11Impl::dbgVerifyCommittedVertexBuffers()
+{
+ CComPtr<ID3D11InputLayout> pInputLayout;
+ m_pd3d11DeviceContext->IAGetInputLayout(&pInputLayout);
+ VERIFY(pInputLayout == m_CommittedD3D11InputLayout, "Inconsistent input layout");
+
+ const Uint32 MaxVBs = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT;
+ ID3D11Buffer* pVBs[MaxVBs];
+ UINT Strides[MaxVBs];
+ UINT Offsets[MaxVBs];
+ m_pd3d11DeviceContext->IAGetVertexBuffers(0, MaxVBs, pVBs, Strides, Offsets);
+ auto NumBoundVBs = m_NumCommittedD3D11VBs;
+ for (Uint32 Slot = 0; Slot < MaxVBs; ++Slot)
+ {
+ if (Slot < NumBoundVBs)
+ {
+ const auto& BoundD3D11VB = m_CommittedD3D11VertexBuffers[Slot];
+ auto BoundVBStride = m_CommittedD3D11VBStrides[Slot];
+ auto BoundVBOffset = m_CommittedD3D11VBOffsets[Slot];
+ if (BoundD3D11VB && !pVBs[Slot])
+ VERIFY(pVBs[Slot] == nullptr, "Missing D3D11 buffer detected at slot ", Slot);
+ if (!BoundD3D11VB && pVBs[Slot])
+ VERIFY(pVBs[Slot] == nullptr, "Unexpected D3D11 buffer detected at slot ", Slot);
+ if (BoundD3D11VB && pVBs[Slot])
+ {
+ VERIFY(BoundD3D11VB == pVBs[Slot], "Vertex buffer mismatch detected at slot ", Slot);
+ VERIFY(BoundVBOffset == Offsets[Slot], "Offset mismatch detected at slot ", Slot);
+ VERIFY(BoundVBStride == Strides[Slot], "Stride mismatch detected at slot ", Slot);
+ }
+ }
+ else
+ {
+ VERIFY(pVBs[Slot] == nullptr, "Unexpected D3D11 buffer detected at slot ", Slot);
+ }
+
+ if (pVBs[Slot])
+ pVBs[Slot]->Release();
+ }
+}
+
+template <typename TD3D11ShaderType, typename TGetShaderMethodType>
+void dbgVerifyCommittedShadersHelper(SHADER_TYPE ShaderType,
+ const CComPtr<ID3D11DeviceChild> BoundD3DShaders[],
+ ID3D11DeviceContext* pCtx,
+ TGetShaderMethodType GetShaderMethod)
+{
+ RefCntAutoPtr<TD3D11ShaderType> pctxShader;
+ (pCtx->*GetShaderMethod)(&pctxShader, nullptr, nullptr);
+ const auto& BoundShader = BoundD3DShaders[GetShaderTypeIndex(ShaderType)];
+ VERIFY(BoundShader == pctxShader, GetShaderTypeLiteralName(ShaderType), " binding mismatch detected");
+}
+void DeviceContextD3D11Impl::dbgVerifyCommittedShaders()
+{
+# define VERIFY_SHADER(NAME, Name, N) dbgVerifyCommittedShadersHelper<ID3D11##Name##Shader>(SHADER_TYPE_##NAME, m_CommittedD3DShaders, m_pd3d11DeviceContext, &ID3D11DeviceContext::N##SGetShader)
+ // These shaders which are not set will be unbound from the D3D11 device context
+ VERIFY_SHADER(VERTEX, Vertex, V);
+ VERIFY_SHADER(PIXEL, Pixel, P);
+ VERIFY_SHADER(GEOMETRY, Geometry, G);
+ VERIFY_SHADER(DOMAIN, Domain, D);
+ VERIFY_SHADER(HULL, Hull, H);
+ VERIFY_SHADER(COMPUTE, Compute, C);
+}
+
+#endif // VERIFY_CONTEXT_BINDINGS
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp
index 779ce893..21a65108 100755
--- a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp
@@ -104,11 +104,11 @@ ShaderResourcesD3D11::ShaderResourcesD3D11(RenderDeviceD3D11Impl* pDeviceD3D11Im
const char* CombinedSamplerSuffix;
ShaderResourcesD3D11& Resources;
};
-
+
CComPtr<ID3D11ShaderReflection> pShaderReflection;
- HRESULT hr = D3DReflect(pShaderBytecode->GetBufferPointer(), pShaderBytecode->GetBufferSize(), __uuidof(pShaderReflection), reinterpret_cast<void**>(&pShaderReflection));
+ HRESULT hr = D3DReflect(pShaderBytecode->GetBufferPointer(), pShaderBytecode->GetBufferSize(), __uuidof(pShaderReflection), reinterpret_cast<void**>(&pShaderReflection));
CHECK_D3D_RESULT_THROW(hr, "Failed to get the shader reflection");
-
+
Initialize<D3D11_SHADER_DESC, D3D11_SHADER_INPUT_BIND_DESC>(
static_cast<ID3D11ShaderReflection*>(pShaderReflection),