From c057068e64b2123d426ad84606e8a756af11913f Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sat, 10 Dec 2016 20:18:41 -1000 Subject: [PATCH] use hash table for pool buffers --- include/boo/graphicsdev/GL.hpp | 1 + .../boo/graphicsdev/IGraphicsDataFactory.hpp | 6 ++ include/boo/graphicsdev/Vulkan.hpp | 1 + lib/graphicsdev/D3D11.cpp | 74 +++++++++++++------ lib/graphicsdev/D3D12.cpp | 14 +++- lib/graphicsdev/GL.cpp | 15 +++- lib/graphicsdev/Vulkan.cpp | 20 +++-- lib/win/ApplicationWin32.cpp | 32 ++++++-- 8 files changed, 118 insertions(+), 45 deletions(-) diff --git a/include/boo/graphicsdev/GL.hpp b/include/boo/graphicsdev/GL.hpp index c4a65e1..b368e2b 100644 --- a/include/boo/graphicsdev/GL.hpp +++ b/include/boo/graphicsdev/GL.hpp @@ -26,6 +26,7 @@ class GLDataFactory : public IGraphicsDataFactory void destroyPool(IGraphicsBufferPool*); IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use, size_t stride, size_t count); + void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf); public: GLDataFactory(IGraphicsContext* parent, uint32_t drawSamples); ~GLDataFactory() {destroyAllData();} diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index 6278906..b62af19 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -266,6 +266,7 @@ private: virtual void destroyPool(IGraphicsBufferPool*)=0; virtual IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use, size_t stride, size_t count)=0; + virtual void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf)=0; }; using FactoryCommitFunc = std::function; @@ -368,6 +369,11 @@ public: { return m_factory->newPoolBuffer(m_pool, use, stride, count); } + + void deletePoolBuffer(IGraphicsBufferD* buf) + { + m_factory->deletePoolBuffer(m_pool, buf); + } }; } diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp index 525d83c..08dba13 100644 --- a/include/boo/graphicsdev/Vulkan.hpp +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -97,6 +97,7 @@ class VulkanDataFactory : public IGraphicsDataFactory void destroyAllData(); IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool *pool, BufferUse use, size_t stride, size_t count); + void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf); public: VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples); ~VulkanDataFactory() {destroyAllData();} diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index e19668c..b3a6716 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -59,22 +59,37 @@ struct D3D11Data : IGraphicsData } }; +class D3D11GraphicsBufferD; + struct D3D11Pool : IGraphicsBufferPool { - size_t m_deleteCountdown = 4; - std::vector> m_DBufs; - - bool decref() + struct Buffer { - if (!m_deleteCountdown) - Log.report(logvisor::Fatal, "Can't decrement 0-data"); - --m_deleteCountdown; - if (!m_deleteCountdown) + size_t m_deleteCountdown = 4; + std::unique_ptr m_buf; + Buffer(D3D11GraphicsBufferD* buf) : m_buf(buf) {} + + bool decref() { - delete this; - return true; + if (!m_deleteCountdown) + Log.report(logvisor::Fatal, "Can't decrement 0-data"); + --m_deleteCountdown; + if (!m_deleteCountdown) + { + delete this; + return true; + } + return false; } - return false; + }; + + std::unordered_map m_DBufs; + + void destroyPool(std::unordered_set& delsOut) + { + for (auto& b : m_DBufs) + delsOut.emplace(b.second); + m_DBufs.clear(); } }; @@ -1060,9 +1075,11 @@ void D3D11GraphicsBufferD::update(ID3D11DeviceContext* ctx, int b) { ID3D11Buffer* res = m_bufs[b].Get(); D3D11_MAPPED_SUBRESOURCE d; - ctx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d); - memcpy(d.pData, m_cpuBuf.get(), m_cpuSz); - ctx->Unmap(res, 0); + if (SUCCEEDED(ctx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d))) + { + memcpy(d.pData, m_cpuBuf.get(), m_cpuSz); + ctx->Unmap(res, 0); + } m_validSlots |= slot; } } @@ -1129,7 +1146,7 @@ class D3D11DataFactory : public ID3DDataFactory std::unordered_set m_committedPools; std::mutex m_committedMutex; std::unordered_set m_deletedData; - std::unordered_set m_deletedPools; + std::unordered_set m_deletedPoolBufs; uint32_t m_sampleCount; void destroyData(IGraphicsData* d) @@ -1146,7 +1163,7 @@ class D3D11DataFactory : public ID3DDataFactory for (IGraphicsData* data : m_committedData) m_deletedData.insert(static_cast(data)); for (IGraphicsBufferPool* pool : m_committedPools) - m_deletedPools.insert(static_cast(pool)); + static_cast(pool)->destroyPool(m_deletedPoolBufs); m_committedData.clear(); m_committedPools.clear(); } @@ -1156,7 +1173,7 @@ class D3D11DataFactory : public ID3DDataFactory std::unique_lock lk(m_committedMutex); D3D11Pool* pool = static_cast(p); m_committedPools.erase(pool); - m_deletedPools.insert(pool); + pool->destroyPool(m_deletedPoolBufs); } void procDeletes() @@ -1171,12 +1188,12 @@ class D3D11DataFactory : public ID3DDataFactory } ++it; } - for (auto it = m_deletedPools.begin(); it != m_deletedPools.end();) + for (auto it = m_deletedPoolBufs.begin(); it != m_deletedPoolBufs.end();) { - D3D11Pool* cpool = static_cast(*it); + D3D11Pool::Buffer* cpool = *it; if (cpool->decref()) { - it = m_deletedPools.erase(it); + it = m_deletedPoolBufs.erase(it); continue; } ++it; @@ -1189,10 +1206,21 @@ class D3D11DataFactory : public ID3DDataFactory D3D11CommandQueue* q = static_cast(m_parent->getCommandQueue()); D3D11Pool* pool = static_cast(p); D3D11GraphicsBufferD* retval = new D3D11GraphicsBufferD(q, use, m_ctx, stride, count); - pool->m_DBufs.emplace_back(retval); + pool->m_DBufs.emplace(std::make_pair(retval, new D3D11Pool::Buffer(retval))); return retval; } + void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf) + { + D3D11Pool* pool = static_cast(p); + auto search = pool->m_DBufs.find(static_cast(buf)); + if (search != pool->m_DBufs.end()) + { + m_deletedPoolBufs.emplace(search->second); + pool->m_DBufs.erase(search); + } + } + public: D3D11DataFactory(IGraphicsContext* parent, D3D11Context* ctx, uint32_t sampleCount) : m_parent(parent), m_ctx(ctx), m_sampleCount(sampleCount) @@ -1404,8 +1432,8 @@ void D3D11CommandQueue::ProcessDynamicLoads(ID3D11DeviceContext* ctx) } for (D3D11Pool* p : gfxF->m_committedPools) { - for (std::unique_ptr& b : p->m_DBufs) - b->update(ctx, m_drawBuf); + for (auto& b : p->m_DBufs) + b.second->m_buf->update(ctx, m_drawBuf); } } diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index 705ed55..2595f6e 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -64,7 +64,7 @@ struct D3D12Pool : IGraphicsBufferPool Buffer(ComPtr&& heap, class D3D12GraphicsBufferD* buf) : m_bufHeap(std::move(heap)), m_buf(buf) {} }; - std::vector m_DBufs; + std::unordered_map m_DBufs; }; static const D3D12_RESOURCE_STATES USE_TABLE[] = @@ -1586,10 +1586,16 @@ class D3D12DataFactory : public ID3DDataFactory /* Place resources */ PlaceBufferForGPU(retval, m_ctx, bufHeap.Get(), 0); - pool->m_DBufs.emplace_back(std::move(bufHeap), retval); + pool->m_DBufs.emplace(std::make_pair(retval, D3D12Pool::Buffer{std::move(bufHeap), retval})); return retval; } + void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf) + { + D3D12Pool* pool = static_cast(p); + pool->m_DBufs.erase(static_cast(buf)); + } + public: D3D12DataFactory(IGraphicsContext* parent, D3D12Context* ctx, uint32_t sampleCount) : m_parent(parent), m_ctx(ctx), m_sampleCount(sampleCount) @@ -1893,8 +1899,8 @@ void D3D12CommandQueue::execute() } for (D3D12Pool* p : gfxF->m_committedPools) { - for (D3D12Pool::Buffer& b : p->m_DBufs) - b.m_buf->update(m_fillBuf); + for (auto& b : p->m_DBufs) + b.second.m_buf->update(m_fillBuf); } datalk.unlock(); diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index 5c2e4d8..9795698 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "logvisor/logvisor.hpp" @@ -32,7 +33,7 @@ struct GLData : IGraphicsData struct GLPool : IGraphicsBufferPool { - std::vector> m_DBufs; + std::unordered_map> m_DBufs; }; static const GLenum USE_TABLE[] = @@ -738,10 +739,16 @@ IGraphicsBufferD* GLDataFactory::newPoolBuffer(IGraphicsBufferPool* p, BufferUse { GLPool* pool = static_cast(p); GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count); - pool->m_DBufs.emplace_back(retval); + pool->m_DBufs.emplace(std::make_pair(retval, retval)); return retval; } +void GLDataFactory::deletePoolBuffer(IGraphicsBufferPool *p, IGraphicsBufferD *buf) +{ + GLPool* pool = static_cast(p); + pool->m_DBufs.erase(static_cast(buf)); +} + static const GLint SEMANTIC_COUNT_TABLE[] = { 0, @@ -1297,8 +1304,8 @@ struct GLCommandQueue : IGraphicsCommandQueue } for (GLPool* p : gfxF->m_committedPools) { - for (std::unique_ptr& b : p->m_DBufs) - b->update(m_completeBuf); + for (auto& b : p->m_DBufs) + b.second->update(m_completeBuf); } datalk.unlock(); glFlush(); diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index 3316902..0cd12d9 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -687,14 +687,14 @@ struct VulkanPool : IGraphicsBufferPool Buffer(VkDeviceMemory mem, class VulkanGraphicsBufferD* buf) : m_bufMem(mem), m_buffer(buf) {} }; - std::vector m_DBufs; + std::unordered_map m_DBufs; bool m_dead = false; VulkanPool(VulkanContext* ctx) : m_ctx(ctx) {} ~VulkanPool() { - for (Buffer& buf : m_DBufs) - if (buf.m_bufMem) - vk::FreeMemory(m_ctx->m_dev, buf.m_bufMem, nullptr); + for (auto& buf : m_DBufs) + if (buf.second.m_bufMem) + vk::FreeMemory(m_ctx->m_dev, buf.second.m_bufMem, nullptr); } }; @@ -3221,10 +3221,16 @@ IGraphicsBufferD* VulkanDataFactory::newPoolBuffer(IGraphicsBufferPool* p, Buffe retval->placeForGPU(m_ctx, bufMem); } - pool->m_DBufs.emplace_back(bufMem, retval); + pool->m_DBufs.emplace(std::make_pair(retval, VulkanPool::Buffer{bufMem, retval})); return retval; } +void VulkanDataFactory::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf) +{ + VulkanPool* pool = static_cast(p); + pool->m_DBufs.erase(static_cast(buf)); +} + GraphicsBufferPoolToken VulkanDataFactory::newBufferPool() { std::unique_lock lk(m_committedMutex); @@ -3252,8 +3258,8 @@ void VulkanCommandQueue::execute() } for (VulkanPool* p : gfxF->m_committedPools) { - for (VulkanPool::Buffer& b : p->m_DBufs) - b.m_buffer->update(m_fillBuf); + for (auto& b : p->m_DBufs) + b.second.m_buffer->update(m_fillBuf); } datalk.unlock(); diff --git a/lib/win/ApplicationWin32.cpp b/lib/win/ApplicationWin32.cpp index 8d4b629..e3e5b7c 100644 --- a/lib/win/ApplicationWin32.cpp +++ b/lib/win/ApplicationWin32.cpp @@ -142,7 +142,7 @@ public: #if _WIN32_WINNT_WIN10 HMODULE d3d12lib = LoadLibraryW(L"D3D12.dll"); if (!no12 && !noD3d && d3d12lib) - { + { #if _DEBUG { PFN_D3D12_GET_DEBUG_INTERFACE MyD3D12GetDebugInterface = @@ -165,15 +165,32 @@ public: if (!MyD3D12CreateDevice) Log.report(logvisor::Fatal, "unable to find D3D12CreateDevice in D3D12.dll"); + /* Obtain DXGI Factory */ + HRESULT hr = MyCreateDXGIFactory1(__uuidof(IDXGIFactory2), &m_3dCtx.m_ctx12.m_dxFactory); + if (FAILED(hr)) + Log.report(logvisor::Fatal, "unable to create DXGI factory"); + + /* Adapter */ + ComPtr ppAdapter; + for (UINT adapterIndex = 0; ; ++adapterIndex) + { + ComPtr pAdapter; + if (DXGI_ERROR_NOT_FOUND == m_3dCtx.m_ctx12.m_dxFactory->EnumAdapters1(adapterIndex, &pAdapter)) + break; + + // Check to see if the adapter supports Direct3D 12, but don't create the + // actual device yet. + if (SUCCEEDED(MyD3D12CreateDevice(pAdapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) + { + ppAdapter = std::move(pAdapter); + break; + } + } + /* Create device */ - HRESULT hr = MyD3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), &m_3dCtx.m_ctx12.m_dev); + hr = ppAdapter ? MyD3D12CreateDevice(ppAdapter.Get(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), &m_3dCtx.m_ctx12.m_dev) : E_FAIL; if (!FAILED(hr)) { - /* Obtain DXGI Factory */ - hr = MyCreateDXGIFactory1(__uuidof(IDXGIFactory2), &m_3dCtx.m_ctx12.m_dxFactory); - if (FAILED(hr)) - Log.report(logvisor::Fatal, "unable to create DXGI factory"); - /* Establish loader objects */ if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), &m_3dCtx.m_ctx12.m_loadqalloc))) @@ -204,6 +221,7 @@ public: { /* Some Win10 client HW doesn't support D3D12 (despite being supposedly HW-agnostic) */ m_3dCtx.m_ctx12.m_dev.Reset(); + m_3dCtx.m_ctx12.m_dxFactory.Reset(); } } #endif