From 934034aa4f9865abffcd2bf5d0e6080cf37bd68f Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Mon, 16 Dec 2024 18:37:11 +0100 Subject: [PATCH] encode: Init buffer after binding external memory --- .../decode/vulkan_resource_initializer.cpp | 17 ++- framework/encode/api_capture_manager.h | 16 +++ framework/encode/capture_manager.cpp | 113 ++++++++++++++++++ framework/encode/capture_manager.h | 12 ++ framework/encode/vulkan_capture_manager.cpp | 8 ++ framework/encode/vulkan_capture_manager.h | 33 +++++ framework/encode/vulkan_handle_wrappers.h | 1 + 7 files changed, 197 insertions(+), 3 deletions(-) diff --git a/framework/decode/vulkan_resource_initializer.cpp b/framework/decode/vulkan_resource_initializer.cpp index e554b42bbb..1f2e06c61f 100644 --- a/framework/decode/vulkan_resource_initializer.cpp +++ b/framework/decode/vulkan_resource_initializer.cpp @@ -77,9 +77,20 @@ VulkanResourceInitializer::~VulkanResourceInitializer() resource_allocator_->FreeMemoryDirect(staging_memory_, nullptr, staging_memory_data_); } - device_table_->DestroySampler(device_, draw_sampler_, nullptr); - device_table_->DestroyDescriptorPool(device_, draw_pool_, nullptr); - device_table_->DestroyDescriptorSetLayout(device_, draw_set_layout_, nullptr); + if (draw_sampler_ != VK_NULL_HANDLE) + { + device_table_->DestroySampler(device_, draw_sampler_, nullptr); + } + + if (draw_pool_ != VK_NULL_HANDLE) + { + device_table_->DestroyDescriptorPool(device_, draw_pool_, nullptr); + } + + if (draw_set_layout_ != VK_NULL_HANDLE) + { + device_table_->DestroyDescriptorSetLayout(device_, draw_set_layout_, nullptr); + } } VkResult VulkanResourceInitializer::LoadData(VkDeviceSize size, diff --git a/framework/encode/api_capture_manager.h b/framework/encode/api_capture_manager.h index 9f2e3d177c..4e3b2d3994 100644 --- a/framework/encode/api_capture_manager.h +++ b/framework/encode/api_capture_manager.h @@ -200,6 +200,22 @@ class ApiCaptureManager { common_manager_->WriteFillMemoryCmd(api_family_, memory_id, offset, size, data); } + + void WriteBeginResourceInitCmd(format::HandleId device_id, uint64_t max_resource_size) + { + common_manager_->WriteBeginResourceInitCmd(api_family_, device_id, max_resource_size); + } + + void WriteEndResourceInitCmd(format::HandleId device_id) + { + common_manager_->WriteEndResourceInitCmd(api_family_, device_id); + } + + void WriteInitBufferCmd(format::HandleId device_id, format::HandleId buffer_id, uint64_t offset, uint64_t size, const void* data) + { + common_manager_->WriteInitBufferCmd(api_family_, device_id, buffer_id, offset, size, data); + } + void WriteCreateHeapAllocationCmd(uint64_t allocation_id, uint64_t allocation_size) { common_manager_->WriteCreateHeapAllocationCmd(api_family_, allocation_id, allocation_size); diff --git a/framework/encode/capture_manager.cpp b/framework/encode/capture_manager.cpp index 3296c49a5e..776eaf44c1 100644 --- a/framework/encode/capture_manager.cpp +++ b/framework/encode/capture_manager.cpp @@ -1454,6 +1454,119 @@ void CommonCaptureManager::WriteFillMemoryCmd( } } +void CommonCaptureManager::WriteBeginResourceInitCmd(format::ApiFamilyId api_family, + format::HandleId device_id, + uint64_t max_resource_size) +{ + if ((capture_mode_ & kModeWrite) != kModeWrite) + { + return; + } + + GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, max_resource_size); + + format::BeginResourceInitCommand init_cmd; + + auto thread_data = GetThreadData(); + GFXRECON_ASSERT(thread_data != nullptr); + + init_cmd.meta_header.block_header.type = format::BlockType::kMetaDataBlock; + init_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(init_cmd); + init_cmd.meta_header.meta_data_id = + format::MakeMetaDataId(api_family, format::MetaDataType::kBeginResourceInitCommand); + init_cmd.thread_id = thread_data->thread_id_; + init_cmd.device_id = device_id; + init_cmd.max_resource_size = max_resource_size; + init_cmd.max_copy_size = max_resource_size; + + WriteToFile(&init_cmd, sizeof(init_cmd)); +} + +void CommonCaptureManager::WriteEndResourceInitCmd(format::ApiFamilyId api_family, format::HandleId device_id) +{ + if ((capture_mode_ & kModeWrite) != kModeWrite) + { + return; + } + + format::EndResourceInitCommand init_cmd; + + auto thread_data = GetThreadData(); + GFXRECON_ASSERT(thread_data != nullptr); + + init_cmd.meta_header.block_header.type = format::BlockType::kMetaDataBlock; + init_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(init_cmd); + init_cmd.meta_header.meta_data_id = + format::MakeMetaDataId(api_family, format::MetaDataType::kEndResourceInitCommand); + init_cmd.thread_id = thread_data->thread_id_; + init_cmd.device_id = device_id; + + WriteToFile(&init_cmd, sizeof(init_cmd)); +} + +void CommonCaptureManager::WriteInitBufferCmd(format::ApiFamilyId api_family, + format::HandleId device_id, + format::HandleId buffer_id, + uint64_t offset, + uint64_t size, + const void* data) +{ + if ((capture_mode_ & kModeWrite) != kModeWrite) + { + return; + } + + GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, size); + + format::InitBufferCommandHeader init_cmd; + size_t header_size = sizeof(format::InitBufferCommandHeader); + const uint8_t* uncompressed_data = (static_cast(data) + offset); + size_t uncompressed_size = static_cast(size); + + auto thread_data = GetThreadData(); + assert(thread_data != nullptr); + + init_cmd.meta_header.block_header.type = format::BlockType::kMetaDataBlock; + init_cmd.meta_header.meta_data_id = format::MakeMetaDataId(api_family, format::MetaDataType::kInitBufferCommand); + init_cmd.thread_id = thread_data->thread_id_; + init_cmd.device_id = device_id; + init_cmd.buffer_id = buffer_id; + init_cmd.data_size = size; + + bool not_compressed = true; + + if (compressor_ != nullptr) + { + size_t compressed_size = + compressor_->Compress(uncompressed_size, uncompressed_data, &thread_data->compressed_buffer_, header_size); + + if ((compressed_size > 0) && (compressed_size < uncompressed_size)) + { + not_compressed = false; + + // We don't have a special header for compressed fill commands because the header always includes + // the uncompressed size, so we just change the type to indicate the data is compressed. + init_cmd.meta_header.block_header.type = format::BlockType::kCompressedMetaDataBlock; + + // Calculate size of packet with uncompressed data size. + init_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(init_cmd) + compressed_size; + + // Copy header to beginning of compressed_buffer_ + util::platform::MemoryCopy(thread_data->compressed_buffer_.data(), header_size, &init_cmd, header_size); + + WriteToFile(thread_data->compressed_buffer_.data(), header_size + compressed_size); + } + } + + if (not_compressed) + { + // Calculate size of packet with compressed data size. + init_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(init_cmd) + uncompressed_size; + + CombineAndWriteToFile({ { &init_cmd, header_size }, { uncompressed_data, uncompressed_size } }); + } +} + void CommonCaptureManager::WriteCreateHeapAllocationCmd(format::ApiFamilyId api_family, uint64_t allocation_id, uint64_t allocation_size) diff --git a/framework/encode/capture_manager.h b/framework/encode/capture_manager.h index db09c8c58a..89ce04ede0 100644 --- a/framework/encode/capture_manager.h +++ b/framework/encode/capture_manager.h @@ -301,6 +301,18 @@ class CommonCaptureManager void WriteFillMemoryCmd( format::ApiFamilyId api_family, format::HandleId memory_id, uint64_t offset, uint64_t size, const void* data); + void + WriteBeginResourceInitCmd(format::ApiFamilyId api_family, format::HandleId device_id, uint64_t max_resource_size); + + void WriteEndResourceInitCmd(format::ApiFamilyId api_family, format::HandleId device_id); + + void WriteInitBufferCmd(format::ApiFamilyId api_family, + format::HandleId device_id, + format::HandleId buffer_id, + uint64_t offset, + uint64_t size, + const void* data); + void WriteCreateHeapAllocationCmd(format::ApiFamilyId api_family, uint64_t allocation_id, uint64_t allocation_size); void WriteToFile(const void* data, size_t size, util::FileOutputStream* file_stream = nullptr); diff --git a/framework/encode/vulkan_capture_manager.cpp b/framework/encode/vulkan_capture_manager.cpp index 6d8663d6fc..5ecd688551 100644 --- a/framework/encode/vulkan_capture_manager.cpp +++ b/framework/encode/vulkan_capture_manager.cpp @@ -1087,6 +1087,14 @@ VkResult VulkanCaptureManager::OverrideAllocateMemory(VkDevice } } #endif + + if (auto import_memfd = graphics::vulkan_struct_get_pnext(pAllocateInfo_unwrapped)) + { + if (import_memfd->fd >= 0) + { + memory_wrapper->imported_fd = import_memfd->fd; + } + } } else if (external_memory != nullptr) { diff --git a/framework/encode/vulkan_capture_manager.h b/framework/encode/vulkan_capture_manager.h index 02cbae96d0..ead28674b8 100644 --- a/framework/encode/vulkan_capture_manager.h +++ b/framework/encode/vulkan_capture_manager.h @@ -777,6 +777,39 @@ class VulkanCaptureManager : public ApiCaptureManager assert(state_tracker_ != nullptr); state_tracker_->TrackBufferMemoryBinding(device, buffer, memory, memoryOffset); } + else if (IsCaptureModeWrite() && (result == VK_SUCCESS)) + { + auto* device_wrapper = vulkan_wrappers::GetWrapper(device); + auto* buffer_wrapper = vulkan_wrappers::GetWrapper(buffer); + auto* memory_wrapper = vulkan_wrappers::GetWrapper(memory); + + if (memory_wrapper->imported_fd >= 0) + { + // create staging buffer, bind this memory, write init buffer command + graphics::VulkanResourcesUtil resource_util(device_wrapper->handle, + device_wrapper->physical_device->handle, + device_wrapper->layer_table, + *device_wrapper->physical_device->layer_table_ref, + device_wrapper->physical_device->memory_properties); + VkResult staging_result = resource_util.CreateStagingBuffer(buffer_wrapper->size); + if (staging_result == VK_SUCCESS) + { + std::vector data; + staging_result = resource_util.ReadFromBufferResource( + buffer, buffer_wrapper->size, memoryOffset, buffer_wrapper->queue_family_index, data); + if (staging_result == VK_SUCCESS) + { + WriteBeginResourceInitCmd(device_wrapper->handle_id, buffer_wrapper->size); + WriteInitBufferCmd(device_wrapper->handle_id, + buffer_wrapper->handle_id, + memoryOffset, + buffer_wrapper->size, + data.data()); + WriteEndResourceInitCmd(device_wrapper->handle_id); + } + } + } + } } void PostProcess_vkBindBufferMemory2(VkResult result, diff --git a/framework/encode/vulkan_handle_wrappers.h b/framework/encode/vulkan_handle_wrappers.h index 2d49eecd43..595a2813b7 100644 --- a/framework/encode/vulkan_handle_wrappers.h +++ b/framework/encode/vulkan_handle_wrappers.h @@ -253,6 +253,7 @@ struct DeviceMemoryWrapper : public HandleWrapper uintptr_t shadow_allocation{ util::PageGuardManager::kNullShadowHandle }; AHardwareBuffer* hardware_buffer{ nullptr }; format::HandleId hardware_buffer_memory_id{ format::kNullHandleId }; + int imported_fd{ -1 }; // State tracking info for memory with device addresses. format::HandleId device_id{ format::kNullHandleId };