diff --git a/include/bgfx.h b/include/bgfx.h index 257086a5..77b551f1 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -278,6 +278,9 @@ namespace bgfx { } + /// + typedef void (*ReleaseFn)(void* _ptr, void* _userData); + /// struct Memory { @@ -604,8 +607,11 @@ namespace bgfx /// Make reference to data to pass to bgfx. Unlike `bgfx::alloc` this call /// doesn't allocate memory for data. It just copies pointer to data. You - /// must make sure data is available for at least 2 `bgfx::frame` calls. - const Memory* makeRef(const void* _data, uint32_t _size); + /// can pass `ReleaseFn` function pointer to release this memory after it's + /// consumed, or you must make sure data is available for at least 2 + /// `bgfx::frame` calls. `ReleaseFn` function must be able to be called + /// called from any thread. + const Memory* makeRef(const void* _data, uint32_t _size, ReleaseFn _releaseFn = NULL, void* _userData = NULL); /// Set debug flags. /// diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 3a353942..03b20e71 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -2099,18 +2099,41 @@ again: return mem; } - const Memory* makeRef(const void* _data, uint32_t _size) + struct MemoryRef { - Memory* mem = (Memory*)BX_ALLOC(g_allocator, sizeof(Memory) ); - mem->size = _size; - mem->data = (uint8_t*)_data; - return mem; + Memory mem; + ReleaseFn releaseFn; + void* userData; + }; + + const Memory* makeRef(const void* _data, uint32_t _size, ReleaseFn _releaseFn, void* _userData) + { + MemoryRef* memRef = (MemoryRef*)BX_ALLOC(g_allocator, sizeof(MemoryRef) ); + memRef->mem.size = _size; + memRef->mem.data = (uint8_t*)_data; + memRef->releaseFn = _releaseFn; + memRef->userData = _userData; + return &memRef->mem; + } + + bool isMemoryRef(const Memory* _mem) + { + return _mem->data != (uint8_t*)_mem + sizeof(Memory); } void release(const Memory* _mem) { BX_CHECK(NULL != _mem, "_mem can't be NULL"); - BX_FREE(g_allocator, const_cast(_mem) ); + Memory* mem = const_cast(_mem); + if (isMemoryRef(mem) ) + { + MemoryRef* memRef = reinterpret_cast(mem); + if (NULL != memRef->releaseFn) + { + memRef->releaseFn(mem->data, memRef->userData); + } + } + BX_FREE(g_allocator, mem); } void setDebug(uint32_t _debug)