From 3cf64d721e3d274d7c2202eef8858d6d2f2c9a9d Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 3 Jan 2020 22:28:38 -0800 Subject: D3D12 backend: renamed QueryManager to QueryManagerD3D12 --- Graphics/GraphicsEngineD3D12/CMakeLists.txt | 4 +- .../GraphicsEngineD3D12/include/QueryManager.h | 88 --------- .../include/QueryManagerD3D12.h | 88 +++++++++ .../include/RenderDeviceD3D12Impl.h | 6 +- .../src/DeviceContextD3D12Impl.cpp | 18 +- .../GraphicsEngineD3D12/src/QueryD3D12Impl.cpp | 2 +- Graphics/GraphicsEngineD3D12/src/QueryManager.cpp | 215 -------------------- .../GraphicsEngineD3D12/src/QueryManagerD3D12.cpp | 216 +++++++++++++++++++++ 8 files changed, 319 insertions(+), 318 deletions(-) delete mode 100644 Graphics/GraphicsEngineD3D12/include/QueryManager.h create mode 100644 Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.h delete mode 100644 Graphics/GraphicsEngineD3D12/src/QueryManager.cpp create mode 100644 Graphics/GraphicsEngineD3D12/src/QueryManagerD3D12.cpp (limited to 'Graphics/GraphicsEngineD3D12') diff --git a/Graphics/GraphicsEngineD3D12/CMakeLists.txt b/Graphics/GraphicsEngineD3D12/CMakeLists.txt index 6fbe75b5..8a59dd4d 100644 --- a/Graphics/GraphicsEngineD3D12/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3D12/CMakeLists.txt @@ -22,7 +22,7 @@ set(INCLUDE include/pch.h include/PipelineStateD3D12Impl.h include/QueryD3D12Impl.h - include/QueryManager.h + include/QueryManagerD3D12.h include/RenderDeviceD3D12Impl.h include/RootSignature.h include/SamplerD3D12Impl.h @@ -72,7 +72,7 @@ set(SRC src/GenerateMips.cpp src/PipelineStateD3D12Impl.cpp src/QueryD3D12Impl.cpp - src/QueryManager.cpp + src/QueryManagerD3D12.cpp src/RenderDeviceD3D12Impl.cpp src/RootSignature.cpp src/SamplerD3D12Impl.cpp diff --git a/Graphics/GraphicsEngineD3D12/include/QueryManager.h b/Graphics/GraphicsEngineD3D12/include/QueryManager.h deleted file mode 100644 index fc8044f9..00000000 --- a/Graphics/GraphicsEngineD3D12/include/QueryManager.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include -#include -#include -#include - -#include "Query.h" - -namespace Diligent -{ - -class CommandContext; - -// https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#queries - -class QueryManager -{ -public: - QueryManager(ID3D12Device* pd3d12Device, - const Uint32 QueryHeapSizes[]); - ~QueryManager(); - - // clang-format off - QueryManager (const QueryManager&) = delete; - QueryManager ( QueryManager&&) = delete; - QueryManager& operator = (const QueryManager&) = delete; - QueryManager& operator = ( QueryManager&&) = delete; - // clang-format on - - static constexpr Uint32 InvalidIndex = static_cast(-1); - - Uint32 AllocateQuery(QUERY_TYPE Type); - void ReleaseQuery(QUERY_TYPE Type, Uint32 Index); - - ID3D12QueryHeap* GetQueryHeap(QUERY_TYPE Type) - { - return m_Heaps[Type].pd3d12QueryHeap; - } - - void BeginQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index); - void EndQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index); - void ReadQueryData(QUERY_TYPE Type, Uint32 Index, void* pDataPtr, Uint32 DataSize) const; - -private: - struct QueryHeapInfo - { - CComPtr pd3d12QueryHeap; - std::deque AvailableQueries; - std::vector ResolveBufferOffsets; - Uint32 HeapSize = 0; - }; - - std::mutex m_HeapMutex; - std::array m_Heaps; - - // Readback buffer that will contain the query data. - CComPtr m_pd3d12ResolveBuffer; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.h b/Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.h new file mode 100644 index 00000000..0600c2e4 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/QueryManagerD3D12.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#pragma once + +#include +#include +#include +#include + +#include "Query.h" + +namespace Diligent +{ + +class CommandContext; + +// https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#queries + +class QueryManagerD3D12 +{ +public: + QueryManagerD3D12(ID3D12Device* pd3d12Device, + const Uint32 QueryHeapSizes[]); + ~QueryManagerD3D12(); + + // clang-format off + QueryManagerD3D12 (const QueryManagerD3D12&) = delete; + QueryManagerD3D12 ( QueryManagerD3D12&&) = delete; + QueryManagerD3D12& operator = (const QueryManagerD3D12&) = delete; + QueryManagerD3D12& operator = ( QueryManagerD3D12&&) = delete; + // clang-format on + + static constexpr Uint32 InvalidIndex = static_cast(-1); + + Uint32 AllocateQuery(QUERY_TYPE Type); + void ReleaseQuery(QUERY_TYPE Type, Uint32 Index); + + ID3D12QueryHeap* GetQueryHeap(QUERY_TYPE Type) + { + return m_Heaps[Type].pd3d12QueryHeap; + } + + void BeginQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index); + void EndQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index); + void ReadQueryData(QUERY_TYPE Type, Uint32 Index, void* pDataPtr, Uint32 DataSize) const; + +private: + struct QueryHeapInfo + { + CComPtr pd3d12QueryHeap; + std::deque AvailableQueries; + std::vector ResolveBufferOffsets; + Uint32 HeapSize = 0; + }; + + std::mutex m_HeapMutex; + std::array m_Heaps; + + // Readback buffer that will contain the query data. + CComPtr m_pd3d12ResolveBuffer; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h index 248cabec..922a4c22 100644 --- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h @@ -39,7 +39,7 @@ #include "Atomics.h" #include "CommandQueueD3D12.h" #include "GenerateMips.h" -#include "QueryManager.h" +#include "QueryManagerD3D12.h" namespace Diligent { @@ -128,7 +128,7 @@ public: } const GenerateMipsHelper& GetMipsGenerator() const { return m_MipsGenerator; } - QueryManager& GetQueryManager() { return m_QueryMgr; } + QueryManagerD3D12& GetQueryManager() { return m_QueryMgr; } D3D_FEATURE_LEVEL GetD3DFeatureLevel() const; @@ -157,7 +157,7 @@ private: // Note: mips generator must be released after the device has been idled GenerateMipsHelper m_MipsGenerator; - QueryManager m_QueryMgr; + QueryManagerD3D12 m_QueryMgr; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index eb49d52c..617c492e 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -1702,10 +1702,10 @@ void DeviceContextD3D12Impl::BeginQuery(IQuery* pQuery) if (QueryType != QUERY_TYPE_TIMESTAMP) ++m_ActiveQueriesCounter; - auto& QueueMgr = m_pDevice->GetQueryManager(); + auto& QueryMgr = m_pDevice->GetQueryManager(); auto& Ctx = GetCmdContext(); auto Idx = pQueryD3D12Impl->GetQueryHeapIndex(); - QueueMgr.BeginQuery(Ctx, QueryType, Idx); + QueryMgr.BeginQuery(Ctx, QueryType, Idx); } void DeviceContextD3D12Impl::EndQuery(IQuery* pQuery) @@ -1713,18 +1713,18 @@ void DeviceContextD3D12Impl::EndQuery(IQuery* pQuery) if (!TDeviceContextBase::EndQuery(pQuery, 0)) return; - auto* pQueryD3D12Impl = ValidatedCast(pQuery); - if (pQueryD3D12Impl->GetDesc().Type != QUERY_TYPE_TIMESTAMP) + auto* pQueryD3D12Impl = ValidatedCast(pQuery); + const auto QueryType = pQueryD3D12Impl->GetDesc().Type; + if (QueryType != QUERY_TYPE_TIMESTAMP) { VERIFY(m_ActiveQueriesCounter > 0, "Active query counter is 0 which means there was a mismatch between BeginQuery() / EndQuery() calls"); --m_ActiveQueriesCounter; } - const auto QueryType = pQueryD3D12Impl->GetDesc().Type; - auto& QueueMgr = m_pDevice->GetQueryManager(); - auto& Ctx = GetCmdContext(); - auto Idx = pQueryD3D12Impl->GetQueryHeapIndex(); - QueueMgr.EndQuery(Ctx, QueryType, Idx); + auto& QueryMgr = m_pDevice->GetQueryManager(); + auto& Ctx = GetCmdContext(); + auto Idx = pQueryD3D12Impl->GetQueryHeapIndex(); + QueryMgr.EndQuery(Ctx, QueryType, Idx); } void DeviceContextD3D12Impl::TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers) diff --git a/Graphics/GraphicsEngineD3D12/src/QueryD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/QueryD3D12Impl.cpp index cb8d7e02..6c055e51 100644 --- a/Graphics/GraphicsEngineD3D12/src/QueryD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/QueryD3D12Impl.cpp @@ -43,7 +43,7 @@ QueryD3D12Impl::QueryD3D12Impl(IReferenceCounters* pRefCounters, { auto& QueryMgr = pDevice->GetQueryManager(); m_QueryHeapIndex = QueryMgr.AllocateQuery(m_Desc.Type); - if (m_QueryHeapIndex == QueryManager::InvalidIndex) + if (m_QueryHeapIndex == QueryManagerD3D12::InvalidIndex) { LOG_ERROR_AND_THROW("Failed to allocate D3D12 query for type ", GetQueryTypeString(m_Desc.Type), ". Increase the query pool size in EngineD3D12CreateInfo."); diff --git a/Graphics/GraphicsEngineD3D12/src/QueryManager.cpp b/Graphics/GraphicsEngineD3D12/src/QueryManager.cpp deleted file mode 100644 index 6474383c..00000000 --- a/Graphics/GraphicsEngineD3D12/src/QueryManager.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * 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 "QueryManager.h" -#include "RenderDeviceD3D12Impl.h" -#include "D3D12TypeConversions.h" -#include "GraphicsAccessories.h" - -namespace Diligent -{ - -static Uint32 GetQueryDataSize(QUERY_TYPE QueryType) -{ - // clang-format off - switch (QueryType) - { - case QUERY_TYPE_OCCLUSION: - case QUERY_TYPE_BINARY_OCCLUSION: - case QUERY_TYPE_TIMESTAMP: - return sizeof(Uint64); - break; - - case QUERY_TYPE_PIPELINE_STATISTICS: - return sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS); - break; - - default: - UNEXPECTED("Unexpected query type"); - return 0; - } - // clang-format on -} - -QueryManager::QueryManager(ID3D12Device* pd3d12Device, - const Uint32 QueryHeapSizes[]) -{ - Uint32 ResolveBufferOffset = 0; - for (Uint32 QueryType = QUERY_TYPE_UNDEFINED + 1; QueryType < QUERY_TYPE_NUM_TYPES; ++QueryType) - { - // clang-format off - static_assert(QUERY_TYPE_OCCLUSION == 1, "Unexpected value of QUERY_TYPE_OCCLUSION. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); - static_assert(QUERY_TYPE_BINARY_OCCLUSION == 2, "Unexpected value of QUERY_TYPE_BINARY_OCCLUSION. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); - static_assert(QUERY_TYPE_TIMESTAMP == 3, "Unexpected value of QUERY_TYPE_TIMESTAMP. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); - static_assert(QUERY_TYPE_PIPELINE_STATISTICS== 4, "Unexpected value of QUERY_TYPE_PIPELINE_STATISTICS. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); - static_assert(QUERY_TYPE_NUM_TYPES == 5, "Unexpected value of QUERY_TYPE_NUM_TYPES. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); - // clang-format on - auto& HeapInfo = m_Heaps[QueryType]; - - D3D12_QUERY_HEAP_DESC d3d12HeapDesc = {}; - - HeapInfo.HeapSize = QueryHeapSizes[QueryType]; - d3d12HeapDesc.Type = QueryTypeToD3D12QueryHeapType(static_cast(QueryType)); - d3d12HeapDesc.Count = HeapInfo.HeapSize; - - auto hr = pd3d12Device->CreateQueryHeap(&d3d12HeapDesc, __uuidof(HeapInfo.pd3d12QueryHeap), reinterpret_cast(&HeapInfo.pd3d12QueryHeap)); - CHECK_D3D_RESULT_THROW(hr, "Failed to create D3D12 query heap of type"); - - // AlignedDestinationBufferOffset must be a multiple of 8 bytes. - // https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#resolvequerydata - Uint32 AlignedQueryDataSize = Align(GetQueryDataSize(static_cast(QueryType)), Uint32{8}); - HeapInfo.AvailableQueries.resize(HeapInfo.HeapSize); - HeapInfo.ResolveBufferOffsets.resize(HeapInfo.HeapSize); - for (Uint32 i = 0; i < HeapInfo.HeapSize; ++i) - { - HeapInfo.AvailableQueries[i] = i; - HeapInfo.ResolveBufferOffsets[i] = ResolveBufferOffset; - ResolveBufferOffset += AlignedQueryDataSize; - } - } - - D3D12_RESOURCE_DESC D3D12BuffDesc = {}; - D3D12BuffDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - D3D12BuffDesc.Alignment = 0; - D3D12BuffDesc.Width = ResolveBufferOffset; - D3D12BuffDesc.Height = 1; - D3D12BuffDesc.DepthOrArraySize = 1; - D3D12BuffDesc.MipLevels = 1; - D3D12BuffDesc.Format = DXGI_FORMAT_UNKNOWN; - D3D12BuffDesc.SampleDesc.Count = 1; - D3D12BuffDesc.SampleDesc.Quality = 0; - // Layout must be D3D12_TEXTURE_LAYOUT_ROW_MAJOR, as buffer memory layouts are - // understood by applications and row-major texture data is commonly marshaled through buffers. - D3D12BuffDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - D3D12BuffDesc.Flags = D3D12_RESOURCE_FLAG_NONE; - - D3D12_HEAP_PROPERTIES HeapProps = {}; - HeapProps.Type = D3D12_HEAP_TYPE_READBACK; - HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; - HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - HeapProps.CreationNodeMask = 1; - HeapProps.VisibleNodeMask = 1; - - // The destination buffer of a query resolve operation must be in the D3D12_RESOURCE_USAGE_COPY_DEST state. - // ResolveQueryData works with all heap types (default, upload, readback). - // https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#resolvequerydata - auto hr = pd3d12Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, - &D3D12BuffDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, - __uuidof(m_pd3d12ResolveBuffer), - reinterpret_cast(static_cast(&m_pd3d12ResolveBuffer))); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to create D3D12 resolve buffer"); -} - -QueryManager::~QueryManager() -{ - for (Uint32 QueryType = QUERY_TYPE_UNDEFINED + 1; QueryType < QUERY_TYPE_NUM_TYPES; ++QueryType) - { - auto& HeapInfo = m_Heaps[QueryType]; - if (HeapInfo.AvailableQueries.size() != HeapInfo.HeapSize) - { - auto OutstandingQueries = HeapInfo.HeapSize - HeapInfo.AvailableQueries.size(); - if (OutstandingQueries == 1) - { - LOG_ERROR_MESSAGE("One query of type ", GetQueryTypeString(static_cast(QueryType)), - " has not been returned to the query manager"); - } - else - { - LOG_ERROR_MESSAGE(OutstandingQueries, " queries of type ", - GetQueryTypeString(static_cast(QueryType)), - " have not been returned to the query manager"); - } - } - } -} - -Uint32 QueryManager::AllocateQuery(QUERY_TYPE Type) -{ - std::lock_guard Lock(m_HeapMutex); - - Uint32 Index = InvalidIndex; - auto& HeapInfo = m_Heaps[Type]; - if (!HeapInfo.AvailableQueries.empty()) - { - Index = HeapInfo.AvailableQueries.front(); - HeapInfo.AvailableQueries.pop_front(); - } - - return Index; -} - -void QueryManager::ReleaseQuery(QUERY_TYPE Type, Uint32 Index) -{ - std::lock_guard Lock(m_HeapMutex); - auto& HeapInfo = m_Heaps[Type]; - - VERIFY(Index < HeapInfo.HeapSize, "Query index ", Index, " is out of range"); -#ifdef _DEBUG - for (const auto& ind : HeapInfo.AvailableQueries) - { - VERIFY(ind != Index, "Index ", Index, " already present in available queries list"); - } -#endif - HeapInfo.AvailableQueries.push_back(Index); -} - -void QueryManager::BeginQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index) -{ - auto d3d12QueryType = QueryTypeToD3D12QueryType(Type); - Ctx.BeginQuery(m_Heaps[Type].pd3d12QueryHeap, d3d12QueryType, Index); -} - -void QueryManager::EndQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index) -{ - auto d3d12QueryType = QueryTypeToD3D12QueryType(Type); - auto& HeapInfo = m_Heaps[Type]; - Ctx.EndQuery(HeapInfo.pd3d12QueryHeap, d3d12QueryType, Index); - - // https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#resolvequerydata - Ctx.ResolveQueryData(HeapInfo.pd3d12QueryHeap, d3d12QueryType, Index, 1, m_pd3d12ResolveBuffer, HeapInfo.ResolveBufferOffsets[Index]); -} - -void QueryManager::ReadQueryData(QUERY_TYPE Type, Uint32 Index, void* pDataPtr, Uint32 DataSize) const -{ - auto& HeapInfo = m_Heaps[Type]; - auto QueryDataSize = GetQueryDataSize(Type); - VERIFY_EXPR(QueryDataSize == DataSize); - auto Offset = HeapInfo.ResolveBufferOffsets[Index]; - D3D12_RANGE ReadRange; - ReadRange.Begin = Offset; - ReadRange.End = Offset + QueryDataSize; - - void* pBufferData = nullptr; - // The pointer returned by Map is never offset by any values in pReadRange. - m_pd3d12ResolveBuffer->Map(0, &ReadRange, &pBufferData); - memcpy(pDataPtr, reinterpret_cast(pBufferData) + Offset, QueryDataSize); - m_pd3d12ResolveBuffer->Unmap(0, nullptr); -} - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/QueryManagerD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/QueryManagerD3D12.cpp new file mode 100644 index 00000000..b62ab877 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/src/QueryManagerD3D12.cpp @@ -0,0 +1,216 @@ +/* + * 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 "QueryManagerD3D12.h" +#include "D3D12TypeConversions.h" +#include "GraphicsAccessories.h" +#include "CommandContext.h" +#include "Align.h" + +namespace Diligent +{ + +static Uint32 GetQueryDataSize(QUERY_TYPE QueryType) +{ + // clang-format off + switch (QueryType) + { + case QUERY_TYPE_OCCLUSION: + case QUERY_TYPE_BINARY_OCCLUSION: + case QUERY_TYPE_TIMESTAMP: + return sizeof(Uint64); + break; + + case QUERY_TYPE_PIPELINE_STATISTICS: + return sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS); + break; + + default: + UNEXPECTED("Unexpected query type"); + return 0; + } + // clang-format on +} + +QueryManagerD3D12::QueryManagerD3D12(ID3D12Device* pd3d12Device, + const Uint32 QueryHeapSizes[]) +{ + Uint32 ResolveBufferOffset = 0; + for (Uint32 QueryType = QUERY_TYPE_UNDEFINED + 1; QueryType < QUERY_TYPE_NUM_TYPES; ++QueryType) + { + // clang-format off + static_assert(QUERY_TYPE_OCCLUSION == 1, "Unexpected value of QUERY_TYPE_OCCLUSION. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); + static_assert(QUERY_TYPE_BINARY_OCCLUSION == 2, "Unexpected value of QUERY_TYPE_BINARY_OCCLUSION. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); + static_assert(QUERY_TYPE_TIMESTAMP == 3, "Unexpected value of QUERY_TYPE_TIMESTAMP. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); + static_assert(QUERY_TYPE_PIPELINE_STATISTICS== 4, "Unexpected value of QUERY_TYPE_PIPELINE_STATISTICS. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); + static_assert(QUERY_TYPE_NUM_TYPES == 5, "Unexpected value of QUERY_TYPE_NUM_TYPES. EngineD3D12CreateInfo::QueryPoolSizes must be updated"); + // clang-format on + auto& HeapInfo = m_Heaps[QueryType]; + + D3D12_QUERY_HEAP_DESC d3d12HeapDesc = {}; + + HeapInfo.HeapSize = QueryHeapSizes[QueryType]; + d3d12HeapDesc.Type = QueryTypeToD3D12QueryHeapType(static_cast(QueryType)); + d3d12HeapDesc.Count = HeapInfo.HeapSize; + + auto hr = pd3d12Device->CreateQueryHeap(&d3d12HeapDesc, __uuidof(HeapInfo.pd3d12QueryHeap), reinterpret_cast(&HeapInfo.pd3d12QueryHeap)); + CHECK_D3D_RESULT_THROW(hr, "Failed to create D3D12 query heap of type"); + + // AlignedDestinationBufferOffset must be a multiple of 8 bytes. + // https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#resolvequerydata + Uint32 AlignedQueryDataSize = Align(GetQueryDataSize(static_cast(QueryType)), Uint32{8}); + HeapInfo.AvailableQueries.resize(HeapInfo.HeapSize); + HeapInfo.ResolveBufferOffsets.resize(HeapInfo.HeapSize); + for (Uint32 i = 0; i < HeapInfo.HeapSize; ++i) + { + HeapInfo.AvailableQueries[i] = i; + HeapInfo.ResolveBufferOffsets[i] = ResolveBufferOffset; + ResolveBufferOffset += AlignedQueryDataSize; + } + } + + D3D12_RESOURCE_DESC D3D12BuffDesc = {}; + D3D12BuffDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + D3D12BuffDesc.Alignment = 0; + D3D12BuffDesc.Width = ResolveBufferOffset; + D3D12BuffDesc.Height = 1; + D3D12BuffDesc.DepthOrArraySize = 1; + D3D12BuffDesc.MipLevels = 1; + D3D12BuffDesc.Format = DXGI_FORMAT_UNKNOWN; + D3D12BuffDesc.SampleDesc.Count = 1; + D3D12BuffDesc.SampleDesc.Quality = 0; + // Layout must be D3D12_TEXTURE_LAYOUT_ROW_MAJOR, as buffer memory layouts are + // understood by applications and row-major texture data is commonly marshaled through buffers. + D3D12BuffDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + D3D12BuffDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + D3D12_HEAP_PROPERTIES HeapProps = {}; + HeapProps.Type = D3D12_HEAP_TYPE_READBACK; + HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + HeapProps.CreationNodeMask = 1; + HeapProps.VisibleNodeMask = 1; + + // The destination buffer of a query resolve operation must be in the D3D12_RESOURCE_USAGE_COPY_DEST state. + // ResolveQueryData works with all heap types (default, upload, readback). + // https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#resolvequerydata + auto hr = pd3d12Device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, + &D3D12BuffDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + __uuidof(m_pd3d12ResolveBuffer), + reinterpret_cast(static_cast(&m_pd3d12ResolveBuffer))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create D3D12 resolve buffer"); +} + +QueryManagerD3D12::~QueryManagerD3D12() +{ + for (Uint32 QueryType = QUERY_TYPE_UNDEFINED + 1; QueryType < QUERY_TYPE_NUM_TYPES; ++QueryType) + { + auto& HeapInfo = m_Heaps[QueryType]; + if (HeapInfo.AvailableQueries.size() != HeapInfo.HeapSize) + { + auto OutstandingQueries = HeapInfo.HeapSize - HeapInfo.AvailableQueries.size(); + if (OutstandingQueries == 1) + { + LOG_ERROR_MESSAGE("One query of type ", GetQueryTypeString(static_cast(QueryType)), + " has not been returned to the query manager"); + } + else + { + LOG_ERROR_MESSAGE(OutstandingQueries, " queries of type ", + GetQueryTypeString(static_cast(QueryType)), + " have not been returned to the query manager"); + } + } + } +} + +Uint32 QueryManagerD3D12::AllocateQuery(QUERY_TYPE Type) +{ + std::lock_guard Lock(m_HeapMutex); + + Uint32 Index = InvalidIndex; + auto& HeapInfo = m_Heaps[Type]; + if (!HeapInfo.AvailableQueries.empty()) + { + Index = HeapInfo.AvailableQueries.front(); + HeapInfo.AvailableQueries.pop_front(); + } + + return Index; +} + +void QueryManagerD3D12::ReleaseQuery(QUERY_TYPE Type, Uint32 Index) +{ + std::lock_guard Lock(m_HeapMutex); + + auto& HeapInfo = m_Heaps[Type]; + VERIFY(Index < HeapInfo.HeapSize, "Query index ", Index, " is out of range"); +#ifdef _DEBUG + for (const auto& ind : HeapInfo.AvailableQueries) + { + VERIFY(ind != Index, "Index ", Index, " already present in available queries list"); + } +#endif + HeapInfo.AvailableQueries.push_back(Index); +} + +void QueryManagerD3D12::BeginQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index) +{ + auto d3d12QueryType = QueryTypeToD3D12QueryType(Type); + Ctx.BeginQuery(m_Heaps[Type].pd3d12QueryHeap, d3d12QueryType, Index); +} + +void QueryManagerD3D12::EndQuery(CommandContext& Ctx, QUERY_TYPE Type, Uint32 Index) +{ + auto d3d12QueryType = QueryTypeToD3D12QueryType(Type); + auto& HeapInfo = m_Heaps[Type]; + Ctx.EndQuery(HeapInfo.pd3d12QueryHeap, d3d12QueryType, Index); + + // https://microsoft.github.io/DirectX-Specs/d3d/CountersAndQueries.html#resolvequerydata + Ctx.ResolveQueryData(HeapInfo.pd3d12QueryHeap, d3d12QueryType, Index, 1, m_pd3d12ResolveBuffer, HeapInfo.ResolveBufferOffsets[Index]); +} + +void QueryManagerD3D12::ReadQueryData(QUERY_TYPE Type, Uint32 Index, void* pDataPtr, Uint32 DataSize) const +{ + auto& HeapInfo = m_Heaps[Type]; + auto QueryDataSize = GetQueryDataSize(Type); + VERIFY_EXPR(QueryDataSize == DataSize); + auto Offset = HeapInfo.ResolveBufferOffsets[Index]; + D3D12_RANGE ReadRange; + ReadRange.Begin = Offset; + ReadRange.End = Offset + QueryDataSize; + + void* pBufferData = nullptr; + // The pointer returned by Map is never offset by any values in pReadRange. + m_pd3d12ResolveBuffer->Map(0, &ReadRange, &pBufferData); + memcpy(pDataPtr, reinterpret_cast(pBufferData) + Offset, QueryDataSize); + m_pd3d12ResolveBuffer->Unmap(0, nullptr); +} + +} // namespace Diligent -- cgit v1.2.3