From e13b87cdd9f169565fb2fefd0413890bcbafbb7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sun, 4 Oct 2026 19:56:08 -0700 Subject: [PATCH] Sized handle allocators, timer query rings and free handle queues by use. (#4025) --- src/bgfx.cpp | 132 +++++++++--------- src/bgfx_p.h | 302 +++++++++++++++++++++-------------------- src/renderer.h | 36 +++++ src/renderer_d3d11.cpp | 12 +- src/renderer_d3d11.h | 5 +- src/renderer_d3d12.cpp | 1 + src/renderer_d3d12.h | 5 +- src/renderer_gl.h | 17 ++- src/renderer_vk.cpp | 1 + src/renderer_vk.h | 5 +- 10 files changed, 293 insertions(+), 223 deletions(-) diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 0b75b20ec..6deb6fa45 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -2588,65 +2588,75 @@ namespace bgfx if (BX_ENABLED(BGFX_CONFIG_DEBUG) ) { -#define CHECK_HANDLE_LEAK(_name, _handleAlloc) \ - BX_MACRO_BLOCK_BEGIN \ - if (0 != _handleAlloc.getNumHandles() ) \ - { \ - BX_TRACE("LEAK: %s %d (max: %d)" \ - , _name \ - , _handleAlloc.getNumHandles() \ - , _handleAlloc.getMaxHandles() \ - ); \ - for (uint16_t ii = 0, num = _handleAlloc.getNumHandles(); ii < num; ++ii) \ - { \ - BX_TRACE("\t%3d: %4d", ii, _handleAlloc.getHandleAt(ii) ); \ - } \ - } \ +#define CHECK_HANDLE_LEAK(_name, _handleAlloc) \ + BX_MACRO_BLOCK_BEGIN \ + if (0 != _handleAlloc.getNumHandles() ) \ + { \ + BX_TRACE("LEAK: %s %d (max: %d)" \ + , _name \ + , _handleAlloc.getNumHandles() \ + , _handleAlloc.getMaxHandles() \ + ); \ + uint16_t ii = 0; BX_UNUSED(ii); \ + for (uint16_t idx = _handleAlloc.findFirst() \ + ; bx::kInvalidHandle != idx \ + ; idx = _handleAlloc.findNext(idx), ++ii \ + ) \ + { \ + BX_TRACE("\t%3d: %4d", ii, idx); \ + } \ + } \ BX_MACRO_BLOCK_END -#define CHECK_HANDLE_LEAK_NAME(_name, _handleAlloc, _type, _ref) \ - BX_MACRO_BLOCK_BEGIN \ - if (0 != _handleAlloc.getNumHandles() ) \ - { \ - BX_TRACE("LEAK: %s %d (max: %d)" \ - , _name \ - , _handleAlloc.getNumHandles() \ - , _handleAlloc.getMaxHandles() \ - ); \ - for (uint16_t ii = 0, num = _handleAlloc.getNumHandles(); ii < num; ++ii) \ - { \ - uint16_t idx = _handleAlloc.getHandleAt(ii); \ - const _type& ref = _ref[idx]; BX_UNUSED(ref); \ - BX_TRACE("\t%3d: %4d %s" \ - , ii \ - , idx \ - , ref.m_name.getCPtr() \ - ); \ - } \ - } \ +#define CHECK_HANDLE_LEAK_NAME(_name, _handleAlloc, _type, _ref) \ + BX_MACRO_BLOCK_BEGIN \ + if (0 != _handleAlloc.getNumHandles() ) \ + { \ + BX_TRACE("LEAK: %s %d (max: %d)" \ + , _name \ + , _handleAlloc.getNumHandles() \ + , _handleAlloc.getMaxHandles() \ + ); \ + uint16_t ii = 0; BX_UNUSED(ii); \ + for (uint16_t idx = _handleAlloc.findFirst() \ + ; bx::kInvalidHandle != idx \ + ; idx = _handleAlloc.findNext(idx), ++ii \ + ) \ + { \ + const _type& ref = _ref[idx]; BX_UNUSED(ref); \ + BX_TRACE("\t%3d: %4d %s" \ + , ii \ + , idx \ + , ref.m_name.getCPtr() \ + ); \ + } \ + } \ BX_MACRO_BLOCK_END -#define CHECK_HANDLE_LEAK_RC_NAME(_name, _handleAlloc, _type, _ref) \ - BX_MACRO_BLOCK_BEGIN \ - if (0 != _handleAlloc.getNumHandles() ) \ - { \ - BX_TRACE("LEAK: %s %d (max: %d)" \ - , _name \ - , _handleAlloc.getNumHandles() \ - , _handleAlloc.getMaxHandles() \ - ); \ - for (uint16_t ii = 0, num = _handleAlloc.getNumHandles(); ii < num; ++ii) \ - { \ - uint16_t idx = _handleAlloc.getHandleAt(ii); \ - const _type& ref = _ref[idx]; BX_UNUSED(ref); \ - BX_TRACE("\t%3d: %4d %s (count %d)" \ - , ii \ - , idx \ - , ref.m_name.getCPtr() \ - , ref.m_refCount \ - ); \ - } \ - } \ +#define CHECK_HANDLE_LEAK_RC_NAME(_name, _handleAlloc, _type, _ref) \ + BX_MACRO_BLOCK_BEGIN \ + if (0 != _handleAlloc.getNumHandles() ) \ + { \ + BX_TRACE("LEAK: %s %d (max: %d)" \ + , _name \ + , _handleAlloc.getNumHandles() \ + , _handleAlloc.getMaxHandles() \ + ); \ + uint16_t ii = 0; BX_UNUSED(ii); \ + for (uint16_t idx = _handleAlloc.findFirst() \ + ; bx::kInvalidHandle != idx \ + ; idx = _handleAlloc.findNext(idx), ++ii \ + ) \ + { \ + const _type& ref = _ref[idx]; BX_UNUSED(ref); \ + BX_TRACE("\t%3d: %4d %s (count %d)" \ + , ii \ + , idx \ + , ref.m_name.getCPtr() \ + , ref.m_refCount \ + ); \ + } \ + } \ BX_MACRO_BLOCK_END CHECK_HANDLE_LEAK ("DynamicIndexBufferHandle", m_dynamicIndexBufferHandle ); @@ -2667,17 +2677,17 @@ namespace bgfx void Context::freeDynamicBuffers() { - for (uint16_t ii = 0, num = m_numFreeDynamicIndexBufferHandles; ii < num; ++ii) + for (uint16_t ii = 0, num = m_freeDynamicIndexBuffer.getNumQueued(); ii < num; ++ii) { - destroyDynamicIndexBufferInternal(m_freeDynamicIndexBufferHandle[ii]); + destroyDynamicIndexBufferInternal(m_freeDynamicIndexBuffer.get(ii) ); } - m_numFreeDynamicIndexBufferHandles = 0; + m_freeDynamicIndexBuffer.reset(); - for (uint16_t ii = 0, num = m_numFreeDynamicVertexBufferHandles; ii < num; ++ii) + for (uint16_t ii = 0, num = m_freeDynamicVertexBuffer.getNumQueued(); ii < num; ++ii) { - destroyDynamicVertexBufferInternal(m_freeDynamicVertexBufferHandle[ii]); + destroyDynamicVertexBufferInternal(m_freeDynamicVertexBuffer.get(ii) ); } - m_numFreeDynamicVertexBufferHandles = 0; + m_freeDynamicVertexBuffer.reset(); for (uint16_t ii = 0, num = m_numFreeOcclusionQueryHandles; ii < num; ++ii) { diff --git a/src/bgfx_p.h b/src/bgfx_p.h index a844cfb83..753c840ad 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -2870,6 +2870,7 @@ namespace bgfx uint32_t m_size; uint16_t m_stride; uint16_t m_flags; + VertexLayoutHandle m_layoutHandle = BGFX_INVALID_HANDLE; }; struct BufferRef @@ -2961,7 +2962,7 @@ namespace bgfx uint32_t m_startVertex; uint32_t m_numVertices; uint16_t m_stride; - VertexLayoutHandle m_layoutHandle; + VertexLayoutHandle m_layoutHandle = BGFX_INVALID_HANDLE; uint16_t m_flags; }; @@ -3706,10 +3707,10 @@ namespace bgfx void create() { - bx::memSet(m_used, 0, sizeof(m_used) ); - bx::memSet(m_touched, 0, sizeof(m_touched) ); + m_alloc.reset(); + m_alloc.alloc(); - m_used[0] = 1; + bx::memSet(m_touched, 0, sizeof(m_touched) ); } void destroy() @@ -3724,44 +3725,36 @@ namespace bgfx uint16_t alloc() { - for (uint32_t blockIdx = 0; blockIdx < kNumBlocks; ++blockIdx) + const uint16_t idx = m_alloc.alloc(); + + if (bx::kInvalidHandle == idx + || idx >= kNumNames) { - const uint64_t avail = ~m_used[blockIdx]; - - if (0 != avail) - { - const uint32_t bit = bx::countTrailingZeros(avail); - const uint32_t idx = blockIdx*kBlock + bit; - - if (idx >= kNumNames) - { - break; - } - -#if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE - if (NULL == m_block[blockIdx]) - { - char* block = (char*)bx::alloc(g_allocator, kBlock*kNameSize); - bx::memSet(block, 0, kBlock*kNameSize); - - bx::atomicExchangePtr( (void**)&m_block[blockIdx], block); - } -#endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE - - m_used[blockIdx] |= UINT64_C(1) << bit; - m_touched[blockIdx] = true; - - return uint16_t(idx); - } + BX_ASSERT(false, "Out of view names."); + m_alloc.free(idx); + return 0; } - BX_ASSERT(false, "Out of view names."); - return 0; + const uint32_t blockIdx = idx / kBlock; + +#if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + if (NULL == m_block[blockIdx]) + { + char* block = (char*)bx::alloc(g_allocator, kBlock*kNameSize); + bx::memSet(block, 0, kBlock*kNameSize); + + bx::atomicExchangePtr( (void**)&m_block[blockIdx], block); + } +#endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + + m_touched[blockIdx] = true; + + return idx; } void free(uint16_t _idx) { - m_used[_idx / kBlock] &= ~(UINT64_C(1) << (_idx & kBlockMask) ); + m_alloc.free(_idx); } const char* get(uint16_t _idx) const @@ -3791,7 +3784,7 @@ namespace bgfx { for (uint32_t ii = 1; ii < kNumBlocks; ++ii) { - if (0 == m_used[ii] + if (m_alloc.getBits().testNone(ii*kBlock, (ii+1)*kBlock) && !m_touched[ii]) { #if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE @@ -3819,8 +3812,8 @@ namespace bgfx char m_name[kNumBlocks][kBlock*kNameSize] = {}; #endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE - uint64_t m_used[kNumBlocks]; - bool m_touched[kNumBlocks]; + bool m_touched[kNumBlocks]; + bx::HandleAlloc2T m_alloc; }; struct UniformCacheKey @@ -4021,6 +4014,89 @@ namespace bgfx FrameBufferHandle handle; }; + template + struct FreeHandle + { + FreeHandle() + : m_num(0) + { + } + + bool isQueued(Ty _handle) + { + for (uint32_t ii = 0, num = m_num; ii < num; ++ii) + { + if (m_queue[ii].idx == _handle.idx) + { + return true; + } + } + + return false; + } + + bool queue(Ty _handle) + { + if (BX_ENABLED(BGFX_CONFIG_DEBUG) ) + { + if (isQueued(_handle) ) + { + return false; + } + } + + reserve(m_num + 1); + m_queue[m_num] = _handle; + ++m_num; + + return true; + } + + void reset() + { + m_num = 0; + } + + Ty get(uint16_t _idx) const + { + return m_queue[_idx]; + } + + uint16_t getNumQueued() const + { + return m_num; + } + +#if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + ~FreeHandle() + { + bx::free(g_allocator, m_queue); + } + + private: + void reserve(uint32_t _num) + { + if (_num > m_capacity) + { + m_capacity = bx::min(bx::alignUp(_num, 64), Max); + m_queue = (Ty*)bx::realloc(g_allocator, m_queue, sizeof(Ty)*m_capacity); + } + } + + Ty* m_queue = NULL; + uint32_t m_capacity = 0; +#else + private: + void reserve(uint32_t /*_num*/) + { + } + + Ty m_queue[Max]; +#endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + + uint16_t m_num; + }; + BX_ALIGN_DECL_CACHE_LINE(struct) Frame { Frame() @@ -4435,62 +4511,6 @@ namespace bgfx CommandBuffer m_cmdPre; CommandBuffer m_cmdPost; - template - struct FreeHandle - { - FreeHandle() - : m_num(0) - { - } - - bool isQueued(Ty _handle) - { - for (uint32_t ii = 0, num = m_num; ii < num; ++ii) - { - if (m_queue[ii].idx == _handle.idx) - { - return true; - } - } - - return false; - } - - bool queue(Ty _handle) - { - if (BX_ENABLED(BGFX_CONFIG_DEBUG) ) - { - if (isQueued(_handle) ) - { - return false; - } - } - - m_queue[m_num] = _handle; - ++m_num; - - return true; - } - - void reset() - { - m_num = 0; - } - - Ty get(uint16_t _idx) const - { - return m_queue[_idx]; - } - - uint16_t getNumQueued() const - { - return m_num; - } - - Ty m_queue[Max]; - uint16_t m_num; - }; - FreeHandle m_freeIndexBuffer; FreeHandle m_freeVertexLayout; FreeHandle m_freeVertexBuffer; @@ -5137,21 +5157,18 @@ namespace bgfx void init() { - bx::memSet(m_refCount, 0, sizeof(m_refCount) ); - bx::memSet(m_stride, 0, sizeof(m_stride) ); - bx::memSet(m_vertexBufferRef, 0xff, sizeof(m_vertexBufferRef) ); - bx::memSet(m_dynamicVertexBufferRef, 0xff, sizeof(m_dynamicVertexBufferRef) ); + bx::memSet(m_refCount, 0, sizeof(m_refCount) ); + bx::memSet(m_stride, 0, sizeof(m_stride) ); } template - void shutdown(bx::HandleAllocT& _handleAlloc) + void shutdown(bx::HandleAlloc2T& _handleAlloc) { - for (uint16_t ii = 0, num = _handleAlloc.getNumHandles(); ii < num; ++ii) + for (uint16_t idx = _handleAlloc.findFirst(); bx::kInvalidHandle != idx; idx = _handleAlloc.findNext(idx) ) { - VertexLayoutHandle handle = { _handleAlloc.getHandleAt(ii) }; - m_refCount[handle.idx] = 0; - m_vertexLayoutMap.removeByHandle(handle.idx); - _handleAlloc.free(handle.idx); + m_refCount[idx] = 0; + m_vertexLayoutMap.removeByHandle(idx); + _handleAlloc.free(idx); } m_vertexLayoutMap.reset(); @@ -5169,18 +5186,18 @@ namespace bgfx m_vertexLayoutMap.insert(_hash, _layoutHandle.idx); } - void add(VertexBufferHandle _handle, VertexLayoutHandle _layoutHandle, uint32_t _hash) + void add(VertexBuffer& _vb, VertexLayoutHandle _layoutHandle, uint32_t _hash) { - BX_ASSERT(!isValid(m_vertexBufferRef[_handle.idx]), ""); - m_vertexBufferRef[_handle.idx] = _layoutHandle; + BX_ASSERT(!isValid(_vb.m_layoutHandle), ""); + _vb.m_layoutHandle = _layoutHandle; m_refCount[_layoutHandle.idx]++; m_vertexLayoutMap.insert(_hash, _layoutHandle.idx); } - void add(DynamicVertexBufferHandle _handle, VertexLayoutHandle _layoutHandle, uint32_t _hash) + void add(DynamicVertexBuffer& _dvb, VertexLayoutHandle _layoutHandle, uint32_t _hash) { - BX_ASSERT(!isValid(m_dynamicVertexBufferRef[_handle.idx]), ""); - m_dynamicVertexBufferRef[_handle.idx] = _layoutHandle; + BX_ASSERT(!isValid(_dvb.m_layoutHandle), ""); + _dvb.m_layoutHandle = _layoutHandle; m_refCount[_layoutHandle.idx]++; m_vertexLayoutMap.insert(_hash, _layoutHandle.idx); } @@ -5201,20 +5218,18 @@ namespace bgfx return BGFX_INVALID_HANDLE; } - VertexLayoutHandle release(VertexBufferHandle _handle) + VertexLayoutHandle release(VertexBuffer& _vb) { - VertexLayoutHandle layoutHandle = m_vertexBufferRef[_handle.idx]; - layoutHandle = release(layoutHandle); - m_vertexBufferRef[_handle.idx] = BGFX_INVALID_HANDLE; + VertexLayoutHandle layoutHandle = release(_vb.m_layoutHandle); + _vb.m_layoutHandle = BGFX_INVALID_HANDLE; return layoutHandle; } - VertexLayoutHandle release(DynamicVertexBufferHandle _handle) + VertexLayoutHandle release(DynamicVertexBuffer& _dvb) { - VertexLayoutHandle layoutHandle = m_dynamicVertexBufferRef[_handle.idx]; - layoutHandle = release(layoutHandle); - m_dynamicVertexBufferRef[_handle.idx] = BGFX_INVALID_HANDLE; + VertexLayoutHandle layoutHandle = release(_dvb.m_layoutHandle); + _dvb.m_layoutHandle = BGFX_INVALID_HANDLE; return layoutHandle; } @@ -5224,8 +5239,6 @@ namespace bgfx uint16_t m_refCount[BGFX_CONFIG_MAX_VERTEX_LAYOUTS]; uint16_t m_stride[BGFX_CONFIG_MAX_VERTEX_LAYOUTS]; - VertexLayoutHandle m_vertexBufferRef[BGFX_CONFIG_MAX_VERTEX_BUFFERS]; - VertexLayoutHandle m_dynamicVertexBufferRef[BGFX_CONFIG_MAX_DYNAMIC_VERTEX_BUFFERS]; }; // First-fit non-local allocator. @@ -5835,8 +5848,6 @@ namespace bgfx , m_tempValues(NULL) , m_tempCapacity(0) , m_numDrawCallsPeak(0) - , m_numFreeDynamicIndexBufferHandles(0) - , m_numFreeDynamicVertexBufferHandles(0) , m_numFreeOcclusionQueryHandles(0) , m_numNewOcclusionQueryHandles(0) , m_colorPaletteDirty(2) @@ -5990,9 +6001,8 @@ namespace bgfx } } - for (uint16_t ii = 0, num = m_textureHandle.getNumHandles(); ii < num; ++ii) + for (uint16_t textureIdx = m_textureHandle.findFirst(); bx::kInvalidHandle != textureIdx; textureIdx = m_textureHandle.findNext(textureIdx) ) { - uint16_t textureIdx = m_textureHandle.getHandleAt(ii); const TextureRef& ref = m_textureRef[textureIdx]; if (BackbufferRatio::Count != ref.m_bbRatio) { @@ -6234,9 +6244,8 @@ namespace bgfx return BGFX_INVALID_HANDLE; } - m_vertexLayoutRef.add(handle, layoutHandle, _layout.m_hash); - VertexBuffer& vb = m_vertexBuffers.alloc(handle.idx); + m_vertexLayoutRef.add(vb, layoutHandle, _layout.m_hash); vb.m_size = _mem->size; vb.m_stride = _layout.m_stride; vb.m_flags = _flags; @@ -6287,7 +6296,7 @@ namespace bgfx void destroyVertexBufferInternal(VertexBufferHandle _handle) { - VertexLayoutHandle layoutHandle = m_vertexLayoutRef.release(_handle); + VertexLayoutHandle layoutHandle = m_vertexLayoutRef.release(m_vertexBuffers[_handle.idx]); if (isValid(layoutHandle) ) { CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyVertexLayout); @@ -6455,7 +6464,7 @@ namespace bgfx BGFX_CHECK_HANDLE("destroyDynamicIndexBuffer", m_dynamicIndexBufferHandle, _handle); - m_freeDynamicIndexBufferHandle[m_numFreeDynamicIndexBufferHandles++] = _handle; + m_freeDynamicIndexBuffer.queue(_handle); } void destroy(const DynamicIndexBuffer& _dib) @@ -6579,9 +6588,8 @@ namespace bgfx dvb.m_startVertex = bx::strideAlign(dvb.m_offset, _layout.m_stride)/_layout.m_stride; dvb.m_numVertices = _num; dvb.m_stride = _layout.m_stride; - dvb.m_layoutHandle = layoutHandle; dvb.m_flags = _flags; - m_vertexLayoutRef.add(handle, layoutHandle, _layout.m_hash); + m_vertexLayoutRef.add(dvb, layoutHandle, _layout.m_hash); return handle; } @@ -6657,7 +6665,7 @@ namespace bgfx BGFX_CHECK_HANDLE("destroyDynamicVertexBuffer", m_dynamicVertexBufferHandle, _handle); - m_freeDynamicVertexBufferHandle[m_numFreeDynamicVertexBufferHandles++] = _handle; + m_freeDynamicVertexBuffer.queue(_handle); } void destroy(const DynamicVertexBuffer& _dvb) @@ -6680,7 +6688,7 @@ namespace bgfx void destroyDynamicVertexBufferInternal(DynamicVertexBufferHandle _handle) { - VertexLayoutHandle layoutHandle = m_vertexLayoutRef.release(_handle); + VertexLayoutHandle layoutHandle = m_vertexLayoutRef.release(m_dynamicVertexBuffers[_handle.idx]); BGFX_CHECK_HANDLE_INVALID_OK("destroyDynamicVertexBufferInternal", m_layoutHandle, layoutHandle); if (isValid(layoutHandle) ) @@ -6787,7 +6795,7 @@ namespace bgfx if (NULL != _layout) { layoutHandle = findOrCreateVertexLayout(*_layout); - m_vertexLayoutRef.add(handle, layoutHandle, _layout->m_hash); + m_vertexLayoutRef.add(m_vertexBuffers[handle.idx], layoutHandle, _layout->m_hash); stride = _layout->m_stride; } @@ -8543,30 +8551,28 @@ namespace bgfx HandleArenaT m_dynamicIndexBuffers; HandleArenaT m_dynamicVertexBuffers; - uint16_t m_numFreeDynamicIndexBufferHandles; - uint16_t m_numFreeDynamicVertexBufferHandles; uint16_t m_numFreeOcclusionQueryHandles; uint16_t m_numNewOcclusionQueryHandles; - DynamicIndexBufferHandle m_freeDynamicIndexBufferHandle[BGFX_CONFIG_MAX_DYNAMIC_INDEX_BUFFERS]; - DynamicVertexBufferHandle m_freeDynamicVertexBufferHandle[BGFX_CONFIG_MAX_DYNAMIC_VERTEX_BUFFERS]; + FreeHandle m_freeDynamicIndexBuffer; + FreeHandle m_freeDynamicVertexBuffer; OcclusionQueryHandle m_freeOcclusionQueryHandle[BGFX_CONFIG_MAX_OCCLUSION_QUERIES]; OcclusionQueryHandle m_newOcclusionQueryHandle[BGFX_CONFIG_MAX_OCCLUSION_QUERIES]; NonLocalAllocator m_dynIndexBufferAllocator; - bx::HandleAllocT m_dynamicIndexBufferHandle; + bx::HandleAlloc2T m_dynamicIndexBufferHandle; NonLocalAllocator m_dynVertexBufferAllocator; - bx::HandleAllocT m_dynamicVertexBufferHandle; + bx::HandleAlloc2T m_dynamicVertexBufferHandle; - bx::HandleAllocT m_indexBufferHandle; - bx::HandleAllocT m_layoutHandle; + bx::HandleAlloc2T m_indexBufferHandle; + bx::HandleAlloc2T m_layoutHandle; - bx::HandleAllocT m_vertexBufferHandle; - bx::HandleAllocT m_shaderHandle; - bx::HandleAllocT m_programHandle; - bx::HandleAllocT m_textureHandle; - bx::HandleAllocT m_frameBufferHandle; - bx::HandleAllocT m_uniformHandle; - bx::HandleAllocT m_occlusionQueryHandle; + bx::HandleAlloc2T m_vertexBufferHandle; + bx::HandleAlloc2T m_shaderHandle; + bx::HandleAlloc2T m_programHandle; + bx::HandleAlloc2T m_textureHandle; + bx::HandleAlloc2T m_frameBufferHandle; + bx::HandleAlloc2T m_uniformHandle; + bx::HandleAlloc2T m_occlusionQueryHandle; typedef bx::HandleHashMapT UniformHashMap; UniformHashMap m_uniformHashMap; diff --git a/src/renderer.h b/src/renderer.h index 19af62365..85cd51296 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -84,6 +84,42 @@ namespace bgfx _control.resize(int32_t(_size) - int32_t(_control.getSize() ) ); } + template + class TimerQueryArrayT + { + public: + TimerQueryArrayT(uint32_t _num) + : m_query(NULL) + , m_num(0) + { + resize(_num); + } + + ~TimerQueryArrayT() + { + bx::free(g_allocator, m_query); + } + + void resize(uint32_t _num) + { + if (_num != m_num) + { + m_query = (QueryT*)bx::realloc(g_allocator, m_query, sizeof(QueryT)*_num); + m_num = _num; + } + } + + QueryT& operator[](uint32_t _idx) + { + BX_ASSERT(_idx < m_num, "Timer query index %d out of range %d.", _idx, m_num); + return m_query[_idx]; + } + + private: + QueryT* m_query; + uint32_t m_num; + }; + template class TimerResultT { diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 15fe1527b..c83ded6f5 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -6366,7 +6366,10 @@ namespace bgfx { namespace d3d11 { const uint32_t num = newSize - size; - bx::memMove(&m_query[write+num], &m_query[write], (size-write)*sizeof(Query) ); + m_query.resize(newSize); + + Query* query = &m_query[0]; + bx::memMove(&query[write+num], &query[write], (size-write)*sizeof(Query) ); create(write, write+num); } else if (newSize < size) @@ -6378,8 +6381,11 @@ namespace bgfx { namespace d3d11 destroy(write, write+back); destroy(0, front); - bx::memMove(&m_query[write], &m_query[write+back], (size-write-back)*sizeof(Query) ); - bx::memMove(&m_query[0], &m_query[front], newSize*sizeof(Query) ); + Query* query = &m_query[0]; + bx::memMove(&query[write], &query[write+back], (size-write-back)*sizeof(Query) ); + bx::memMove(&query[0], &query[front], newSize*sizeof(Query) ); + + m_query.resize(newSize); } } diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index 368684fb8..01130bb72 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -480,7 +480,8 @@ namespace bgfx { namespace d3d11 struct TimerQueryD3D11 { TimerQueryD3D11() - : m_control(kMinTimerQueries) + : m_query(kMinTimerQueries) + , m_control(kMinTimerQueries) { } @@ -523,7 +524,7 @@ namespace bgfx { namespace d3d11 TimerResultT m_result; - Query m_query[kMaxTimerQueries]; + TimerQueryArrayT m_query; bx::RingBufferControl m_control; }; diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index 54c54a25e..5c17cb4df 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -8563,6 +8563,7 @@ namespace bgfx { namespace d3d12 shutdown(); bgfx::resize(m_control, _size); + m_query.resize(m_control.getSize() ); create(); m_result.resetPending(); diff --git a/src/renderer_d3d12.h b/src/renderer_d3d12.h index 68adef8a1..e2a98b72e 100644 --- a/src/renderer_d3d12.h +++ b/src/renderer_d3d12.h @@ -750,7 +750,8 @@ namespace bgfx { namespace d3d12 struct TimerQueryD3D12 { TimerQueryD3D12() - : m_control(kMinTimerQueries) + : m_query(kMinTimerQueries) + , m_control(kMinTimerQueries) { } @@ -789,7 +790,7 @@ namespace bgfx { namespace d3d12 uint64_t m_frequency; TimerResultT m_result; - Query m_query[kMaxTimerQueries]; + TimerQueryArrayT m_query; ID3D12Resource* m_readback; ID3D12QueryHeap* m_queryHeap; diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 957f89bd5..cdceea59d 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -1660,7 +1660,8 @@ namespace bgfx { namespace gl struct TimerQueryGL { TimerQueryGL() - : m_control(kMinTimerQueries) + : m_query(kMinTimerQueries) + , m_control(kMinTimerQueries) { } @@ -1711,7 +1712,10 @@ namespace bgfx { namespace gl { const uint32_t num = newSize - size; - bx::memMove(&m_query[write+num], &m_query[write], (size-write)*sizeof(Query) ); + m_query.resize(newSize); + + Query* query = &m_query[0]; + bx::memMove(&query[write+num], &query[write], (size-write)*sizeof(Query) ); create(write, write+num); } else if (newSize < size) @@ -1723,8 +1727,11 @@ namespace bgfx { namespace gl destroy(write, write+back); destroy(0, front); - bx::memMove(&m_query[write], &m_query[write+back], (size-write-back)*sizeof(Query) ); - bx::memMove(&m_query[0], &m_query[front], newSize*sizeof(Query) ); + Query* query = &m_query[0]; + bx::memMove(&query[write], &query[write+back], (size-write-back)*sizeof(Query) ); + bx::memMove(&query[0], &query[front], newSize*sizeof(Query) ); + + m_query.resize(newSize); } } @@ -1844,7 +1851,7 @@ namespace bgfx { namespace gl TimerResultT m_result; - Query m_query[kMaxTimerQueries]; + TimerQueryArrayT m_query; bx::RingBufferControl m_control; }; diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 9a7043eee..309c8932b 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -6443,6 +6443,7 @@ VK_DESTROY s_renderVK->recycleMemory(m_readbackMemory); bgfx::resize(m_control, _size); + m_query.resize(m_control.getSize() ); VK_CHECK(create() ); m_result.resetPending(); diff --git a/src/renderer_vk.h b/src/renderer_vk.h index a817bcc73..66256f278 100644 --- a/src/renderer_vk.h +++ b/src/renderer_vk.h @@ -605,7 +605,8 @@ VK_DESTROY_FUNC(DescriptorSet); struct TimerQueryVK { TimerQueryVK() - : m_control(kMinTimerQueries) + : m_query(kMinTimerQueries) + , m_control(kMinTimerQueries) { } @@ -644,7 +645,7 @@ VK_DESTROY_FUNC(DescriptorSet); uint64_t m_frequency; TimerResultT m_result; - Query m_query[kMaxTimerQueries]; + TimerQueryArrayT m_query; VkBuffer m_readback; DeviceMemoryAllocationVK m_readbackMemory;