From 3de816bf34bbd74e8dc5637abce41b21403d267d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Wed, 28 Jan 2015 17:56:29 -0800 Subject: [PATCH] Added dynamic buffer resizing. --- include/bgfx.h | 10 +-- include/bgfxdefines.h | 3 +- src/bgfx.cpp | 7 +- src/bgfx_p.h | 173 ++++++++++++++++++++++++++++++------------ 4 files changed, 138 insertions(+), 55 deletions(-) diff --git a/include/bgfx.h b/include/bgfx.h index 8a01ff61..58f9a281 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -615,7 +615,7 @@ namespace bgfx /// @remarks /// Only 16-bit index buffer is supported. /// - IndexBufferHandle createIndexBuffer(const Memory* _mem, uint8_t _flags = BGFX_BUFFER_COMPUTE_NONE); + IndexBufferHandle createIndexBuffer(const Memory* _mem, uint8_t _flags = BGFX_BUFFER_NONE); /// Destroy static index buffer. void destroyIndexBuffer(IndexBufferHandle _handle); @@ -626,7 +626,7 @@ namespace bgfx /// @param _decl Vertex declaration. /// @returns Static vertex buffer handle. /// - VertexBufferHandle createVertexBuffer(const Memory* _mem, const VertexDecl& _decl, uint8_t _flags = BGFX_BUFFER_COMPUTE_NONE); + VertexBufferHandle createVertexBuffer(const Memory* _mem, const VertexDecl& _decl, uint8_t _flags = BGFX_BUFFER_NONE); /// Destroy static vertex buffer. /// @@ -642,7 +642,7 @@ namespace bgfx /// @remarks /// Only 16-bit index buffer is supported. /// - DynamicIndexBufferHandle createDynamicIndexBuffer(uint32_t _num, uint8_t _flags = BGFX_BUFFER_COMPUTE_NONE); + DynamicIndexBufferHandle createDynamicIndexBuffer(uint32_t _num, uint8_t _flags = BGFX_BUFFER_NONE); /// Create dynamic index buffer and initialized it. /// @@ -651,7 +651,7 @@ namespace bgfx /// @remarks /// Only 16-bit index buffer is supported. /// - DynamicIndexBufferHandle createDynamicIndexBuffer(const Memory* _mem); + DynamicIndexBufferHandle createDynamicIndexBuffer(const Memory* _mem, uint8_t _flags = BGFX_BUFFER_NONE); /// Update dynamic index buffer. /// @@ -672,7 +672,7 @@ namespace bgfx /// @param _decl Vertex declaration. /// @param _flags `BGFX_BUFFER_*` flags. /// - DynamicVertexBufferHandle createDynamicVertexBuffer(uint16_t _num, const VertexDecl& _decl, uint8_t _flags = BGFX_BUFFER_COMPUTE_NONE); + DynamicVertexBufferHandle createDynamicVertexBuffer(uint16_t _num, const VertexDecl& _decl, uint8_t _flags = BGFX_BUFFER_NONE); /// Create dynamic vertex buffer and initialize it. /// diff --git a/include/bgfxdefines.h b/include/bgfxdefines.h index e4650b9e..ec652508 100644 --- a/include/bgfxdefines.h +++ b/include/bgfxdefines.h @@ -221,9 +221,10 @@ #define BGFX_DEBUG_TEXT UINT32_C(0x00000008) /// -#define BGFX_BUFFER_COMPUTE_NONE UINT8_C(0x00) +#define BGFX_BUFFER_NONE UINT8_C(0x00) #define BGFX_BUFFER_COMPUTE_READ UINT8_C(0x01) #define BGFX_BUFFER_COMPUTE_WRITE UINT8_C(0x02) +#define BGFX_BUFFER_ALLOW_RESIZE UINT8_C(0x04) #define BGFX_BUFFER_COMPUTE_READ_WRITE (BGFX_BUFFER_COMPUTE_READ | BGFX_BUFFER_COMPUTE_WRITE) /// diff --git a/src/bgfx.cpp b/src/bgfx.cpp index ba4ae8aa..ea0de73a 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -1014,6 +1014,9 @@ namespace bgfx getCommandBuffer(CommandBuffer::RendererShutdownEnd); frame(); + m_dynVertexBufferAllocator.compact(); + m_dynIndexBufferAllocator.compact(); + m_declRef.shutdown(m_vertexDeclHandle); #if BGFX_CONFIG_MULTITHREADED @@ -2121,11 +2124,11 @@ again: return s_ctx->createDynamicIndexBuffer(_num, _flags); } - DynamicIndexBufferHandle createDynamicIndexBuffer(const Memory* _mem) + DynamicIndexBufferHandle createDynamicIndexBuffer(const Memory* _mem, uint8_t _flags) { BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); - return s_ctx->createDynamicIndexBuffer(_mem); + return s_ctx->createDynamicIndexBuffer(_mem, _flags); } void updateDynamicIndexBuffer(DynamicIndexBufferHandle _handle, const Memory* _mem) diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 99bc3ec9..709e59b5 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -1180,6 +1180,7 @@ namespace bgfx uint32_t m_offset; uint32_t m_size; uint32_t m_startIndex; + uint8_t m_flags; }; struct DynamicVertexBuffer @@ -2014,46 +2015,57 @@ namespace bgfx m_vertexBufferHandle.free(_handle.idx); } + uint64_t allocDynamicIndexBuffer(uint32_t _size, uint8_t _flags) + { + uint64_t ptr = m_dynIndexBufferAllocator.alloc(_size); + if (ptr == NonLocalAllocator::invalidBlock) + { + IndexBufferHandle indexBufferHandle = { m_indexBufferHandle.alloc() }; + BX_WARN(isValid(indexBufferHandle), "Failed to allocate index buffer handle."); + if (!isValid(indexBufferHandle)) + { + return ptr; + } + + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicIndexBuffer); + cmdbuf.write(indexBufferHandle); + cmdbuf.write(BGFX_CONFIG_DYNAMIC_INDEX_BUFFER_SIZE); + cmdbuf.write(_flags); + + m_dynIndexBufferAllocator.add(uint64_t(indexBufferHandle.idx) << 32, BGFX_CONFIG_DYNAMIC_INDEX_BUFFER_SIZE); + ptr = m_dynIndexBufferAllocator.alloc(_size); + } + + return ptr; + } + BGFX_API_FUNC(DynamicIndexBufferHandle createDynamicIndexBuffer(uint32_t _num, uint8_t _flags) ) { DynamicIndexBufferHandle handle = BGFX_INVALID_HANDLE; uint32_t size = BX_ALIGN_16( (_num+1)*2); uint64_t ptr = 0; - if (0 != (_flags & BGFX_BUFFER_COMPUTE_WRITE)) + if (0 != (_flags & BGFX_BUFFER_COMPUTE_WRITE) ) { - VertexBufferHandle vertexBufferHandle = { m_vertexBufferHandle.alloc() }; - if (!isValid(vertexBufferHandle)) + IndexBufferHandle indexBufferHandle = { m_indexBufferHandle.alloc() }; + if (!isValid(indexBufferHandle)) { return handle; } - CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicVertexBuffer); - cmdbuf.write(vertexBufferHandle); + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicIndexBuffer); + cmdbuf.write(indexBufferHandle); cmdbuf.write(size); cmdbuf.write(_flags); - ptr = uint64_t(vertexBufferHandle.idx) << 32; + ptr = uint64_t(indexBufferHandle.idx) << 32; } else { - ptr = m_dynIndexBufferAllocator.alloc(size); + ptr = allocDynamicIndexBuffer(size, _flags); if (ptr == NonLocalAllocator::invalidBlock) { - IndexBufferHandle indexBufferHandle = { m_indexBufferHandle.alloc() }; - BX_WARN(isValid(indexBufferHandle), "Failed to allocate index buffer handle."); - if (!isValid(indexBufferHandle)) - { - return handle; - } - - CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicIndexBuffer); - cmdbuf.write(indexBufferHandle); - cmdbuf.write(BGFX_CONFIG_DYNAMIC_INDEX_BUFFER_SIZE); - cmdbuf.write(_flags); - - m_dynIndexBufferAllocator.add(uint64_t(indexBufferHandle.idx) << 32, BGFX_CONFIG_DYNAMIC_INDEX_BUFFER_SIZE); - ptr = m_dynIndexBufferAllocator.alloc(size); + return handle; } } @@ -2069,13 +2081,15 @@ namespace bgfx dib.m_offset = uint32_t(ptr); dib.m_size = size; dib.m_startIndex = strideAlign(dib.m_offset, 2)/2; + dib.m_flags = _flags; return handle; } - BGFX_API_FUNC(DynamicIndexBufferHandle createDynamicIndexBuffer(const Memory* _mem) ) + BGFX_API_FUNC(DynamicIndexBufferHandle createDynamicIndexBuffer(const Memory* _mem, uint8_t _flags) ) { - DynamicIndexBufferHandle handle = createDynamicIndexBuffer(_mem->size/2, BGFX_BUFFER_COMPUTE_NONE); + BX_CHECK(0 == (_flags & BGFX_BUFFER_COMPUTE_READ_WRITE), "Cannot initialize compute buffer from CPU."); + DynamicIndexBufferHandle handle = createDynamicIndexBuffer(_mem->size/2, _flags); if (isValid(handle) ) { updateDynamicIndexBuffer(handle, _mem); @@ -2086,10 +2100,31 @@ namespace bgfx BGFX_API_FUNC(void updateDynamicIndexBuffer(DynamicIndexBufferHandle _handle, const Memory* _mem) ) { DynamicIndexBuffer& dib = m_dynamicIndexBuffers[_handle.idx]; + BX_CHECK(0 == (dib.m_flags & BGFX_BUFFER_COMPUTE_READ_WRITE), "Can't update GPU buffer from CPU."); + + if (dib.m_size < _mem->size + && 0 != (dib.m_flags & BGFX_BUFFER_ALLOW_RESIZE) ) + { + m_dynIndexBufferAllocator.free(uint64_t(dib.m_handle.idx)<<32 | dib.m_offset); + m_dynIndexBufferAllocator.compact(); + + uint64_t ptr = allocDynamicIndexBuffer(_mem->size, dib.m_flags); + dib.m_handle.idx = uint16_t(ptr>>32); + dib.m_offset = uint32_t(ptr); + dib.m_size = _mem->size; + dib.m_startIndex = strideAlign(dib.m_offset, 2)/2; + } + + uint32_t offset = dib.m_startIndex*2; + uint32_t size = bx::uint32_min(dib.m_size, _mem->size); + BX_CHECK(_mem->size <= size, "Truncating dynamic index buffer update (size %d, mem size %d)." + , size + , _mem->size + ); CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::UpdateDynamicIndexBuffer); cmdbuf.write(dib.m_handle); - cmdbuf.write(dib.m_startIndex*2); - cmdbuf.write(dib.m_size); + cmdbuf.write(offset); + cmdbuf.write(size); cmdbuf.write(_mem); } @@ -2101,10 +2136,45 @@ namespace bgfx void destroyDynamicIndexBufferInternal(DynamicIndexBufferHandle _handle) { DynamicIndexBuffer& dib = m_dynamicIndexBuffers[_handle.idx]; - m_dynIndexBufferAllocator.free(uint64_t(dib.m_handle.idx)<<32 | dib.m_offset); + + if (0 != (dib.m_flags & BGFX_BUFFER_COMPUTE_WRITE) ) + { + destroyIndexBuffer(dib.m_handle); + } + else + { + m_dynIndexBufferAllocator.free(uint64_t(dib.m_handle.idx)<<32 | dib.m_offset); + m_dynIndexBufferAllocator.compact(); + } + m_dynamicIndexBufferHandle.free(_handle.idx); } + uint64_t allocDynamicVertexBuffer(uint32_t _size, uint8_t _flags) + { + uint64_t ptr = m_dynVertexBufferAllocator.alloc(_size); + if (ptr == NonLocalAllocator::invalidBlock) + { + VertexBufferHandle vertexBufferHandle = { m_vertexBufferHandle.alloc() }; + + BX_WARN(isValid(vertexBufferHandle), "Failed to allocate dynamic vertex buffer handle."); + if (!isValid(vertexBufferHandle) ) + { + return NonLocalAllocator::invalidBlock; + } + + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicVertexBuffer); + cmdbuf.write(vertexBufferHandle); + cmdbuf.write(BGFX_CONFIG_DYNAMIC_VERTEX_BUFFER_SIZE); + cmdbuf.write(_flags); + + m_dynVertexBufferAllocator.add(uint64_t(vertexBufferHandle.idx)<<32, BGFX_CONFIG_DYNAMIC_VERTEX_BUFFER_SIZE); + ptr = m_dynVertexBufferAllocator.alloc(_size); + } + + return ptr; + } + BGFX_API_FUNC(DynamicVertexBufferHandle createDynamicVertexBuffer(uint16_t _num, const VertexDecl& _decl, uint8_t _flags) ) { DynamicVertexBufferHandle handle = BGFX_INVALID_HANDLE; @@ -2128,24 +2198,10 @@ namespace bgfx } else { - ptr = m_dynVertexBufferAllocator.alloc(size); + ptr = allocDynamicVertexBuffer(size, _flags); if (ptr == NonLocalAllocator::invalidBlock) { - VertexBufferHandle vertexBufferHandle = { m_vertexBufferHandle.alloc() }; - - BX_WARN(isValid(vertexBufferHandle), "Failed to allocate dynamic vertex buffer handle."); - if (!isValid(vertexBufferHandle) ) - { - return handle; - } - - CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicVertexBuffer); - cmdbuf.write(vertexBufferHandle); - cmdbuf.write(BGFX_CONFIG_DYNAMIC_VERTEX_BUFFER_SIZE); - cmdbuf.write(_flags); - - m_dynVertexBufferAllocator.add(uint64_t(vertexBufferHandle.idx)<<32, BGFX_CONFIG_DYNAMIC_VERTEX_BUFFER_SIZE); - ptr = m_dynVertexBufferAllocator.alloc(size); + return handle; } } @@ -2170,7 +2226,7 @@ namespace bgfx { uint32_t numVertices = _mem->size/_decl.m_stride; BX_CHECK(numVertices <= UINT16_MAX, "Num vertices exceeds maximum (num %d, max %d).", numVertices, UINT16_MAX); - DynamicVertexBufferHandle handle = createDynamicVertexBuffer(uint16_t(numVertices), _decl, BGFX_BUFFER_COMPUTE_NONE); + DynamicVertexBufferHandle handle = createDynamicVertexBuffer(uint16_t(numVertices), _decl, BGFX_BUFFER_NONE); if (isValid(handle) ) { updateDynamicVertexBuffer(handle, _mem); @@ -2181,11 +2237,32 @@ namespace bgfx BGFX_API_FUNC(void updateDynamicVertexBuffer(DynamicVertexBufferHandle _handle, const Memory* _mem) ) { DynamicVertexBuffer& dvb = m_dynamicVertexBuffers[_handle.idx]; - BX_CHECK(!dvb.m_flags, "Can't update GPU buffer from CPU."); + BX_CHECK(0 == (dvb.m_flags & BGFX_BUFFER_COMPUTE_READ_WRITE), "Can't update GPU buffer from CPU."); + + if (dvb.m_size < _mem->size + && 0 != (dvb.m_flags & BGFX_BUFFER_ALLOW_RESIZE) ) + { + m_dynVertexBufferAllocator.free(uint64_t(dvb.m_handle.idx)<<32 | dvb.m_offset); + m_dynVertexBufferAllocator.compact(); + + uint64_t ptr = allocDynamicVertexBuffer(_mem->size, dvb.m_flags); + dvb.m_handle.idx = uint16_t(ptr>>32); + dvb.m_offset = uint32_t(ptr); + dvb.m_size = _mem->size; + dvb.m_startVertex = strideAlign(dvb.m_offset, dvb.m_stride)/dvb.m_stride; + } + + uint32_t offset = dvb.m_startVertex*dvb.m_stride; + uint32_t size = bx::uint32_min(dvb.m_size, _mem->size); + BX_CHECK(_mem->size <= size, "Truncating dynamic vertex buffer update (size %d, mem size %d)." + , dvb.m_size + , _mem->size + ); + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::UpdateDynamicVertexBuffer); cmdbuf.write(dvb.m_handle); - cmdbuf.write(dvb.m_startVertex*dvb.m_stride); - cmdbuf.write(dvb.m_size); + cmdbuf.write(offset); + cmdbuf.write(size); cmdbuf.write(_mem); } @@ -2212,7 +2289,9 @@ namespace bgfx else { m_dynVertexBufferAllocator.free(uint64_t(dvb.m_handle.idx)<<32 | dvb.m_offset); + m_dynVertexBufferAllocator.compact(); } + m_dynamicVertexBufferHandle.free(_handle.idx); } @@ -2237,7 +2316,7 @@ namespace bgfx CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicIndexBuffer); cmdbuf.write(handle); cmdbuf.write(_size); - cmdbuf.write(uint8_t(BGFX_BUFFER_COMPUTE_NONE) ); + cmdbuf.write(uint8_t(BGFX_BUFFER_NONE) ); ib = (TransientIndexBuffer*)BX_ALLOC(g_allocator, sizeof(TransientIndexBuffer)+_size); ib->data = (uint8_t*)&ib[1];