Просмотр исходного кода

Fix a command buffer leak that occurs in dx12

alessand10 8 месяцев назад
Родитель
Сommit
9ea97c017b

+ 17 - 1
drivers/d3d12/rendering_device_driver_d3d12.cpp

@@ -2292,6 +2292,19 @@ bool RenderingDeviceDriverD3D12::command_pool_reset(CommandPoolID p_cmd_pool) {
 
 void RenderingDeviceDriverD3D12::command_pool_free(CommandPoolID p_cmd_pool) {
 	CommandPoolInfo *command_pool = (CommandPoolInfo *)(p_cmd_pool.id);
+
+	// Destroy all command buffers associated with this command pool, mirroring Vulkan's behavior.
+	SelfList<CommandBufferInfo> *cmd_buf_elem = command_pool->command_buffers.first();
+	while (cmd_buf_elem != nullptr) {
+		CommandBufferInfo *cmd_buf_info = cmd_buf_elem->self();
+		cmd_buf_elem = cmd_buf_elem->next();
+
+		cmd_buf_info->cmd_list.Reset();
+		cmd_buf_info->cmd_allocator.Reset();
+
+		VersatileResource::free(resources_allocator, cmd_buf_info);
+	}
+
 	memdelete(command_pool);
 }
 
@@ -2300,7 +2313,7 @@ void RenderingDeviceDriverD3D12::command_pool_free(CommandPoolID p_cmd_pool) {
 RDD::CommandBufferID RenderingDeviceDriverD3D12::command_buffer_create(CommandPoolID p_cmd_pool) {
 	DEV_ASSERT(p_cmd_pool);
 
-	const CommandPoolInfo *command_pool = (CommandPoolInfo *)(p_cmd_pool.id);
+	CommandPoolInfo *command_pool = (CommandPoolInfo *)(p_cmd_pool.id);
 	D3D12_COMMAND_LIST_TYPE list_type;
 	if (command_pool->buffer_type == COMMAND_BUFFER_TYPE_SECONDARY) {
 		list_type = D3D12_COMMAND_LIST_TYPE_BUNDLE;
@@ -2336,6 +2349,9 @@ RDD::CommandBufferID RenderingDeviceDriverD3D12::command_buffer_create(CommandPo
 	cmd_buf_info->cmd_allocator = cmd_allocator;
 	cmd_buf_info->cmd_list = cmd_list;
 
+	// Add this command buffer to the command pool's list of command buffers.
+	command_pool->command_buffers.add(&cmd_buf_info->command_buffer_info_elem);
+
 	return CommandBufferID(cmd_buf_info);
 }
 

+ 6 - 0
drivers/d3d12/rendering_device_driver_d3d12.h

@@ -430,6 +430,9 @@ private:
 	struct CommandPoolInfo {
 		CommandQueueFamilyID queue_family;
 		CommandBufferType buffer_type = COMMAND_BUFFER_TYPE_PRIMARY;
+		// Since there are no command pools in D3D12, we need to track the command buffers created by this pool
+		// so that we can free them when the pool is freed.
+		SelfList<CommandBufferInfo>::List command_buffers;
 	};
 
 public:
@@ -458,6 +461,9 @@ private:
 	// Leveraging knowledge of actual usage and D3D12 specifics (namely, command lists from the same allocator
 	// can't be freely begun and ended), an allocator per list works better.
 	struct CommandBufferInfo {
+		// Store a self list reference to be used by the command pool.
+		SelfList<CommandBufferInfo> command_buffer_info_elem{ this };
+
 		ComPtr<ID3D12CommandAllocator> cmd_allocator;
 		ComPtr<ID3D12GraphicsCommandList> cmd_list;