diff --git a/filament/backend/src/vulkan/VulkanBlitter.cpp b/filament/backend/src/vulkan/VulkanBlitter.cpp index 811daea858..b3a812b1c2 100644 --- a/filament/backend/src/vulkan/VulkanBlitter.cpp +++ b/filament/backend/src/vulkan/VulkanBlitter.cpp @@ -214,8 +214,11 @@ void VulkanBlitter::shutdown() noexcept { delete mDepthResolveProgram; mDepthResolveProgram = nullptr; - delete mTriangleBuffer; - mTriangleBuffer = nullptr; + if (mTriangleBuffer) { + mTriangleBuffer->terminate(mContext); + delete mTriangleBuffer; + mTriangleBuffer = nullptr; + } delete mParamsBuffer; mParamsBuffer = nullptr; @@ -261,7 +264,8 @@ void VulkanBlitter::lazyInit() noexcept { mTriangleBuffer = new VulkanBuffer(mContext, mStagePool, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, sizeof(kTriangleVertices)); - mTriangleBuffer->loadFromCpu(kTriangleVertices, 0, sizeof(kTriangleVertices)); + mTriangleBuffer->loadFromCpu(mContext, mStagePool, + kTriangleVertices, 0, sizeof(kTriangleVertices)); mParamsBuffer = new VulkanUniformBuffer(mContext, mStagePool, sizeof(BlitterUniforms), backend::BufferUsage::STATIC); diff --git a/filament/backend/src/vulkan/VulkanBuffer.cpp b/filament/backend/src/vulkan/VulkanBuffer.cpp index 6417dc8e00..9e4a3c499f 100644 --- a/filament/backend/src/vulkan/VulkanBuffer.cpp +++ b/filament/backend/src/vulkan/VulkanBuffer.cpp @@ -25,7 +25,7 @@ namespace filament { namespace backend { VulkanBuffer::VulkanBuffer(VulkanContext& context, VulkanStagePool& stagePool, - VkBufferUsageFlags usage, uint32_t numBytes) : mContext(context), mStagePool(stagePool) { + VkBufferUsageFlags usage, uint32_t numBytes) { // Create the VkBuffer. VkBufferCreateInfo bufferInfo { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -38,19 +38,27 @@ VulkanBuffer::VulkanBuffer(VulkanContext& context, VulkanStagePool& stagePool, } VulkanBuffer::~VulkanBuffer() { - vmaDestroyBuffer(mContext.allocator, mGpuBuffer, mGpuMemory); + assert_invariant(mGpuMemory == VK_NULL_HANDLE); + assert_invariant(mGpuBuffer == VK_NULL_HANDLE); } -void VulkanBuffer::loadFromCpu(const void* cpuData, uint32_t byteOffset, uint32_t numBytes) const { - assert_invariant(byteOffset == 0); - VulkanStage const* stage = mStagePool.acquireStage(numBytes); - void* mapped; - vmaMapMemory(mContext.allocator, stage->memory, &mapped); - memcpy(mapped, cpuData, numBytes); - vmaUnmapMemory(mContext.allocator, stage->memory); - vmaFlushAllocation(mContext.allocator, stage->memory, byteOffset, numBytes); +void VulkanBuffer::terminate(VulkanContext& context) { + vmaDestroyBuffer(context.allocator, mGpuBuffer, mGpuMemory); + mGpuMemory = VK_NULL_HANDLE; + mGpuBuffer = VK_NULL_HANDLE; +} - const VkCommandBuffer cmdbuffer = mContext.commands->get().cmdbuffer; +void VulkanBuffer::loadFromCpu(VulkanContext& context, VulkanStagePool& stagePool, + const void* cpuData, uint32_t byteOffset, uint32_t numBytes) const { + assert_invariant(byteOffset == 0); + VulkanStage const* stage = stagePool.acquireStage(numBytes); + void* mapped; + vmaMapMemory(context.allocator, stage->memory, &mapped); + memcpy(mapped, cpuData, numBytes); + vmaUnmapMemory(context.allocator, stage->memory); + vmaFlushAllocation(context.allocator, stage->memory, byteOffset, numBytes); + + const VkCommandBuffer cmdbuffer = context.commands->get().cmdbuffer; VkBufferCopy region { .size = numBytes }; vkCmdCopyBuffer(cmdbuffer, stage->buffer, mGpuBuffer, 1, ®ion); diff --git a/filament/backend/src/vulkan/VulkanBuffer.h b/filament/backend/src/vulkan/VulkanBuffer.h index 33fad3447d..be8bc5fa0a 100644 --- a/filament/backend/src/vulkan/VulkanBuffer.h +++ b/filament/backend/src/vulkan/VulkanBuffer.h @@ -29,11 +29,11 @@ public: VulkanBuffer(VulkanContext& context, VulkanStagePool& stagePool, VkBufferUsageFlags usage, uint32_t numBytes); ~VulkanBuffer(); - void loadFromCpu(const void* cpuData, uint32_t byteOffset, uint32_t numBytes) const; + void terminate(VulkanContext& context); + void loadFromCpu(VulkanContext& context, VulkanStagePool& stagePool, + const void* cpuData, uint32_t byteOffset, uint32_t numBytes) const; VkBuffer getGpuBuffer() const { return mGpuBuffer; } private: - VulkanContext& mContext; - VulkanStagePool& mStagePool; VmaAllocation mGpuMemory = VK_NULL_HANDLE; VkBuffer mGpuBuffer = VK_NULL_HANDLE; }; diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index d81debc996..e9bd82a18c 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -454,8 +454,8 @@ void VulkanDriver::createIndexBufferR(Handle ibh, auto elementSize = (uint8_t) getElementTypeSize(elementType); auto indexBuffer = construct_handle(mHandleMap, ibh, mContext, mStagePool, elementSize, indexCount); - mDisposer.createDisposable(indexBuffer, [this, ibh] () { - destruct_handle(mHandleMap, ibh); + mDisposer.createDisposable(indexBuffer, [this, ibh]() { + destruct_handle(mContext, mHandleMap, ibh); }); } @@ -470,8 +470,8 @@ void VulkanDriver::createBufferObjectR(Handle boh, uint32_t byteCount, BufferObjectBinding bindingType, BufferUsage usage) { auto bufferObject = construct_handle(mHandleMap, boh, mContext, mStagePool, byteCount, bindingType, usage); - mDisposer.createDisposable(bufferObject, [this, boh] () { - destruct_handle(mHandleMap, boh); + mDisposer.createDisposable(bufferObject, [this, boh]() { + destruct_handle(mContext, mHandleMap, boh); }); } @@ -859,7 +859,7 @@ void VulkanDriver::setVertexBufferObject(Handle vbh, uint32_t in void VulkanDriver::updateIndexBuffer(Handle ibh, BufferDescriptor&& p, uint32_t byteOffset) { auto ib = handle_cast(mHandleMap, ibh); - ib->buffer.loadFromCpu(p.buffer, byteOffset, p.size); + ib->buffer.loadFromCpu(mContext, mStagePool, p.buffer, byteOffset, p.size); mDisposer.acquire(ib); scheduleDestroy(std::move(p)); } @@ -867,7 +867,7 @@ void VulkanDriver::updateIndexBuffer(Handle ibh, BufferDescriptor void VulkanDriver::updateBufferObject(Handle boh, BufferDescriptor&& bd, uint32_t byteOffset) { auto bo = handle_cast(mHandleMap, boh); - bo->buffer.loadFromCpu(bd.buffer, byteOffset, bd.size); + bo->buffer.loadFromCpu(mContext, mStagePool, bd.buffer, byteOffset, bd.size); mDisposer.acquire(bo); scheduleDestroy(std::move(bd)); } diff --git a/filament/backend/src/vulkan/VulkanDriver.h b/filament/backend/src/vulkan/VulkanDriver.h index 5fea1339ca..d5f4de7f13 100644 --- a/filament/backend/src/vulkan/VulkanDriver.h +++ b/filament/backend/src/vulkan/VulkanDriver.h @@ -144,6 +144,21 @@ private: handleMap.erase(handle.getId()); } + // This version of destruct_handle take a VulkanContext and calls a terminate(VulkanContext&) + // on the handle before calling the dtor + template + void destruct_handle(VulkanContext& context, HandleMap& handleMap, const Handle& handle) noexcept { + std::lock_guard lock(mHandleMapMutex); + // Call the destructor, remove the blob, don't bother reclaiming the integer id. + auto iter = handleMap.find(handle.getId()); + assert_invariant(iter != handleMap.end()); + Blob& blob = iter->second; + assert_invariant(blob.size() == sizeof(Dp)); + reinterpret_cast(blob.data())->terminate(context); + reinterpret_cast(blob.data())->~Dp(); + handleMap.erase(handle.getId()); + } + void refreshSwapChain(); void collectGarbage(); diff --git a/filament/backend/src/vulkan/VulkanHandles.h b/filament/backend/src/vulkan/VulkanHandles.h index 5a613e07bb..e7ca2cc772 100644 --- a/filament/backend/src/vulkan/VulkanHandles.h +++ b/filament/backend/src/vulkan/VulkanHandles.h @@ -90,15 +90,17 @@ struct VulkanIndexBuffer : public HwIndexBuffer { buffer(context, stagePool, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, elementSize * indexCount), indexType(elementSize == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32) {} - const VulkanBuffer buffer; + void terminate(VulkanContext& context) { buffer.terminate(context); } + VulkanBuffer buffer; const VkIndexType indexType; }; struct VulkanBufferObject : public HwBufferObject { VulkanBufferObject(VulkanContext& context, VulkanStagePool& stagePool, uint32_t byteCount, BufferObjectBinding bindingType, BufferUsage usage); - const VulkanBuffer buffer; - BufferObjectBinding bindingType; + void terminate(VulkanContext& context) { buffer.terminate(context); } + VulkanBuffer buffer; + const BufferObjectBinding bindingType; }; struct VulkanUniformBuffer : public HwUniformBuffer {