From 7ab7855a5d5d421e4c0df32338b91548ea7593eb Mon Sep 17 00:00:00 2001 From: ziga-lunarg Date: Tue, 15 Oct 2024 20:44:44 +0200 Subject: [PATCH 01/16] Add support for copying ahb without cpu read mask --- framework/decode/api_decoder.h | 2 + framework/decode/custom_ags_decoder.h | 2 + framework/decode/dx12_decoder_base.cpp | 4 +- framework/decode/dx12_decoder_base.h | 2 + framework/decode/file_processor.cpp | 79 +++ framework/decode/info_decoder.h | 2 + framework/decode/metadata_consumer_base.h | 4 +- framework/decode/metadata_json_consumer.h | 6 +- framework/decode/stat_decoder_base.h | 2 + framework/decode/vulkan_cpp_consumer_base.cpp | 2 + framework/decode/vulkan_cpp_consumer_base.h | 4 +- framework/decode/vulkan_decoder_base.cpp | 4 +- framework/decode/vulkan_decoder_base.h | 2 + .../decode/vulkan_replay_consumer_base.cpp | 556 +++++++++++++++-- .../decode/vulkan_replay_consumer_base.h | 6 +- framework/encode/vulkan_capture_common.cpp | 580 +++++++++++++++++- framework/encode/vulkan_capture_common.h | 20 +- framework/encode/vulkan_capture_manager.cpp | 5 +- framework/encode/vulkan_handle_wrappers.h | 1 + framework/encode/vulkan_state_writer.cpp | 1 + framework/format/format.h | 84 ++- 21 files changed, 1255 insertions(+), 113 deletions(-) diff --git a/framework/decode/api_decoder.h b/framework/decode/api_decoder.h index 3ae8f524e6..475e04f2fd 100644 --- a/framework/decode/api_decoder.h +++ b/framework/decode/api_decoder.h @@ -106,6 +106,8 @@ class ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/custom_ags_decoder.h b/framework/decode/custom_ags_decoder.h index 8b59257c51..aadb575364 100644 --- a/framework/decode/custom_ags_decoder.h +++ b/framework/decode/custom_ags_decoder.h @@ -80,6 +80,8 @@ class AgsDecoder : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/dx12_decoder_base.cpp b/framework/decode/dx12_decoder_base.cpp index c84f9dbf7b..f20636a030 100644 --- a/framework/decode/dx12_decoder_base.cpp +++ b/framework/decode/dx12_decoder_base.cpp @@ -109,6 +109,8 @@ void Dx12DecoderBase::DispatchResizeWindowCommand2( void Dx12DecoderBase::DispatchCreateHardwareBufferCommand( format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, @@ -124,7 +126,7 @@ void Dx12DecoderBase::DispatchCreateHardwareBufferCommand( for (auto consumer : consumers_) { consumer->ProcessCreateHardwareBufferCommand( - memory_id, buffer_id, format, width, height, stride, usage, layers, plane_info); + device_id, queue_id, memory_id, buffer_id, format, width, height, stride, usage, layers, plane_info); } } diff --git a/framework/decode/dx12_decoder_base.h b/framework/decode/dx12_decoder_base.h index 63b0261b22..5c9f8f5a21 100644 --- a/framework/decode/dx12_decoder_base.h +++ b/framework/decode/dx12_decoder_base.h @@ -125,6 +125,8 @@ class Dx12DecoderBase : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/file_processor.cpp b/framework/decode/file_processor.cpp index 9c219171df..706547300d 100644 --- a/framework/decode/file_processor.cpp +++ b/framework/decode/file_processor.cpp @@ -1098,6 +1098,81 @@ bool FileProcessor::ProcessMetaData(const format::BlockHeader& block_header, for if (decoder->SupportsMetaDataId(meta_data_id)) { decoder->DispatchCreateHardwareBufferCommand(header.thread_id, + 0u, + 0u, + header.memory_id, + header.buffer_id, + header.format, + header.width, + header.height, + header.stride, + header.usage, + header.layers, + entries); + } + } + } + else + { + if (format::IsBlockCompressed(block_header.type)) + { + HandleBlockReadError(kErrorReadingCompressedBlockData, + "Failed to read create hardware buffer meta-data block"); + } + else + { + HandleBlockReadError(kErrorReadingBlockData, + "Failed to read create hardware buffer meta-data block"); + } + } + } + else + { + HandleBlockReadError(kErrorReadingBlockHeader, + "Failed to read create hardware buffer meta-data block header"); + } + } + else if (meta_data_type == format::MetaDataType::kCreateHardwareBufferCommand_deprecated2) + { + format::CreateHardwareBufferCommandHeader_deprecated2 header; + + success = ReadBytes(&header.thread_id, sizeof(header.thread_id)); + success = success && ReadBytes(&header.memory_id, sizeof(header.memory_id)); + success = success && ReadBytes(&header.buffer_id, sizeof(header.buffer_id)); + success = success && ReadBytes(&header.format, sizeof(header.format)); + success = success && ReadBytes(&header.width, sizeof(header.width)); + success = success && ReadBytes(&header.height, sizeof(header.height)); + success = success && ReadBytes(&header.stride, sizeof(header.stride)); + success = success && ReadBytes(&header.usage, sizeof(header.usage)); + success = success && ReadBytes(&header.layers, sizeof(header.layers)); + success = success && ReadBytes(&header.planes, sizeof(header.planes)); + + if (success) + { + std::vector entries; + + for (uint64_t i = 0; i < header.planes; ++i) + { + format::HardwareBufferPlaneInfo entry; + + if (!ReadBytes(&entry, sizeof(entry))) + { + success = false; + break; + } + + entries.emplace_back(std::move(entry)); + } + + if (success) + { + for (auto decoder : decoders_) + { + if (decoder->SupportsMetaDataId(meta_data_id)) + { + decoder->DispatchCreateHardwareBufferCommand(header.thread_id, + 0u, + 0u, header.memory_id, header.buffer_id, header.format, @@ -1135,6 +1210,8 @@ bool FileProcessor::ProcessMetaData(const format::BlockHeader& block_header, for format::CreateHardwareBufferCommandHeader header; success = ReadBytes(&header.thread_id, sizeof(header.thread_id)); + success = success && ReadBytes(&header.device_id, sizeof(header.device_id)); + success = success && ReadBytes(&header.queue_id, sizeof(header.queue_id)); success = success && ReadBytes(&header.memory_id, sizeof(header.memory_id)); success = success && ReadBytes(&header.buffer_id, sizeof(header.buffer_id)); success = success && ReadBytes(&header.format, sizeof(header.format)); @@ -1169,6 +1246,8 @@ bool FileProcessor::ProcessMetaData(const format::BlockHeader& block_header, for if (decoder->SupportsMetaDataId(meta_data_id)) { decoder->DispatchCreateHardwareBufferCommand(header.thread_id, + header.device_id, + header.queue_id, header.memory_id, header.buffer_id, header.format, diff --git a/framework/decode/info_decoder.h b/framework/decode/info_decoder.h index 790f699f08..cdb82b4d60 100644 --- a/framework/decode/info_decoder.h +++ b/framework/decode/info_decoder.h @@ -100,6 +100,8 @@ class InfoDecoder : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/metadata_consumer_base.h b/framework/decode/metadata_consumer_base.h index 80f7c28d95..da5f2f06cd 100644 --- a/framework/decode/metadata_consumer_base.h +++ b/framework/decode/metadata_consumer_base.h @@ -47,7 +47,9 @@ class MetadataConsumerBase virtual void ProcessResizeWindowCommand2(format::HandleId surface_id, uint32_t width, uint32_t height, uint32_t pre_transform) {} - virtual void ProcessCreateHardwareBufferCommand(format::HandleId memory_id, + virtual void ProcessCreateHardwareBufferCommand(format::HandleId device_id, + format::HandleId queue_id, + format::HandleId memory_id, uint64_t buffer_id, uint32_t format, uint32_t width, diff --git a/framework/decode/metadata_json_consumer.h b/framework/decode/metadata_json_consumer.h index b3ca94687e..32c81bc34e 100644 --- a/framework/decode/metadata_json_consumer.h +++ b/framework/decode/metadata_json_consumer.h @@ -121,7 +121,9 @@ class MetadataJsonConsumer : public Base } virtual void - ProcessCreateHardwareBufferCommand(format::HandleId memory_id, + ProcessCreateHardwareBufferCommand(format::HandleId device_id, + format::HandleId queue_id, + format::HandleId memory_id, uint64_t buffer_id, uint32_t format, uint32_t width, @@ -133,6 +135,8 @@ class MetadataJsonConsumer : public Base { const util::JsonOptions& json_options = GetOptions(); auto& jdata = WriteMetaCommandStart("CreateHardwareBufferCommand"); + HandleToJson(jdata["device_id"], device_id, json_options); + HandleToJson(jdata["queue_id"], queue_id, json_options); HandleToJson(jdata["memory_id"], memory_id, json_options); HandleToJson(jdata["buffer_id"], buffer_id, json_options); FieldToJson(jdata["format"], format, json_options); diff --git a/framework/decode/stat_decoder_base.h b/framework/decode/stat_decoder_base.h index ceba9c6165..f4daa4553b 100644 --- a/framework/decode/stat_decoder_base.h +++ b/framework/decode/stat_decoder_base.h @@ -100,6 +100,8 @@ class StatDecoderBase : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/vulkan_cpp_consumer_base.cpp b/framework/decode/vulkan_cpp_consumer_base.cpp index e749fec7f0..a04b57522c 100644 --- a/framework/decode/vulkan_cpp_consumer_base.cpp +++ b/framework/decode/vulkan_cpp_consumer_base.cpp @@ -3208,6 +3208,8 @@ void VulkanCppConsumerBase::ProcessResizeWindowCommand2(format::HandleId surface } void VulkanCppConsumerBase::ProcessCreateHardwareBufferCommand( + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/vulkan_cpp_consumer_base.h b/framework/decode/vulkan_cpp_consumer_base.h index ee104923d3..09ad6f2844 100644 --- a/framework/decode/vulkan_cpp_consumer_base.h +++ b/framework/decode/vulkan_cpp_consumer_base.h @@ -656,7 +656,9 @@ class VulkanCppConsumerBase : public VulkanConsumer uint32_t height, uint32_t pre_transform) override; virtual void - ProcessCreateHardwareBufferCommand(format::HandleId memory_id, + ProcessCreateHardwareBufferCommand(format::HandleId device_id, + format::HandleId queue_id, + format::HandleId memory_id, uint64_t buffer_id, uint32_t format, uint32_t width, diff --git a/framework/decode/vulkan_decoder_base.cpp b/framework/decode/vulkan_decoder_base.cpp index b809cd4715..0a2b610f27 100644 --- a/framework/decode/vulkan_decoder_base.cpp +++ b/framework/decode/vulkan_decoder_base.cpp @@ -126,6 +126,8 @@ void VulkanDecoderBase::DispatchResizeWindowCommand2( void VulkanDecoderBase::DispatchCreateHardwareBufferCommand( format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, @@ -141,7 +143,7 @@ void VulkanDecoderBase::DispatchCreateHardwareBufferCommand( for (auto consumer : consumers_) { consumer->ProcessCreateHardwareBufferCommand( - memory_id, buffer_id, format, width, height, stride, usage, layers, plane_info); + device_id, queue_id, memory_id, buffer_id, format, width, height, stride, usage, layers, plane_info); } } diff --git a/framework/decode/vulkan_decoder_base.h b/framework/decode/vulkan_decoder_base.h index e2ae477ac6..bd34e73b45 100644 --- a/framework/decode/vulkan_decoder_base.h +++ b/framework/decode/vulkan_decoder_base.h @@ -107,6 +107,8 @@ class VulkanDecoderBase : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index 897ed69792..4fb37c831c 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -1,6 +1,6 @@ /* ** Copyright (c) 2018-2020 Valve Corporation -** Copyright (c) 2018-2023 LunarG, Inc. +** Copyright (c) 2018-2025 LunarG, Inc. ** Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. ** ** Permission is hereby granted, free of charge, to any person obtaining a @@ -378,53 +378,529 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id void* buffer_data = nullptr; const HardwareBufferMemoryInfo& buffer_info = entry->second; - int lock_result = AHardwareBuffer_lock( - buffer_info.hardware_buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr, &buffer_data); + AHardwareBuffer_Desc desc; + AHardwareBuffer_describe(buffer_info.hardware_buffer, &desc); - if (lock_result == 0) + if ((desc.usage & AHARDWAREBUFFER_USAGE_CPU_READ_MASK) != 0) { - assert(buffer_data != nullptr); - if (buffer_info.plane_info.size() == 1) + int lock_result = AHardwareBuffer_lock( + buffer_info.hardware_buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr, &buffer_data); + + if (lock_result == 0) { - GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, size); - GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, offset); - - size_t data_size = static_cast(size); - size_t data_offset = static_cast(offset); - size_t capture_row_pitch = buffer_info.plane_info[0].capture_row_pitch; - size_t replay_row_pitch = buffer_info.plane_info[0].replay_row_pitch; - uint32_t height = buffer_info.plane_info[0].height; - - resource::CopyImageSubresourceMemory(static_cast(buffer_data), - data, - data_offset, - data_size, - replay_row_pitch, - capture_row_pitch, - height); + assert(buffer_data != nullptr); + + if (buffer_info.plane_info.size() == 1) + { + GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, size); + GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, offset); + + size_t data_size = static_cast(size); + size_t data_offset = static_cast(offset); + size_t capture_row_pitch = buffer_info.plane_info[0].capture_row_pitch; + size_t replay_row_pitch = buffer_info.plane_info[0].replay_row_pitch; + uint32_t height = buffer_info.plane_info[0].height; + + resource::CopyImageSubresourceMemory(static_cast(buffer_data), + data, + data_offset, + data_size, + replay_row_pitch, + capture_row_pitch, + height); + } + else + { + // TODO: multi-plane image format support when strides do not match. + GFXRECON_LOG_WARNING( + "Ignoring fill memory command for AHardwareBuffer with multi-plane format and " + "mismatched capture/replay strides (Memory ID = %" PRIu64 "): support not yet implemented", + memory_id); + } + + lock_result = AHardwareBuffer_unlock(buffer_info.hardware_buffer, nullptr); + if (lock_result != 0) + { + GFXRECON_LOG_WARNING( + "AHardwareBuffer_unlock failed for AHardwareBuffer object (Memory ID = %" PRIu64 ")", + memory_id); + } } else - { - // TODO: multi-plane image format support when strides do not match. - GFXRECON_LOG_WARNING("Ignoring fill memory command for AHardwareBuffer with multi-plane format and " - "mismatched capture/replay strides (Memory ID = %" PRIu64 - "): support not yet implemented", - memory_id); - } - - lock_result = AHardwareBuffer_unlock(buffer_info.hardware_buffer, nullptr); - if (lock_result != 0) { GFXRECON_LOG_WARNING( - "AHardwareBuffer_unlock failed for AHardwareBuffer object (Memory ID = %" PRIu64 ")", - memory_id); + "AHardwareBuffer_lock failed for AHardwareBuffer object (Memory ID = %" PRIu64 ")", memory_id); } } - else - { - GFXRECON_LOG_WARNING("AHardwareBuffer_lock failed for AHardwareBuffer object (Memory ID = %" PRIu64 ")", - memory_id); + else if (buffer_info.device_id != 0) + { + VkResult vk_result = VK_SUCCESS; + + VulkanDeviceInfo* device_info = object_info_table_->GetVkDeviceInfo(buffer_info.device_id); + VulkanQueueInfo* queue_info = object_info_table_->GetVkQueueInfo(buffer_info.queue_id); + VkDevice device = device_info->handle; + auto device_table = GetDeviceTable(device); + auto physical_device_info = object_info_table_->GetVkPhysicalDeviceInfo(device_info->parent_id); + auto memory_properties = &physical_device_info->capture_memory_properties; + + VkAndroidHardwareBufferFormatPropertiesANDROID format_properties; + format_properties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; + format_properties.pNext = nullptr; + + VkAndroidHardwareBufferPropertiesANDROID properties; + properties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; + properties.pNext = &format_properties; + + if (vk_result == VK_SUCCESS) + vk_result = device_table->GetAndroidHardwareBufferPropertiesANDROID( + device, buffer_info.hardware_buffer, &properties); + + const size_t ahb_size = properties.allocationSize; + GFXRECON_ASSERT(ahb_size != 0); + + VkExternalMemoryBufferCreateInfo external_memory_buffer_create_info; + external_memory_buffer_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO; + external_memory_buffer_create_info.pNext = nullptr; + external_memory_buffer_create_info.handleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + + VkBufferCreateInfo buffer_create_info; + buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_create_info.pNext = &external_memory_buffer_create_info; + buffer_create_info.flags = 0u; + buffer_create_info.size = ahb_size; + buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + buffer_create_info.queueFamilyIndexCount = 0u; + buffer_create_info.pQueueFamilyIndices = nullptr; + + VkBuffer ahb_data_buffer; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateBuffer(device, &buffer_create_info, nullptr, &ahb_data_buffer); + + VkImportAndroidHardwareBufferInfoANDROID import_ahb_info; + import_ahb_info.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; + import_ahb_info.pNext = nullptr; + import_ahb_info.buffer = buffer_info.hardware_buffer; + + VkMemoryAllocateInfo memory_allocate_info; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = &import_ahb_info; + memory_allocate_info.allocationSize = ahb_size; + + uint32_t memory_index = memory_properties->memoryTypeCount; + for (uint32_t i = 0; i < memory_properties->memoryTypeCount; ++i) + { + if ((properties.memoryTypeBits & (1 << i)) && + (memory_properties->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) > 0) + { + memory_index = i; + } + } + GFXRECON_ASSERT(memory_index < memory_properties->memoryTypeCount); + memory_allocate_info.memoryTypeIndex = memory_index; + + VkDeviceMemory buffer_memory; + if (vk_result == VK_SUCCESS) + vk_result = device_table->AllocateMemory(device, &memory_allocate_info, nullptr, &buffer_memory); + + if (vk_result == VK_SUCCESS) + vk_result = device_table->BindBufferMemory(device, ahb_data_buffer, buffer_memory, 0); + + VkBufferCreateInfo host_readable_buffer_info; + host_readable_buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + host_readable_buffer_info.pNext = nullptr; + host_readable_buffer_info.flags = 0u; + host_readable_buffer_info.size = ahb_size; + host_readable_buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + host_readable_buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + host_readable_buffer_info.queueFamilyIndexCount = 0u; + host_readable_buffer_info.pQueueFamilyIndices = nullptr; + + VkBuffer host_readable_buffer; + if (vk_result == VK_SUCCESS) + vk_result = + device_table->CreateBuffer(device, &host_readable_buffer_info, nullptr, &host_readable_buffer); + + VkMemoryRequirements host_readable_memory_requirements; + device_table->GetBufferMemoryRequirements( + device, host_readable_buffer, &host_readable_memory_requirements); + + VkMemoryAllocateInfo host_readable_allocate_info; + host_readable_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + host_readable_allocate_info.pNext = nullptr; + host_readable_allocate_info.allocationSize = host_readable_memory_requirements.size; + + memory_index = memory_properties->memoryTypeCount; + for (uint32_t i = 0; i < memory_properties->memoryTypeCount; ++i) + { + if ((host_readable_memory_requirements.memoryTypeBits & (1 << i)) && + (memory_properties->memoryTypes[i].propertyFlags & + (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) == + (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) + { + memory_index = i; + } + } + GFXRECON_ASSERT(memory_index < memory_properties->memoryTypeCount); + host_readable_allocate_info.memoryTypeIndex = memory_index; + + VkDeviceMemory host_readable_buffer_memory; + if (vk_result == VK_SUCCESS) + vk_result = device_table->AllocateMemory( + device, &host_readable_allocate_info, nullptr, &host_readable_buffer_memory); + + if (vk_result == VK_SUCCESS) + vk_result = + device_table->BindBufferMemory(device, host_readable_buffer, host_readable_buffer_memory, 0); + + void* host_readable_buffer_data; + device_table->MapMemory( + device, host_readable_buffer_memory, 0u, ahb_size, 0u, &host_readable_buffer_data); + memcpy(host_readable_buffer_data, data, host_readable_buffer_info.size); + + // #version 450 + // + // layout(constant_id = 0) const uint rowLength = 1; + // layout(constant_id = 1) const uint totalSize = 1; + // + // layout(local_size_x = 32, local_size_y = 32) in; + // + // layout(set = 0, binding = 0, std430) buffer InputBuffer { + // uint in_data[]; + // }; + // + // layout(set = 0, binding = 1, std430) buffer OutputBuffer { + // uint out_data[]; + // }; + // + // void main() { + // uint i = gl_GlobalInvocationID.y * rowLength + gl_GlobalInvocationID.x; + // if (i < totalSize) { + // out_data[i] = in_data[i]; + // } + // } + + std::vector shader = { + 0x07230203, 0x00010000, 0x0008000b, 0x0000002e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, + 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, + 0x0006000f, 0x00000005, 0x00000004, 0x6e69616d, 0x00000000, 0x0000000b, 0x00060010, 0x00000004, + 0x00000011, 0x00000020, 0x00000020, 0x00000001, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, + 0x00000004, 0x6e69616d, 0x00000000, 0x00030005, 0x00000008, 0x00000069, 0x00080005, 0x0000000b, + 0x475f6c67, 0x61626f6c, 0x766e496c, 0x7461636f, 0x496e6f69, 0x00000044, 0x00050005, 0x00000010, + 0x4c776f72, 0x74676e65, 0x00000068, 0x00050005, 0x00000017, 0x61746f74, 0x7a69536c, 0x00000065, + 0x00060005, 0x0000001d, 0x7074754f, 0x75427475, 0x72656666, 0x00000000, 0x00060006, 0x0000001d, + 0x00000000, 0x5f74756f, 0x61746164, 0x00000000, 0x00030005, 0x0000001f, 0x00000000, 0x00050005, + 0x00000024, 0x75706e49, 0x66754274, 0x00726566, 0x00050006, 0x00000024, 0x00000000, 0x645f6e69, + 0x00617461, 0x00030005, 0x00000026, 0x00000000, 0x00040047, 0x0000000b, 0x0000000b, 0x0000001c, + 0x00040047, 0x00000010, 0x00000001, 0x00000000, 0x00040047, 0x00000017, 0x00000001, 0x00000001, + 0x00040047, 0x0000001c, 0x00000006, 0x00000004, 0x00050048, 0x0000001d, 0x00000000, 0x00000023, + 0x00000000, 0x00030047, 0x0000001d, 0x00000003, 0x00040047, 0x0000001f, 0x00000022, 0x00000000, + 0x00040047, 0x0000001f, 0x00000021, 0x00000001, 0x00040047, 0x00000023, 0x00000006, 0x00000004, + 0x00050048, 0x00000024, 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000024, 0x00000003, + 0x00040047, 0x00000026, 0x00000022, 0x00000000, 0x00040047, 0x00000026, 0x00000021, 0x00000000, + 0x00040047, 0x0000002d, 0x0000000b, 0x00000019, 0x00020013, 0x00000002, 0x00030021, 0x00000003, + 0x00000002, 0x00040015, 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, + 0x00000006, 0x00040017, 0x00000009, 0x00000006, 0x00000003, 0x00040020, 0x0000000a, 0x00000001, + 0x00000009, 0x0004003b, 0x0000000a, 0x0000000b, 0x00000001, 0x0004002b, 0x00000006, 0x0000000c, + 0x00000001, 0x00040020, 0x0000000d, 0x00000001, 0x00000006, 0x00040032, 0x00000006, 0x00000010, + 0x00000001, 0x0004002b, 0x00000006, 0x00000012, 0x00000000, 0x00040032, 0x00000006, 0x00000017, + 0x00000001, 0x00020014, 0x00000018, 0x0003001d, 0x0000001c, 0x00000006, 0x0003001e, 0x0000001d, + 0x0000001c, 0x00040020, 0x0000001e, 0x00000002, 0x0000001d, 0x0004003b, 0x0000001e, 0x0000001f, + 0x00000002, 0x00040015, 0x00000020, 0x00000020, 0x00000001, 0x0004002b, 0x00000020, 0x00000021, + 0x00000000, 0x0003001d, 0x00000023, 0x00000006, 0x0003001e, 0x00000024, 0x00000023, 0x00040020, + 0x00000025, 0x00000002, 0x00000024, 0x0004003b, 0x00000025, 0x00000026, 0x00000002, 0x00040020, + 0x00000028, 0x00000002, 0x00000006, 0x0004002b, 0x00000006, 0x0000002c, 0x00000020, 0x0006002c, + 0x00000009, 0x0000002d, 0x0000002c, 0x0000002c, 0x0000000c, 0x00050036, 0x00000002, 0x00000004, + 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007, + 0x00050041, 0x0000000d, 0x0000000e, 0x0000000b, 0x0000000c, 0x0004003d, 0x00000006, 0x0000000f, + 0x0000000e, 0x00050084, 0x00000006, 0x00000011, 0x0000000f, 0x00000010, 0x00050041, 0x0000000d, + 0x00000013, 0x0000000b, 0x00000012, 0x0004003d, 0x00000006, 0x00000014, 0x00000013, 0x00050080, + 0x00000006, 0x00000015, 0x00000011, 0x00000014, 0x0003003e, 0x00000008, 0x00000015, 0x0004003d, + 0x00000006, 0x00000016, 0x00000008, 0x000500b0, 0x00000018, 0x00000019, 0x00000016, 0x00000017, + 0x000300f7, 0x0000001b, 0x00000000, 0x000400fa, 0x00000019, 0x0000001a, 0x0000001b, 0x000200f8, + 0x0000001a, 0x0004003d, 0x00000006, 0x00000022, 0x00000008, 0x0004003d, 0x00000006, 0x00000027, + 0x00000008, 0x00060041, 0x00000028, 0x00000029, 0x00000026, 0x00000021, 0x00000027, 0x0004003d, + 0x00000006, 0x0000002a, 0x00000029, 0x00060041, 0x00000028, 0x0000002b, 0x0000001f, 0x00000021, + 0x00000022, 0x0003003e, 0x0000002b, 0x0000002a, 0x000200f9, 0x0000001b, 0x000200f8, 0x0000001b, + 0x000100fd, 0x00010038, + }; + + VkShaderModuleCreateInfo shader_module_create_info; + shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_module_create_info.pNext = nullptr; + shader_module_create_info.flags = 0u; + shader_module_create_info.codeSize = shader.size() * sizeof(uint32_t); + shader_module_create_info.pCode = shader.data(); + VkShaderModule compute_shader_module = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateShaderModule( + device, &shader_module_create_info, nullptr, &compute_shader_module); + + uint32_t unit_size = sizeof(uint32_t); + uint32_t group_count_x = ahb_size / 32u / 32u / unit_size; + if (ahb_size % (32u * 32u * unit_size) != 0) + ++group_count_x; + uint32_t row_length = group_count_x * 32u; + + VkSpecializationMapEntry specialization_entries[2]; + specialization_entries[0].constantID = 0u; + specialization_entries[0].offset = 0u; + specialization_entries[0].size = sizeof(uint32_t); + specialization_entries[1].constantID = 1u; + specialization_entries[1].offset = sizeof(uint32_t); + specialization_entries[1].size = sizeof(uint32_t); + + uint32_t specialization_data[2]; + specialization_data[0] = row_length; + specialization_data[1] = ahb_size / sizeof(uint32_t); + + VkSpecializationInfo specialization_info; + specialization_info.mapEntryCount = 2u; + specialization_info.pMapEntries = specialization_entries; + specialization_info.dataSize = sizeof(uint32_t) * 2u; + specialization_info.pData = specialization_data; + + VkPipelineShaderStageCreateInfo shader_stage_create_info; + shader_stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shader_stage_create_info.pNext = nullptr; + shader_stage_create_info.flags = 0u; + shader_stage_create_info.stage = VK_SHADER_STAGE_COMPUTE_BIT; + shader_stage_create_info.module = compute_shader_module; + shader_stage_create_info.pName = "main"; + shader_stage_create_info.pSpecializationInfo = &specialization_info; + + VkDescriptorSetLayoutBinding bindings[2]; + bindings[0].binding = 0u; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[0].descriptorCount = 1u; + bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindings[0].pImmutableSamplers = nullptr; + bindings[1].binding = 1u; + bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[1].descriptorCount = 1u; + bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindings[1].pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info; + descriptor_set_layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptor_set_layout_create_info.pNext = nullptr; + descriptor_set_layout_create_info.flags = 0u; + descriptor_set_layout_create_info.bindingCount = 2u; + descriptor_set_layout_create_info.pBindings = bindings; + + VkDescriptorSetLayout descriptor_set_layout = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateDescriptorSetLayout( + device, &descriptor_set_layout_create_info, nullptr, &descriptor_set_layout); + + VkPipelineLayoutCreateInfo pipeline_layout_create_info; + pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeline_layout_create_info.pNext = nullptr; + pipeline_layout_create_info.flags = 0u; + pipeline_layout_create_info.setLayoutCount = 1u; + pipeline_layout_create_info.pSetLayouts = &descriptor_set_layout; + pipeline_layout_create_info.pushConstantRangeCount = 0u; + pipeline_layout_create_info.pPushConstantRanges = nullptr; + + VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreatePipelineLayout( + device, &pipeline_layout_create_info, nullptr, &pipeline_layout); + + VkComputePipelineCreateInfo compute_pipeline_create_info; + compute_pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + compute_pipeline_create_info.pNext = nullptr; + compute_pipeline_create_info.flags = 0u; + compute_pipeline_create_info.stage = shader_stage_create_info; + compute_pipeline_create_info.layout = pipeline_layout; + compute_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; + compute_pipeline_create_info.basePipelineIndex = -1; + + VkPipeline compute_pipeline = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateComputePipelines( + device, VK_NULL_HANDLE, 1u, &compute_pipeline_create_info, nullptr, &compute_pipeline); + + VkDescriptorPoolSize pool_size; + pool_size.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + pool_size.descriptorCount = 2u; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info; + descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptor_pool_create_info.pNext = nullptr; + descriptor_pool_create_info.flags = 0u; + descriptor_pool_create_info.maxSets = 1u; + descriptor_pool_create_info.poolSizeCount = 1u; + descriptor_pool_create_info.pPoolSizes = &pool_size; + + VkDescriptorPool descriptor_pool = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateDescriptorPool( + device, &descriptor_pool_create_info, nullptr, &descriptor_pool); + + VkDescriptorSetAllocateInfo descriptor_set_allocate_info; + descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + descriptor_set_allocate_info.pNext = nullptr; + descriptor_set_allocate_info.descriptorPool = descriptor_pool; + descriptor_set_allocate_info.descriptorSetCount = 1u; + descriptor_set_allocate_info.pSetLayouts = &descriptor_set_layout; + + VkDescriptorSet descriptor_set = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = + device_table->AllocateDescriptorSets(device, &descriptor_set_allocate_info, &descriptor_set); + + VkDescriptorBufferInfo buffer_infos[2]; + buffer_infos[0].buffer = host_readable_buffer; + buffer_infos[0].offset = 0u; + buffer_infos[0].range = VK_WHOLE_SIZE; + buffer_infos[1].buffer = ahb_data_buffer; + buffer_infos[1].offset = 0u; + buffer_infos[1].range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet descriptor_writes[2]; + descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[0].pNext = nullptr; + descriptor_writes[0].dstSet = descriptor_set; + descriptor_writes[0].dstBinding = 0u; + descriptor_writes[0].dstArrayElement = 0u; + descriptor_writes[0].descriptorCount = 1u; + descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[0].pImageInfo = nullptr; + descriptor_writes[0].pBufferInfo = &buffer_infos[0]; + descriptor_writes[0].pTexelBufferView = nullptr; + descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[1].pNext = nullptr; + descriptor_writes[1].dstSet = descriptor_set; + descriptor_writes[1].dstBinding = 1u; + descriptor_writes[1].dstArrayElement = 0u; + descriptor_writes[1].descriptorCount = 1u; + descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[1].pImageInfo = nullptr; + descriptor_writes[1].pBufferInfo = &buffer_infos[1]; + descriptor_writes[1].pTexelBufferView = nullptr; + + if (vk_result == VK_SUCCESS) + device_table->UpdateDescriptorSets(device, 2u, descriptor_writes, 0u, nullptr); + + VkCommandPoolCreateInfo command_pool_create_info; + command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + command_pool_create_info.pNext = nullptr; + command_pool_create_info.flags = 0u; + command_pool_create_info.queueFamilyIndex = queue_info->family_index; + + VkCommandPool command_pool; + device_table->CreateCommandPool(device, &command_pool_create_info, nullptr, &command_pool); + + VkCommandBufferAllocateInfo command_buffer_allocate_info; + command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_allocate_info.pNext = nullptr; + command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_allocate_info.commandPool = command_pool; + command_buffer_allocate_info.commandBufferCount = 1; + + VkCommandBuffer command_buffer; + if (vk_result == VK_SUCCESS) + vk_result = + device_table->AllocateCommandBuffers(device, &command_buffer_allocate_info, &command_buffer); + + VkCommandBufferBeginInfo command_buffer_begin_info; + command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + command_buffer_begin_info.pNext = nullptr; + command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + command_buffer_begin_info.pInheritanceInfo = nullptr; + if (vk_result == VK_SUCCESS) + vk_result = device_table->BeginCommandBuffer(command_buffer, &command_buffer_begin_info); + + if (vk_result == VK_SUCCESS) + { + VkBufferMemoryBarrier pre_buffer_barriers[2]; + pre_buffer_barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + pre_buffer_barriers[0].pNext = nullptr; + pre_buffer_barriers[0].srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + pre_buffer_barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + pre_buffer_barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_buffer_barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_buffer_barriers[0].buffer = host_readable_buffer; + pre_buffer_barriers[0].offset = 0u; + pre_buffer_barriers[0].size = ahb_size; + pre_buffer_barriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + pre_buffer_barriers[1].pNext = nullptr; + pre_buffer_barriers[1].srcAccessMask = VK_ACCESS_NONE; + pre_buffer_barriers[1].dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + pre_buffer_barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_buffer_barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_buffer_barriers[1].buffer = ahb_data_buffer; + pre_buffer_barriers[1].offset = 0u; + pre_buffer_barriers[1].size = ahb_size; + + device_table->CmdPipelineBarrier(command_buffer, + VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + 0, + 0, + nullptr, + 2, + pre_buffer_barriers, + 0, + nullptr); + + device_table->CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline); + device_table->CmdBindDescriptorSets(command_buffer, + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeline_layout, + 0, + 1, + &descriptor_set, + 0, + nullptr); + device_table->CmdDispatch(command_buffer, group_count_x, 1u, 1u); + + device_table->EndCommandBuffer(command_buffer); + } + + VkFenceCreateInfo fence_create_info; + fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_create_info.pNext = nullptr; + fence_create_info.flags = 0u; + + VkFence fence; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateFence(device, &fence_create_info, nullptr, &fence); + + VkSubmitInfo submit_info; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 0u; + submit_info.pWaitSemaphores = nullptr; + submit_info.pWaitDstStageMask = nullptr; + submit_info.commandBufferCount = 1u; + submit_info.pCommandBuffers = &command_buffer; + submit_info.signalSemaphoreCount = 0u; + submit_info.pSignalSemaphores = nullptr; + + if (vk_result == VK_SUCCESS) + vk_result = device_table->QueueSubmit(queue_info->handle, 1, &submit_info, fence); + + if (vk_result == VK_SUCCESS) + vk_result = device_table->WaitForFences(device, 1u, &fence, VK_TRUE, UINT64_MAX); + + device_table->DestroyFence(device, fence, nullptr); + device_table->DestroyCommandPool(device, command_pool, nullptr); + device_table->DestroyDescriptorPool(device, descriptor_pool, nullptr); + device_table->DestroyPipeline(device, compute_pipeline, nullptr); + device_table->DestroyDescriptorSetLayout(device, descriptor_set_layout, nullptr); + device_table->DestroyPipelineLayout(device, pipeline_layout, nullptr); + device_table->DestroyShaderModule(device, compute_shader_module, nullptr); + device_table->FreeMemory(device, buffer_memory, nullptr); + device_table->FreeMemory(device, host_readable_buffer_memory, nullptr); + device_table->DestroyBuffer(device, ahb_data_buffer, nullptr); + device_table->DestroyBuffer(device, host_readable_buffer, nullptr); + + if (vk_result != VK_SUCCESS) + GFXRECON_LOG_ERROR("Failed to copy data to AHardwareBuffer that is not cpu readable"); } } } @@ -516,6 +992,8 @@ void VulkanReplayConsumerBase::ProcessResizeWindowCommand2(format::HandleId surf } void VulkanReplayConsumerBase::ProcessCreateHardwareBufferCommand( + format::HandleId device_id, + format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, @@ -588,6 +1066,8 @@ void VulkanReplayConsumerBase::ProcessCreateHardwareBufferCommand( HardwareBufferMemoryInfo& memory_info = hardware_buffer_memory_info_[memory_id]; memory_info.hardware_buffer = buffer; + memory_info.device_id = device_id; + memory_info.queue_id = queue_id; memory_info.compatible_strides = true; // Check for matching strides. diff --git a/framework/decode/vulkan_replay_consumer_base.h b/framework/decode/vulkan_replay_consumer_base.h index 4edd1e4ecf..8de811c178 100644 --- a/framework/decode/vulkan_replay_consumer_base.h +++ b/framework/decode/vulkan_replay_consumer_base.h @@ -107,7 +107,9 @@ class VulkanReplayConsumerBase : public VulkanConsumer uint32_t pre_transform) override; virtual void - ProcessCreateHardwareBufferCommand(format::HandleId memory_id, + ProcessCreateHardwareBufferCommand(format::HandleId device_id, + format::HandleId queue_id, + format::HandleId memory_id, uint64_t buffer_id, uint32_t format, uint32_t width, @@ -1647,6 +1649,8 @@ class VulkanReplayConsumerBase : public VulkanConsumer struct HardwareBufferMemoryInfo { AHardwareBuffer* hardware_buffer; + format::HandleId device_id; + format::HandleId queue_id; bool compatible_strides; std::vector plane_info; }; diff --git a/framework/encode/vulkan_capture_common.cpp b/framework/encode/vulkan_capture_common.cpp index b012a22b07..fde1236866 100644 --- a/framework/encode/vulkan_capture_common.cpp +++ b/framework/encode/vulkan_capture_common.cpp @@ -1,5 +1,5 @@ /* - ** Copyright (c) 2024 LunarG, Inc. + ** Copyright (c) 2024-2025 LunarG, Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and associated documentation files (the "Software"), @@ -29,12 +29,14 @@ GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(encode) -void CommonWriteCreateHardwareBufferCmd(format::ThreadId thread_id, - format::HandleId memory_id, - AHardwareBuffer* hardware_buffer, - const std::vector& plane_info, - VulkanCaptureManager* vulkan_capture_manager, - VulkanStateWriter* vulkan_state_writer) +static void CommonWriteCreateHardwareBufferCmd(format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId queue_id, + format::HandleId memory_id, + AHardwareBuffer* hardware_buffer, + const std::vector& plane_info, + VulkanCaptureManager* vulkan_capture_manager, + VulkanStateWriter* vulkan_state_writer) { #if defined(VK_USE_PLATFORM_ANDROID_KHR) if (vulkan_capture_manager && !vulkan_capture_manager->IsCaptureModeWrite()) @@ -50,6 +52,8 @@ void CommonWriteCreateHardwareBufferCmd(format::ThreadId create_buffer_cmd.meta_header.meta_data_id = format::MakeMetaDataId( format::ApiFamilyId::ApiFamily_Vulkan, format::MetaDataType::kCreateHardwareBufferCommand); create_buffer_cmd.thread_id = thread_id; + create_buffer_cmd.device_id = device_id; + create_buffer_cmd.queue_id = queue_id; create_buffer_cmd.memory_id = memory_id; create_buffer_cmd.buffer_id = reinterpret_cast(hardware_buffer); @@ -127,12 +131,13 @@ static void CommonWriteFillMemoryCmd(format::HandleId memory_id, } } -void CommonProcessHardwareBuffer(format::ThreadId thread_id, - format::HandleId memory_id, - AHardwareBuffer* hardware_buffer, - size_t allocation_size, - VulkanCaptureManager* vulkan_capture_manager, - VulkanStateWriter* vulkan_state_writer) +void CommonProcessHardwareBuffer(format::ThreadId thread_id, + const vulkan_wrappers::DeviceWrapper* device_wrapper, + format::HandleId memory_id, + AHardwareBuffer* hardware_buffer, + size_t allocation_size, + VulkanCaptureManager* vulkan_capture_manager, + VulkanStateWriter* vulkan_state_writer) { #if defined(VK_USE_PLATFORM_ANDROID_KHR) assert(hardware_buffer != nullptr); @@ -179,7 +184,7 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id, // Write CreateHardwareBufferCmd with or without the AHB payload CommonWriteCreateHardwareBufferCmd( - thread_id, memory_id, hardware_buffer, plane_info, vulkan_capture_manager, vulkan_state_writer); + thread_id, 0u, 0u, memory_id, hardware_buffer, plane_info, vulkan_capture_manager, vulkan_state_writer); // If AHardwareBuffer_lockPlanes failed (or is not available) try AHardwareBuffer_lock if (result != 0) @@ -233,18 +238,549 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id, } else { - // The AHB is not CPU-readable + // The AHB is not CPU-readable, copy the data into a host visible buffer on the GPU + format::HandleId device_id = device_wrapper->handle_id; + VkDevice device = device_wrapper->handle; + auto physical_device_wrapper = device_wrapper->physical_device; + auto physical_device = physical_device_wrapper->handle; + const VulkanInstanceTable* instance_table = vulkan_wrappers::GetInstanceTable(physical_device); + auto device_table = vulkan_wrappers::GetDeviceTable(device); + auto memory_properties = &physical_device_wrapper->memory_properties; + + uint32_t device_queue_index = -1; + uint32_t queue_family_index = -1; + + uint32_t queue_family_count; + instance_table->GetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr); + std::vector queue_family_properties(queue_family_count); + instance_table->GetPhysicalDeviceQueueFamilyProperties( + physical_device, &queue_family_count, queue_family_properties.data()); + + for (size_t i = 0; i < device_wrapper->queue_family_indices.size(); ++i) + { + uint32_t qfi = device_wrapper->queue_family_indices[i]; + if ((queue_family_properties[qfi].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0) + { + device_queue_index = i; + queue_family_index = qfi; + break; + } + } + + if (device_queue_index == -1 || queue_family_index == -1) + return; + + auto queue_wrapper = device_wrapper->child_queues[device_queue_index]; + format::HandleId queue_id = queue_wrapper->handle_id; // Write CreateHardwareBufferCmd without the AHB payload - CommonWriteCreateHardwareBufferCmd( - thread_id, memory_id, hardware_buffer, plane_info, vulkan_capture_manager, vulkan_state_writer); + CommonWriteCreateHardwareBufferCmd(thread_id, + device_id, + queue_id, + memory_id, + hardware_buffer, + plane_info, + vulkan_capture_manager, + vulkan_state_writer); + + VkResult vk_result = VK_SUCCESS; + + // Query the AHB size + VkAndroidHardwareBufferFormatPropertiesANDROID format_properties; + format_properties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; + format_properties.pNext = nullptr; + + VkAndroidHardwareBufferPropertiesANDROID properties; + properties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; + properties.pNext = &format_properties; + + if (vk_result == VK_SUCCESS) + vk_result = device_table->GetAndroidHardwareBufferPropertiesANDROID(device, hardware_buffer, &properties); + + const size_t ahb_size = properties.allocationSize; + GFXRECON_ASSERT(ahb_size > 0); + + VkExternalMemoryBufferCreateInfo external_memory_buffer_create_info; + external_memory_buffer_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO; + external_memory_buffer_create_info.pNext = nullptr; + external_memory_buffer_create_info.handleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + + VkBufferCreateInfo buffer_create_info; + buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_create_info.pNext = &external_memory_buffer_create_info; + buffer_create_info.flags = 0u; + buffer_create_info.size = ahb_size; + buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + buffer_create_info.queueFamilyIndexCount = 0u; + buffer_create_info.pQueueFamilyIndices = nullptr; + + VkBuffer ahb_data_buffer; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateBuffer(device, &buffer_create_info, nullptr, &ahb_data_buffer); + + VkMemoryRequirements memory_requirements; + device_table->GetBufferMemoryRequirements(device, ahb_data_buffer, &memory_requirements); + + VkImportAndroidHardwareBufferInfoANDROID import_ahb_info; + import_ahb_info.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; + import_ahb_info.pNext = nullptr; + import_ahb_info.buffer = hardware_buffer; + + VkMemoryAllocateInfo memory_allocate_info; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = &import_ahb_info; + memory_allocate_info.allocationSize = memory_requirements.size; + + uint32_t memory_index = memory_properties->memoryTypeCount; + for (uint32_t i = 0; i < memory_properties->memoryTypeCount; ++i) + { + if ((memory_requirements.memoryTypeBits & (1 << i)) && + (memory_properties->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) > 0) + { + memory_index = i; + break; + } + } + GFXRECON_ASSERT(memory_index < memory_properties->memoryTypeCount); + memory_allocate_info.memoryTypeIndex = memory_index; + + VkDeviceMemory buffer_memory; + if (vk_result == VK_SUCCESS) + vk_result = device_table->AllocateMemory(device, &memory_allocate_info, nullptr, &buffer_memory); + + if (vk_result == VK_SUCCESS) + vk_result = device_table->BindBufferMemory(device, ahb_data_buffer, buffer_memory, 0); + + VkBufferCreateInfo host_buffer_info; + host_buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + host_buffer_info.pNext = nullptr; + host_buffer_info.flags = 0u; + host_buffer_info.size = ahb_size; + host_buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + host_buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + host_buffer_info.queueFamilyIndexCount = 0u; + host_buffer_info.pQueueFamilyIndices = nullptr; + + VkBuffer host_buffer; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateBuffer(device, &host_buffer_info, nullptr, &host_buffer); + + VkMemoryRequirements host_reabable_memory_requirements; + device_table->GetBufferMemoryRequirements(device, host_buffer, &host_reabable_memory_requirements); + + VkMemoryAllocateInfo host_readable_allocate_info; + host_readable_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + host_readable_allocate_info.pNext = nullptr; + host_readable_allocate_info.allocationSize = host_reabable_memory_requirements.size; + + memory_index = memory_properties->memoryTypeCount; + for (uint32_t i = 0; i < memory_properties->memoryTypeCount; ++i) + { + if ((host_reabable_memory_requirements.memoryTypeBits & (1 << i)) && + (memory_properties->memoryTypes[i].propertyFlags & + (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) == + (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) + { + memory_index = i; + break; + } + } + GFXRECON_ASSERT(memory_index < memory_properties->memoryTypeCount); + host_readable_allocate_info.memoryTypeIndex = memory_index; + + VkDeviceMemory host_buffer_memory; + if (vk_result == VK_SUCCESS) + vk_result = + device_table->AllocateMemory(device, &host_readable_allocate_info, nullptr, &host_buffer_memory); + + if (vk_result == VK_SUCCESS) + vk_result = device_table->BindBufferMemory(device, host_buffer, host_buffer_memory, 0); + + // #version 450 + // + // layout(constant_id = 0) const uint rowLength = 1; + // layout(constant_id = 1) const uint totalSize = 1; + // + // layout(local_size_x = 32, local_size_y = 32) in; + // + // layout(set = 0, binding = 0, std430) buffer InputBuffer { + // uint in_data[]; + // }; + // + // layout(set = 0, binding = 1, std430) buffer OutputBuffer { + // uint out_data[]; + // }; + // + // void main() { + // uint i = gl_GlobalInvocationID.y * rowLength + gl_GlobalInvocationID.x; + // if (i < totalSize) { + // out_data[i] = in_data[i]; + // } + // } + + std::vector shader = { + 0x07230203, 0x00010000, 0x0008000b, 0x0000002e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, + 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0006000f, 0x00000005, + 0x00000004, 0x6e69616d, 0x00000000, 0x0000000b, 0x00060010, 0x00000004, 0x00000011, 0x00000020, 0x00000020, + 0x00000001, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00030005, + 0x00000008, 0x00000069, 0x00080005, 0x0000000b, 0x475f6c67, 0x61626f6c, 0x766e496c, 0x7461636f, 0x496e6f69, + 0x00000044, 0x00050005, 0x00000010, 0x4c776f72, 0x74676e65, 0x00000068, 0x00050005, 0x00000017, 0x61746f74, + 0x7a69536c, 0x00000065, 0x00060005, 0x0000001d, 0x7074754f, 0x75427475, 0x72656666, 0x00000000, 0x00060006, + 0x0000001d, 0x00000000, 0x5f74756f, 0x61746164, 0x00000000, 0x00030005, 0x0000001f, 0x00000000, 0x00050005, + 0x00000024, 0x75706e49, 0x66754274, 0x00726566, 0x00050006, 0x00000024, 0x00000000, 0x645f6e69, 0x00617461, + 0x00030005, 0x00000026, 0x00000000, 0x00040047, 0x0000000b, 0x0000000b, 0x0000001c, 0x00040047, 0x00000010, + 0x00000001, 0x00000000, 0x00040047, 0x00000017, 0x00000001, 0x00000001, 0x00040047, 0x0000001c, 0x00000006, + 0x00000004, 0x00050048, 0x0000001d, 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x0000001d, 0x00000003, + 0x00040047, 0x0000001f, 0x00000022, 0x00000000, 0x00040047, 0x0000001f, 0x00000021, 0x00000001, 0x00040047, + 0x00000023, 0x00000006, 0x00000004, 0x00050048, 0x00000024, 0x00000000, 0x00000023, 0x00000000, 0x00030047, + 0x00000024, 0x00000003, 0x00040047, 0x00000026, 0x00000022, 0x00000000, 0x00040047, 0x00000026, 0x00000021, + 0x00000000, 0x00040047, 0x0000002d, 0x0000000b, 0x00000019, 0x00020013, 0x00000002, 0x00030021, 0x00000003, + 0x00000002, 0x00040015, 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, + 0x00040017, 0x00000009, 0x00000006, 0x00000003, 0x00040020, 0x0000000a, 0x00000001, 0x00000009, 0x0004003b, + 0x0000000a, 0x0000000b, 0x00000001, 0x0004002b, 0x00000006, 0x0000000c, 0x00000001, 0x00040020, 0x0000000d, + 0x00000001, 0x00000006, 0x00040032, 0x00000006, 0x00000010, 0x00000001, 0x0004002b, 0x00000006, 0x00000012, + 0x00000000, 0x00040032, 0x00000006, 0x00000017, 0x00000001, 0x00020014, 0x00000018, 0x0003001d, 0x0000001c, + 0x00000006, 0x0003001e, 0x0000001d, 0x0000001c, 0x00040020, 0x0000001e, 0x00000002, 0x0000001d, 0x0004003b, + 0x0000001e, 0x0000001f, 0x00000002, 0x00040015, 0x00000020, 0x00000020, 0x00000001, 0x0004002b, 0x00000020, + 0x00000021, 0x00000000, 0x0003001d, 0x00000023, 0x00000006, 0x0003001e, 0x00000024, 0x00000023, 0x00040020, + 0x00000025, 0x00000002, 0x00000024, 0x0004003b, 0x00000025, 0x00000026, 0x00000002, 0x00040020, 0x00000028, + 0x00000002, 0x00000006, 0x0004002b, 0x00000006, 0x0000002c, 0x00000020, 0x0006002c, 0x00000009, 0x0000002d, + 0x0000002c, 0x0000002c, 0x0000000c, 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, + 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007, 0x00050041, 0x0000000d, 0x0000000e, 0x0000000b, + 0x0000000c, 0x0004003d, 0x00000006, 0x0000000f, 0x0000000e, 0x00050084, 0x00000006, 0x00000011, 0x0000000f, + 0x00000010, 0x00050041, 0x0000000d, 0x00000013, 0x0000000b, 0x00000012, 0x0004003d, 0x00000006, 0x00000014, + 0x00000013, 0x00050080, 0x00000006, 0x00000015, 0x00000011, 0x00000014, 0x0003003e, 0x00000008, 0x00000015, + 0x0004003d, 0x00000006, 0x00000016, 0x00000008, 0x000500b0, 0x00000018, 0x00000019, 0x00000016, 0x00000017, + 0x000300f7, 0x0000001b, 0x00000000, 0x000400fa, 0x00000019, 0x0000001a, 0x0000001b, 0x000200f8, 0x0000001a, + 0x0004003d, 0x00000006, 0x00000022, 0x00000008, 0x0004003d, 0x00000006, 0x00000027, 0x00000008, 0x00060041, + 0x00000028, 0x00000029, 0x00000026, 0x00000021, 0x00000027, 0x0004003d, 0x00000006, 0x0000002a, 0x00000029, + 0x00060041, 0x00000028, 0x0000002b, 0x0000001f, 0x00000021, 0x00000022, 0x0003003e, 0x0000002b, 0x0000002a, + 0x000200f9, 0x0000001b, 0x000200f8, 0x0000001b, 0x000100fd, 0x00010038, + }; + + VkShaderModuleCreateInfo shader_module_create_info; + shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_module_create_info.pNext = nullptr; + shader_module_create_info.flags = 0u; + shader_module_create_info.codeSize = shader.size() * sizeof(uint32_t); + shader_module_create_info.pCode = shader.data(); + VkShaderModule compute_shader_module = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = + device_table->CreateShaderModule(device, &shader_module_create_info, nullptr, &compute_shader_module); + + uint32_t unit_size = sizeof(uint32_t); + uint32_t group_count_x = ahb_size / 32u / 32u / unit_size; + if (ahb_size % (32u * 32u * unit_size) != 0) + ++group_count_x; + uint32_t rowLength = group_count_x * 32u; + + VkSpecializationMapEntry specialization_entries[2]; + specialization_entries[0].constantID = 0u; + specialization_entries[0].offset = 0u; + specialization_entries[0].size = sizeof(uint32_t); + specialization_entries[1].constantID = 1u; + specialization_entries[1].offset = sizeof(uint32_t); + specialization_entries[1].size = sizeof(uint32_t); + + uint32_t specialization_data[2]; + specialization_data[0] = rowLength; + specialization_data[1] = ahb_size / sizeof(uint32_t); + + VkSpecializationInfo specialization_info; + specialization_info.mapEntryCount = 2u; + specialization_info.pMapEntries = specialization_entries; + specialization_info.dataSize = sizeof(uint32_t) * 2u; + specialization_info.pData = specialization_data; + + VkPipelineShaderStageCreateInfo shader_stage_create_info; + shader_stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shader_stage_create_info.pNext = nullptr; + shader_stage_create_info.flags = 0u; + shader_stage_create_info.stage = VK_SHADER_STAGE_COMPUTE_BIT; + shader_stage_create_info.module = compute_shader_module; + shader_stage_create_info.pName = "main"; + shader_stage_create_info.pSpecializationInfo = &specialization_info; + + VkDescriptorSetLayoutBinding bindings[2]; + bindings[0].binding = 0u; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[0].descriptorCount = 1u; + bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindings[0].pImmutableSamplers = nullptr; + bindings[1].binding = 1u; + bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + bindings[1].descriptorCount = 1u; + bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindings[1].pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info; + descriptor_set_layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptor_set_layout_create_info.pNext = nullptr; + descriptor_set_layout_create_info.flags = 0u; + descriptor_set_layout_create_info.bindingCount = 2u; + descriptor_set_layout_create_info.pBindings = bindings; + + VkDescriptorSetLayout descriptor_set_layout = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateDescriptorSetLayout( + device, &descriptor_set_layout_create_info, nullptr, &descriptor_set_layout); + + VkPipelineLayoutCreateInfo pipeline_layout_create_info; + pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeline_layout_create_info.pNext = nullptr; + pipeline_layout_create_info.flags = 0u; + pipeline_layout_create_info.setLayoutCount = 1u; + pipeline_layout_create_info.pSetLayouts = &descriptor_set_layout; + pipeline_layout_create_info.pushConstantRangeCount = 0u; + pipeline_layout_create_info.pPushConstantRanges = nullptr; + + VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = + device_table->CreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &pipeline_layout); + + VkComputePipelineCreateInfo compute_pipeline_create_info; + compute_pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + compute_pipeline_create_info.pNext = nullptr; + compute_pipeline_create_info.flags = 0u; + compute_pipeline_create_info.stage = shader_stage_create_info; + compute_pipeline_create_info.layout = pipeline_layout; + compute_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; + compute_pipeline_create_info.basePipelineIndex = -1; + + VkPipeline compute_pipeline = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateComputePipelines( + device, VK_NULL_HANDLE, 1u, &compute_pipeline_create_info, nullptr, &compute_pipeline); + + VkDescriptorPoolSize pool_size; + pool_size.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + pool_size.descriptorCount = 2u; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info; + descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptor_pool_create_info.pNext = nullptr; + descriptor_pool_create_info.flags = 0u; + descriptor_pool_create_info.maxSets = 1u; + descriptor_pool_create_info.poolSizeCount = 1u; + descriptor_pool_create_info.pPoolSizes = &pool_size; + + VkDescriptorPool descriptor_pool = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = + device_table->CreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, &descriptor_pool); + + VkDescriptorSetAllocateInfo descriptor_set_allocate_info; + descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + descriptor_set_allocate_info.pNext = nullptr; + descriptor_set_allocate_info.descriptorPool = descriptor_pool; + descriptor_set_allocate_info.descriptorSetCount = 1u; + descriptor_set_allocate_info.pSetLayouts = &descriptor_set_layout; + + VkDescriptorSet descriptor_set = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = device_table->AllocateDescriptorSets(device, &descriptor_set_allocate_info, &descriptor_set); + + VkDescriptorBufferInfo buffer_infos[2]; + buffer_infos[0].buffer = ahb_data_buffer; + buffer_infos[0].offset = 0u; + buffer_infos[0].range = VK_WHOLE_SIZE; + buffer_infos[1].buffer = host_buffer; + buffer_infos[1].offset = 0u; + buffer_infos[1].range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet descriptor_writes[2]; + descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[0].pNext = nullptr; + descriptor_writes[0].dstSet = descriptor_set; + descriptor_writes[0].dstBinding = 0u; + descriptor_writes[0].dstArrayElement = 0u; + descriptor_writes[0].descriptorCount = 1u; + descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[0].pImageInfo = nullptr; + descriptor_writes[0].pBufferInfo = &buffer_infos[0]; + descriptor_writes[0].pTexelBufferView = nullptr; + descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[1].pNext = nullptr; + descriptor_writes[1].dstSet = descriptor_set; + descriptor_writes[1].dstBinding = 1u; + descriptor_writes[1].dstArrayElement = 0u; + descriptor_writes[1].descriptorCount = 1u; + descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[1].pImageInfo = nullptr; + descriptor_writes[1].pBufferInfo = &buffer_infos[1]; + descriptor_writes[1].pTexelBufferView = nullptr; + + if (vk_result == VK_SUCCESS) + device_table->UpdateDescriptorSets(device, 2u, descriptor_writes, 0u, nullptr); + + VkCommandPoolCreateInfo command_pool_create_info; + command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + command_pool_create_info.pNext = nullptr; + command_pool_create_info.flags = 0u; + command_pool_create_info.queueFamilyIndex = queue_family_index; + + VkCommandPool command_pool; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateCommandPool(device, &command_pool_create_info, nullptr, &command_pool); + + VkCommandBufferAllocateInfo command_buffer_allocate_info; + command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_allocate_info.pNext = nullptr; + command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_allocate_info.commandPool = command_pool; + command_buffer_allocate_info.commandBufferCount = 1u; + + VkCommandBuffer command_buffer; + if (vk_result == VK_SUCCESS) + vk_result = device_table->AllocateCommandBuffers(device, &command_buffer_allocate_info, &command_buffer); + + VkCommandBufferBeginInfo command_buffer_begin_info; + command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + command_buffer_begin_info.pNext = nullptr; + command_buffer_begin_info.flags = 0u; + command_buffer_begin_info.pInheritanceInfo = nullptr; + if (vk_result == VK_SUCCESS) + vk_result = device_table->BeginCommandBuffer(command_buffer, &command_buffer_begin_info); + + if (vk_result == VK_SUCCESS) + { + VkBufferMemoryBarrier pre_buffer_barriers[2]; + pre_buffer_barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + pre_buffer_barriers[0].pNext = nullptr; + pre_buffer_barriers[0].srcAccessMask = VK_ACCESS_NONE; + pre_buffer_barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + pre_buffer_barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_buffer_barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_buffer_barriers[0].buffer = ahb_data_buffer; + pre_buffer_barriers[0].offset = 0u; + pre_buffer_barriers[0].size = ahb_size; + pre_buffer_barriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + pre_buffer_barriers[1].pNext = nullptr; + pre_buffer_barriers[1].srcAccessMask = VK_ACCESS_NONE; + pre_buffer_barriers[1].dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + pre_buffer_barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_buffer_barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_buffer_barriers[1].buffer = host_buffer; + pre_buffer_barriers[1].offset = 0u; + pre_buffer_barriers[1].size = ahb_size; + + device_table->CmdPipelineBarrier(command_buffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + 0, + 0, + nullptr, + 2, + pre_buffer_barriers, + 0, + nullptr); + + device_table->CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline); + device_table->CmdBindDescriptorSets( + command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set, 0, nullptr); + device_table->CmdDispatch(command_buffer, group_count_x, 1u, 1u); + + VkBufferMemoryBarrier post_buffer_barrier; + post_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + post_buffer_barrier.pNext = nullptr; + post_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + post_buffer_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT; + post_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + post_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + post_buffer_barrier.buffer = host_buffer; + post_buffer_barrier.offset = 0u; + post_buffer_barrier.size = ahb_size; + + device_table->CmdPipelineBarrier(command_buffer, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_HOST_BIT, + 0, + 0, + nullptr, + 1, + &post_buffer_barrier, + 0, + nullptr); + + device_table->EndCommandBuffer(command_buffer); + } - // Dump zeros for AHB payload. - std::vector zeros(allocation_size, 0); - CommonWriteFillMemoryCmd(memory_id, zeros.size(), zeros.data(), vulkan_capture_manager, vulkan_state_writer); + VkSubmitInfo submit_info; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 0u; + submit_info.pWaitSemaphores = nullptr; + submit_info.pWaitDstStageMask = nullptr; + submit_info.commandBufferCount = 1u; + submit_info.pCommandBuffers = &command_buffer; + submit_info.signalSemaphoreCount = 0u; + submit_info.pSignalSemaphores = nullptr; + + VkFenceCreateInfo fence_create_info; + fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_create_info.pNext = nullptr; + fence_create_info.flags = 0u; + + VkFence fence; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateFence(device, &fence_create_info, nullptr, &fence); + + auto queue = device_wrapper->child_queues[0]->handle; + if (vk_result == VK_SUCCESS) + vk_result = device_table->QueueSubmit(queue, 1, &submit_info, fence); + if (vk_result == VK_SUCCESS) + vk_result = device_table->WaitForFences(device, 1u, &fence, VK_TRUE, UINT64_MAX); + + void* data; + if (vk_result == VK_SUCCESS) + vk_result = device_table->MapMemory(device, host_buffer_memory, 0u, ahb_size, 0u, &data); + + if (vk_result == VK_SUCCESS) + { + CommonWriteFillMemoryCmd(memory_id, ahb_size, data, vulkan_capture_manager, vulkan_state_writer); + + if (vulkan_capture_manager) + { + // Track the memory with the PageGuardManager + const auto tracking_mode = vulkan_capture_manager->GetMemoryTrackingMode(); + if ((tracking_mode == CaptureSettings::MemoryTrackingMode::kPageGuard || + tracking_mode == CaptureSettings::MemoryTrackingMode::kUserfaultfd) && + vulkan_capture_manager->GetPageGuardTrackAhbMemory()) + { + GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, ahb_size); + + util::PageGuardManager* manager = util::PageGuardManager::Get(); + GFXRECON_ASSERT(manager != nullptr); + + manager->AddTrackedMemory(memory_id, + data, + 0, + static_cast(ahb_size), + util::PageGuardManager::kNullShadowHandle, + false, // No shadow memory for the imported AHB memory. + false); // Write watch is not supported for this case. + } + } + } - GFXRECON_LOG_WARNING("AHardwareBuffer cannot be read: hardware buffer data will be omitted " - "from the capture file"); + device_table->DestroyFence(device, fence, nullptr); + device_table->DestroyCommandPool(device, command_pool, nullptr); + device_table->DestroyDescriptorPool(device, descriptor_pool, nullptr); + device_table->DestroyPipeline(device, compute_pipeline, nullptr); + device_table->DestroyDescriptorSetLayout(device, descriptor_set_layout, nullptr); + device_table->DestroyPipelineLayout(device, pipeline_layout, nullptr); + device_table->DestroyShaderModule(device, compute_shader_module, nullptr); + device_table->FreeMemory(device, buffer_memory, nullptr); + device_table->FreeMemory(device, host_buffer_memory, nullptr); + device_table->DestroyBuffer(device, ahb_data_buffer, nullptr); + device_table->DestroyBuffer(device, host_buffer, nullptr); + + if (vk_result != VK_SUCCESS) + GFXRECON_LOG_ERROR("Failed to copy data from AHardwareBuffer that is not cpu readable"); } #else GFXRECON_UNREFERENCED_PARAMETER(thread_id); diff --git a/framework/encode/vulkan_capture_common.h b/framework/encode/vulkan_capture_common.h index 76bc5a0c2a..62e88b021d 100644 --- a/framework/encode/vulkan_capture_common.h +++ b/framework/encode/vulkan_capture_common.h @@ -33,19 +33,13 @@ GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(encode) -void CommonWriteCreateHardwareBufferCmd(format::ThreadId thread_id, - format::HandleId memory_id, - AHardwareBuffer* hardware_buffer, - const std::vector& plane_info, - VulkanCaptureManager* vulkan_capture_manager, - VulkanStateWriter* vulkan_state_writer); - -void CommonProcessHardwareBuffer(format::ThreadId thread_id, - format::HandleId memory_id, - AHardwareBuffer* hardware_buffer, - size_t allocation_size, - VulkanCaptureManager* vulkan_capture_manager, - VulkanStateWriter* vulkan_state_writer); +void CommonProcessHardwareBuffer(format::ThreadId thread_id, + const vulkan_wrappers::DeviceWrapper* device_wrapper, + format::HandleId memory_id, + AHardwareBuffer* hardware_buffer, + size_t allocation_size, + VulkanCaptureManager* vulkan_capture_manager, + VulkanStateWriter* vulkan_state_writer); GFXRECON_END_NAMESPACE(encode) GFXRECON_END_NAMESPACE(gfxrecon) diff --git a/framework/encode/vulkan_capture_manager.cpp b/framework/encode/vulkan_capture_manager.cpp index 1426989f5a..ada351b0e8 100644 --- a/framework/encode/vulkan_capture_manager.cpp +++ b/framework/encode/vulkan_capture_manager.cpp @@ -738,12 +738,14 @@ VkResult VulkanCaptureManager::OverrideCreateDevice(VkPhysicalDevice wrapper->physical_device = physical_device_wrapper; } + wrapper->queue_family_indices.resize(pCreateInfo_unwrapped->queueCreateInfoCount); for (uint32_t q = 0; q < pCreateInfo_unwrapped->queueCreateInfoCount; ++q) { const VkDeviceQueueCreateInfo* queue_create_info = &pCreateInfo_unwrapped->pQueueCreateInfos[q]; assert(wrapper->queue_family_creation_flags.find(queue_create_info->queueFamilyIndex) == wrapper->queue_family_creation_flags.end()); wrapper->queue_family_creation_flags[queue_create_info->queueFamilyIndex] = queue_create_info->flags; + wrapper->queue_family_indices[q] = pCreateInfo_unwrapped->pQueueCreateInfos[q].queueFamilyIndex; } } @@ -1752,7 +1754,8 @@ void VulkanCaptureManager::ProcessHardwareBuffer(format::ThreadId thread_id, { const size_t ahb_size = properties.allocationSize; assert(ahb_size); - CommonProcessHardwareBuffer(thread_id, memory_id, hardware_buffer, ahb_size, this, nullptr); + + CommonProcessHardwareBuffer(thread_id, device_wrapper, memory_id, hardware_buffer, ahb_size, this, nullptr); } else { diff --git a/framework/encode/vulkan_handle_wrappers.h b/framework/encode/vulkan_handle_wrappers.h index 99b3ff3a23..82fe1d486c 100644 --- a/framework/encode/vulkan_handle_wrappers.h +++ b/framework/encode/vulkan_handle_wrappers.h @@ -169,6 +169,7 @@ struct DeviceWrapper : public HandleWrapper // Physical device property & feature state at device creation graphics::VulkanDevicePropertyFeatureInfo property_feature_info; std::unordered_map queue_family_creation_flags; + std::vector queue_family_indices; }; struct FenceWrapper : public HandleWrapper diff --git a/framework/encode/vulkan_state_writer.cpp b/framework/encode/vulkan_state_writer.cpp index 835d30b328..9e95fb7ef7 100644 --- a/framework/encode/vulkan_state_writer.cpp +++ b/framework/encode/vulkan_state_writer.cpp @@ -1368,6 +1368,7 @@ void VulkanStateWriter::WriteDeviceMemoryState(const VulkanStateTable& state_tab { const vulkan_wrappers::DeviceMemoryWrapper* wrapper = hardware_buffer.second; CommonProcessHardwareBuffer(thread_data_->thread_id_, + wrapper->parent_device, wrapper->hardware_buffer_memory_id, wrapper->hardware_buffer, wrapper->allocation_size, diff --git a/framework/format/format.h b/framework/format/format.h index 3a55840b96..df285d36c9 100644 --- a/framework/format/format.h +++ b/framework/format/format.h @@ -122,42 +122,42 @@ enum AdapterType enum class MetaDataType : uint16_t { - kUnknownMetaDataType = 0, - kDisplayMessageCommand = 1, - kFillMemoryCommand = 2, - kResizeWindowCommand = 3, - kSetSwapchainImageStateCommand = 4, - kBeginResourceInitCommand = 5, - kEndResourceInitCommand = 6, - kInitBufferCommand = 7, - kInitImageCommand = 8, - kCreateHardwareBufferCommand_deprecated = 9, - kDestroyHardwareBufferCommand = 10, - kSetDevicePropertiesCommand = 11, - kSetDeviceMemoryPropertiesCommand = 12, - kResizeWindowCommand2 = 13, - kSetOpaqueAddressCommand = 14, - kSetRayTracingShaderGroupHandlesCommand = 15, - kCreateHeapAllocationCommand = 16, - kInitSubresourceCommand = 17, - kExeFileInfoCommand = 18, - kInitDx12AccelerationStructureCommand = 19, - kFillMemoryResourceValueCommand = 20, - kDxgiAdapterInfoCommand = 21, - kDriverInfoCommand = 22, - kReserved23 = 23, - kCreateHardwareBufferCommand = 24, - kReserved25 = 25, - kDx12RuntimeInfoCommand = 26, - kParentToChildDependency = 27, + kUnknownMetaDataType = 0, + kDisplayMessageCommand = 1, + kFillMemoryCommand = 2, + kResizeWindowCommand = 3, + kSetSwapchainImageStateCommand = 4, + kBeginResourceInitCommand = 5, + kEndResourceInitCommand = 6, + kInitBufferCommand = 7, + kInitImageCommand = 8, + kCreateHardwareBufferCommand_deprecated = 9, + kDestroyHardwareBufferCommand = 10, + kSetDevicePropertiesCommand = 11, + kSetDeviceMemoryPropertiesCommand = 12, + kResizeWindowCommand2 = 13, + kSetOpaqueAddressCommand = 14, + kSetRayTracingShaderGroupHandlesCommand = 15, + kCreateHeapAllocationCommand = 16, + kInitSubresourceCommand = 17, + kExeFileInfoCommand = 18, + kInitDx12AccelerationStructureCommand = 19, + kFillMemoryResourceValueCommand = 20, + kDxgiAdapterInfoCommand = 21, + kDriverInfoCommand = 22, + kReserved23 = 23, + kCreateHardwareBufferCommand_deprecated2 = 24, + kReserved25 = 25, + kDx12RuntimeInfoCommand = 26, + kParentToChildDependency = 27, kVulkanBuildAccelerationStructuresCommand = 28, kVulkanCopyAccelerationStructuresCommand = 29, kVulkanWriteAccelerationStructuresPropertiesCommand = 30, - kReserved31 = 31, - kSetEnvironmentVariablesCommand = 32, - kViewRelativeLocation = 33, - kExecuteBlocksFromFile = 34, - kReserved35 = 35 + kReserved31 = 31, + kSetEnvironmentVariablesCommand = 32, + kViewRelativeLocation = 33, + kExecuteBlocksFromFile = 34, + kCreateHardwareBufferCommand = 35, }; // MetaDataId is stored in the capture file and its type must be uint32_t to avoid breaking capture file compatibility. @@ -406,10 +406,28 @@ struct CreateHardwareBufferCommandHeader_deprecated // HardwareBufferLayerInfo records. When unavailable, 'planes' is zero. }; +struct CreateHardwareBufferCommandHeader_deprecated2 +{ + MetaDataHeader meta_header; + ThreadId thread_id; + HandleId memory_id; // Globally unique ID assigned to the buffer for tracking memory modifications. + uint64_t buffer_id; // Address of the buffer object. + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t stride; // Size of a row in pixels. + uint64_t usage; + uint32_t layers; + uint32_t planes; // When additional multi-plane data is available, header is followed by 'planes' count + // HardwareBufferLayerInfo records. When unavailable, 'planes' is zero. +}; + struct CreateHardwareBufferCommandHeader { MetaDataHeader meta_header; ThreadId thread_id; + HandleId device_id; + HandleId queue_id; HandleId memory_id; // Globally unique ID assigned to the buffer for tracking memory modifications. uint64_t buffer_id; // Address of the buffer object. uint32_t format; From 6061402abb718c72319944bdb9da0d7c93276846 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Wed, 26 Feb 2025 11:46:22 +0100 Subject: [PATCH 02/16] util: Enable/check getPhysicalDeviceProperties2 Device utilities check for features and properties using vkGetPhysicalDeviceProperties2 which is available from Vulkan version 1.1 or its KHR version by enabling the corresponding extension. Make sure to enable this extension when API version is < 1.1 and only call vkGetPhysicalDeviceProperties2KHR if it was available and enabled. --- android/framework/graphics/CMakeLists.txt | 2 + framework/decode/vulkan_address_replacer.cpp | 2 +- framework/decode/vulkan_feature_util.cpp | 16 +++++++ framework/decode/vulkan_feature_util.h | 4 ++ framework/decode/vulkan_object_info.h | 14 +++--- .../decode/vulkan_replay_consumer_base.cpp | 48 +++++++++++-------- framework/encode/vulkan_capture_manager.cpp | 10 ++-- framework/encode/vulkan_handle_wrappers.h | 27 ++++++----- framework/encode/vulkan_state_writer.cpp | 12 ++--- framework/graphics/CMakeLists.txt | 2 + framework/graphics/vulkan_device_util.cpp | 35 +++++++------- framework/graphics/vulkan_device_util.h | 14 ++++-- framework/graphics/vulkan_instance_util.cpp | 46 ++++++++++++++++++ framework/graphics/vulkan_instance_util.h | 45 +++++++++++++++++ 14 files changed, 203 insertions(+), 74 deletions(-) create mode 100644 framework/graphics/vulkan_instance_util.cpp create mode 100644 framework/graphics/vulkan_instance_util.h diff --git a/android/framework/graphics/CMakeLists.txt b/android/framework/graphics/CMakeLists.txt index ee9b24ee59..3f9539ae50 100644 --- a/android/framework/graphics/CMakeLists.txt +++ b/android/framework/graphics/CMakeLists.txt @@ -8,6 +8,8 @@ target_sources(gfxrecon_graphics ${GFXRECON_SOURCE_DIR}/framework/graphics/vulkan_check_buffer_references.cpp ${GFXRECON_SOURCE_DIR}/framework/graphics/vulkan_device_util.h ${GFXRECON_SOURCE_DIR}/framework/graphics/vulkan_device_util.cpp + ${GFXRECON_SOURCE_DIR}/framework/graphics/vulkan_instance_util.h + ${GFXRECON_SOURCE_DIR}/framework/graphics/vulkan_instance_util.cpp ${GFXRECON_SOURCE_DIR}/framework/graphics/vulkan_resources_util.h ${GFXRECON_SOURCE_DIR}/framework/graphics/vulkan_resources_util.cpp ${GFXRECON_SOURCE_DIR}/framework/graphics/vulkan_util.h diff --git a/framework/decode/vulkan_address_replacer.cpp b/framework/decode/vulkan_address_replacer.cpp index bc64747774..c2ba6a3ddf 100644 --- a/framework/decode/vulkan_address_replacer.cpp +++ b/framework/decode/vulkan_address_replacer.cpp @@ -181,7 +181,7 @@ VulkanAddressReplacer::VulkanAddressReplacer(const VulkanDeviceInfo* GFXRECON_ASSERT(physical_device_info_ != nullptr); device_ = device_info->handle; resource_allocator_ = device_info->allocator.get(); - get_device_address_fn_ = physical_device_info_->parent_api_version >= VK_API_VERSION_1_2 + get_device_address_fn_ = physical_device_info_->parent_info.api_version >= VK_API_VERSION_1_2 ? device_table->GetBufferDeviceAddress : device_table->GetBufferDeviceAddressKHR; diff --git a/framework/decode/vulkan_feature_util.cpp b/framework/decode/vulkan_feature_util.cpp index b86fbcc622..a08410dc9e 100644 --- a/framework/decode/vulkan_feature_util.cpp +++ b/framework/decode/vulkan_feature_util.cpp @@ -161,6 +161,22 @@ bool IsSupportedExtension(const std::vector& extensions_names, cons return false; } +bool EnableExtensionIfSupported(const std::vector& properties, + std::vector* extensions, + const char* extension) +{ + GFXRECON_ASSERT(extensions != nullptr); + GFXRECON_ASSERT(extension != nullptr); + + if (IsSupportedExtension(properties, extension)) + { + extensions->push_back(extension); + return true; + } + + return false; +} + bool IsIgnorableExtension(const char* extension) { return kIgnorableExtensions.count(extension) > 0; diff --git a/framework/decode/vulkan_feature_util.h b/framework/decode/vulkan_feature_util.h index 9f160ea5ec..fd16936483 100644 --- a/framework/decode/vulkan_feature_util.h +++ b/framework/decode/vulkan_feature_util.h @@ -48,6 +48,10 @@ VkResult GetDeviceExtensions(VkPhysicalDevice physical_d bool IsSupportedExtension(const std::vector& properties, const char* extension); bool IsSupportedExtension(const std::vector& extensions_names, const char* extension); +bool EnableExtensionIfSupported(const std::vector& properties, + std::vector* extensions, + const char* extension); + void RemoveUnsupportedExtensions(const std::vector& properties, std::vector* extensions); diff --git a/framework/decode/vulkan_object_info.h b/framework/decode/vulkan_object_info.h index d1d6536084..e5587fe82d 100644 --- a/framework/decode/vulkan_object_info.h +++ b/framework/decode/vulkan_object_info.h @@ -30,6 +30,7 @@ #include "format/format.h" #include "generated/generated_vulkan_dispatch_table.h" #include "graphics/vulkan_device_util.h" +#include "graphics/vulkan_instance_util.h" #include "graphics/vulkan_shader_group_handle.h" #include "util/defines.h" #include "util/spirv_parsing_util.h" @@ -255,8 +256,7 @@ typedef VulkanObjectInfo VulkanIndirectExecutionSet struct VulkanInstanceInfo : public VulkanObjectInfo { - uint32_t api_version{ VK_MAKE_VERSION(1, 0, 0) }; - std::vector enabled_extensions; + graphics::VulkanInstanceUtilInfo util_info{}; std::unordered_map array_counts; // Capture and replay devices sorted in the order that they were originally retrieved from @@ -269,9 +269,10 @@ struct VulkanInstanceInfo : public VulkanObjectInfo struct VulkanPhysicalDeviceInfo : public VulkanObjectInfo { - VkInstance parent{ VK_NULL_HANDLE }; - uint32_t parent_api_version{ 0 }; - std::vector parent_enabled_extensions; + VkInstance parent{ VK_NULL_HANDLE }; + + graphics::VulkanInstanceUtilInfo parent_info{}; + std::unordered_map array_counts; // Capture device properties. @@ -439,8 +440,7 @@ struct VulkanShaderModuleInfo : public VulkanObjectInfo { ShaderDescriptorInfo( VkDescriptorType _type, bool _readonly, uint32_t _accessed, uint32_t _count, bool _is_array) : - type(_type), - readonly(_readonly), accessed(_accessed), count(_count), is_array(_is_array) + type(_type), readonly(_readonly), accessed(_accessed), count(_count), is_array(_is_array) {} ShaderDescriptorInfo(const ShaderDescriptorInfo& other) = default; diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index 4fb37c831c..77dfec0f5c 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -1834,10 +1834,9 @@ void VulkanReplayConsumerBase::SetPhysicalDeviceInstanceInfo(VulkanInstanceInfo* { assert((instance_info != nullptr) && (physical_device_info != nullptr)); - physical_device_info->parent = instance_info->handle; - physical_device_info->parent_api_version = instance_info->api_version; - physical_device_info->parent_enabled_extensions = instance_info->enabled_extensions; - physical_device_info->replay_device_info = &instance_info->replay_device_info[replay_device]; + physical_device_info->parent = instance_info->handle; + physical_device_info->parent_info = instance_info->util_info; + physical_device_info->replay_device_info = &instance_info->replay_device_info[replay_device]; } void VulkanReplayConsumerBase::SetPhysicalDeviceProperties(VulkanPhysicalDeviceInfo* physical_device_info, @@ -2015,7 +2014,7 @@ bool VulkanReplayConsumerBase::GetOverrideDevice(VulkanInstanceInfo* insta if (replay_device_info->properties == std::nullopt) { - graphics::VulkanDeviceUtil::GetReplayDeviceProperties(physical_device_info->parent_api_version, + graphics::VulkanDeviceUtil::GetReplayDeviceProperties(physical_device_info->parent_info, GetInstanceTable(physical_device_info->handle), physical_device_info->handle, replay_device_info); @@ -2101,7 +2100,7 @@ bool VulkanReplayConsumerBase::GetOverrideDeviceGroup(VulkanInstanceInfo* if (replay_device_info->properties == std::nullopt) { - graphics::VulkanDeviceUtil::GetReplayDeviceProperties(physical_device_info->parent_api_version, + graphics::VulkanDeviceUtil::GetReplayDeviceProperties(physical_device_info->parent_info, GetInstanceTable(physical_device_info->handle), physical_device_info->handle, replay_device_info); @@ -2156,7 +2155,7 @@ void VulkanReplayConsumerBase::GetMatchingDevice(VulkanInstanceInfo* insta if (replay_device_info->properties == std::nullopt) { - graphics::VulkanDeviceUtil::GetReplayDeviceProperties(physical_device_info->parent_api_version, + graphics::VulkanDeviceUtil::GetReplayDeviceProperties(physical_device_info->parent_info, GetInstanceTable(physical_device_info->handle), physical_device_info->handle, replay_device_info); @@ -2180,7 +2179,7 @@ void VulkanReplayConsumerBase::GetMatchingDevice(VulkanInstanceInfo* insta { if (replay_info.properties == std::nullopt) { - graphics::VulkanDeviceUtil::GetReplayDeviceProperties(physical_device_info->parent_api_version, + graphics::VulkanDeviceUtil::GetReplayDeviceProperties(physical_device_info->parent_info, GetInstanceTable(physical_device), physical_device, &replay_info); @@ -2468,7 +2467,7 @@ void VulkanReplayConsumerBase::InitializeResourceAllocator(const VulkanPhysicalD functions.set_debug_utils_object_name = instance_table->SetDebugUtilsObjectNameEXT; functions.set_debug_utils_object_tag = instance_table->SetDebugUtilsObjectTagEXT; - if (physical_device_info->parent_api_version >= VK_MAKE_VERSION(1, 1, 0)) + if (physical_device_info->parent_info.api_version >= VK_MAKE_VERSION(1, 1, 0)) { functions.get_physical_device_memory_properties2 = instance_table->GetPhysicalDeviceMemoryProperties2; functions.get_buffer_memory_requirements2 = device_table->GetBufferMemoryRequirements2; @@ -2478,7 +2477,7 @@ void VulkanReplayConsumerBase::InitializeResourceAllocator(const VulkanPhysicalD } else { - const auto& instance_extensions = physical_device_info->parent_enabled_extensions; + const auto& instance_extensions = physical_device_info->parent_info.enabled_extensions; if (std::find(instance_extensions.begin(), instance_extensions.end(), @@ -2507,7 +2506,7 @@ void VulkanReplayConsumerBase::InitializeResourceAllocator(const VulkanPhysicalD auto replay_device_info = physical_device_info->replay_device_info; assert(replay_device_info->memory_properties); - VkResult result = allocator->Initialize(std::min(physical_device_info->parent_api_version, + VkResult result = allocator->Initialize(std::min(physical_device_info->parent_info.api_version, physical_device_info->replay_device_info->properties->apiVersion), physical_device_info->parent, physical_device_info->handle, @@ -2919,7 +2918,6 @@ bool VulkanReplayConsumerBase::CheckPNextChainForFrameBoundary(const VulkanDevic void VulkanReplayConsumerBase::ModifyCreateInstanceInfo( const StructPointerDecoder* pCreateInfo, CreateInstanceInfoState& create_state) { - const VkInstanceCreateInfo* replay_create_info = pCreateInfo->GetPointer(); if (loader_handle_ == nullptr) @@ -3000,6 +2998,14 @@ void VulkanReplayConsumerBase::ModifyCreateInstanceInfo( } } + // All VK_KHR_get_physical_device_properties2 functionalities are included in Vulkan 1.1, + // otherwise always enable it if available. + if (modified_create_info.pApplicationInfo->apiVersion < VK_MAKE_VERSION(1, 1, 0)) + { + feature_util::EnableExtensionIfSupported( + available_extensions, &modified_extensions, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + } + if (options_.remove_unsupported_features) { // Remove enabled extensions that are not available from the replay instance. @@ -3117,10 +3123,10 @@ void VulkanReplayConsumerBase::PostCreateInstanceUpdateState(const VkInstance if (modified_create_info.pApplicationInfo != nullptr) { - instance_info.api_version = modified_create_info.pApplicationInfo->apiVersion; - instance_info.enabled_extensions.assign(modified_create_info.ppEnabledExtensionNames, - modified_create_info.ppEnabledExtensionNames + - modified_create_info.enabledExtensionCount); + instance_info.util_info.api_version = modified_create_info.pApplicationInfo->apiVersion; + instance_info.util_info.enabled_extensions.assign(modified_create_info.ppEnabledExtensionNames, + modified_create_info.ppEnabledExtensionNames + + modified_create_info.enabledExtensionCount); } } @@ -3291,7 +3297,7 @@ void VulkanReplayConsumerBase::ModifyCreateDeviceInfo( // Enable necessary features create_state.property_feature_info = create_state.device_util.EnableRequiredPhysicalDeviceFeatures( - physical_device_info->parent_api_version, instance_table, physical_device, &modified_create_info); + physical_device_info->parent_info, instance_table, physical_device, &modified_create_info); // Abort on/Remove unsupported features feature_util::CheckUnsupportedFeatures(physical_device, @@ -7081,11 +7087,11 @@ VkResult VulkanReplayConsumerBase::OverrideCreateSwapchainKHR( auto colorspace_extension_map_iterator = kColorSpaceExtensionMap.find(replay_create_info->imageColorSpace); if (colorspace_extension_map_iterator != kColorSpaceExtensionMap.end()) { - auto supported_extension_iterator = std::find(instance_info->enabled_extensions.begin(), - instance_info->enabled_extensions.end(), + auto supported_extension_iterator = std::find(instance_info->util_info.enabled_extensions.begin(), + instance_info->util_info.enabled_extensions.end(), colorspace_extension_map_iterator->second); colorspace_extension_used_unsupported = - supported_extension_iterator == instance_info->enabled_extensions.end(); + supported_extension_iterator == instance_info->util_info.enabled_extensions.end(); } if (colorspace_extension_used_unsupported) @@ -9601,7 +9607,7 @@ VkResult VulkanReplayConsumerBase::OverrideGetPhysicalDeviceToolProperties( PointerDecoder* pToolCount, StructPointerDecoder* pToolProperties) { - const auto& instance_extensions = physical_device_info->parent_enabled_extensions; + const auto& instance_extensions = physical_device_info->parent_info.enabled_extensions; if (std::find(instance_extensions.begin(), instance_extensions.end(), VK_EXT_TOOLING_INFO_EXTENSION_NAME) != instance_extensions.end()) { diff --git a/framework/encode/vulkan_capture_manager.cpp b/framework/encode/vulkan_capture_manager.cpp index ada351b0e8..d91b7bfa5d 100644 --- a/framework/encode/vulkan_capture_manager.cpp +++ b/framework/encode/vulkan_capture_manager.cpp @@ -640,7 +640,7 @@ VkResult VulkanCaptureManager::OverrideCreateDevice(VkPhysicalDevice graphics::VulkanDeviceUtil device_util; graphics::VulkanDevicePropertyFeatureInfo property_feature_info = device_util.EnableRequiredPhysicalDeviceFeatures( - physical_device_wrapper->instance_api_version, instance_table, physicalDevice, pCreateInfo_unwrapped); + physical_device_wrapper->instance_info, instance_table, physicalDevice, pCreateInfo_unwrapped); // TODO: Only enable KHR_external_memory_capabilities for 1.0 API version. size_t extension_count = pCreateInfo_unwrapped->enabledExtensionCount; @@ -837,7 +837,7 @@ VkResult VulkanCaptureManager::OverrideCreateBuffer(VkDevice info.buffer = buffer_wrapper->handle; uint64_t opaque_address = 0; - if (device_wrapper->physical_device->instance_api_version >= VK_MAKE_VERSION(1, 2, 0)) + if (device_wrapper->physical_device->instance_info.api_version >= VK_MAKE_VERSION(1, 2, 0)) { opaque_address = device_table->GetBufferOpaqueCaptureAddress(device_unwrapped, &info); } @@ -1105,7 +1105,7 @@ VkResult VulkanCaptureManager::OverrideAllocateMemory(VkDevice memory_wrapper->handle }; uint64_t address = 0; - if (device_wrapper->physical_device->instance_api_version >= VK_MAKE_VERSION(1, 2, 0)) + if (device_wrapper->physical_device->instance_info.api_version >= VK_MAKE_VERSION(1, 2, 0)) { address = vulkan_wrappers::GetDeviceTable(device)->GetDeviceMemoryOpaqueCaptureAddress(device_unwrapped, &info); @@ -1170,7 +1170,7 @@ void VulkanCaptureManager::OverrideGetPhysicalDeviceProperties2(VkPhysicalDevice auto physical_device_wrapper = vulkan_wrappers::GetWrapper(physicalDevice); GFXRECON_ASSERT(physical_device_wrapper != nullptr) - if (physical_device_wrapper->instance_api_version >= VK_MAKE_VERSION(1, 1, 0)) + if (physical_device_wrapper->instance_info.api_version >= VK_MAKE_VERSION(1, 1, 0)) { vulkan_wrappers::GetInstanceTable(physicalDevice)->GetPhysicalDeviceProperties2(physicalDevice, pProperties); } @@ -1700,7 +1700,7 @@ void VulkanCaptureManager::ProcessEnumeratePhysicalDevices(VkResult res physical_device_wrapper->memory_properties = std::move(memory_properties); } - physical_device_wrapper->instance_api_version = instance_wrapper->api_version; + physical_device_wrapper->instance_info.api_version = instance_wrapper->api_version; WriteSetDevicePropertiesCommand(physical_device_id, properties); WriteSetDeviceMemoryPropertiesCommand(physical_device_id, physical_device_wrapper->memory_properties); diff --git a/framework/encode/vulkan_handle_wrappers.h b/framework/encode/vulkan_handle_wrappers.h index 82fe1d486c..8d68c871dd 100644 --- a/framework/encode/vulkan_handle_wrappers.h +++ b/framework/encode/vulkan_handle_wrappers.h @@ -30,6 +30,7 @@ #include "format/format.h" #include "generated/generated_vulkan_dispatch_table.h" #include "graphics/vulkan_device_util.h" +#include "graphics/vulkan_instance_util.h" #include "util/defines.h" #include "util/memory_output_stream.h" #include "util/page_guard_manager.h" @@ -127,9 +128,9 @@ struct DisplayKHRWrapper : public HandleWrapper // handle wrapper, which will filter duplicate handle retrievals and ensure that the wrapper is destroyed. struct PhysicalDeviceWrapper : public HandleWrapper { - VulkanInstanceTable* layer_table_ref{ nullptr }; - std::vector child_displays; - uint32_t instance_api_version{ 0 }; + VulkanInstanceTable* layer_table_ref{ nullptr }; + std::vector child_displays; + graphics::VulkanInstanceUtilInfo instance_info{}; // Track memory types for use when creating snapshots of buffer and image resource memory content. VkPhysicalDeviceMemoryProperties memory_properties{}; @@ -216,16 +217,16 @@ struct BufferWrapper : public HandleWrapper, AssetWrapperBase struct ImageViewWrapper; struct ImageWrapper : public HandleWrapper, AssetWrapperBase { - VkImageType image_type{ VK_IMAGE_TYPE_2D }; - VkFormat format{ VK_FORMAT_UNDEFINED }; - bool external_format{ false }; - VkExtent3D extent{ 0, 0, 0 }; - uint32_t mip_levels{ 0 }; - uint32_t array_layers{ 0 }; - VkSampleCountFlagBits samples{}; - VkImageTiling tiling{}; - VkImageLayout current_layout{ VK_IMAGE_LAYOUT_UNDEFINED }; - bool is_swapchain_image{ false }; + VkImageType image_type{ VK_IMAGE_TYPE_2D }; + VkFormat format{ VK_FORMAT_UNDEFINED }; + bool external_format{ false }; + VkExtent3D extent{ 0, 0, 0 }; + uint32_t mip_levels{ 0 }; + uint32_t array_layers{ 0 }; + VkSampleCountFlagBits samples{}; + VkImageTiling tiling{}; + VkImageLayout current_layout{ VK_IMAGE_LAYOUT_UNDEFINED }; + bool is_swapchain_image{ false }; std::set image_views; }; diff --git a/framework/encode/vulkan_state_writer.cpp b/framework/encode/vulkan_state_writer.cpp index 9e95fb7ef7..ac684d99e2 100644 --- a/framework/encode/vulkan_state_writer.cpp +++ b/framework/encode/vulkan_state_writer.cpp @@ -465,7 +465,7 @@ void VulkanStateWriter::WriteSemaphoreState(const VulkanStateTable& state_table) // Query current semaphore value uint64_t semaphore_value; format::ApiCallId signal_call_id; - if (device_wrapper->physical_device->instance_api_version >= VK_MAKE_VERSION(1, 2, 0)) + if (device_wrapper->physical_device->instance_info.api_version >= VK_MAKE_VERSION(1, 2, 0)) { device_wrapper->layer_table.GetSemaphoreCounterValue( device_wrapper->handle, wrapper->handle, &semaphore_value); @@ -1399,9 +1399,9 @@ void VulkanStateWriter::WriteBufferDeviceAddressState(const VulkanStateTable& st if ((wrapper->device_id != format::kNullHandleId) && (wrapper->address != 0)) { auto physical_device_wrapper = wrapper->bind_device->physical_device; - auto call_id = physical_device_wrapper->instance_api_version >= VK_MAKE_VERSION(1, 2, 0) - ? format::ApiCall_vkGetBufferDeviceAddress - : format::ApiCall_vkGetBufferDeviceAddressKHR; + auto call_id = physical_device_wrapper->instance_info.api_version >= VK_MAKE_VERSION(1, 2, 0) + ? format::ApiCall_vkGetBufferDeviceAddress + : format::ApiCall_vkGetBufferDeviceAddressKHR; parameter_stream_.Clear(); encoder_.EncodeHandleIdValue(wrapper->bind_device->handle_id); @@ -1514,7 +1514,7 @@ void VulkanStateWriter::WriteASInputMemoryState(ASInputBuffer& buffer) }; uint64_t address = 0; - if (device_wrapper->physical_device->instance_api_version >= VK_MAKE_VERSION(1, 2, 0)) + if (device_wrapper->physical_device->instance_info.api_version >= VK_MAKE_VERSION(1, 2, 0)) { buffer.actual_address = device_wrapper->layer_table.GetBufferDeviceAddress(device_wrapper->handle, &buffer_address_info); @@ -1555,7 +1555,7 @@ void VulkanStateWriter::WriteASInputMemoryState(ASInputBuffer& buffer) EncodePNextStruct(&encoder_, buffer_address_info.pNext); encoder_.EncodeHandleIdValue(buffer.handle_id); encoder_.EncodeVkDeviceAddressValue(buffer.actual_address); - auto call_id = device_wrapper->physical_device->instance_api_version >= VK_MAKE_VERSION(1, 2, 0) + auto call_id = device_wrapper->physical_device->instance_info.api_version >= VK_MAKE_VERSION(1, 2, 0) ? format::ApiCall_vkGetBufferDeviceAddress : format::ApiCall_vkGetBufferDeviceAddressKHR; WriteFunctionCall(call_id, ¶meter_stream_); diff --git a/framework/graphics/CMakeLists.txt b/framework/graphics/CMakeLists.txt index 794deb7c2a..e8dcf1491f 100644 --- a/framework/graphics/CMakeLists.txt +++ b/framework/graphics/CMakeLists.txt @@ -48,6 +48,8 @@ target_sources(gfxrecon_graphics ${CMAKE_CURRENT_LIST_DIR}/vulkan_resources_util.cpp ${CMAKE_CURRENT_LIST_DIR}/vulkan_device_util.h ${CMAKE_CURRENT_LIST_DIR}/vulkan_device_util.cpp + ${CMAKE_CURRENT_LIST_DIR}/vulkan_instance_util.h + ${CMAKE_CURRENT_LIST_DIR}/vulkan_instance_util.cpp ${CMAKE_CURRENT_LIST_DIR}/vulkan_util.h ${CMAKE_CURRENT_LIST_DIR}/vulkan_util.cpp ${CMAKE_CURRENT_LIST_DIR}/vulkan_struct_deep_copy.h diff --git a/framework/graphics/vulkan_device_util.cpp b/framework/graphics/vulkan_device_util.cpp index eb20ff6111..8bc1d75696 100644 --- a/framework/graphics/vulkan_device_util.cpp +++ b/framework/graphics/vulkan_device_util.cpp @@ -21,6 +21,7 @@ */ #include "graphics/vulkan_device_util.h" +#include "graphics/vulkan_instance_util.h" #include "decode/vulkan_object_info.h" #include "util/logging.h" @@ -51,7 +52,7 @@ uint32_t GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& memory_prope // Requires Vulkan version >= 1.1 or VK_KHR_get_physical_device_properties2 // feature_struct sType must be set, pNext must be nullptr template -static void GetPhysicalDeviceFeatures(uint32_t instance_api_version, +static void GetPhysicalDeviceFeatures(const VulkanInstanceUtilInfo& instance_info, const encode::VulkanInstanceTable* instance_table, const VkPhysicalDevice physical_device, T& feature_struct) @@ -60,11 +61,11 @@ static void GetPhysicalDeviceFeatures(uint32_t instanc feature_struct.pNext = nullptr; VkPhysicalDeviceFeatures2 features2{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; features2.pNext = &feature_struct; - if (instance_api_version >= VK_MAKE_VERSION(1, 1, 0)) + if (instance_info.api_version >= VK_MAKE_VERSION(1, 1, 0)) { instance_table->GetPhysicalDeviceFeatures2(physical_device, &features2); } - else + else if (instance_info.IsEnabledExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { instance_table->GetPhysicalDeviceFeatures2KHR(physical_device, &features2); } @@ -74,7 +75,7 @@ static void GetPhysicalDeviceFeatures(uint32_t instanc // Requires Vulkan version >= 1.1 or VK_KHR_get_physical_device_properties2 // properties_struct sType must be set, pNext must be nullptr template -static void GetPhysicalDeviceProperties(uint32_t instance_api_version, +static void GetPhysicalDeviceProperties(const VulkanInstanceUtilInfo& instance_info, const encode::VulkanInstanceTable* instance_table, const VkPhysicalDevice physical_device, T& properties_struct) @@ -83,18 +84,18 @@ static void GetPhysicalDeviceProperties(uint32_t insta properties_struct.pNext = nullptr; VkPhysicalDeviceProperties2 properties2{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 }; properties2.pNext = &properties_struct; - if (instance_api_version >= VK_MAKE_VERSION(1, 1, 0)) + if (instance_info.api_version >= VK_MAKE_VERSION(1, 1, 0)) { instance_table->GetPhysicalDeviceProperties2(physical_device, &properties2); } - else + else if (instance_info.IsEnabledExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { instance_table->GetPhysicalDeviceProperties2KHR(physical_device, &properties2); } } template -VkBool32 VulkanDeviceUtil::EnableRequiredBufferDeviceAddressFeatures(uint32_t instance_api_version, +VkBool32 VulkanDeviceUtil::EnableRequiredBufferDeviceAddressFeatures(const VulkanInstanceUtilInfo& instance_info, const encode::VulkanInstanceTable* instance_table, const VkPhysicalDevice physical_device, T* feature_struct) @@ -122,7 +123,7 @@ VkBool32 VulkanDeviceUtil::EnableRequiredBufferDeviceAddressFeatures(uint32_t in { // Get buffer_address properties T supported_features{ feature_struct->sType, nullptr }; - GetPhysicalDeviceFeatures(instance_api_version, instance_table, physical_device, supported_features); + GetPhysicalDeviceFeatures(instance_info, instance_table, physical_device, supported_features); // Enable bufferDeviceAddressCaptureReplay if it is supported if (supported_features.bufferDeviceAddressCaptureReplay) @@ -135,7 +136,7 @@ VkBool32 VulkanDeviceUtil::EnableRequiredBufferDeviceAddressFeatures(uint32_t in } VulkanDevicePropertyFeatureInfo -VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(uint32_t instance_api_version, +VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(const VulkanInstanceUtilInfo& instance_info, const encode::VulkanInstanceTable* instance_table, const VkPhysicalDevice physical_device, const VkDeviceCreateInfo* create_info) @@ -151,7 +152,7 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(uint32_t { auto vulkan_1_2_features = reinterpret_cast(current_struct); result.feature_bufferDeviceAddressCaptureReplay = EnableRequiredBufferDeviceAddressFeatures( - instance_api_version, instance_table, physical_device, vulkan_1_2_features); + instance_info, instance_table, physical_device, vulkan_1_2_features); } break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES: @@ -159,7 +160,7 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(uint32_t auto buffer_address_features = reinterpret_cast(current_struct); result.feature_bufferDeviceAddressCaptureReplay = EnableRequiredBufferDeviceAddressFeatures( - instance_api_version, instance_table, physical_device, buffer_address_features); + instance_info, instance_table, physical_device, buffer_address_features); } break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR: @@ -178,8 +179,7 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(uint32_t VkPhysicalDeviceAccelerationStructureFeaturesKHR supported_features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR, nullptr }; - GetPhysicalDeviceFeatures( - instance_api_version, instance_table, physical_device, supported_features); + GetPhysicalDeviceFeatures(instance_info, instance_table, physical_device, supported_features); // Enable accelerationStructureCaptureReplay if it is supported if (supported_features.accelerationStructureCaptureReplay) @@ -208,8 +208,7 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(uint32_t VkPhysicalDeviceRayTracingPipelineFeaturesKHR supported_features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR, nullptr }; - GetPhysicalDeviceFeatures( - instance_api_version, instance_table, physical_device, supported_features); + GetPhysicalDeviceFeatures(instance_info, instance_table, physical_device, supported_features); result.feature_rayTracingPipelineShaderGroupHandleCaptureReplay = rt_pipeline_features->rayTracingPipelineShaderGroupHandleCaptureReplay && @@ -220,7 +219,7 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(uint32_t VkPhysicalDeviceRayTracingPipelinePropertiesKHR rt_properties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR, nullptr }; - GetPhysicalDeviceProperties(instance_api_version, instance_table, physical_device, rt_properties); + GetPhysicalDeviceProperties(instance_info, instance_table, physical_device, rt_properties); result.property_shaderGroupHandleSize = rt_properties.shaderGroupHandleSize; if (result.feature_rayTracingPipelineShaderGroupHandleCaptureReplay) @@ -259,7 +258,7 @@ void VulkanDeviceUtil::RestoreModifiedPhysicalDeviceFeatures() } } -void VulkanDeviceUtil::GetReplayDeviceProperties(uint32_t instance_api_version, +void VulkanDeviceUtil::GetReplayDeviceProperties(const VulkanInstanceUtilInfo& instance_info, const encode::VulkanInstanceTable* instance_table, VkPhysicalDevice physical_device, decode::VulkanReplayDeviceInfo* replay_device_info) @@ -270,7 +269,7 @@ void VulkanDeviceUtil::GetReplayDeviceProperties(uint32_t VkPhysicalDeviceProperties2 device_properties2; device_properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - if (instance_api_version >= VK_MAKE_VERSION(1, 1, 0)) + if (instance_info.api_version >= VK_MAKE_VERSION(1, 1, 0)) { // pNext-chaining VkPhysicalDeviceRayTracingPipelinePropertiesKHR raytracing_properties; diff --git a/framework/graphics/vulkan_device_util.h b/framework/graphics/vulkan_device_util.h index eaa91dace1..0830d93fb8 100644 --- a/framework/graphics/vulkan_device_util.h +++ b/framework/graphics/vulkan_device_util.h @@ -37,10 +37,18 @@ struct VulkanReplayDeviceInfo; GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(graphics) +struct VulkanInstanceUtilInfo; + uint32_t GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& memory_properties, uint32_t type_bits, VkMemoryPropertyFlags property_flags); +struct VulkanInstanceVersionExtensionInfo +{ + uint32_t api_version{ VK_MAKE_VERSION(1, 0, 0) }; + std::vector enabled_extensions; +}; + struct VulkanDevicePropertyFeatureInfo { uint32_t property_shaderGroupHandleSize{ 0 }; @@ -59,7 +67,7 @@ class VulkanDeviceUtil // to revert incoming data to original values (e.g., prior to writing to the capture file). // feature_* property_* members store the state of the features/properties after this call. VulkanDevicePropertyFeatureInfo - EnableRequiredPhysicalDeviceFeatures(uint32_t instance_api_version, + EnableRequiredPhysicalDeviceFeatures(const VulkanInstanceUtilInfo& instance_info, const encode::VulkanInstanceTable* instance_table, const VkPhysicalDevice physical_device, const VkDeviceCreateInfo* create_info); @@ -68,14 +76,14 @@ class VulkanDeviceUtil void RestoreModifiedPhysicalDeviceFeatures(); // Populates various property-structs in the provided replay_device_info - static void GetReplayDeviceProperties(uint32_t instance_api_version, + static void GetReplayDeviceProperties(const VulkanInstanceUtilInfo& instance_info, const encode::VulkanInstanceTable* instance_table, VkPhysicalDevice physical_device, decode::VulkanReplayDeviceInfo* replay_device_info); private: template - VkBool32 EnableRequiredBufferDeviceAddressFeatures(uint32_t instance_api_version, + VkBool32 EnableRequiredBufferDeviceAddressFeatures(const VulkanInstanceUtilInfo& instance_info, const encode::VulkanInstanceTable* instance_table, const VkPhysicalDevice physical_device, T* feature_struct); diff --git a/framework/graphics/vulkan_instance_util.cpp b/framework/graphics/vulkan_instance_util.cpp new file mode 100644 index 0000000000..9b31a5e445 --- /dev/null +++ b/framework/graphics/vulkan_instance_util.cpp @@ -0,0 +1,46 @@ +/* +** Copyright (c) 2025 LunarG, Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and associated documentation files (the "Software"), +** to deal in the Software without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Software, and to permit persons to whom the +** Software is furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +*/ + +#include "graphics/vulkan_instance_util.h" + +#include "util/platform.h" + +GFXRECON_BEGIN_NAMESPACE(gfxrecon) +GFXRECON_BEGIN_NAMESPACE(graphics) + +bool VulkanInstanceUtilInfo::IsEnabledExtension(const char* extension) const +{ + GFXRECON_ASSERT(extension != nullptr); + + for (const auto& name : enabled_extensions) + { + if (util::platform::StringCompare(name.c_str(), extension) == 0) + { + return true; + } + } + + return false; +} + +GFXRECON_END_NAMESPACE(graphics) +GFXRECON_END_NAMESPACE(gfxrecon) diff --git a/framework/graphics/vulkan_instance_util.h b/framework/graphics/vulkan_instance_util.h new file mode 100644 index 0000000000..617d629181 --- /dev/null +++ b/framework/graphics/vulkan_instance_util.h @@ -0,0 +1,45 @@ +/* +** Copyright (c) 2025 LunarG, Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and associated documentation files (the "Software"), +** to deal in the Software without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Software, and to permit persons to whom the +** Software is furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +*/ + +#ifndef GFXRECON_GRAPHICS_VULKAN_INSTANCE_UTIL_H +#define GFXRECON_GRAPHICS_VULKAN_INSTANCE_UTIL_H + +#include "generated/generated_vulkan_dispatch_table.h" +#include "util/defines.h" + +#include "vulkan/vulkan.h" + +GFXRECON_BEGIN_NAMESPACE(gfxrecon) +GFXRECON_BEGIN_NAMESPACE(graphics) + +struct VulkanInstanceUtilInfo +{ + uint32_t api_version{ VK_MAKE_VERSION(1, 0, 0) }; + std::vector enabled_extensions{}; + + bool IsEnabledExtension(const char* extension) const; +}; + +GFXRECON_END_NAMESPACE(graphics) +GFXRECON_END_NAMESPACE(gfxrecon) + +#endif // GFXRECON_GRAPHICS_VULKAN_INSTANCE_UTIL_H From 5b2263e11196f63c8836f6975b16bfa506307b0f Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Thu, 20 Feb 2025 09:41:13 +0100 Subject: [PATCH 03/16] util: Enable samplerYcbcrConversion features Non-CPU readable AHB memory can not be copied, but it can be sampled with a Ycbcr sampler. If available, enable the corresponding feature is enabled for capture. --- framework/graphics/vulkan_device_util.cpp | 78 +++++++++++++++++++++-- framework/graphics/vulkan_device_util.h | 14 +++- 2 files changed, 87 insertions(+), 5 deletions(-) diff --git a/framework/graphics/vulkan_device_util.cpp b/framework/graphics/vulkan_device_util.cpp index 8bc1d75696..6523a0c79f 100644 --- a/framework/graphics/vulkan_device_util.cpp +++ b/framework/graphics/vulkan_device_util.cpp @@ -1,5 +1,5 @@ /* -** Copyright (c) 2021 LunarG, Inc. +** Copyright (c) 2021-2025 LunarG, Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and associated documentation files (the "Software"), @@ -135,6 +135,36 @@ VkBool32 VulkanDeviceUtil::EnableRequiredBufferDeviceAddressFeatures(const Vulka return feature_struct->bufferDeviceAddressCaptureReplay; } +template +VkBool32 VulkanDeviceUtil::EnableSamplerYcbcrConversionFeatures(const VulkanInstanceUtilInfo& instance_info, + const encode::VulkanInstanceTable* instance_table, + const VkPhysicalDevice physical_device, + T* feature_struct) +{ + // Type must be feature struct type that contains samplerYcbcrConversion + static_assert(std::is_same::value || + std::is_same::value, + "Unexpected type for EnableSamplerYcbcrConversionFeatures"); + + // Save original application's feature state + samplerYcbcrConversion_original = feature_struct->samplerYcbcrConversion; + samplerYcbcrConversion_ptr = (&feature_struct->samplerYcbcrConversion); + + // Enable the sampler Ycbcr conversion feature if it supported by the device + if (!feature_struct->samplerYcbcrConversion) + { + T supported_features{ feature_struct->sType, nullptr }; + GetPhysicalDeviceFeatures(instance_info, instance_table, physical_device, supported_features); + + if (supported_features.samplerYcbcrConversion) + { + feature_struct->samplerYcbcrConversion = VK_TRUE; + } + } + + return feature_struct->samplerYcbcrConversion; +} + VulkanDevicePropertyFeatureInfo VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(const VulkanInstanceUtilInfo& instance_info, const encode::VulkanInstanceTable* instance_table, @@ -142,9 +172,18 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(const VulkanInstanceUtilI const VkDeviceCreateInfo* create_info) { VulkanDevicePropertyFeatureInfo result; - VkBaseOutStructure* current_struct = reinterpret_cast(create_info)->pNext; - while (current_struct != nullptr) + GFXRECON_ASSERT(create_info != nullptr); + VkBaseOutStructure* current_struct = + const_cast(reinterpret_cast(create_info)); + + // If the pNext chain includes a VkPhysicalDeviceVulkan11Features structure, then it must not include a + // VkPhysicalDeviceSamplerYcbcrConversionFeatures structure + bool vulkan_1_1_features_found = false; + bool sampler_ycbcr_conversion_features_found = false; + + while (current_struct->pNext != nullptr) { + current_struct = current_struct->pNext; switch (current_struct->sType) { // Enable bufferDeviceAddressCaptureReplay if bufferDeviceAddress feature is enabled @@ -155,6 +194,24 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(const VulkanInstanceUtilI instance_info, instance_table, physical_device, vulkan_1_2_features); } break; + // samplerYcbcrConversion is required for sampling images with external format + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: + { + sampler_ycbcr_conversion_features_found = true; + auto* sampler_ycbcr_conversion_features = + reinterpret_cast(current_struct); + result.feature_samplerYcbcrConversion = EnableSamplerYcbcrConversionFeatures( + instance_info, instance_table, physical_device, sampler_ycbcr_conversion_features); + } + break; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: + { + vulkan_1_1_features_found = true; + auto* vulkan_1_1_features = reinterpret_cast(current_struct); + result.feature_samplerYcbcrConversion = EnableSamplerYcbcrConversionFeatures( + instance_info, instance_table, physical_device, vulkan_1_1_features); + } + break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES: { auto buffer_address_features = @@ -232,7 +289,20 @@ VulkanDeviceUtil::EnableRequiredPhysicalDeviceFeatures(const VulkanInstanceUtilI default: break; } - current_struct = current_struct->pNext; + } + + if (!vulkan_1_1_features_found && !sampler_ycbcr_conversion_features_found) + { + // If the app is not requesting any Vulkan 1.1 feature or sampler YCbCr conversion feature, inject our own. + static VkPhysicalDeviceSamplerYcbcrConversionFeatures sampler_ycbcr_conversion_features = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES + }; + result.feature_samplerYcbcrConversion = EnableSamplerYcbcrConversionFeatures( + instance_info, instance_table, physical_device, &sampler_ycbcr_conversion_features); + if (result.feature_samplerYcbcrConversion == VK_TRUE) + { + current_struct->pNext = reinterpret_cast(&sampler_ycbcr_conversion_features); + } } return result; diff --git a/framework/graphics/vulkan_device_util.h b/framework/graphics/vulkan_device_util.h index 0830d93fb8..53903744e0 100644 --- a/framework/graphics/vulkan_device_util.h +++ b/framework/graphics/vulkan_device_util.h @@ -1,5 +1,5 @@ /* -** Copyright (c) 2021 LunarG, Inc. +** Copyright (c) 2021-2025 LunarG, Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and associated documentation files (the "Software"), @@ -57,6 +57,8 @@ struct VulkanDevicePropertyFeatureInfo VkBool32 feature_bufferDeviceAddressCaptureReplay{ VK_FALSE }; VkBool32 feature_accelerationStructureCaptureReplay{ VK_FALSE }; VkBool32 feature_rayTracingPipelineShaderGroupHandleCaptureReplay{ VK_FALSE }; + + VkBool32 feature_samplerYcbcrConversion{ VK_FALSE }; }; class VulkanDeviceUtil @@ -88,6 +90,12 @@ class VulkanDeviceUtil const VkPhysicalDevice physical_device, T* feature_struct); + template + VkBool32 EnableSamplerYcbcrConversionFeatures(const VulkanInstanceUtilInfo& instance_info, + const encode::VulkanInstanceTable* instance_table, + const VkPhysicalDevice physical_device, + T* feature_struct); + private: // VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddressCaptureReplay VkBool32* bufferDeviceAddressCaptureReplay_ptr{ nullptr }; @@ -100,6 +108,10 @@ class VulkanDeviceUtil // VkPhysicalDeviceRayTracingPipelineFeaturesKHR::rayTracingPipelineShaderGroupHandleCaptureReplay VkBool32* rayTracingPipelineShaderGroupHandleCaptureReplay_ptr{ nullptr }; VkBool32 rayTracingPipelineShaderGroupHandleCaptureReplay_original{ VK_FALSE }; + + // VkPhysicalDeviceSamplerYcbcrConversionFeatures + VkBool32* samplerYcbcrConversion_ptr{ nullptr }; + VkBool32 samplerYcbcrConversion_original{ VK_FALSE }; }; GFXRECON_END_NAMESPACE(graphics) From b095a549e6175d53993d7f4a402463baff426a92 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Wed, 26 Feb 2025 16:00:49 +0100 Subject: [PATCH 04/16] encode: Fix AHB image sampling Import non-CPU readable Android Hardware Buffers with a VkImage. Use a Ycbcr conversion sampler to get data from external unknown format to RGBA8. Finally, read the data from GPU to host for a FillImageMemory command. --- framework/encode/vulkan_capture_common.cpp | 827 +++++++++++++-------- 1 file changed, 505 insertions(+), 322 deletions(-) diff --git a/framework/encode/vulkan_capture_common.cpp b/framework/encode/vulkan_capture_common.cpp index fde1236866..878c7f20e9 100644 --- a/framework/encode/vulkan_capture_common.cpp +++ b/framework/encode/vulkan_capture_common.cpp @@ -300,43 +300,78 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id const size_t ahb_size = properties.allocationSize; GFXRECON_ASSERT(ahb_size > 0); - VkExternalMemoryBufferCreateInfo external_memory_buffer_create_info; - external_memory_buffer_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO; - external_memory_buffer_create_info.pNext = nullptr; - external_memory_buffer_create_info.handleTypes = + VkExternalFormatANDROID external_format = {}; + external_format.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; + external_format.pNext = nullptr; + if (format_properties.format == VK_FORMAT_UNDEFINED) + { + external_format.externalFormat = format_properties.externalFormat; + } + + VkExternalMemoryImageCreateInfo external_memory_image_create_info; + external_memory_image_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; + external_memory_image_create_info.pNext = &external_format; + external_memory_image_create_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; - VkBufferCreateInfo buffer_create_info; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.pNext = &external_memory_buffer_create_info; - buffer_create_info.flags = 0u; - buffer_create_info.size = ahb_size; - buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - buffer_create_info.queueFamilyIndexCount = 0u; - buffer_create_info.pQueueFamilyIndices = nullptr; - - VkBuffer ahb_data_buffer; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateBuffer(device, &buffer_create_info, nullptr, &ahb_data_buffer); + VkImageUsageFlags image_usage = 0; + if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) + { + image_usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + } + if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) + { + image_usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + // If the pNext chain includes a VkExternalFormatANDROID structure whose externalFormat member is not 0, usage + // must not include any usages except VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + // or VK_IMAGE_USAGE_SAMPLED_BIT. + if (format_properties.format != VK_FORMAT_UNDEFINED) + { + image_usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + } - VkMemoryRequirements memory_requirements; - device_table->GetBufferMemoryRequirements(device, ahb_data_buffer, &memory_requirements); + VkImageCreateInfo image_create_info; + image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_create_info.pNext = &external_memory_image_create_info; + image_create_info.flags = 0u; + image_create_info.imageType = VK_IMAGE_TYPE_2D; + image_create_info.format = format_properties.format; + image_create_info.extent = { desc.width, desc.height, 1u }; + image_create_info.mipLevels = 1u; + image_create_info.arrayLayers = 1u; + image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_create_info.usage = image_usage; + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_create_info.queueFamilyIndexCount = 0u; + image_create_info.pQueueFamilyIndices = nullptr; + image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VkImage ahb_image; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateImage(device, &image_create_info, nullptr, &ahb_image); VkImportAndroidHardwareBufferInfoANDROID import_ahb_info; import_ahb_info.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; import_ahb_info.pNext = nullptr; import_ahb_info.buffer = hardware_buffer; + VkMemoryDedicatedAllocateInfo memory_dedicated_allocate_info; + memory_dedicated_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; + memory_dedicated_allocate_info.pNext = &import_ahb_info; + memory_dedicated_allocate_info.image = ahb_image; + memory_dedicated_allocate_info.buffer = VK_NULL_HANDLE; + VkMemoryAllocateInfo memory_allocate_info; memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_allocate_info.pNext = &import_ahb_info; - memory_allocate_info.allocationSize = memory_requirements.size; + memory_allocate_info.pNext = &memory_dedicated_allocate_info; + memory_allocate_info.allocationSize = properties.allocationSize; uint32_t memory_index = memory_properties->memoryTypeCount; for (uint32_t i = 0; i < memory_properties->memoryTypeCount; ++i) { - if ((memory_requirements.memoryTypeBits & (1 << i)) && + if ((properties.memoryTypeBits & (1 << i)) && (memory_properties->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) > 0) { memory_index = i; @@ -346,39 +381,121 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id GFXRECON_ASSERT(memory_index < memory_properties->memoryTypeCount); memory_allocate_info.memoryTypeIndex = memory_index; - VkDeviceMemory buffer_memory; + VkDeviceMemory image_memory; if (vk_result == VK_SUCCESS) - vk_result = device_table->AllocateMemory(device, &memory_allocate_info, nullptr, &buffer_memory); + vk_result = device_table->AllocateMemory(device, &memory_allocate_info, nullptr, &image_memory); if (vk_result == VK_SUCCESS) - vk_result = device_table->BindBufferMemory(device, ahb_data_buffer, buffer_memory, 0); - - VkBufferCreateInfo host_buffer_info; - host_buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - host_buffer_info.pNext = nullptr; - host_buffer_info.flags = 0u; - host_buffer_info.size = ahb_size; - host_buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; - host_buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - host_buffer_info.queueFamilyIndexCount = 0u; - host_buffer_info.pQueueFamilyIndices = nullptr; - - VkBuffer host_buffer; + vk_result = device_table->BindImageMemory(device, ahb_image, image_memory, 0); + + VkSamplerYcbcrConversionCreateInfo sampler_ycbcr_conversion_create_info; + sampler_ycbcr_conversion_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO; + sampler_ycbcr_conversion_create_info.pNext = &external_format; + sampler_ycbcr_conversion_create_info.format = format_properties.format; + sampler_ycbcr_conversion_create_info.ycbcrModel = format_properties.suggestedYcbcrModel; + sampler_ycbcr_conversion_create_info.ycbcrRange = format_properties.suggestedYcbcrRange; + sampler_ycbcr_conversion_create_info.components = format_properties.samplerYcbcrConversionComponents; + sampler_ycbcr_conversion_create_info.xChromaOffset = format_properties.suggestedXChromaOffset; + sampler_ycbcr_conversion_create_info.yChromaOffset = format_properties.suggestedYChromaOffset; + sampler_ycbcr_conversion_create_info.chromaFilter = VK_FILTER_LINEAR; + sampler_ycbcr_conversion_create_info.forceExplicitReconstruction = VK_FALSE; + + VkSamplerYcbcrConversion ycbcr_conversion; if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateBuffer(device, &host_buffer_info, nullptr, &host_buffer); + vk_result = device_table->CreateSamplerYcbcrConversion( + device, &sampler_ycbcr_conversion_create_info, nullptr, &ycbcr_conversion); + + VkSamplerYcbcrConversionInfo sampler_ycbcr_conversion_info = {}; + sampler_ycbcr_conversion_info.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO; + sampler_ycbcr_conversion_info.pNext = nullptr; + sampler_ycbcr_conversion_info.conversion = ycbcr_conversion; + + VkImageViewCreateInfo image_view_create_info; + image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + image_view_create_info.pNext = &sampler_ycbcr_conversion_info; + image_view_create_info.flags = 0u; + image_view_create_info.image = ahb_image; + image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + image_view_create_info.format = format_properties.format; + image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + image_view_create_info.subresourceRange.baseMipLevel = 0u; + image_view_create_info.subresourceRange.levelCount = 1u; + image_view_create_info.subresourceRange.baseArrayLayer = 0u; + image_view_create_info.subresourceRange.layerCount = 1u; + + VkImageView image_view; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateImageView(device, &image_view_create_info, nullptr, &image_view); + + VkSamplerCreateInfo sampler_create_info; + sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + sampler_create_info.pNext = &sampler_ycbcr_conversion_info; + sampler_create_info.flags = 0u; + sampler_create_info.magFilter = VK_FILTER_LINEAR; + sampler_create_info.minFilter = VK_FILTER_LINEAR; + sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + sampler_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler_create_info.mipLodBias = 0.0f; + sampler_create_info.anisotropyEnable = VK_FALSE; + sampler_create_info.maxAnisotropy = 1.0f; + sampler_create_info.compareEnable = VK_FALSE; + sampler_create_info.compareOp = VK_COMPARE_OP_NEVER; + sampler_create_info.minLod = 0.0f; + sampler_create_info.maxLod = 0.0f; + sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + sampler_create_info.unnormalizedCoordinates = VK_FALSE; + VkSampler sampler; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateSampler(device, &sampler_create_info, nullptr, &sampler); - VkMemoryRequirements host_reabable_memory_requirements; - device_table->GetBufferMemoryRequirements(device, host_buffer, &host_reabable_memory_requirements); + VkImageUsageFlags host_image_usage = VK_IMAGE_USAGE_STORAGE_BIT; + VkFormat host_image_format = format_properties.format; + if (format_properties.format == VK_FORMAT_UNDEFINED) + { + host_image_format = VK_FORMAT_R8G8B8A8_UNORM; + } + else + { + host_image_usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + } + + VkImageCreateInfo host_image_create_info{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, nullptr }; + host_image_create_info.flags = 0u; + host_image_create_info.imageType = VK_IMAGE_TYPE_2D; + host_image_create_info.format = host_image_format; + host_image_create_info.extent = { desc.width, desc.height, 1u }; + host_image_create_info.mipLevels = 1u; + host_image_create_info.arrayLayers = 1u; + host_image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + host_image_create_info.tiling = VK_IMAGE_TILING_LINEAR; + host_image_create_info.usage = host_image_usage; + host_image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + host_image_create_info.queueFamilyIndexCount = 0u; + host_image_create_info.pQueueFamilyIndices = nullptr; + host_image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VkImage host_image = VK_NULL_HANDLE; + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateImage(device, &host_image_create_info, nullptr, &host_image); + + VkMemoryRequirements host_readable_memory_requirements; + device_table->GetImageMemoryRequirements(device, host_image, &host_readable_memory_requirements); VkMemoryAllocateInfo host_readable_allocate_info; host_readable_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; host_readable_allocate_info.pNext = nullptr; - host_readable_allocate_info.allocationSize = host_reabable_memory_requirements.size; + host_readable_allocate_info.allocationSize = host_readable_memory_requirements.size; memory_index = memory_properties->memoryTypeCount; for (uint32_t i = 0; i < memory_properties->memoryTypeCount; ++i) { - if ((host_reabable_memory_requirements.memoryTypeBits & (1 << i)) && + if ((host_readable_memory_requirements.memoryTypeBits & (1 << i)) && (memory_properties->memoryTypes[i].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) == (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) @@ -390,232 +507,31 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id GFXRECON_ASSERT(memory_index < memory_properties->memoryTypeCount); host_readable_allocate_info.memoryTypeIndex = memory_index; - VkDeviceMemory host_buffer_memory; - if (vk_result == VK_SUCCESS) - vk_result = - device_table->AllocateMemory(device, &host_readable_allocate_info, nullptr, &host_buffer_memory); - - if (vk_result == VK_SUCCESS) - vk_result = device_table->BindBufferMemory(device, host_buffer, host_buffer_memory, 0); - - // #version 450 - // - // layout(constant_id = 0) const uint rowLength = 1; - // layout(constant_id = 1) const uint totalSize = 1; - // - // layout(local_size_x = 32, local_size_y = 32) in; - // - // layout(set = 0, binding = 0, std430) buffer InputBuffer { - // uint in_data[]; - // }; - // - // layout(set = 0, binding = 1, std430) buffer OutputBuffer { - // uint out_data[]; - // }; - // - // void main() { - // uint i = gl_GlobalInvocationID.y * rowLength + gl_GlobalInvocationID.x; - // if (i < totalSize) { - // out_data[i] = in_data[i]; - // } - // } - - std::vector shader = { - 0x07230203, 0x00010000, 0x0008000b, 0x0000002e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, - 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0006000f, 0x00000005, - 0x00000004, 0x6e69616d, 0x00000000, 0x0000000b, 0x00060010, 0x00000004, 0x00000011, 0x00000020, 0x00000020, - 0x00000001, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00030005, - 0x00000008, 0x00000069, 0x00080005, 0x0000000b, 0x475f6c67, 0x61626f6c, 0x766e496c, 0x7461636f, 0x496e6f69, - 0x00000044, 0x00050005, 0x00000010, 0x4c776f72, 0x74676e65, 0x00000068, 0x00050005, 0x00000017, 0x61746f74, - 0x7a69536c, 0x00000065, 0x00060005, 0x0000001d, 0x7074754f, 0x75427475, 0x72656666, 0x00000000, 0x00060006, - 0x0000001d, 0x00000000, 0x5f74756f, 0x61746164, 0x00000000, 0x00030005, 0x0000001f, 0x00000000, 0x00050005, - 0x00000024, 0x75706e49, 0x66754274, 0x00726566, 0x00050006, 0x00000024, 0x00000000, 0x645f6e69, 0x00617461, - 0x00030005, 0x00000026, 0x00000000, 0x00040047, 0x0000000b, 0x0000000b, 0x0000001c, 0x00040047, 0x00000010, - 0x00000001, 0x00000000, 0x00040047, 0x00000017, 0x00000001, 0x00000001, 0x00040047, 0x0000001c, 0x00000006, - 0x00000004, 0x00050048, 0x0000001d, 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x0000001d, 0x00000003, - 0x00040047, 0x0000001f, 0x00000022, 0x00000000, 0x00040047, 0x0000001f, 0x00000021, 0x00000001, 0x00040047, - 0x00000023, 0x00000006, 0x00000004, 0x00050048, 0x00000024, 0x00000000, 0x00000023, 0x00000000, 0x00030047, - 0x00000024, 0x00000003, 0x00040047, 0x00000026, 0x00000022, 0x00000000, 0x00040047, 0x00000026, 0x00000021, - 0x00000000, 0x00040047, 0x0000002d, 0x0000000b, 0x00000019, 0x00020013, 0x00000002, 0x00030021, 0x00000003, - 0x00000002, 0x00040015, 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, - 0x00040017, 0x00000009, 0x00000006, 0x00000003, 0x00040020, 0x0000000a, 0x00000001, 0x00000009, 0x0004003b, - 0x0000000a, 0x0000000b, 0x00000001, 0x0004002b, 0x00000006, 0x0000000c, 0x00000001, 0x00040020, 0x0000000d, - 0x00000001, 0x00000006, 0x00040032, 0x00000006, 0x00000010, 0x00000001, 0x0004002b, 0x00000006, 0x00000012, - 0x00000000, 0x00040032, 0x00000006, 0x00000017, 0x00000001, 0x00020014, 0x00000018, 0x0003001d, 0x0000001c, - 0x00000006, 0x0003001e, 0x0000001d, 0x0000001c, 0x00040020, 0x0000001e, 0x00000002, 0x0000001d, 0x0004003b, - 0x0000001e, 0x0000001f, 0x00000002, 0x00040015, 0x00000020, 0x00000020, 0x00000001, 0x0004002b, 0x00000020, - 0x00000021, 0x00000000, 0x0003001d, 0x00000023, 0x00000006, 0x0003001e, 0x00000024, 0x00000023, 0x00040020, - 0x00000025, 0x00000002, 0x00000024, 0x0004003b, 0x00000025, 0x00000026, 0x00000002, 0x00040020, 0x00000028, - 0x00000002, 0x00000006, 0x0004002b, 0x00000006, 0x0000002c, 0x00000020, 0x0006002c, 0x00000009, 0x0000002d, - 0x0000002c, 0x0000002c, 0x0000000c, 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, - 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007, 0x00050041, 0x0000000d, 0x0000000e, 0x0000000b, - 0x0000000c, 0x0004003d, 0x00000006, 0x0000000f, 0x0000000e, 0x00050084, 0x00000006, 0x00000011, 0x0000000f, - 0x00000010, 0x00050041, 0x0000000d, 0x00000013, 0x0000000b, 0x00000012, 0x0004003d, 0x00000006, 0x00000014, - 0x00000013, 0x00050080, 0x00000006, 0x00000015, 0x00000011, 0x00000014, 0x0003003e, 0x00000008, 0x00000015, - 0x0004003d, 0x00000006, 0x00000016, 0x00000008, 0x000500b0, 0x00000018, 0x00000019, 0x00000016, 0x00000017, - 0x000300f7, 0x0000001b, 0x00000000, 0x000400fa, 0x00000019, 0x0000001a, 0x0000001b, 0x000200f8, 0x0000001a, - 0x0004003d, 0x00000006, 0x00000022, 0x00000008, 0x0004003d, 0x00000006, 0x00000027, 0x00000008, 0x00060041, - 0x00000028, 0x00000029, 0x00000026, 0x00000021, 0x00000027, 0x0004003d, 0x00000006, 0x0000002a, 0x00000029, - 0x00060041, 0x00000028, 0x0000002b, 0x0000001f, 0x00000021, 0x00000022, 0x0003003e, 0x0000002b, 0x0000002a, - 0x000200f9, 0x0000001b, 0x000200f8, 0x0000001b, 0x000100fd, 0x00010038, - }; - - VkShaderModuleCreateInfo shader_module_create_info; - shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shader_module_create_info.pNext = nullptr; - shader_module_create_info.flags = 0u; - shader_module_create_info.codeSize = shader.size() * sizeof(uint32_t); - shader_module_create_info.pCode = shader.data(); - VkShaderModule compute_shader_module = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = - device_table->CreateShaderModule(device, &shader_module_create_info, nullptr, &compute_shader_module); - - uint32_t unit_size = sizeof(uint32_t); - uint32_t group_count_x = ahb_size / 32u / 32u / unit_size; - if (ahb_size % (32u * 32u * unit_size) != 0) - ++group_count_x; - uint32_t rowLength = group_count_x * 32u; - - VkSpecializationMapEntry specialization_entries[2]; - specialization_entries[0].constantID = 0u; - specialization_entries[0].offset = 0u; - specialization_entries[0].size = sizeof(uint32_t); - specialization_entries[1].constantID = 1u; - specialization_entries[1].offset = sizeof(uint32_t); - specialization_entries[1].size = sizeof(uint32_t); - - uint32_t specialization_data[2]; - specialization_data[0] = rowLength; - specialization_data[1] = ahb_size / sizeof(uint32_t); - - VkSpecializationInfo specialization_info; - specialization_info.mapEntryCount = 2u; - specialization_info.pMapEntries = specialization_entries; - specialization_info.dataSize = sizeof(uint32_t) * 2u; - specialization_info.pData = specialization_data; - - VkPipelineShaderStageCreateInfo shader_stage_create_info; - shader_stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shader_stage_create_info.pNext = nullptr; - shader_stage_create_info.flags = 0u; - shader_stage_create_info.stage = VK_SHADER_STAGE_COMPUTE_BIT; - shader_stage_create_info.module = compute_shader_module; - shader_stage_create_info.pName = "main"; - shader_stage_create_info.pSpecializationInfo = &specialization_info; - - VkDescriptorSetLayoutBinding bindings[2]; - bindings[0].binding = 0u; - bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - bindings[0].descriptorCount = 1u; - bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; - bindings[0].pImmutableSamplers = nullptr; - bindings[1].binding = 1u; - bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - bindings[1].descriptorCount = 1u; - bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; - bindings[1].pImmutableSamplers = nullptr; - - VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info; - descriptor_set_layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptor_set_layout_create_info.pNext = nullptr; - descriptor_set_layout_create_info.flags = 0u; - descriptor_set_layout_create_info.bindingCount = 2u; - descriptor_set_layout_create_info.pBindings = bindings; - - VkDescriptorSetLayout descriptor_set_layout = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateDescriptorSetLayout( - device, &descriptor_set_layout_create_info, nullptr, &descriptor_set_layout); - - VkPipelineLayoutCreateInfo pipeline_layout_create_info; - pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_create_info.pNext = nullptr; - pipeline_layout_create_info.flags = 0u; - pipeline_layout_create_info.setLayoutCount = 1u; - pipeline_layout_create_info.pSetLayouts = &descriptor_set_layout; - pipeline_layout_create_info.pushConstantRangeCount = 0u; - pipeline_layout_create_info.pPushConstantRanges = nullptr; - - VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = - device_table->CreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &pipeline_layout); - - VkComputePipelineCreateInfo compute_pipeline_create_info; - compute_pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - compute_pipeline_create_info.pNext = nullptr; - compute_pipeline_create_info.flags = 0u; - compute_pipeline_create_info.stage = shader_stage_create_info; - compute_pipeline_create_info.layout = pipeline_layout; - compute_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; - compute_pipeline_create_info.basePipelineIndex = -1; - - VkPipeline compute_pipeline = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateComputePipelines( - device, VK_NULL_HANDLE, 1u, &compute_pipeline_create_info, nullptr, &compute_pipeline); - - VkDescriptorPoolSize pool_size; - pool_size.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - pool_size.descriptorCount = 2u; - - VkDescriptorPoolCreateInfo descriptor_pool_create_info; - descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - descriptor_pool_create_info.pNext = nullptr; - descriptor_pool_create_info.flags = 0u; - descriptor_pool_create_info.maxSets = 1u; - descriptor_pool_create_info.poolSizeCount = 1u; - descriptor_pool_create_info.pPoolSizes = &pool_size; - - VkDescriptorPool descriptor_pool = VK_NULL_HANDLE; + VkDeviceMemory host_image_memory = VK_NULL_HANDLE; if (vk_result == VK_SUCCESS) - vk_result = - device_table->CreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, &descriptor_pool); + vk_result = device_table->AllocateMemory(device, &host_readable_allocate_info, nullptr, &host_image_memory); - VkDescriptorSetAllocateInfo descriptor_set_allocate_info; - descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - descriptor_set_allocate_info.pNext = nullptr; - descriptor_set_allocate_info.descriptorPool = descriptor_pool; - descriptor_set_allocate_info.descriptorSetCount = 1u; - descriptor_set_allocate_info.pSetLayouts = &descriptor_set_layout; - - VkDescriptorSet descriptor_set = VK_NULL_HANDLE; if (vk_result == VK_SUCCESS) - vk_result = device_table->AllocateDescriptorSets(device, &descriptor_set_allocate_info, &descriptor_set); - - VkDescriptorBufferInfo buffer_infos[2]; - buffer_infos[0].buffer = ahb_data_buffer; - buffer_infos[0].offset = 0u; - buffer_infos[0].range = VK_WHOLE_SIZE; - buffer_infos[1].buffer = host_buffer; - buffer_infos[1].offset = 0u; - buffer_infos[1].range = VK_WHOLE_SIZE; - - VkWriteDescriptorSet descriptor_writes[2]; - descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[0].pNext = nullptr; - descriptor_writes[0].dstSet = descriptor_set; - descriptor_writes[0].dstBinding = 0u; - descriptor_writes[0].dstArrayElement = 0u; - descriptor_writes[0].descriptorCount = 1u; - descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - descriptor_writes[0].pImageInfo = nullptr; - descriptor_writes[0].pBufferInfo = &buffer_infos[0]; - descriptor_writes[0].pTexelBufferView = nullptr; - descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[1].pNext = nullptr; - descriptor_writes[1].dstSet = descriptor_set; - descriptor_writes[1].dstBinding = 1u; - descriptor_writes[1].dstArrayElement = 0u; - descriptor_writes[1].descriptorCount = 1u; - descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - descriptor_writes[1].pImageInfo = nullptr; - descriptor_writes[1].pBufferInfo = &buffer_infos[1]; - descriptor_writes[1].pTexelBufferView = nullptr; - + vk_result = device_table->BindImageMemory(device, host_image, host_image_memory, 0); + + VkImageViewCreateInfo host_image_view_create_info{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, nullptr }; + host_image_view_create_info.flags = 0u; + host_image_view_create_info.image = host_image; + host_image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + host_image_view_create_info.format = host_image_create_info.format; + host_image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + host_image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + host_image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + host_image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + host_image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + host_image_view_create_info.subresourceRange.baseMipLevel = 0u; + host_image_view_create_info.subresourceRange.levelCount = 1u; + host_image_view_create_info.subresourceRange.baseArrayLayer = 0u; + host_image_view_create_info.subresourceRange.layerCount = 1u; + + VkImageView host_image_view; if (vk_result == VK_SUCCESS) - device_table->UpdateDescriptorSets(device, 2u, descriptor_writes, 0u, nullptr); + vk_result = device_table->CreateImageView(device, &host_image_view_create_info, nullptr, &host_image_view); VkCommandPoolCreateInfo command_pool_create_info; command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; @@ -646,69 +562,335 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id if (vk_result == VK_SUCCESS) vk_result = device_table->BeginCommandBuffer(command_buffer, &command_buffer_begin_info); - if (vk_result == VK_SUCCESS) + VkShaderModule compute_shader_module = VK_NULL_HANDLE; + VkDescriptorSetLayout descriptor_set_layout = VK_NULL_HANDLE; + VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; + VkPipeline compute_pipeline = VK_NULL_HANDLE; + VkDescriptorPool descriptor_pool = VK_NULL_HANDLE; + VkDescriptorSet descriptor_set = VK_NULL_HANDLE; + + if (format_properties.format != VK_FORMAT_UNDEFINED) { - VkBufferMemoryBarrier pre_buffer_barriers[2]; - pre_buffer_barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - pre_buffer_barriers[0].pNext = nullptr; - pre_buffer_barriers[0].srcAccessMask = VK_ACCESS_NONE; - pre_buffer_barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - pre_buffer_barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_buffer_barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_buffer_barriers[0].buffer = ahb_data_buffer; - pre_buffer_barriers[0].offset = 0u; - pre_buffer_barriers[0].size = ahb_size; - pre_buffer_barriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - pre_buffer_barriers[1].pNext = nullptr; - pre_buffer_barriers[1].srcAccessMask = VK_ACCESS_NONE; - pre_buffer_barriers[1].dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - pre_buffer_barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_buffer_barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_buffer_barriers[1].buffer = host_buffer; - pre_buffer_barriers[1].offset = 0u; - pre_buffer_barriers[1].size = ahb_size; + VkImageMemoryBarrier barriers[2] = {}; + barriers[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barriers[0].pNext = nullptr; + barriers[0].srcAccessMask = 0u; + barriers[0].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + barriers[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + barriers[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[0].image = ahb_image; + barriers[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barriers[0].subresourceRange.baseMipLevel = 0u; + barriers[0].subresourceRange.levelCount = 1u; + barriers[0].subresourceRange.baseArrayLayer = 0u; + barriers[0].subresourceRange.layerCount = 1u; + barriers[1].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barriers[1].pNext = nullptr; + barriers[1].srcAccessMask = 0u; + barriers[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + barriers[1].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + barriers[1].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[1].image = host_image; + barriers[1].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barriers[1].subresourceRange.baseMipLevel = 0u; + barriers[1].subresourceRange.levelCount = 1u; + barriers[1].subresourceRange.baseArrayLayer = 0u; + barriers[1].subresourceRange.layerCount = 1u; device_table->CmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, - 2, - pre_buffer_barriers, - 0, - nullptr); - - device_table->CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline); - device_table->CmdBindDescriptorSets( - command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set, 0, nullptr); - device_table->CmdDispatch(command_buffer, group_count_x, 1u, 1u); - - VkBufferMemoryBarrier post_buffer_barrier; - post_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - post_buffer_barrier.pNext = nullptr; - post_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - post_buffer_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT; - post_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - post_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - post_buffer_barrier.buffer = host_buffer; - post_buffer_barrier.offset = 0u; - post_buffer_barrier.size = ahb_size; - - device_table->CmdPipelineBarrier(command_buffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_HOST_BIT, - 0, 0, nullptr, - 1, - &post_buffer_barrier, - 0, - nullptr); + 2, + barriers); + + VkImageCopy copy_region = {}; + copy_region.dstSubresource.layerCount = 1; + copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_region.extent = { desc.width, desc.height, 1 }; + copy_region.srcSubresource.layerCount = 1; + copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + device_table->CmdCopyImage(command_buffer, + ahb_image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + host_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + ©_region); + } + else + { + // #version 450 + // + // layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + // + // layout(set = 0, binding = 0) uniform sampler2D ahb_image; + // layout(set = 0, binding = 1, rgba8) uniform writeonly image2D host_image; + // + // void main() { + // int id_x = int(gl_GlobalInvocationID.x); + // int id_y = int(gl_GlobalInvocationID.y); + // + // ivec2 image_size = textureSize(ahb_image, 0); + // + // if (id_x >= image_size.x || id_y >= image_size.y) { + // return; + // } + // + // vec2 coords = vec2( + // float(id_x) / float(image_size.x), + // float(id_y) / float(image_size.y) + // ); + // + // vec4 color = texture(ahb_image, coords); + // imageStore(host_image, ivec2(id_x, id_y), color); + // } + + std::vector shader = { + 0x07230203, 0x00010000, 0x0008000b, 0x00000054, 0x00000000, 0x00020011, 0x00000001, 0x00020011, + 0x00000032, 0x0006000b, 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, + 0x00000000, 0x00000001, 0x0006000f, 0x00000005, 0x00000004, 0x6e69616d, 0x00000000, 0x0000000c, + 0x00060010, 0x00000004, 0x00000011, 0x00000010, 0x00000010, 0x00000001, 0x00030003, 0x00000002, + 0x000001c2, 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00040005, 0x00000008, 0x785f6469, + 0x00000000, 0x00080005, 0x0000000c, 0x475f6c67, 0x61626f6c, 0x766e496c, 0x7461636f, 0x496e6f69, + 0x00000044, 0x00040005, 0x00000012, 0x795f6469, 0x00000000, 0x00050005, 0x00000019, 0x67616d69, + 0x69735f65, 0x0000657a, 0x00050005, 0x0000001e, 0x5f626861, 0x67616d69, 0x00000065, 0x00040005, + 0x00000035, 0x726f6f63, 0x00007364, 0x00040005, 0x00000045, 0x6f6c6f63, 0x00000072, 0x00050005, + 0x0000004c, 0x74736f68, 0x616d695f, 0x00006567, 0x00040047, 0x0000000c, 0x0000000b, 0x0000001c, + 0x00040047, 0x0000001e, 0x00000021, 0x00000000, 0x00040047, 0x0000001e, 0x00000022, 0x00000000, + 0x00030047, 0x0000004c, 0x00000019, 0x00040047, 0x0000004c, 0x00000021, 0x00000001, 0x00040047, + 0x0000004c, 0x00000022, 0x00000000, 0x00040047, 0x00000053, 0x0000000b, 0x00000019, 0x00020013, + 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015, 0x00000006, 0x00000020, 0x00000001, + 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x00040015, 0x00000009, 0x00000020, 0x00000000, + 0x00040017, 0x0000000a, 0x00000009, 0x00000003, 0x00040020, 0x0000000b, 0x00000001, 0x0000000a, + 0x0004003b, 0x0000000b, 0x0000000c, 0x00000001, 0x0004002b, 0x00000009, 0x0000000d, 0x00000000, + 0x00040020, 0x0000000e, 0x00000001, 0x00000009, 0x0004002b, 0x00000009, 0x00000013, 0x00000001, + 0x00040017, 0x00000017, 0x00000006, 0x00000002, 0x00040020, 0x00000018, 0x00000007, 0x00000017, + 0x00030016, 0x0000001a, 0x00000020, 0x00090019, 0x0000001b, 0x0000001a, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0003001b, 0x0000001c, 0x0000001b, 0x00040020, + 0x0000001d, 0x00000000, 0x0000001c, 0x0004003b, 0x0000001d, 0x0000001e, 0x00000000, 0x0004002b, + 0x00000006, 0x00000020, 0x00000000, 0x00020014, 0x00000023, 0x00040017, 0x00000033, 0x0000001a, + 0x00000002, 0x00040020, 0x00000034, 0x00000007, 0x00000033, 0x00040017, 0x00000043, 0x0000001a, + 0x00000004, 0x00040020, 0x00000044, 0x00000007, 0x00000043, 0x0004002b, 0x0000001a, 0x00000048, + 0x00000000, 0x00090019, 0x0000004a, 0x0000001a, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000004, 0x00040020, 0x0000004b, 0x00000000, 0x0000004a, 0x0004003b, 0x0000004b, + 0x0000004c, 0x00000000, 0x0004002b, 0x00000009, 0x00000052, 0x00000010, 0x0006002c, 0x0000000a, + 0x00000053, 0x00000052, 0x00000052, 0x00000013, 0x00050036, 0x00000002, 0x00000004, 0x00000000, + 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007, 0x0004003b, + 0x00000007, 0x00000012, 0x00000007, 0x0004003b, 0x00000018, 0x00000019, 0x00000007, 0x0004003b, + 0x00000034, 0x00000035, 0x00000007, 0x0004003b, 0x00000044, 0x00000045, 0x00000007, 0x00050041, + 0x0000000e, 0x0000000f, 0x0000000c, 0x0000000d, 0x0004003d, 0x00000009, 0x00000010, 0x0000000f, + 0x0004007c, 0x00000006, 0x00000011, 0x00000010, 0x0003003e, 0x00000008, 0x00000011, 0x00050041, + 0x0000000e, 0x00000014, 0x0000000c, 0x00000013, 0x0004003d, 0x00000009, 0x00000015, 0x00000014, + 0x0004007c, 0x00000006, 0x00000016, 0x00000015, 0x0003003e, 0x00000012, 0x00000016, 0x0004003d, + 0x0000001c, 0x0000001f, 0x0000001e, 0x00040064, 0x0000001b, 0x00000021, 0x0000001f, 0x00050067, + 0x00000017, 0x00000022, 0x00000021, 0x00000020, 0x0003003e, 0x00000019, 0x00000022, 0x0004003d, + 0x00000006, 0x00000024, 0x00000008, 0x00050041, 0x00000007, 0x00000025, 0x00000019, 0x0000000d, + 0x0004003d, 0x00000006, 0x00000026, 0x00000025, 0x000500af, 0x00000023, 0x00000027, 0x00000024, + 0x00000026, 0x000400a8, 0x00000023, 0x00000028, 0x00000027, 0x000300f7, 0x0000002a, 0x00000000, + 0x000400fa, 0x00000028, 0x00000029, 0x0000002a, 0x000200f8, 0x00000029, 0x0004003d, 0x00000006, + 0x0000002b, 0x00000012, 0x00050041, 0x00000007, 0x0000002c, 0x00000019, 0x00000013, 0x0004003d, + 0x00000006, 0x0000002d, 0x0000002c, 0x000500af, 0x00000023, 0x0000002e, 0x0000002b, 0x0000002d, + 0x000200f9, 0x0000002a, 0x000200f8, 0x0000002a, 0x000700f5, 0x00000023, 0x0000002f, 0x00000027, + 0x00000005, 0x0000002e, 0x00000029, 0x000300f7, 0x00000031, 0x00000000, 0x000400fa, 0x0000002f, + 0x00000030, 0x00000031, 0x000200f8, 0x00000030, 0x000100fd, 0x000200f8, 0x00000031, 0x0004003d, + 0x00000006, 0x00000036, 0x00000008, 0x0004006f, 0x0000001a, 0x00000037, 0x00000036, 0x00050041, + 0x00000007, 0x00000038, 0x00000019, 0x0000000d, 0x0004003d, 0x00000006, 0x00000039, 0x00000038, + 0x0004006f, 0x0000001a, 0x0000003a, 0x00000039, 0x00050088, 0x0000001a, 0x0000003b, 0x00000037, + 0x0000003a, 0x0004003d, 0x00000006, 0x0000003c, 0x00000012, 0x0004006f, 0x0000001a, 0x0000003d, + 0x0000003c, 0x00050041, 0x00000007, 0x0000003e, 0x00000019, 0x00000013, 0x0004003d, 0x00000006, + 0x0000003f, 0x0000003e, 0x0004006f, 0x0000001a, 0x00000040, 0x0000003f, 0x00050088, 0x0000001a, + 0x00000041, 0x0000003d, 0x00000040, 0x00050050, 0x00000033, 0x00000042, 0x0000003b, 0x00000041, + 0x0003003e, 0x00000035, 0x00000042, 0x0004003d, 0x0000001c, 0x00000046, 0x0000001e, 0x0004003d, + 0x00000033, 0x00000047, 0x00000035, 0x00070058, 0x00000043, 0x00000049, 0x00000046, 0x00000047, + 0x00000002, 0x00000048, 0x0003003e, 0x00000045, 0x00000049, 0x0004003d, 0x0000004a, 0x0000004d, + 0x0000004c, 0x0004003d, 0x00000006, 0x0000004e, 0x00000008, 0x0004003d, 0x00000006, 0x0000004f, + 0x00000012, 0x00050050, 0x00000017, 0x00000050, 0x0000004e, 0x0000004f, 0x0004003d, 0x00000043, + 0x00000051, 0x00000045, 0x00040063, 0x0000004d, 0x00000050, 0x00000051, 0x000100fd, 0x00010038, + }; + + VkShaderModuleCreateInfo shader_module_create_info; + shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_module_create_info.pNext = nullptr; + shader_module_create_info.flags = 0u; + shader_module_create_info.codeSize = shader.size() * sizeof(uint32_t); + shader_module_create_info.pCode = shader.data(); + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateShaderModule( + device, &shader_module_create_info, nullptr, &compute_shader_module); + + VkPipelineShaderStageCreateInfo shader_stage_create_info; + shader_stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shader_stage_create_info.pNext = nullptr; + shader_stage_create_info.flags = 0u; + shader_stage_create_info.stage = VK_SHADER_STAGE_COMPUTE_BIT; + shader_stage_create_info.module = compute_shader_module; + shader_stage_create_info.pName = "main"; + shader_stage_create_info.pSpecializationInfo = nullptr; + + VkDescriptorSetLayoutBinding bindings[2]; + bindings[0].binding = 0u; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[0].descriptorCount = 1u; + bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindings[0].pImmutableSamplers = &sampler; + bindings[1].binding = 1u; + bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + bindings[1].descriptorCount = 1u; + bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindings[1].pImmutableSamplers = nullptr; + + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info; + descriptor_set_layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptor_set_layout_create_info.pNext = nullptr; + descriptor_set_layout_create_info.flags = 0u; + descriptor_set_layout_create_info.bindingCount = 2u; + descriptor_set_layout_create_info.pBindings = bindings; + + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateDescriptorSetLayout( + device, &descriptor_set_layout_create_info, nullptr, &descriptor_set_layout); + + VkPipelineLayoutCreateInfo pipeline_layout_create_info; + pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeline_layout_create_info.pNext = nullptr; + pipeline_layout_create_info.flags = 0u; + pipeline_layout_create_info.setLayoutCount = 1u; + pipeline_layout_create_info.pSetLayouts = &descriptor_set_layout; + pipeline_layout_create_info.pushConstantRangeCount = 0u; + pipeline_layout_create_info.pPushConstantRanges = nullptr; + + if (vk_result == VK_SUCCESS) + vk_result = + device_table->CreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &pipeline_layout); + + VkComputePipelineCreateInfo compute_pipeline_create_info; + compute_pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + compute_pipeline_create_info.pNext = nullptr; + compute_pipeline_create_info.flags = 0u; + compute_pipeline_create_info.stage = shader_stage_create_info; + compute_pipeline_create_info.layout = pipeline_layout; + compute_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; + compute_pipeline_create_info.basePipelineIndex = -1; + + device_table->CreateComputePipelines( + device, VK_NULL_HANDLE, 1u, &compute_pipeline_create_info, nullptr, &compute_pipeline); + + VkDescriptorPoolSize pool_sizes[2]; + pool_sizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + pool_sizes[0].descriptorCount = 1u; + pool_sizes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + pool_sizes[1].descriptorCount = 1u; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info; + descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptor_pool_create_info.pNext = nullptr; + descriptor_pool_create_info.flags = 0u; + descriptor_pool_create_info.maxSets = 1u; + descriptor_pool_create_info.poolSizeCount = 2u; + descriptor_pool_create_info.pPoolSizes = pool_sizes; + + if (vk_result == VK_SUCCESS) + vk_result = + device_table->CreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, &descriptor_pool); + + VkDescriptorSetAllocateInfo descriptor_set_allocate_info; + descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + descriptor_set_allocate_info.pNext = nullptr; + descriptor_set_allocate_info.descriptorPool = descriptor_pool; + descriptor_set_allocate_info.descriptorSetCount = 1u; + descriptor_set_allocate_info.pSetLayouts = &descriptor_set_layout; + + if (vk_result == VK_SUCCESS) + vk_result = + device_table->AllocateDescriptorSets(device, &descriptor_set_allocate_info, &descriptor_set); + + VkDescriptorImageInfo image_info = {}; + image_info.sampler = sampler; + image_info.imageView = image_view; + image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + VkDescriptorImageInfo host_image_info = {}; + host_image_info.imageView = host_image_view; + host_image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet descriptor_writes[2] = {}; + descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[0].dstSet = descriptor_set; + descriptor_writes[0].dstBinding = 0u; + descriptor_writes[0].dstArrayElement = 0u; + descriptor_writes[0].descriptorCount = 1u; + descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptor_writes[0].pImageInfo = &image_info; + descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[1].dstSet = descriptor_set; + descriptor_writes[1].dstBinding = 1u; + descriptor_writes[1].dstArrayElement = 0u; + descriptor_writes[1].descriptorCount = 1u; + descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + descriptor_writes[1].pImageInfo = &host_image_info; + + device_table->UpdateDescriptorSets(device, 2u, descriptor_writes, 0u, nullptr); - device_table->EndCommandBuffer(command_buffer); + if (vk_result == VK_SUCCESS) + { + VkImageMemoryBarrier barriers[2] = {}; + barriers[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barriers[0].srcAccessMask = 0u; + barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + barriers[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + barriers[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[0].image = ahb_image; + barriers[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barriers[0].subresourceRange.baseMipLevel = 0u; + barriers[0].subresourceRange.levelCount = 1u; + barriers[0].subresourceRange.baseArrayLayer = 0u; + barriers[0].subresourceRange.layerCount = 1u; + barriers[1].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barriers[1].srcAccessMask = 0u; + barriers[1].dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + barriers[1].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + barriers[1].newLayout = VK_IMAGE_LAYOUT_GENERAL; + barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barriers[1].image = host_image; + barriers[1].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barriers[1].subresourceRange.baseMipLevel = 0u; + barriers[1].subresourceRange.levelCount = 1u; + barriers[1].subresourceRange.baseArrayLayer = 0u; + barriers[1].subresourceRange.layerCount = 1u; + + device_table->CmdPipelineBarrier(command_buffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + 0, + 0, + nullptr, + 0, + nullptr, + 2, + barriers); + + device_table->CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline); + device_table->CmdBindDescriptorSets( + command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 1, &descriptor_set, 0, nullptr); + device_table->CmdDispatch(command_buffer, (desc.width + 15) / 16, (desc.height + 15) / 16, 1u); + } } + device_table->EndCommandBuffer(command_buffer); + VkSubmitInfo submit_info; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.pNext = nullptr; @@ -735,13 +917,14 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id if (vk_result == VK_SUCCESS) vk_result = device_table->WaitForFences(device, 1u, &fence, VK_TRUE, UINT64_MAX); - void* data; + void* data; + size_t data_size = host_readable_memory_requirements.size; if (vk_result == VK_SUCCESS) - vk_result = device_table->MapMemory(device, host_buffer_memory, 0u, ahb_size, 0u, &data); + vk_result = device_table->MapMemory(device, host_image_memory, 0u, data_size, 0u, &data); if (vk_result == VK_SUCCESS) { - CommonWriteFillMemoryCmd(memory_id, ahb_size, data, vulkan_capture_manager, vulkan_state_writer); + CommonWriteFillMemoryCmd(memory_id, data_size, data, vulkan_capture_manager, vulkan_state_writer); if (vulkan_capture_manager) { @@ -774,10 +957,10 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id device_table->DestroyDescriptorSetLayout(device, descriptor_set_layout, nullptr); device_table->DestroyPipelineLayout(device, pipeline_layout, nullptr); device_table->DestroyShaderModule(device, compute_shader_module, nullptr); - device_table->FreeMemory(device, buffer_memory, nullptr); - device_table->FreeMemory(device, host_buffer_memory, nullptr); - device_table->DestroyBuffer(device, ahb_data_buffer, nullptr); - device_table->DestroyBuffer(device, host_buffer, nullptr); + device_table->FreeMemory(device, host_image_memory, nullptr); + device_table->FreeMemory(device, image_memory, nullptr); + device_table->DestroyImage(device, ahb_image, nullptr); + device_table->DestroyImage(device, host_image, nullptr); if (vk_result != VK_SUCCESS) GFXRECON_LOG_ERROR("Failed to copy data from AHardwareBuffer that is not cpu readable"); From 1f9d7459f6687461fde552472ba9b9db48476ca0 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Thu, 6 Feb 2025 17:57:06 +0100 Subject: [PATCH 05/16] decode: Workaround non-CPU readable AHB image Importing external memory with external format is not supported at replay time. The capture stored data in RGBA8_UNORM. The content of the Android Hardware Buffer is restored with a Vulkan image which imports the AHB memory, then it's filled reusing functionalities of the resource initializer. Finally, both image views and samplers are patched to remove any reference to Android hardware buffers and external memory formats. --- .../decode/vulkan_replay_consumer_base.cpp | 609 +++++------------- .../decode/vulkan_replay_consumer_base.h | 29 +- .../decode/vulkan_resource_initializer.cpp | 37 +- .../decode/vulkan_resource_initializer.h | 8 +- .../generated_vulkan_replay_consumer.cpp | 12 +- .../vulkan_generators/replay_overrides.json | 3 +- 6 files changed, 235 insertions(+), 463 deletions(-) diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index 77dfec0f5c..3acec492c1 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -173,10 +173,9 @@ static uint32_t GetHardwareBufferFormatBpp(uint32_t format) VulkanReplayConsumerBase::VulkanReplayConsumerBase(std::shared_ptr application, const VulkanReplayOptions& options) : - loader_handle_(nullptr), - get_instance_proc_addr_(nullptr), create_instance_proc_(nullptr), application_(application), options_(options), - loading_trim_state_(false), replaying_trimmed_capture_(false), have_imported_semaphores_(false), fps_info_(nullptr), - omitted_pipeline_cache_data_(false) + loader_handle_(nullptr), get_instance_proc_addr_(nullptr), create_instance_proc_(nullptr), + application_(application), options_(options), loading_trim_state_(false), replaying_trimmed_capture_(false), + have_imported_semaphores_(false), fps_info_(nullptr), omitted_pipeline_cache_data_(false) { object_info_table_ = CommonObjectInfoTable::GetSingleton(); assert(object_info_table_); @@ -435,15 +434,19 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id } else if (buffer_info.device_id != 0) { + // Need to fill AHB memory from Vulkan. + VkResult vk_result = VK_SUCCESS; - VulkanDeviceInfo* device_info = object_info_table_->GetVkDeviceInfo(buffer_info.device_id); - VulkanQueueInfo* queue_info = object_info_table_->GetVkQueueInfo(buffer_info.queue_id); - VkDevice device = device_info->handle; - auto device_table = GetDeviceTable(device); - auto physical_device_info = object_info_table_->GetVkPhysicalDeviceInfo(device_info->parent_id); - auto memory_properties = &physical_device_info->capture_memory_properties; + VulkanDeviceInfo* device_info = object_info_table_->GetVkDeviceInfo(buffer_info.device_id); + + VulkanQueueInfo* queue_info = object_info_table_->GetVkQueueInfo(buffer_info.queue_id); + VkDevice device = device_info->handle; + auto device_table = GetDeviceTable(device); + auto physical_device_info = object_info_table_->GetVkPhysicalDeviceInfo(device_info->parent_id); + auto memory_properties = &physical_device_info->capture_memory_properties; + // Query the AHB size VkAndroidHardwareBufferFormatPropertiesANDROID format_properties; format_properties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; format_properties.pNext = nullptr; @@ -459,35 +462,71 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id const size_t ahb_size = properties.allocationSize; GFXRECON_ASSERT(ahb_size != 0); - VkExternalMemoryBufferCreateInfo external_memory_buffer_create_info; - external_memory_buffer_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO; - external_memory_buffer_create_info.pNext = nullptr; - external_memory_buffer_create_info.handleTypes = + VkExternalFormatANDROID external_format = {}; + external_format.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; + external_format.pNext = nullptr; + if (format_properties.format == VK_FORMAT_UNDEFINED) + { + external_format.externalFormat = format_properties.externalFormat; + } + + VkExternalMemoryImageCreateInfo external_memory_image_create_info; + external_memory_image_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; + external_memory_image_create_info.pNext = &external_format; + external_memory_image_create_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; - VkBufferCreateInfo buffer_create_info; - buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_create_info.pNext = &external_memory_buffer_create_info; - buffer_create_info.flags = 0u; - buffer_create_info.size = ahb_size; - buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - buffer_create_info.queueFamilyIndexCount = 0u; - buffer_create_info.pQueueFamilyIndices = nullptr; - - VkBuffer ahb_data_buffer; + // External format data cannot be refilled at replay time, therefore we expect format to be defined. + GFXRECON_ASSERT(format_properties.format != VK_FORMAT_UNDEFINED); + VkImageUsageFlags image_usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; + VkImageLayout final_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) + { + final_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + image_usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + } + if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) + { + final_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + image_usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + + VkImageCreateInfo image_info; + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.pNext = &external_memory_image_create_info; + image_info.flags = 0u; + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.format = format_properties.format; + image_info.extent = { desc.width, desc.height, 1u }; + image_info.mipLevels = 1u; + image_info.arrayLayers = 1u; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.usage = image_usage; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_info.queueFamilyIndexCount = 0u; + image_info.pQueueFamilyIndices = nullptr; + image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VkImage ahb_image = VK_NULL_HANDLE; if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateBuffer(device, &buffer_create_info, nullptr, &ahb_data_buffer); + vk_result = device_table->CreateImage(device, &image_info, nullptr, &ahb_image); - VkImportAndroidHardwareBufferInfoANDROID import_ahb_info; + VkImportAndroidHardwareBufferInfoANDROID import_ahb_info = {}; import_ahb_info.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; import_ahb_info.pNext = nullptr; import_ahb_info.buffer = buffer_info.hardware_buffer; - VkMemoryAllocateInfo memory_allocate_info; - memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memory_allocate_info.pNext = &import_ahb_info; - memory_allocate_info.allocationSize = ahb_size; + VkMemoryDedicatedAllocateInfo memory_dedicated_allocate_info = {}; + memory_dedicated_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; + memory_dedicated_allocate_info.pNext = &import_ahb_info; + memory_dedicated_allocate_info.image = ahb_image; + memory_dedicated_allocate_info.buffer = VK_NULL_HANDLE; + + VkMemoryAllocateInfo memory_allocate_info = {}; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = &memory_dedicated_allocate_info; + memory_allocate_info.allocationSize = ahb_size; uint32_t memory_index = memory_properties->memoryTypeCount; for (uint32_t i = 0; i < memory_properties->memoryTypeCount; ++i) @@ -496,408 +535,66 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id (memory_properties->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) > 0) { memory_index = i; + break; } } GFXRECON_ASSERT(memory_index < memory_properties->memoryTypeCount); memory_allocate_info.memoryTypeIndex = memory_index; - VkDeviceMemory buffer_memory; + VkDeviceMemory image_memory = VK_NULL_HANDLE; if (vk_result == VK_SUCCESS) - vk_result = device_table->AllocateMemory(device, &memory_allocate_info, nullptr, &buffer_memory); + vk_result = device_table->AllocateMemory(device, &memory_allocate_info, nullptr, &image_memory); if (vk_result == VK_SUCCESS) - vk_result = device_table->BindBufferMemory(device, ahb_data_buffer, buffer_memory, 0); - - VkBufferCreateInfo host_readable_buffer_info; - host_readable_buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - host_readable_buffer_info.pNext = nullptr; - host_readable_buffer_info.flags = 0u; - host_readable_buffer_info.size = ahb_size; - host_readable_buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - host_readable_buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - host_readable_buffer_info.queueFamilyIndexCount = 0u; - host_readable_buffer_info.pQueueFamilyIndices = nullptr; - - VkBuffer host_readable_buffer; - if (vk_result == VK_SUCCESS) - vk_result = - device_table->CreateBuffer(device, &host_readable_buffer_info, nullptr, &host_readable_buffer); - - VkMemoryRequirements host_readable_memory_requirements; - device_table->GetBufferMemoryRequirements( - device, host_readable_buffer, &host_readable_memory_requirements); + vk_result = device_table->BindImageMemory(device, ahb_image, image_memory, 0); - VkMemoryAllocateInfo host_readable_allocate_info; - host_readable_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - host_readable_allocate_info.pNext = nullptr; - host_readable_allocate_info.allocationSize = host_readable_memory_requirements.size; - - memory_index = memory_properties->memoryTypeCount; - for (uint32_t i = 0; i < memory_properties->memoryTypeCount; ++i) - { - if ((host_readable_memory_requirements.memoryTypeBits & (1 << i)) && - (memory_properties->memoryTypes[i].propertyFlags & - (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) == - (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) - { - memory_index = i; - } - } - GFXRECON_ASSERT(memory_index < memory_properties->memoryTypeCount); - host_readable_allocate_info.memoryTypeIndex = memory_index; - - VkDeviceMemory host_readable_buffer_memory; - if (vk_result == VK_SUCCESS) - vk_result = device_table->AllocateMemory( - device, &host_readable_allocate_info, nullptr, &host_readable_buffer_memory); - - if (vk_result == VK_SUCCESS) - vk_result = - device_table->BindBufferMemory(device, host_readable_buffer, host_readable_buffer_memory, 0); - - void* host_readable_buffer_data; - device_table->MapMemory( - device, host_readable_buffer_memory, 0u, ahb_size, 0u, &host_readable_buffer_data); - memcpy(host_readable_buffer_data, data, host_readable_buffer_info.size); - - // #version 450 - // - // layout(constant_id = 0) const uint rowLength = 1; - // layout(constant_id = 1) const uint totalSize = 1; - // - // layout(local_size_x = 32, local_size_y = 32) in; - // - // layout(set = 0, binding = 0, std430) buffer InputBuffer { - // uint in_data[]; - // }; - // - // layout(set = 0, binding = 1, std430) buffer OutputBuffer { - // uint out_data[]; - // }; - // - // void main() { - // uint i = gl_GlobalInvocationID.y * rowLength + gl_GlobalInvocationID.x; - // if (i < totalSize) { - // out_data[i] = in_data[i]; - // } - // } - - std::vector shader = { - 0x07230203, 0x00010000, 0x0008000b, 0x0000002e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, - 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, - 0x0006000f, 0x00000005, 0x00000004, 0x6e69616d, 0x00000000, 0x0000000b, 0x00060010, 0x00000004, - 0x00000011, 0x00000020, 0x00000020, 0x00000001, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, - 0x00000004, 0x6e69616d, 0x00000000, 0x00030005, 0x00000008, 0x00000069, 0x00080005, 0x0000000b, - 0x475f6c67, 0x61626f6c, 0x766e496c, 0x7461636f, 0x496e6f69, 0x00000044, 0x00050005, 0x00000010, - 0x4c776f72, 0x74676e65, 0x00000068, 0x00050005, 0x00000017, 0x61746f74, 0x7a69536c, 0x00000065, - 0x00060005, 0x0000001d, 0x7074754f, 0x75427475, 0x72656666, 0x00000000, 0x00060006, 0x0000001d, - 0x00000000, 0x5f74756f, 0x61746164, 0x00000000, 0x00030005, 0x0000001f, 0x00000000, 0x00050005, - 0x00000024, 0x75706e49, 0x66754274, 0x00726566, 0x00050006, 0x00000024, 0x00000000, 0x645f6e69, - 0x00617461, 0x00030005, 0x00000026, 0x00000000, 0x00040047, 0x0000000b, 0x0000000b, 0x0000001c, - 0x00040047, 0x00000010, 0x00000001, 0x00000000, 0x00040047, 0x00000017, 0x00000001, 0x00000001, - 0x00040047, 0x0000001c, 0x00000006, 0x00000004, 0x00050048, 0x0000001d, 0x00000000, 0x00000023, - 0x00000000, 0x00030047, 0x0000001d, 0x00000003, 0x00040047, 0x0000001f, 0x00000022, 0x00000000, - 0x00040047, 0x0000001f, 0x00000021, 0x00000001, 0x00040047, 0x00000023, 0x00000006, 0x00000004, - 0x00050048, 0x00000024, 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000024, 0x00000003, - 0x00040047, 0x00000026, 0x00000022, 0x00000000, 0x00040047, 0x00000026, 0x00000021, 0x00000000, - 0x00040047, 0x0000002d, 0x0000000b, 0x00000019, 0x00020013, 0x00000002, 0x00030021, 0x00000003, - 0x00000002, 0x00040015, 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, - 0x00000006, 0x00040017, 0x00000009, 0x00000006, 0x00000003, 0x00040020, 0x0000000a, 0x00000001, - 0x00000009, 0x0004003b, 0x0000000a, 0x0000000b, 0x00000001, 0x0004002b, 0x00000006, 0x0000000c, - 0x00000001, 0x00040020, 0x0000000d, 0x00000001, 0x00000006, 0x00040032, 0x00000006, 0x00000010, - 0x00000001, 0x0004002b, 0x00000006, 0x00000012, 0x00000000, 0x00040032, 0x00000006, 0x00000017, - 0x00000001, 0x00020014, 0x00000018, 0x0003001d, 0x0000001c, 0x00000006, 0x0003001e, 0x0000001d, - 0x0000001c, 0x00040020, 0x0000001e, 0x00000002, 0x0000001d, 0x0004003b, 0x0000001e, 0x0000001f, - 0x00000002, 0x00040015, 0x00000020, 0x00000020, 0x00000001, 0x0004002b, 0x00000020, 0x00000021, - 0x00000000, 0x0003001d, 0x00000023, 0x00000006, 0x0003001e, 0x00000024, 0x00000023, 0x00040020, - 0x00000025, 0x00000002, 0x00000024, 0x0004003b, 0x00000025, 0x00000026, 0x00000002, 0x00040020, - 0x00000028, 0x00000002, 0x00000006, 0x0004002b, 0x00000006, 0x0000002c, 0x00000020, 0x0006002c, - 0x00000009, 0x0000002d, 0x0000002c, 0x0000002c, 0x0000000c, 0x00050036, 0x00000002, 0x00000004, - 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007, - 0x00050041, 0x0000000d, 0x0000000e, 0x0000000b, 0x0000000c, 0x0004003d, 0x00000006, 0x0000000f, - 0x0000000e, 0x00050084, 0x00000006, 0x00000011, 0x0000000f, 0x00000010, 0x00050041, 0x0000000d, - 0x00000013, 0x0000000b, 0x00000012, 0x0004003d, 0x00000006, 0x00000014, 0x00000013, 0x00050080, - 0x00000006, 0x00000015, 0x00000011, 0x00000014, 0x0003003e, 0x00000008, 0x00000015, 0x0004003d, - 0x00000006, 0x00000016, 0x00000008, 0x000500b0, 0x00000018, 0x00000019, 0x00000016, 0x00000017, - 0x000300f7, 0x0000001b, 0x00000000, 0x000400fa, 0x00000019, 0x0000001a, 0x0000001b, 0x000200f8, - 0x0000001a, 0x0004003d, 0x00000006, 0x00000022, 0x00000008, 0x0004003d, 0x00000006, 0x00000027, - 0x00000008, 0x00060041, 0x00000028, 0x00000029, 0x00000026, 0x00000021, 0x00000027, 0x0004003d, - 0x00000006, 0x0000002a, 0x00000029, 0x00060041, 0x00000028, 0x0000002b, 0x0000001f, 0x00000021, - 0x00000022, 0x0003003e, 0x0000002b, 0x0000002a, 0x000200f9, 0x0000001b, 0x000200f8, 0x0000001b, - 0x000100fd, 0x00010038, + VkSamplerYcbcrConversionCreateInfo conversion_create_info = { + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO }; - - VkShaderModuleCreateInfo shader_module_create_info; - shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shader_module_create_info.pNext = nullptr; - shader_module_create_info.flags = 0u; - shader_module_create_info.codeSize = shader.size() * sizeof(uint32_t); - shader_module_create_info.pCode = shader.data(); - VkShaderModule compute_shader_module = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateShaderModule( - device, &shader_module_create_info, nullptr, &compute_shader_module); - - uint32_t unit_size = sizeof(uint32_t); - uint32_t group_count_x = ahb_size / 32u / 32u / unit_size; - if (ahb_size % (32u * 32u * unit_size) != 0) - ++group_count_x; - uint32_t row_length = group_count_x * 32u; - - VkSpecializationMapEntry specialization_entries[2]; - specialization_entries[0].constantID = 0u; - specialization_entries[0].offset = 0u; - specialization_entries[0].size = sizeof(uint32_t); - specialization_entries[1].constantID = 1u; - specialization_entries[1].offset = sizeof(uint32_t); - specialization_entries[1].size = sizeof(uint32_t); - - uint32_t specialization_data[2]; - specialization_data[0] = row_length; - specialization_data[1] = ahb_size / sizeof(uint32_t); - - VkSpecializationInfo specialization_info; - specialization_info.mapEntryCount = 2u; - specialization_info.pMapEntries = specialization_entries; - specialization_info.dataSize = sizeof(uint32_t) * 2u; - specialization_info.pData = specialization_data; - - VkPipelineShaderStageCreateInfo shader_stage_create_info; - shader_stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shader_stage_create_info.pNext = nullptr; - shader_stage_create_info.flags = 0u; - shader_stage_create_info.stage = VK_SHADER_STAGE_COMPUTE_BIT; - shader_stage_create_info.module = compute_shader_module; - shader_stage_create_info.pName = "main"; - shader_stage_create_info.pSpecializationInfo = &specialization_info; - - VkDescriptorSetLayoutBinding bindings[2]; - bindings[0].binding = 0u; - bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - bindings[0].descriptorCount = 1u; - bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; - bindings[0].pImmutableSamplers = nullptr; - bindings[1].binding = 1u; - bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - bindings[1].descriptorCount = 1u; - bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; - bindings[1].pImmutableSamplers = nullptr; - - VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info; - descriptor_set_layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptor_set_layout_create_info.pNext = nullptr; - descriptor_set_layout_create_info.flags = 0u; - descriptor_set_layout_create_info.bindingCount = 2u; - descriptor_set_layout_create_info.pBindings = bindings; - - VkDescriptorSetLayout descriptor_set_layout = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateDescriptorSetLayout( - device, &descriptor_set_layout_create_info, nullptr, &descriptor_set_layout); - - VkPipelineLayoutCreateInfo pipeline_layout_create_info; - pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_create_info.pNext = nullptr; - pipeline_layout_create_info.flags = 0u; - pipeline_layout_create_info.setLayoutCount = 1u; - pipeline_layout_create_info.pSetLayouts = &descriptor_set_layout; - pipeline_layout_create_info.pushConstantRangeCount = 0u; - pipeline_layout_create_info.pPushConstantRanges = nullptr; - - VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreatePipelineLayout( - device, &pipeline_layout_create_info, nullptr, &pipeline_layout); - - VkComputePipelineCreateInfo compute_pipeline_create_info; - compute_pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - compute_pipeline_create_info.pNext = nullptr; - compute_pipeline_create_info.flags = 0u; - compute_pipeline_create_info.stage = shader_stage_create_info; - compute_pipeline_create_info.layout = pipeline_layout; - compute_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; - compute_pipeline_create_info.basePipelineIndex = -1; - - VkPipeline compute_pipeline = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateComputePipelines( - device, VK_NULL_HANDLE, 1u, &compute_pipeline_create_info, nullptr, &compute_pipeline); - - VkDescriptorPoolSize pool_size; - pool_size.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - pool_size.descriptorCount = 2u; - - VkDescriptorPoolCreateInfo descriptor_pool_create_info; - descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - descriptor_pool_create_info.pNext = nullptr; - descriptor_pool_create_info.flags = 0u; - descriptor_pool_create_info.maxSets = 1u; - descriptor_pool_create_info.poolSizeCount = 1u; - descriptor_pool_create_info.pPoolSizes = &pool_size; - - VkDescriptorPool descriptor_pool = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateDescriptorPool( - device, &descriptor_pool_create_info, nullptr, &descriptor_pool); - - VkDescriptorSetAllocateInfo descriptor_set_allocate_info; - descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - descriptor_set_allocate_info.pNext = nullptr; - descriptor_set_allocate_info.descriptorPool = descriptor_pool; - descriptor_set_allocate_info.descriptorSetCount = 1u; - descriptor_set_allocate_info.pSetLayouts = &descriptor_set_layout; - - VkDescriptorSet descriptor_set = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = - device_table->AllocateDescriptorSets(device, &descriptor_set_allocate_info, &descriptor_set); - - VkDescriptorBufferInfo buffer_infos[2]; - buffer_infos[0].buffer = host_readable_buffer; - buffer_infos[0].offset = 0u; - buffer_infos[0].range = VK_WHOLE_SIZE; - buffer_infos[1].buffer = ahb_data_buffer; - buffer_infos[1].offset = 0u; - buffer_infos[1].range = VK_WHOLE_SIZE; - - VkWriteDescriptorSet descriptor_writes[2]; - descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[0].pNext = nullptr; - descriptor_writes[0].dstSet = descriptor_set; - descriptor_writes[0].dstBinding = 0u; - descriptor_writes[0].dstArrayElement = 0u; - descriptor_writes[0].descriptorCount = 1u; - descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - descriptor_writes[0].pImageInfo = nullptr; - descriptor_writes[0].pBufferInfo = &buffer_infos[0]; - descriptor_writes[0].pTexelBufferView = nullptr; - descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[1].pNext = nullptr; - descriptor_writes[1].dstSet = descriptor_set; - descriptor_writes[1].dstBinding = 1u; - descriptor_writes[1].dstArrayElement = 0u; - descriptor_writes[1].descriptorCount = 1u; - descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - descriptor_writes[1].pImageInfo = nullptr; - descriptor_writes[1].pBufferInfo = &buffer_infos[1]; - descriptor_writes[1].pTexelBufferView = nullptr; - - if (vk_result == VK_SUCCESS) - device_table->UpdateDescriptorSets(device, 2u, descriptor_writes, 0u, nullptr); - - VkCommandPoolCreateInfo command_pool_create_info; - command_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - command_pool_create_info.pNext = nullptr; - command_pool_create_info.flags = 0u; - command_pool_create_info.queueFamilyIndex = queue_info->family_index; - - VkCommandPool command_pool; - device_table->CreateCommandPool(device, &command_pool_create_info, nullptr, &command_pool); - - VkCommandBufferAllocateInfo command_buffer_allocate_info; - command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_allocate_info.pNext = nullptr; - command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - command_buffer_allocate_info.commandPool = command_pool; - command_buffer_allocate_info.commandBufferCount = 1; - - VkCommandBuffer command_buffer; - if (vk_result == VK_SUCCESS) - vk_result = - device_table->AllocateCommandBuffers(device, &command_buffer_allocate_info, &command_buffer); - - VkCommandBufferBeginInfo command_buffer_begin_info; - command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - command_buffer_begin_info.pNext = nullptr; - command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - command_buffer_begin_info.pInheritanceInfo = nullptr; - if (vk_result == VK_SUCCESS) - vk_result = device_table->BeginCommandBuffer(command_buffer, &command_buffer_begin_info); - - if (vk_result == VK_SUCCESS) - { - VkBufferMemoryBarrier pre_buffer_barriers[2]; - pre_buffer_barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - pre_buffer_barriers[0].pNext = nullptr; - pre_buffer_barriers[0].srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - pre_buffer_barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - pre_buffer_barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_buffer_barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_buffer_barriers[0].buffer = host_readable_buffer; - pre_buffer_barriers[0].offset = 0u; - pre_buffer_barriers[0].size = ahb_size; - pre_buffer_barriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - pre_buffer_barriers[1].pNext = nullptr; - pre_buffer_barriers[1].srcAccessMask = VK_ACCESS_NONE; - pre_buffer_barriers[1].dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - pre_buffer_barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_buffer_barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - pre_buffer_barriers[1].buffer = ahb_data_buffer; - pre_buffer_barriers[1].offset = 0u; - pre_buffer_barriers[1].size = ahb_size; - - device_table->CmdPipelineBarrier(command_buffer, - VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - 0, - 0, - nullptr, - 2, - pre_buffer_barriers, - 0, - nullptr); - - device_table->CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline); - device_table->CmdBindDescriptorSets(command_buffer, - VK_PIPELINE_BIND_POINT_COMPUTE, - pipeline_layout, - 0, - 1, - &descriptor_set, - 0, - nullptr); - device_table->CmdDispatch(command_buffer, group_count_x, 1u, 1u); - - device_table->EndCommandBuffer(command_buffer); - } - - VkFenceCreateInfo fence_create_info; - fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_create_info.pNext = nullptr; - fence_create_info.flags = 0u; - - VkFence fence; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateFence(device, &fence_create_info, nullptr, &fence); - - VkSubmitInfo submit_info; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = nullptr; - submit_info.waitSemaphoreCount = 0u; - submit_info.pWaitSemaphores = nullptr; - submit_info.pWaitDstStageMask = nullptr; - submit_info.commandBufferCount = 1u; - submit_info.pCommandBuffers = &command_buffer; - submit_info.signalSemaphoreCount = 0u; - submit_info.pSignalSemaphores = nullptr; - - if (vk_result == VK_SUCCESS) - vk_result = device_table->QueueSubmit(queue_info->handle, 1, &submit_info, fence); - + conversion_create_info.pNext = &external_format; + conversion_create_info.format = format_properties.format; + conversion_create_info.ycbcrModel = format_properties.suggestedYcbcrModel; + conversion_create_info.ycbcrRange = format_properties.suggestedYcbcrRange; + conversion_create_info.components = format_properties.samplerYcbcrConversionComponents; + conversion_create_info.xChromaOffset = format_properties.suggestedXChromaOffset; + conversion_create_info.yChromaOffset = format_properties.suggestedYChromaOffset; + conversion_create_info.chromaFilter = VK_FILTER_LINEAR; + conversion_create_info.forceExplicitReconstruction = VK_FALSE; + + VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE; if (vk_result == VK_SUCCESS) - vk_result = device_table->WaitForFences(device, 1u, &fence, VK_TRUE, UINT64_MAX); - - device_table->DestroyFence(device, fence, nullptr); - device_table->DestroyCommandPool(device, command_pool, nullptr); - device_table->DestroyDescriptorPool(device, descriptor_pool, nullptr); - device_table->DestroyPipeline(device, compute_pipeline, nullptr); - device_table->DestroyDescriptorSetLayout(device, descriptor_set_layout, nullptr); - device_table->DestroyPipelineLayout(device, pipeline_layout, nullptr); - device_table->DestroyShaderModule(device, compute_shader_module, nullptr); - device_table->FreeMemory(device, buffer_memory, nullptr); - device_table->FreeMemory(device, host_readable_buffer_memory, nullptr); - device_table->DestroyBuffer(device, ahb_data_buffer, nullptr); - device_table->DestroyBuffer(device, host_readable_buffer, nullptr); + vk_result = device_table->CreateSamplerYcbcrConversion( + device, &conversion_create_info, nullptr, &conversion); + + VkBufferImageCopy copy_region = {}; + copy_region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; + copy_region.imageExtent = { desc.width, desc.height, 1 }; + + ProcessBeginResourceInitCommand(buffer_info.device_id, size, size); + + VulkanResourceInitializer* initializer = device_info->resource_initializer.get(); + initializer->InitializeImage(size, + data, + queue_info->family_index, + ahb_image, + image_info.imageType, + VK_FORMAT_R8G8B8A8_UNORM, + image_info.extent, + VK_IMAGE_ASPECT_COLOR_BIT, + image_info.samples, + image_info.usage, + image_info.initialLayout, + final_layout, + image_info.arrayLayers, + 1, + ©_region, + conversion); + + ProcessEndResourceInitCommand(buffer_info.device_id); + + device_table->DestroySamplerYcbcrConversion(device, conversion, nullptr); + device_table->FreeMemory(device, image_memory, nullptr); + device_table->DestroyImage(device, ahb_image, nullptr); if (vk_result != VK_SUCCESS) GFXRECON_LOG_ERROR("Failed to copy data to AHardwareBuffer that is not cpu readable"); @@ -1007,6 +704,14 @@ void VulkanReplayConsumerBase::ProcessCreateHardwareBufferCommand( #if defined(VK_USE_PLATFORM_ANDROID_KHR) assert(hardware_buffers_.find(buffer_id) == hardware_buffers_.end()); + // In case of a AHB GPU visible only, we could not capture data in its external format. + // Data was sampled in RGBA format, so we override format and stride. + if ((usage & AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK) == 0) + { + format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; + stride = width; + } + AHardwareBuffer_Desc desc = {}; desc.format = format; desc.height = height; @@ -3172,7 +2877,7 @@ void VulkanReplayConsumerBase::ModifyCreateDeviceInfo( { const VkPhysicalDevice physical_device = physical_device_info->handle; - auto instance_table = GetInstanceTable(physical_device); + auto instance_table = GetInstanceTable(physical_device); assert(instance_table != nullptr); auto replay_create_info = pCreateInfo->GetPointer(); @@ -5018,10 +4723,10 @@ VkResult VulkanReplayConsumerBase::OverrideAllocateMemory( #endif // Check if this allocation was captured with an opaque address - bool uses_address = false; - bool address_override_found = false; - bool uses_import_memory = false; - uint64_t opaque_address = 0; + bool uses_address = false; + bool address_override_found = false; + bool uses_import_memory = false; + uint64_t opaque_address = 0; // FD is not available at replay time graphics::vulkan_struct_remove_pnext(modified_allocate_info); @@ -5776,6 +5481,21 @@ VulkanReplayConsumerBase::OverrideCreateImage(PFN_vkCreateImage modified_create_info->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; } + auto* create_info = const_cast(pCreateInfo->GetPointer()); + // The original image might be external. + auto* external_memory = graphics::vulkan_struct_get_pnext(create_info); + // The external memory might be an unknown format. + auto* external_format = graphics::vulkan_struct_get_pnext(create_info); + if (create_info->format == VK_FORMAT_UNDEFINED) + { + if (external_memory != nullptr && external_format != nullptr) + { + // In this case, the image has been sampled at capture time and format is now RGBA8_UNORM. + create_info->format = VK_FORMAT_R8G8B8A8_UNORM; + external_format->externalFormat = 0; + } + } + VkResult result = allocator->CreateImage( pCreateInfo->GetPointer(), GetAllocationCallbacks(pAllocator), capture_id, replay_image, &allocator_data); @@ -5810,8 +5530,10 @@ VulkanReplayConsumerBase::OverrideCreateImage(PFN_vkCreateImage } // Memory requirements for image with external format can only be queried after the memory is bound - auto* external_format_android = graphics::vulkan_struct_get_pnext(replay_create_info); - if (external_format_android != nullptr && external_format_android->externalFormat != 0) + // Also, if image was created with the VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID + // external memory handle type, then image must be bound to memory + if (external_memory != nullptr && + (external_memory->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0) { image_info->external_format = true; } @@ -5854,6 +5576,23 @@ void VulkanReplayConsumerBase::OverrideDestroyImage( allocator->DestroyImage(image, GetAllocationCallbacks(pAllocator), allocator_data); } +VkResult +VulkanReplayConsumerBase::OverrideCreateSampler(PFN_vkCreateSampler func, + VkResult original_result, + const VulkanDeviceInfo* device_info, + const StructPointerDecoder* pCreateInfo, + const StructPointerDecoder* pAllocator, + HandlePointerDecoder* pSampler) +{ + + auto* replay_create_info = pCreateInfo->GetPointer(); + VkSamplerCreateInfo modified_create_info = *replay_create_info; + // Do not use Ycbcr conversion at replay time + graphics::vulkan_struct_remove_pnext(&modified_create_info); + return func( + device_info->handle, &modified_create_info, GetAllocationCallbacks(pAllocator), pSampler->GetHandlePointer()); +} + VkResult VulkanReplayConsumerBase::OverrideCreateVideoSessionKHR( PFN_vkCreateVideoSessionKHR func, VkResult original_result, @@ -9489,7 +9228,17 @@ VkResult VulkanReplayConsumerBase::OverrideCreateImageView( const VkAllocationCallbacks* allocator = GetAllocationCallbacks(allocator_decoder); VkImageView* out_view = view_decoder->GetHandlePointer(); - VkResult result = func(device, create_info, allocator, out_view); + VkImageViewCreateInfo modified_create_info = *create_info; + + // The external memory might be an unknown format. We have no way to query its format properties, therefore we get + // rid if any Ycbcr conversion sampler. + if (graphics::vulkan_struct_remove_pnext(&modified_create_info)) + { + // In this case, we need to fix the image view format + modified_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; + } + + VkResult result = func(device, &modified_create_info, allocator, out_view); if ((result == VK_SUCCESS) && ((*out_view) != VK_NULL_HANDLE)) { diff --git a/framework/decode/vulkan_replay_consumer_base.h b/framework/decode/vulkan_replay_consumer_base.h index 8de811c178..f311884f76 100644 --- a/framework/decode/vulkan_replay_consumer_base.h +++ b/framework/decode/vulkan_replay_consumer_base.h @@ -1,6 +1,6 @@ /* ** Copyright (c) 2018-2020 Valve Corporation -** Copyright (c) 2018-2023 LunarG, Inc. +** Copyright (c) 2018-2025 LunarG, Inc. ** Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. ** ** Permission is hereby granted, free of charge, to any person obtaining a @@ -192,16 +192,16 @@ class VulkanReplayConsumerBase : public VulkanConsumer format::HandleId commandBuffer, StructPointerDecoder* pPushDescriptorSetWithTemplateInfo) override; - void Process_vkCreateRayTracingPipelinesKHR( - const ApiCallInfo& call_info, - VkResult returnValue, - format::HandleId device, - format::HandleId deferredOperation, - format::HandleId pipelineCache, - uint32_t createInfoCount, - StructPointerDecoder* pCreateInfos, - StructPointerDecoder* pAllocator, - HandlePointerDecoder* pPipelines) override; + void Process_vkCreateRayTracingPipelinesKHR( + const ApiCallInfo& call_info, + VkResult returnValue, + format::HandleId device, + format::HandleId deferredOperation, + format::HandleId pipelineCache, + uint32_t createInfoCount, + StructPointerDecoder* pCreateInfos, + StructPointerDecoder* pAllocator, + HandlePointerDecoder* pPipelines) override; void ProcessBuildVulkanAccelerationStructuresMetaCommand( format::HandleId device, @@ -1425,6 +1425,13 @@ class VulkanReplayConsumerBase : public VulkanConsumer VulkanShaderModuleInfo* shader_module_info, const StructPointerDecoder* pAllocator); + VkResult OverrideCreateSampler(PFN_vkCreateSampler func, + VkResult result, + const VulkanDeviceInfo* device_info, + const StructPointerDecoder* pCreateInfo, + const StructPointerDecoder* pAllocator, + HandlePointerDecoder* pSampler); + std::function()> AsyncCreateGraphicsPipelines(PFN_vkCreateGraphicsPipelines func, VkResult returnValue, diff --git a/framework/decode/vulkan_resource_initializer.cpp b/framework/decode/vulkan_resource_initializer.cpp index c15d79c438..0dd0ede6d7 100644 --- a/framework/decode/vulkan_resource_initializer.cpp +++ b/framework/decode/vulkan_resource_initializer.cpp @@ -1,5 +1,5 @@ /* -** Copyright (c) 2019-2020 LunarG, Inc. +** Copyright (c) 2019-2025 LunarG, Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and associated documentation files (the "Software"), @@ -40,11 +40,11 @@ VulkanResourceInitializer::VulkanResourceInitializer(const VulkanDeviceInfo* bool have_shader_stencil_write, VulkanResourceAllocator* resource_allocator, const encode::VulkanDeviceTable* device_table) : - device_(device_info->handle), - staging_memory_(VK_NULL_HANDLE), staging_memory_data_(0), staging_buffer_(VK_NULL_HANDLE), staging_buffer_data_(0), - draw_sampler_(VK_NULL_HANDLE), draw_pool_(VK_NULL_HANDLE), draw_set_layout_(VK_NULL_HANDLE), - draw_set_(VK_NULL_HANDLE), max_copy_size_(max_copy_size), have_shader_stencil_write_(have_shader_stencil_write), - resource_allocator_(resource_allocator), device_table_(device_table), device_info_(device_info) + device_(device_info->handle), staging_memory_(VK_NULL_HANDLE), staging_memory_data_(0), + staging_buffer_(VK_NULL_HANDLE), staging_buffer_data_(0), draw_sampler_(VK_NULL_HANDLE), draw_pool_(VK_NULL_HANDLE), + draw_set_layout_(VK_NULL_HANDLE), draw_set_(VK_NULL_HANDLE), max_copy_size_(max_copy_size), + have_shader_stencil_write_(have_shader_stencil_write), resource_allocator_(resource_allocator), + device_table_(device_table), device_info_(device_info) { assert((device_info != nullptr) && (device_info->handle != VK_NULL_HANDLE) && (memory_properties.memoryTypeCount > 0) && (memory_properties.memoryHeapCount > 0) && @@ -169,7 +169,8 @@ VkResult VulkanResourceInitializer::InitializeImage(VkDeviceSize dat VkImageLayout final_layout, uint32_t layer_count, uint32_t level_count, - const VkBufferImageCopy* level_copies) + const VkBufferImageCopy* level_copies, + VkSamplerYcbcrConversion conversion) { VkDeviceMemory staging_memory = VK_NULL_HANDLE; VkBuffer staging_buffer = VK_NULL_HANDLE; @@ -212,7 +213,8 @@ VkResult VulkanResourceInitializer::InitializeImage(VkDeviceSize dat final_layout, layer_count, level_count, - level_copies); + level_copies, + conversion); } else { @@ -1258,7 +1260,8 @@ VkResult VulkanResourceInitializer::PixelShaderImageCopy(uint32_t VkImageLayout final_layout, uint32_t layer_count, uint32_t level_count, - const VkBufferImageCopy* level_copies) + const VkBufferImageCopy* level_copies, + VkSamplerYcbcrConversion conversion) { VkQueue queue = VK_NULL_HANDLE; VkCommandBuffer command_buffer = VK_NULL_HANDLE; @@ -1292,7 +1295,9 @@ VkResult VulkanResourceInitializer::PixelShaderImageCopy(uint32_t if (result == VK_SUCCESS) { - VkImageCreateInfo image_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + + VkImageCreateInfo image_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + image_info.pNext = nullptr; image_info.flags = 0; image_info.imageType = type; @@ -1345,8 +1350,11 @@ VkResult VulkanResourceInitializer::PixelShaderImageCopy(uint32_t scissor_rect.extent.width = level_copy.imageExtent.width; scissor_rect.extent.height = level_copy.imageExtent.height; - VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - view_info.pNext = nullptr; + VkSamplerYcbcrConversionInfo conversion_info = { + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, nullptr, conversion + }; + VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + view_info.flags = 0; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; view_info.format = format; @@ -1374,6 +1382,11 @@ VkResult VulkanResourceInitializer::PixelShaderImageCopy(uint32_t { UpdateDrawDescriptorSet(set, staging_view, sampler); + if (conversion != VK_NULL_HANDLE) + { + view_info.pNext = &conversion_info; + view_info.format = VK_FORMAT_UNDEFINED; + } view_info.image = destination; result = CreateFramebufferResources(&view_info, level_copy.imageExtent.width, diff --git a/framework/decode/vulkan_resource_initializer.h b/framework/decode/vulkan_resource_initializer.h index 6c1bdf1f41..1466d87167 100644 --- a/framework/decode/vulkan_resource_initializer.h +++ b/framework/decode/vulkan_resource_initializer.h @@ -1,5 +1,5 @@ /* -** Copyright (c) 2019-2020 LunarG, Inc. +** Copyright (c) 2019-2025 LunarG, Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and associated documentation files (the "Software"), @@ -73,7 +73,8 @@ class VulkanResourceInitializer VkImageLayout final_layout, uint32_t layer_count, uint32_t level_count, - const VkBufferImageCopy* level_copies); + const VkBufferImageCopy* level_copies, + VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE); VkResult TransitionImage(uint32_t queue_family_index, VkImage image, @@ -174,7 +175,8 @@ class VulkanResourceInitializer VkImageLayout final_layout, uint32_t layer_count, uint32_t level_count, - const VkBufferImageCopy* level_copies); + const VkBufferImageCopy* level_copies, + VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE); private: struct CommandExecObjects diff --git a/framework/generated/generated_vulkan_replay_consumer.cpp b/framework/generated/generated_vulkan_replay_consumer.cpp index 807f48cd78..9dff8cd99f 100644 --- a/framework/generated/generated_vulkan_replay_consumer.cpp +++ b/framework/generated/generated_vulkan_replay_consumer.cpp @@ -1089,17 +1089,17 @@ void VulkanReplayConsumer::Process_vkCreateSampler( StructPointerDecoder* pAllocator, HandlePointerDecoder* pSampler) { - VkDevice in_device = MapHandle(device, &CommonObjectInfoTable::GetVkDeviceInfo); - const VkSamplerCreateInfo* in_pCreateInfo = pCreateInfo->GetPointer(); + auto in_device = GetObjectInfoTable().GetVkDeviceInfo(device); + MapStructHandles(pCreateInfo->GetMetaStructPointer(), GetObjectInfoTable()); - const VkAllocationCallbacks* in_pAllocator = GetAllocationCallbacks(pAllocator); if (!pSampler->IsNull()) { pSampler->SetHandleLength(1); } - VkSampler* out_pSampler = pSampler->GetHandlePointer(); + VulkanSamplerInfo handle_info; + pSampler->SetConsumerData(0, &handle_info); - VkResult replay_result = GetDeviceTable(in_device)->CreateSampler(in_device, in_pCreateInfo, in_pAllocator, out_pSampler); + VkResult replay_result = OverrideCreateSampler(GetDeviceTable(in_device->handle)->CreateSampler, returnValue, in_device, pCreateInfo, pAllocator, pSampler); CheckResult("vkCreateSampler", returnValue, replay_result, call_info); - AddHandle(device, pSampler->GetPointer(), out_pSampler, &CommonObjectInfoTable::AddVkSamplerInfo); + AddHandle(device, pSampler->GetPointer(), pSampler->GetHandlePointer(), std::move(handle_info), &CommonObjectInfoTable::AddVkSamplerInfo); } void VulkanReplayConsumer::Process_vkDestroySampler( diff --git a/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json b/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json index 81e3aa2808..d498e587f6 100644 --- a/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json +++ b/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json @@ -137,6 +137,7 @@ "vkCmdBindDescriptorSets" : "OverrideCmdBindDescriptorSets", "vkCmdBindDescriptorSets2KHR" : "OverrideCmdBindDescriptorSets2", "vkCmdBindDescriptorSets2" : "OverrideCmdBindDescriptorSets2", - "vkCmdExecuteCommands" : "OverrideCmdExecuteCommands" + "vkCmdExecuteCommands" : "OverrideCmdExecuteCommands", + "vkCreateSampler": "OverrideCreateSampler" } } \ No newline at end of file From 6234259832d149911a1dbf0bc6f621469dfcebf9 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Thu, 27 Feb 2025 09:59:33 +0100 Subject: [PATCH 06/16] wip: Remove queue id --- framework/decode/api_decoder.h | 1 - framework/decode/custom_ags_decoder.h | 1 - framework/decode/dx12_decoder_base.cpp | 3 +- framework/decode/dx12_decoder_base.h | 1 - framework/decode/file_processor.cpp | 4 -- framework/decode/info_decoder.h | 1 - framework/decode/metadata_consumer_base.h | 1 - framework/decode/metadata_json_consumer.h | 2 - framework/decode/stat_decoder_base.h | 1 - framework/decode/vulkan_cpp_consumer_base.cpp | 1 - framework/decode/vulkan_cpp_consumer_base.h | 1 - framework/decode/vulkan_decoder_base.cpp | 3 +- framework/decode/vulkan_decoder_base.h | 1 - .../decode/vulkan_replay_consumer_base.cpp | 41 +++++++++---------- .../decode/vulkan_replay_consumer_base.h | 2 - framework/encode/vulkan_capture_common.cpp | 39 ++---------------- framework/format/format.h | 1 - 17 files changed, 26 insertions(+), 78 deletions(-) diff --git a/framework/decode/api_decoder.h b/framework/decode/api_decoder.h index 475e04f2fd..bb1e7effef 100644 --- a/framework/decode/api_decoder.h +++ b/framework/decode/api_decoder.h @@ -107,7 +107,6 @@ class ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/custom_ags_decoder.h b/framework/decode/custom_ags_decoder.h index aadb575364..d935571efe 100644 --- a/framework/decode/custom_ags_decoder.h +++ b/framework/decode/custom_ags_decoder.h @@ -81,7 +81,6 @@ class AgsDecoder : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/dx12_decoder_base.cpp b/framework/decode/dx12_decoder_base.cpp index f20636a030..1d3bb0a4ea 100644 --- a/framework/decode/dx12_decoder_base.cpp +++ b/framework/decode/dx12_decoder_base.cpp @@ -110,7 +110,6 @@ void Dx12DecoderBase::DispatchResizeWindowCommand2( void Dx12DecoderBase::DispatchCreateHardwareBufferCommand( format::ThreadId thread_id, format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, @@ -126,7 +125,7 @@ void Dx12DecoderBase::DispatchCreateHardwareBufferCommand( for (auto consumer : consumers_) { consumer->ProcessCreateHardwareBufferCommand( - device_id, queue_id, memory_id, buffer_id, format, width, height, stride, usage, layers, plane_info); + device_id, memory_id, buffer_id, format, width, height, stride, usage, layers, plane_info); } } diff --git a/framework/decode/dx12_decoder_base.h b/framework/decode/dx12_decoder_base.h index 5c9f8f5a21..07045beb19 100644 --- a/framework/decode/dx12_decoder_base.h +++ b/framework/decode/dx12_decoder_base.h @@ -126,7 +126,6 @@ class Dx12DecoderBase : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/file_processor.cpp b/framework/decode/file_processor.cpp index 706547300d..f5dd08deb5 100644 --- a/framework/decode/file_processor.cpp +++ b/framework/decode/file_processor.cpp @@ -1098,7 +1098,6 @@ bool FileProcessor::ProcessMetaData(const format::BlockHeader& block_header, for if (decoder->SupportsMetaDataId(meta_data_id)) { decoder->DispatchCreateHardwareBufferCommand(header.thread_id, - 0u, 0u, header.memory_id, header.buffer_id, @@ -1171,7 +1170,6 @@ bool FileProcessor::ProcessMetaData(const format::BlockHeader& block_header, for if (decoder->SupportsMetaDataId(meta_data_id)) { decoder->DispatchCreateHardwareBufferCommand(header.thread_id, - 0u, 0u, header.memory_id, header.buffer_id, @@ -1211,7 +1209,6 @@ bool FileProcessor::ProcessMetaData(const format::BlockHeader& block_header, for success = ReadBytes(&header.thread_id, sizeof(header.thread_id)); success = success && ReadBytes(&header.device_id, sizeof(header.device_id)); - success = success && ReadBytes(&header.queue_id, sizeof(header.queue_id)); success = success && ReadBytes(&header.memory_id, sizeof(header.memory_id)); success = success && ReadBytes(&header.buffer_id, sizeof(header.buffer_id)); success = success && ReadBytes(&header.format, sizeof(header.format)); @@ -1247,7 +1244,6 @@ bool FileProcessor::ProcessMetaData(const format::BlockHeader& block_header, for { decoder->DispatchCreateHardwareBufferCommand(header.thread_id, header.device_id, - header.queue_id, header.memory_id, header.buffer_id, header.format, diff --git a/framework/decode/info_decoder.h b/framework/decode/info_decoder.h index cdb82b4d60..dc88b77db5 100644 --- a/framework/decode/info_decoder.h +++ b/framework/decode/info_decoder.h @@ -101,7 +101,6 @@ class InfoDecoder : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/metadata_consumer_base.h b/framework/decode/metadata_consumer_base.h index da5f2f06cd..846742ae98 100644 --- a/framework/decode/metadata_consumer_base.h +++ b/framework/decode/metadata_consumer_base.h @@ -48,7 +48,6 @@ class MetadataConsumerBase ProcessResizeWindowCommand2(format::HandleId surface_id, uint32_t width, uint32_t height, uint32_t pre_transform) {} virtual void ProcessCreateHardwareBufferCommand(format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/metadata_json_consumer.h b/framework/decode/metadata_json_consumer.h index 32c81bc34e..4ef4d32819 100644 --- a/framework/decode/metadata_json_consumer.h +++ b/framework/decode/metadata_json_consumer.h @@ -122,7 +122,6 @@ class MetadataJsonConsumer : public Base virtual void ProcessCreateHardwareBufferCommand(format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, @@ -136,7 +135,6 @@ class MetadataJsonConsumer : public Base const util::JsonOptions& json_options = GetOptions(); auto& jdata = WriteMetaCommandStart("CreateHardwareBufferCommand"); HandleToJson(jdata["device_id"], device_id, json_options); - HandleToJson(jdata["queue_id"], queue_id, json_options); HandleToJson(jdata["memory_id"], memory_id, json_options); HandleToJson(jdata["buffer_id"], buffer_id, json_options); FieldToJson(jdata["format"], format, json_options); diff --git a/framework/decode/stat_decoder_base.h b/framework/decode/stat_decoder_base.h index f4daa4553b..a52813664a 100644 --- a/framework/decode/stat_decoder_base.h +++ b/framework/decode/stat_decoder_base.h @@ -101,7 +101,6 @@ class StatDecoderBase : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/vulkan_cpp_consumer_base.cpp b/framework/decode/vulkan_cpp_consumer_base.cpp index a04b57522c..c6fe578536 100644 --- a/framework/decode/vulkan_cpp_consumer_base.cpp +++ b/framework/decode/vulkan_cpp_consumer_base.cpp @@ -3209,7 +3209,6 @@ void VulkanCppConsumerBase::ProcessResizeWindowCommand2(format::HandleId surface void VulkanCppConsumerBase::ProcessCreateHardwareBufferCommand( format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/vulkan_cpp_consumer_base.h b/framework/decode/vulkan_cpp_consumer_base.h index 09ad6f2844..1d0573fe68 100644 --- a/framework/decode/vulkan_cpp_consumer_base.h +++ b/framework/decode/vulkan_cpp_consumer_base.h @@ -657,7 +657,6 @@ class VulkanCppConsumerBase : public VulkanConsumer uint32_t pre_transform) override; virtual void ProcessCreateHardwareBufferCommand(format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/vulkan_decoder_base.cpp b/framework/decode/vulkan_decoder_base.cpp index 0a2b610f27..c83007dad9 100644 --- a/framework/decode/vulkan_decoder_base.cpp +++ b/framework/decode/vulkan_decoder_base.cpp @@ -127,7 +127,6 @@ void VulkanDecoderBase::DispatchResizeWindowCommand2( void VulkanDecoderBase::DispatchCreateHardwareBufferCommand( format::ThreadId thread_id, format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, @@ -143,7 +142,7 @@ void VulkanDecoderBase::DispatchCreateHardwareBufferCommand( for (auto consumer : consumers_) { consumer->ProcessCreateHardwareBufferCommand( - device_id, queue_id, memory_id, buffer_id, format, width, height, stride, usage, layers, plane_info); + device_id, memory_id, buffer_id, format, width, height, stride, usage, layers, plane_info); } } diff --git a/framework/decode/vulkan_decoder_base.h b/framework/decode/vulkan_decoder_base.h index bd34e73b45..f007b8af21 100644 --- a/framework/decode/vulkan_decoder_base.h +++ b/framework/decode/vulkan_decoder_base.h @@ -108,7 +108,6 @@ class VulkanDecoderBase : public ApiDecoder virtual void DispatchCreateHardwareBufferCommand(format::ThreadId thread_id, format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index 3acec492c1..b4248259bc 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -439,8 +439,6 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id VkResult vk_result = VK_SUCCESS; VulkanDeviceInfo* device_info = object_info_table_->GetVkDeviceInfo(buffer_info.device_id); - - VulkanQueueInfo* queue_info = object_info_table_->GetVkQueueInfo(buffer_info.queue_id); VkDevice device = device_info->handle; auto device_table = GetDeviceTable(device); auto physical_device_info = object_info_table_->GetVkPhysicalDeviceInfo(device_info->parent_id); @@ -548,23 +546,26 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id if (vk_result == VK_SUCCESS) vk_result = device_table->BindImageMemory(device, ahb_image, image_memory, 0); - VkSamplerYcbcrConversionCreateInfo conversion_create_info = { - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO - }; - conversion_create_info.pNext = &external_format; - conversion_create_info.format = format_properties.format; - conversion_create_info.ycbcrModel = format_properties.suggestedYcbcrModel; - conversion_create_info.ycbcrRange = format_properties.suggestedYcbcrRange; - conversion_create_info.components = format_properties.samplerYcbcrConversionComponents; - conversion_create_info.xChromaOffset = format_properties.suggestedXChromaOffset; - conversion_create_info.yChromaOffset = format_properties.suggestedYChromaOffset; - conversion_create_info.chromaFilter = VK_FILTER_LINEAR; - conversion_create_info.forceExplicitReconstruction = VK_FALSE; - VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE; - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateSamplerYcbcrConversion( - device, &conversion_create_info, nullptr, &conversion); + if (format_properties.format == VK_FORMAT_UNDEFINED) + { + VkSamplerYcbcrConversionCreateInfo conversion_create_info = { + VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO + }; + conversion_create_info.pNext = &external_format; + conversion_create_info.format = format_properties.format; + conversion_create_info.ycbcrModel = format_properties.suggestedYcbcrModel; + conversion_create_info.ycbcrRange = format_properties.suggestedYcbcrRange; + conversion_create_info.components = format_properties.samplerYcbcrConversionComponents; + conversion_create_info.xChromaOffset = format_properties.suggestedXChromaOffset; + conversion_create_info.yChromaOffset = format_properties.suggestedYChromaOffset; + conversion_create_info.chromaFilter = VK_FILTER_LINEAR; + conversion_create_info.forceExplicitReconstruction = VK_FALSE; + + if (vk_result == VK_SUCCESS) + vk_result = device_table->CreateSamplerYcbcrConversion( + device, &conversion_create_info, nullptr, &conversion); + } VkBufferImageCopy copy_region = {}; copy_region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; @@ -575,7 +576,7 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id VulkanResourceInitializer* initializer = device_info->resource_initializer.get(); initializer->InitializeImage(size, data, - queue_info->family_index, + 0, ahb_image, image_info.imageType, VK_FORMAT_R8G8B8A8_UNORM, @@ -690,7 +691,6 @@ void VulkanReplayConsumerBase::ProcessResizeWindowCommand2(format::HandleId surf void VulkanReplayConsumerBase::ProcessCreateHardwareBufferCommand( format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, @@ -772,7 +772,6 @@ void VulkanReplayConsumerBase::ProcessCreateHardwareBufferCommand( HardwareBufferMemoryInfo& memory_info = hardware_buffer_memory_info_[memory_id]; memory_info.hardware_buffer = buffer; memory_info.device_id = device_id; - memory_info.queue_id = queue_id; memory_info.compatible_strides = true; // Check for matching strides. diff --git a/framework/decode/vulkan_replay_consumer_base.h b/framework/decode/vulkan_replay_consumer_base.h index f311884f76..a2d3c16343 100644 --- a/framework/decode/vulkan_replay_consumer_base.h +++ b/framework/decode/vulkan_replay_consumer_base.h @@ -108,7 +108,6 @@ class VulkanReplayConsumerBase : public VulkanConsumer virtual void ProcessCreateHardwareBufferCommand(format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, uint64_t buffer_id, uint32_t format, @@ -1657,7 +1656,6 @@ class VulkanReplayConsumerBase : public VulkanConsumer { AHardwareBuffer* hardware_buffer; format::HandleId device_id; - format::HandleId queue_id; bool compatible_strides; std::vector plane_info; }; diff --git a/framework/encode/vulkan_capture_common.cpp b/framework/encode/vulkan_capture_common.cpp index 878c7f20e9..5f7f58710e 100644 --- a/framework/encode/vulkan_capture_common.cpp +++ b/framework/encode/vulkan_capture_common.cpp @@ -31,7 +31,6 @@ GFXRECON_BEGIN_NAMESPACE(encode) static void CommonWriteCreateHardwareBufferCmd(format::ThreadId thread_id, format::HandleId device_id, - format::HandleId queue_id, format::HandleId memory_id, AHardwareBuffer* hardware_buffer, const std::vector& plane_info, @@ -53,7 +52,6 @@ static void CommonWriteCreateHardwareBufferCmd(format::ThreadId format::ApiFamilyId::ApiFamily_Vulkan, format::MetaDataType::kCreateHardwareBufferCommand); create_buffer_cmd.thread_id = thread_id; create_buffer_cmd.device_id = device_id; - create_buffer_cmd.queue_id = queue_id; create_buffer_cmd.memory_id = memory_id; create_buffer_cmd.buffer_id = reinterpret_cast(hardware_buffer); @@ -184,7 +182,7 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id // Write CreateHardwareBufferCmd with or without the AHB payload CommonWriteCreateHardwareBufferCmd( - thread_id, 0u, 0u, memory_id, hardware_buffer, plane_info, vulkan_capture_manager, vulkan_state_writer); + thread_id, 0u, memory_id, hardware_buffer, plane_info, vulkan_capture_manager, vulkan_state_writer); // If AHardwareBuffer_lockPlanes failed (or is not available) try AHardwareBuffer_lock if (result != 0) @@ -274,14 +272,8 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id format::HandleId queue_id = queue_wrapper->handle_id; // Write CreateHardwareBufferCmd without the AHB payload - CommonWriteCreateHardwareBufferCmd(thread_id, - device_id, - queue_id, - memory_id, - hardware_buffer, - plane_info, - vulkan_capture_manager, - vulkan_state_writer); + CommonWriteCreateHardwareBufferCmd( + thread_id, device_id, memory_id, hardware_buffer, plane_info, vulkan_capture_manager, vulkan_state_writer); VkResult vk_result = VK_SUCCESS; @@ -911,7 +903,7 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id if (vk_result == VK_SUCCESS) vk_result = device_table->CreateFence(device, &fence_create_info, nullptr, &fence); - auto queue = device_wrapper->child_queues[0]->handle; + auto queue = device_wrapper->child_queues[device_queue_index]->handle; if (vk_result == VK_SUCCESS) vk_result = device_table->QueueSubmit(queue, 1, &submit_info, fence); if (vk_result == VK_SUCCESS) @@ -925,29 +917,6 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id if (vk_result == VK_SUCCESS) { CommonWriteFillMemoryCmd(memory_id, data_size, data, vulkan_capture_manager, vulkan_state_writer); - - if (vulkan_capture_manager) - { - // Track the memory with the PageGuardManager - const auto tracking_mode = vulkan_capture_manager->GetMemoryTrackingMode(); - if ((tracking_mode == CaptureSettings::MemoryTrackingMode::kPageGuard || - tracking_mode == CaptureSettings::MemoryTrackingMode::kUserfaultfd) && - vulkan_capture_manager->GetPageGuardTrackAhbMemory()) - { - GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, ahb_size); - - util::PageGuardManager* manager = util::PageGuardManager::Get(); - GFXRECON_ASSERT(manager != nullptr); - - manager->AddTrackedMemory(memory_id, - data, - 0, - static_cast(ahb_size), - util::PageGuardManager::kNullShadowHandle, - false, // No shadow memory for the imported AHB memory. - false); // Write watch is not supported for this case. - } - } } device_table->DestroyFence(device, fence, nullptr); diff --git a/framework/format/format.h b/framework/format/format.h index df285d36c9..da43dca1ad 100644 --- a/framework/format/format.h +++ b/framework/format/format.h @@ -427,7 +427,6 @@ struct CreateHardwareBufferCommandHeader MetaDataHeader meta_header; ThreadId thread_id; HandleId device_id; - HandleId queue_id; HandleId memory_id; // Globally unique ID assigned to the buffer for tracking memory modifications. uint64_t buffer_id; // Address of the buffer object. uint32_t format; From 50b5646804eba8644ff3b45091975a6c86e3e615 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Thu, 27 Feb 2025 10:42:14 +0100 Subject: [PATCH 07/16] wip: Remove Ycbcr sampler --- .../decode/vulkan_replay_consumer_base.cpp | 47 +++++-------------- .../decode/vulkan_resource_initializer.cpp | 21 ++------- .../decode/vulkan_resource_initializer.h | 6 +-- 3 files changed, 18 insertions(+), 56 deletions(-) diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index b4248259bc..b0d400545e 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -444,7 +444,6 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id auto physical_device_info = object_info_table_->GetVkPhysicalDeviceInfo(device_info->parent_id); auto memory_properties = &physical_device_info->capture_memory_properties; - // Query the AHB size VkAndroidHardwareBufferFormatPropertiesANDROID format_properties; format_properties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; format_properties.pNext = nullptr; @@ -457,25 +456,26 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id vk_result = device_table->GetAndroidHardwareBufferPropertiesANDROID( device, buffer_info.hardware_buffer, &properties); - const size_t ahb_size = properties.allocationSize; - GFXRECON_ASSERT(ahb_size != 0); - - VkExternalFormatANDROID external_format = {}; - external_format.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; - external_format.pNext = nullptr; + // External format data cannot be refilled at replay time, therefore we expect format to be defined. if (format_properties.format == VK_FORMAT_UNDEFINED) { - external_format.externalFormat = format_properties.externalFormat; + GFXRECON_LOG_ERROR("Can not fill GPU AHB with unknown Vulkan format."); + if (format_properties.externalFormat != 0) + { + GFXRECON_LOG_ERROR("Replaying GPU AHB with external format is not supported."); + } + return; } + const VkDeviceSize ahb_size = properties.allocationSize; + GFXRECON_ASSERT(ahb_size != 0); + VkExternalMemoryImageCreateInfo external_memory_image_create_info; external_memory_image_create_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; - external_memory_image_create_info.pNext = &external_format; + external_memory_image_create_info.pNext = nullptr; external_memory_image_create_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; - // External format data cannot be refilled at replay time, therefore we expect format to be defined. - GFXRECON_ASSERT(format_properties.format != VK_FORMAT_UNDEFINED); VkImageUsageFlags image_usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; VkImageLayout final_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) @@ -546,27 +546,6 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id if (vk_result == VK_SUCCESS) vk_result = device_table->BindImageMemory(device, ahb_image, image_memory, 0); - VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE; - if (format_properties.format == VK_FORMAT_UNDEFINED) - { - VkSamplerYcbcrConversionCreateInfo conversion_create_info = { - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO - }; - conversion_create_info.pNext = &external_format; - conversion_create_info.format = format_properties.format; - conversion_create_info.ycbcrModel = format_properties.suggestedYcbcrModel; - conversion_create_info.ycbcrRange = format_properties.suggestedYcbcrRange; - conversion_create_info.components = format_properties.samplerYcbcrConversionComponents; - conversion_create_info.xChromaOffset = format_properties.suggestedXChromaOffset; - conversion_create_info.yChromaOffset = format_properties.suggestedYChromaOffset; - conversion_create_info.chromaFilter = VK_FILTER_LINEAR; - conversion_create_info.forceExplicitReconstruction = VK_FALSE; - - if (vk_result == VK_SUCCESS) - vk_result = device_table->CreateSamplerYcbcrConversion( - device, &conversion_create_info, nullptr, &conversion); - } - VkBufferImageCopy copy_region = {}; copy_region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; copy_region.imageExtent = { desc.width, desc.height, 1 }; @@ -588,12 +567,10 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id final_layout, image_info.arrayLayers, 1, - ©_region, - conversion); + ©_region); ProcessEndResourceInitCommand(buffer_info.device_id); - device_table->DestroySamplerYcbcrConversion(device, conversion, nullptr); device_table->FreeMemory(device, image_memory, nullptr); device_table->DestroyImage(device, ahb_image, nullptr); diff --git a/framework/decode/vulkan_resource_initializer.cpp b/framework/decode/vulkan_resource_initializer.cpp index 0dd0ede6d7..2a1ffa294b 100644 --- a/framework/decode/vulkan_resource_initializer.cpp +++ b/framework/decode/vulkan_resource_initializer.cpp @@ -169,8 +169,7 @@ VkResult VulkanResourceInitializer::InitializeImage(VkDeviceSize dat VkImageLayout final_layout, uint32_t layer_count, uint32_t level_count, - const VkBufferImageCopy* level_copies, - VkSamplerYcbcrConversion conversion) + const VkBufferImageCopy* level_copies) { VkDeviceMemory staging_memory = VK_NULL_HANDLE; VkBuffer staging_buffer = VK_NULL_HANDLE; @@ -213,8 +212,7 @@ VkResult VulkanResourceInitializer::InitializeImage(VkDeviceSize dat final_layout, layer_count, level_count, - level_copies, - conversion); + level_copies); } else { @@ -1260,8 +1258,7 @@ VkResult VulkanResourceInitializer::PixelShaderImageCopy(uint32_t VkImageLayout final_layout, uint32_t layer_count, uint32_t level_count, - const VkBufferImageCopy* level_copies, - VkSamplerYcbcrConversion conversion) + const VkBufferImageCopy* level_copies) { VkQueue queue = VK_NULL_HANDLE; VkCommandBuffer command_buffer = VK_NULL_HANDLE; @@ -1295,7 +1292,6 @@ VkResult VulkanResourceInitializer::PixelShaderImageCopy(uint32_t if (result == VK_SUCCESS) { - VkImageCreateInfo image_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; image_info.pNext = nullptr; @@ -1350,11 +1346,7 @@ VkResult VulkanResourceInitializer::PixelShaderImageCopy(uint32_t scissor_rect.extent.width = level_copy.imageExtent.width; scissor_rect.extent.height = level_copy.imageExtent.height; - VkSamplerYcbcrConversionInfo conversion_info = { - VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, nullptr, conversion - }; - VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - + VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; view_info.flags = 0; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; view_info.format = format; @@ -1382,11 +1374,6 @@ VkResult VulkanResourceInitializer::PixelShaderImageCopy(uint32_t { UpdateDrawDescriptorSet(set, staging_view, sampler); - if (conversion != VK_NULL_HANDLE) - { - view_info.pNext = &conversion_info; - view_info.format = VK_FORMAT_UNDEFINED; - } view_info.image = destination; result = CreateFramebufferResources(&view_info, level_copy.imageExtent.width, diff --git a/framework/decode/vulkan_resource_initializer.h b/framework/decode/vulkan_resource_initializer.h index 1466d87167..154af7e5a6 100644 --- a/framework/decode/vulkan_resource_initializer.h +++ b/framework/decode/vulkan_resource_initializer.h @@ -73,8 +73,7 @@ class VulkanResourceInitializer VkImageLayout final_layout, uint32_t layer_count, uint32_t level_count, - const VkBufferImageCopy* level_copies, - VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE); + const VkBufferImageCopy* level_copies); VkResult TransitionImage(uint32_t queue_family_index, VkImage image, @@ -175,8 +174,7 @@ class VulkanResourceInitializer VkImageLayout final_layout, uint32_t layer_count, uint32_t level_count, - const VkBufferImageCopy* level_copies, - VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE); + const VkBufferImageCopy* level_copies); private: struct CommandExecObjects From 352a5fc890966529530c996a96678c330af9fef3 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Thu, 27 Feb 2025 13:11:43 +0100 Subject: [PATCH 08/16] wip: Patch SamplerYcbcrConversion Instead of modifying the sampler, patch the conversion so that it works with RGBA8 formatted data. --- .../decode/vulkan_replay_consumer_base.cpp | 53 ++++++++++++++----- .../decode/vulkan_replay_consumer_base.h | 8 +++ .../generated_vulkan_replay_consumer.cpp | 11 ++-- .../vulkan_generators/replay_overrides.json | 3 +- 4 files changed, 56 insertions(+), 19 deletions(-) diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index b0d400545e..10b55fd1a5 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -438,11 +438,11 @@ void VulkanReplayConsumerBase::ProcessFillMemoryCommand(uint64_t memory_id VkResult vk_result = VK_SUCCESS; - VulkanDeviceInfo* device_info = object_info_table_->GetVkDeviceInfo(buffer_info.device_id); - VkDevice device = device_info->handle; - auto device_table = GetDeviceTable(device); - auto physical_device_info = object_info_table_->GetVkPhysicalDeviceInfo(device_info->parent_id); - auto memory_properties = &physical_device_info->capture_memory_properties; + VulkanDeviceInfo* device_info = object_info_table_->GetVkDeviceInfo(buffer_info.device_id); + VkDevice device = device_info->handle; + auto device_table = GetDeviceTable(device); + auto physical_device_info = object_info_table_->GetVkPhysicalDeviceInfo(device_info->parent_id); + auto memory_properties = &physical_device_info->capture_memory_properties; VkAndroidHardwareBufferFormatPropertiesANDROID format_properties; format_properties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; @@ -5563,8 +5563,34 @@ VulkanReplayConsumerBase::OverrideCreateSampler(PFN_vkCreateSampler func, auto* replay_create_info = pCreateInfo->GetPointer(); VkSamplerCreateInfo modified_create_info = *replay_create_info; - // Do not use Ycbcr conversion at replay time - graphics::vulkan_struct_remove_pnext(&modified_create_info); + return func( + device_info->handle, &modified_create_info, GetAllocationCallbacks(pAllocator), pSampler->GetHandlePointer()); +} + +VkResult VulkanReplayConsumerBase::OverrideCreateSamplerYcbcrConversion( + PFN_vkCreateSamplerYcbcrConversion func, + VkResult result, + const VulkanDeviceInfo* device_info, + const StructPointerDecoder* pCreateInfo, + const StructPointerDecoder* pAllocator, + HandlePointerDecoder* pSampler) +{ + const auto* replay_create_info = pCreateInfo->GetPointer(); + VkSamplerYcbcrConversionCreateInfo modified_create_info = *replay_create_info; + + // In case of an external format conversion, format is undefined + if (modified_create_info.format == VK_FORMAT_UNDEFINED) + { + // Replaying external formats is not supported + const auto* external_format = + graphics::vulkan_struct_remove_pnext(&modified_create_info); + GFXRECON_ASSERT(external_format != nullptr); + + // External formatted images are expected to have been captured as RGBA8 + modified_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; + // Use a model conversion which does not modify color components + modified_create_info.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; + } return func( device_info->handle, &modified_create_info, GetAllocationCallbacks(pAllocator), pSampler->GetHandlePointer()); } @@ -9206,12 +9232,15 @@ VkResult VulkanReplayConsumerBase::OverrideCreateImageView( VkImageViewCreateInfo modified_create_info = *create_info; - // The external memory might be an unknown format. We have no way to query its format properties, therefore we get - // rid if any Ycbcr conversion sampler. - if (graphics::vulkan_struct_remove_pnext(&modified_create_info)) + // If image has external format, this format is undefined. + if (modified_create_info.format == VK_FORMAT_UNDEFINED) { - // In this case, we need to fix the image view format - modified_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; + if (graphics::vulkan_struct_get_pnext(&modified_create_info)) + { + // Replaying images with external format is not supported. + // The imported image is expected to have RGBA8 format. + modified_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; + } } VkResult result = func(device, &modified_create_info, allocator, out_view); diff --git a/framework/decode/vulkan_replay_consumer_base.h b/framework/decode/vulkan_replay_consumer_base.h index a2d3c16343..3926c8236f 100644 --- a/framework/decode/vulkan_replay_consumer_base.h +++ b/framework/decode/vulkan_replay_consumer_base.h @@ -1431,6 +1431,14 @@ class VulkanReplayConsumerBase : public VulkanConsumer const StructPointerDecoder* pAllocator, HandlePointerDecoder* pSampler); + VkResult OverrideCreateSamplerYcbcrConversion( + PFN_vkCreateSamplerYcbcrConversion func, + VkResult result, + const VulkanDeviceInfo* device_info, + const StructPointerDecoder* pCreateInfo, + const StructPointerDecoder* pAllocator, + HandlePointerDecoder* pSampler); + std::function()> AsyncCreateGraphicsPipelines(PFN_vkCreateGraphicsPipelines func, VkResult returnValue, diff --git a/framework/generated/generated_vulkan_replay_consumer.cpp b/framework/generated/generated_vulkan_replay_consumer.cpp index 9dff8cd99f..ae35d76c9f 100644 --- a/framework/generated/generated_vulkan_replay_consumer.cpp +++ b/framework/generated/generated_vulkan_replay_consumer.cpp @@ -2576,16 +2576,15 @@ void VulkanReplayConsumer::Process_vkCreateSamplerYcbcrConversion( StructPointerDecoder* pAllocator, HandlePointerDecoder* pYcbcrConversion) { - VkDevice in_device = MapHandle(device, &CommonObjectInfoTable::GetVkDeviceInfo); - const VkSamplerYcbcrConversionCreateInfo* in_pCreateInfo = pCreateInfo->GetPointer(); - const VkAllocationCallbacks* in_pAllocator = GetAllocationCallbacks(pAllocator); + auto in_device = GetObjectInfoTable().GetVkDeviceInfo(device); if (!pYcbcrConversion->IsNull()) { pYcbcrConversion->SetHandleLength(1); } - VkSamplerYcbcrConversion* out_pYcbcrConversion = pYcbcrConversion->GetHandlePointer(); + VulkanSamplerYcbcrConversionInfo handle_info; + pYcbcrConversion->SetConsumerData(0, &handle_info); - VkResult replay_result = GetDeviceTable(in_device)->CreateSamplerYcbcrConversion(in_device, in_pCreateInfo, in_pAllocator, out_pYcbcrConversion); + VkResult replay_result = OverrideCreateSamplerYcbcrConversion(GetDeviceTable(in_device->handle)->CreateSamplerYcbcrConversion, returnValue, in_device, pCreateInfo, pAllocator, pYcbcrConversion); CheckResult("vkCreateSamplerYcbcrConversion", returnValue, replay_result, call_info); - AddHandle(device, pYcbcrConversion->GetPointer(), out_pYcbcrConversion, &CommonObjectInfoTable::AddVkSamplerYcbcrConversionInfo); + AddHandle(device, pYcbcrConversion->GetPointer(), pYcbcrConversion->GetHandlePointer(), std::move(handle_info), &CommonObjectInfoTable::AddVkSamplerYcbcrConversionInfo); } void VulkanReplayConsumer::Process_vkDestroySamplerYcbcrConversion( diff --git a/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json b/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json index d498e587f6..5c34143f67 100644 --- a/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json +++ b/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json @@ -138,6 +138,7 @@ "vkCmdBindDescriptorSets2KHR" : "OverrideCmdBindDescriptorSets2", "vkCmdBindDescriptorSets2" : "OverrideCmdBindDescriptorSets2", "vkCmdExecuteCommands" : "OverrideCmdExecuteCommands", - "vkCreateSampler": "OverrideCreateSampler" + "vkCreateSampler": "OverrideCreateSampler", + "vkCreateSamplerYcbcrConversion": "OverrideCreateSamplerYcbcrConversion" } } \ No newline at end of file From f45b2610366358c1e569d034545fe4b6384abbc9 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Mon, 3 Mar 2025 16:06:51 +0100 Subject: [PATCH 09/16] wip: Remove OverrideCreateSampler --- framework/decode/vulkan_replay_consumer_base.cpp | 15 --------------- framework/decode/vulkan_replay_consumer_base.h | 7 ------- .../generated_vulkan_replay_consumer.cpp | 12 ++++++------ .../vulkan_generators/replay_overrides.json | 1 - 4 files changed, 6 insertions(+), 29 deletions(-) diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index 10b55fd1a5..4a4f9a3add 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -5552,21 +5552,6 @@ void VulkanReplayConsumerBase::OverrideDestroyImage( allocator->DestroyImage(image, GetAllocationCallbacks(pAllocator), allocator_data); } -VkResult -VulkanReplayConsumerBase::OverrideCreateSampler(PFN_vkCreateSampler func, - VkResult original_result, - const VulkanDeviceInfo* device_info, - const StructPointerDecoder* pCreateInfo, - const StructPointerDecoder* pAllocator, - HandlePointerDecoder* pSampler) -{ - - auto* replay_create_info = pCreateInfo->GetPointer(); - VkSamplerCreateInfo modified_create_info = *replay_create_info; - return func( - device_info->handle, &modified_create_info, GetAllocationCallbacks(pAllocator), pSampler->GetHandlePointer()); -} - VkResult VulkanReplayConsumerBase::OverrideCreateSamplerYcbcrConversion( PFN_vkCreateSamplerYcbcrConversion func, VkResult result, diff --git a/framework/decode/vulkan_replay_consumer_base.h b/framework/decode/vulkan_replay_consumer_base.h index 3926c8236f..0bfa5cfe4b 100644 --- a/framework/decode/vulkan_replay_consumer_base.h +++ b/framework/decode/vulkan_replay_consumer_base.h @@ -1424,13 +1424,6 @@ class VulkanReplayConsumerBase : public VulkanConsumer VulkanShaderModuleInfo* shader_module_info, const StructPointerDecoder* pAllocator); - VkResult OverrideCreateSampler(PFN_vkCreateSampler func, - VkResult result, - const VulkanDeviceInfo* device_info, - const StructPointerDecoder* pCreateInfo, - const StructPointerDecoder* pAllocator, - HandlePointerDecoder* pSampler); - VkResult OverrideCreateSamplerYcbcrConversion( PFN_vkCreateSamplerYcbcrConversion func, VkResult result, diff --git a/framework/generated/generated_vulkan_replay_consumer.cpp b/framework/generated/generated_vulkan_replay_consumer.cpp index ae35d76c9f..6163e83633 100644 --- a/framework/generated/generated_vulkan_replay_consumer.cpp +++ b/framework/generated/generated_vulkan_replay_consumer.cpp @@ -1089,17 +1089,17 @@ void VulkanReplayConsumer::Process_vkCreateSampler( StructPointerDecoder* pAllocator, HandlePointerDecoder* pSampler) { - auto in_device = GetObjectInfoTable().GetVkDeviceInfo(device); - + VkDevice in_device = MapHandle(device, &CommonObjectInfoTable::GetVkDeviceInfo); + const VkSamplerCreateInfo* in_pCreateInfo = pCreateInfo->GetPointer(); MapStructHandles(pCreateInfo->GetMetaStructPointer(), GetObjectInfoTable()); + const VkAllocationCallbacks* in_pAllocator = GetAllocationCallbacks(pAllocator); if (!pSampler->IsNull()) { pSampler->SetHandleLength(1); } - VulkanSamplerInfo handle_info; - pSampler->SetConsumerData(0, &handle_info); + VkSampler* out_pSampler = pSampler->GetHandlePointer(); - VkResult replay_result = OverrideCreateSampler(GetDeviceTable(in_device->handle)->CreateSampler, returnValue, in_device, pCreateInfo, pAllocator, pSampler); + VkResult replay_result = GetDeviceTable(in_device)->CreateSampler(in_device, in_pCreateInfo, in_pAllocator, out_pSampler); CheckResult("vkCreateSampler", returnValue, replay_result, call_info); - AddHandle(device, pSampler->GetPointer(), pSampler->GetHandlePointer(), std::move(handle_info), &CommonObjectInfoTable::AddVkSamplerInfo); + AddHandle(device, pSampler->GetPointer(), out_pSampler, &CommonObjectInfoTable::AddVkSamplerInfo); } void VulkanReplayConsumer::Process_vkDestroySampler( diff --git a/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json b/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json index 5c34143f67..14dbf21d75 100644 --- a/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json +++ b/framework/generated/khronos_generators/vulkan_generators/replay_overrides.json @@ -138,7 +138,6 @@ "vkCmdBindDescriptorSets2KHR" : "OverrideCmdBindDescriptorSets2", "vkCmdBindDescriptorSets2" : "OverrideCmdBindDescriptorSets2", "vkCmdExecuteCommands" : "OverrideCmdExecuteCommands", - "vkCreateSampler": "OverrideCreateSampler", "vkCreateSamplerYcbcrConversion": "OverrideCreateSamplerYcbcrConversion" } } \ No newline at end of file From b57fac97e760b25c50b6a7454c0beb65dca75700 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Mon, 3 Mar 2025 18:15:34 +0100 Subject: [PATCH 10/16] wip: Move write command functions --- framework/encode/command_writer.cpp | 121 +++++++++++++ framework/encode/command_writer.h | 11 ++ framework/encode/vulkan_capture_common.cpp | 182 ++++---------------- framework/encode/vulkan_capture_common.h | 17 +- framework/encode/vulkan_capture_manager.cpp | 24 ++- framework/encode/vulkan_state_writer.cpp | 3 +- framework/encode/vulkan_state_writer.h | 1 + 7 files changed, 201 insertions(+), 158 deletions(-) diff --git a/framework/encode/command_writer.cpp b/framework/encode/command_writer.cpp index 22a803d05c..ff43a7d2ba 100644 --- a/framework/encode/command_writer.cpp +++ b/framework/encode/command_writer.cpp @@ -22,6 +22,10 @@ #include "encode/command_writer.h" +#if defined(VK_USE_PLATFORM_ANDROID_KHR) +#include +#endif + GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(encode) @@ -161,5 +165,122 @@ void CommandWriter::WriteInitImageCmd(format::ApiFamilyId api_family, } } +void CommandWriter::WriteFillMemoryCmd( + format::ApiFamilyId api_family, format::HandleId memory_id, uint64_t offset, uint64_t size, const void* data) +{ + GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, size); + + format::FillMemoryCommandHeader fill_cmd; + size_t header_size = sizeof(format::FillMemoryCommandHeader); + const uint8_t* uncompressed_data = (static_cast(data) + offset); + size_t uncompressed_size = static_cast(size); + + fill_cmd.meta_header.block_header.type = format::BlockType::kMetaDataBlock; + fill_cmd.meta_header.meta_data_id = format::MakeMetaDataId(api_family, format::MetaDataType::kFillMemoryCommand); + fill_cmd.thread_id = thread_data_->thread_id_; + fill_cmd.memory_id = memory_id; + fill_cmd.memory_offset = offset; + fill_cmd.memory_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. + fill_cmd.meta_header.block_header.type = format::BlockType::kCompressedMetaDataBlock; + + // Calculate size of packet with uncompressed data size. + fill_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(fill_cmd) + compressed_size; + + // Copy header to beginning of compressed_buffer_ + util::platform::MemoryCopy(thread_data_->compressed_buffer_.data(), header_size, &fill_cmd, header_size); + + output_stream_->Write(thread_data_->compressed_buffer_.data(), header_size + compressed_size); + } + } + + if (not_compressed) + { + // Calculate size of packet with compressed data size. + fill_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(fill_cmd) + uncompressed_size; + + output_stream_->CombineAndWrite({ { &fill_cmd, header_size }, { uncompressed_data, uncompressed_size } }, + thread_data_->GetScratchBuffer()); + } +} + +void CommandWriter::WriteCreateHardwareBufferCmd(format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId memory_id, + AHardwareBuffer* hardware_buffer, + const std::vector& plane_info) +{ +#if defined(VK_USE_PLATFORM_ANDROID_KHR) + GFXRECON_ASSERT(hardware_buffer != nullptr); + + format::CreateHardwareBufferCommandHeader create_buffer_cmd; + + create_buffer_cmd.meta_header.block_header.type = format::BlockType::kMetaDataBlock; + create_buffer_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(create_buffer_cmd); + create_buffer_cmd.meta_header.meta_data_id = format::MakeMetaDataId( + format::ApiFamilyId::ApiFamily_Vulkan, format::MetaDataType::kCreateHardwareBufferCommand); + create_buffer_cmd.thread_id = thread_id; + create_buffer_cmd.device_id = device_id; + create_buffer_cmd.memory_id = memory_id; + create_buffer_cmd.buffer_id = reinterpret_cast(hardware_buffer); + + // Get AHB description data. + AHardwareBuffer_Desc ahb_desc = {}; + AHardwareBuffer_describe(hardware_buffer, &ahb_desc); + + create_buffer_cmd.format = ahb_desc.format; + create_buffer_cmd.width = ahb_desc.width; + create_buffer_cmd.height = ahb_desc.height; + create_buffer_cmd.stride = ahb_desc.stride; + create_buffer_cmd.usage = ahb_desc.usage; + create_buffer_cmd.layers = ahb_desc.layers; + + size_t planes_size = 0; + + if (plane_info.empty()) + { + create_buffer_cmd.planes = 0; + } + else + { + create_buffer_cmd.planes = static_cast(plane_info.size()); + // Update size of packet with compressed or uncompressed data size. + planes_size = sizeof(plane_info[0]) * plane_info.size(); + create_buffer_cmd.meta_header.block_header.size += planes_size; + } + + if (planes_size > 0) + { + output_stream_->CombineAndWrite( + { { &create_buffer_cmd, sizeof(create_buffer_cmd) }, { plane_info.data(), planes_size } }, + thread_data_->GetScratchBuffer()); + } + else + { + output_stream_->Write(&create_buffer_cmd, sizeof(create_buffer_cmd)); + } +#else + GFXRECON_UNREFERENCED_PARAMETER(thread_id); + GFXRECON_UNREFERENCED_PARAMETER(memory_id); + GFXRECON_UNREFERENCED_PARAMETER(hardware_buffer); + GFXRECON_UNREFERENCED_PARAMETER(plane_info); + + GFXRECON_LOG_ERROR("Skipping create AHardwareBuffer command write for unsupported platform"); +#endif +} + GFXRECON_END_NAMESPACE(encode) GFXRECON_END_NAMESPACE(gfxrecon) diff --git a/framework/encode/command_writer.h b/framework/encode/command_writer.h index 43c38ba0d8..e10356f112 100644 --- a/framework/encode/command_writer.h +++ b/framework/encode/command_writer.h @@ -29,6 +29,8 @@ #include "util/thread_data.h" #include "util/output_stream.h" +struct AHardwareBuffer; + GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(encode) @@ -57,6 +59,15 @@ class CommandWriter uint64_t p_size, const void* p_data); + void WriteFillMemoryCmd( + format::ApiFamilyId api_family, format::HandleId memory_id, uint64_t offset, uint64_t size, const void* data); + + void WriteCreateHardwareBufferCmd(format::ThreadId thread_id, + format::HandleId device_id, + format::HandleId memory_id, + AHardwareBuffer* hardware_buffer, + const std::vector& plane_info); + private: util::ThreadData* thread_data_; util::OutputStream* output_stream_; diff --git a/framework/encode/vulkan_capture_common.cpp b/framework/encode/vulkan_capture_common.cpp index 5f7f58710e..fabcf95865 100644 --- a/framework/encode/vulkan_capture_common.cpp +++ b/framework/encode/vulkan_capture_common.cpp @@ -29,116 +29,15 @@ GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(encode) -static void CommonWriteCreateHardwareBufferCmd(format::ThreadId thread_id, - format::HandleId device_id, - format::HandleId memory_id, - AHardwareBuffer* hardware_buffer, - const std::vector& plane_info, - VulkanCaptureManager* vulkan_capture_manager, - VulkanStateWriter* vulkan_state_writer) +void* CommonProcessHardwareBuffer(format::ThreadId thread_id, + const vulkan_wrappers::DeviceWrapper* device_wrapper, + format::HandleId memory_id, + AHardwareBuffer* hardware_buffer, + size_t allocation_size, + CommandWriter* command_writer) { #if defined(VK_USE_PLATFORM_ANDROID_KHR) - if (vulkan_capture_manager && !vulkan_capture_manager->IsCaptureModeWrite()) - { - return; - } - assert(hardware_buffer != nullptr); - - format::CreateHardwareBufferCommandHeader create_buffer_cmd; - - create_buffer_cmd.meta_header.block_header.type = format::BlockType::kMetaDataBlock; - create_buffer_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(create_buffer_cmd); - create_buffer_cmd.meta_header.meta_data_id = format::MakeMetaDataId( - format::ApiFamilyId::ApiFamily_Vulkan, format::MetaDataType::kCreateHardwareBufferCommand); - create_buffer_cmd.thread_id = thread_id; - create_buffer_cmd.device_id = device_id; - create_buffer_cmd.memory_id = memory_id; - create_buffer_cmd.buffer_id = reinterpret_cast(hardware_buffer); - - // Get AHB description data. - AHardwareBuffer_Desc ahb_desc = {}; - AHardwareBuffer_describe(hardware_buffer, &ahb_desc); - - create_buffer_cmd.format = ahb_desc.format; - create_buffer_cmd.width = ahb_desc.width; - create_buffer_cmd.height = ahb_desc.height; - create_buffer_cmd.stride = ahb_desc.stride; - create_buffer_cmd.usage = ahb_desc.usage; - create_buffer_cmd.layers = ahb_desc.layers; - - size_t planes_size = 0; - - if (plane_info.empty()) - { - create_buffer_cmd.planes = 0; - } - else - { - create_buffer_cmd.planes = static_cast(plane_info.size()); - // Update size of packet with compressed or uncompressed data size. - planes_size = sizeof(plane_info[0]) * plane_info.size(); - create_buffer_cmd.meta_header.block_header.size += planes_size; - } - - if (vulkan_capture_manager) - { - if (planes_size > 0) - { - vulkan_capture_manager->CombineAndWriteToFile( - { { &create_buffer_cmd, sizeof(create_buffer_cmd) }, { plane_info.data(), planes_size } }); - } - else - { - vulkan_capture_manager->WriteToFile(&create_buffer_cmd, sizeof(create_buffer_cmd)); - } - } - else if (vulkan_state_writer) - { - vulkan_state_writer->OutputStreamWrite(&create_buffer_cmd, sizeof(create_buffer_cmd)); - - if (planes_size > 0) - { - vulkan_state_writer->OutputStreamWrite(plane_info.data(), planes_size); - } - } -#else - GFXRECON_UNREFERENCED_PARAMETER(thread_id); - GFXRECON_UNREFERENCED_PARAMETER(memory_id); - GFXRECON_UNREFERENCED_PARAMETER(hardware_buffer); - GFXRECON_UNREFERENCED_PARAMETER(plane_info); - GFXRECON_UNREFERENCED_PARAMETER(vulkan_capture_manager); - GFXRECON_UNREFERENCED_PARAMETER(vulkan_state_writer); - - GFXRECON_LOG_ERROR("Skipping create AHardwareBuffer command write for unsupported platform"); -#endif -} - -static void CommonWriteFillMemoryCmd(format::HandleId memory_id, - uint64_t size, - const void* data, - VulkanCaptureManager* vulkan_capture_manager, - VulkanStateWriter* vulkan_state_writer) -{ - if (vulkan_capture_manager) - { - vulkan_capture_manager->WriteFillMemoryCmd(memory_id, 0u, size, data); - } - else - { - vulkan_state_writer->WriteFillMemoryCmd(memory_id, 0u, size, data); - } -} - -void CommonProcessHardwareBuffer(format::ThreadId thread_id, - const vulkan_wrappers::DeviceWrapper* device_wrapper, - format::HandleId memory_id, - AHardwareBuffer* hardware_buffer, - size_t allocation_size, - VulkanCaptureManager* vulkan_capture_manager, - VulkanStateWriter* vulkan_state_writer) -{ -#if defined(VK_USE_PLATFORM_ANDROID_KHR) - assert(hardware_buffer != nullptr); + GFXRECON_ASSERT(hardware_buffer != nullptr); // If this is the first device memory object to reference the hardware buffer, write a buffer creation // command to the capture file and setup memory tracking. @@ -181,8 +80,10 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id #endif // Write CreateHardwareBufferCmd with or without the AHB payload - CommonWriteCreateHardwareBufferCmd( - thread_id, 0u, memory_id, hardware_buffer, plane_info, vulkan_capture_manager, vulkan_state_writer); + if (command_writer != nullptr) + { + command_writer->WriteCreateHardwareBufferCmd(thread_id, 0u, memory_id, hardware_buffer, plane_info); + } // If AHardwareBuffer_lockPlanes failed (or is not available) try AHardwareBuffer_lock if (result != 0) @@ -192,29 +93,9 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id if (result == 0 && data != nullptr) { - CommonWriteFillMemoryCmd(memory_id, allocation_size, data, vulkan_capture_manager, vulkan_state_writer); - - if (vulkan_capture_manager) + if (command_writer != nullptr) { - // Track the memory with the PageGuardManager - const auto tracking_mode = vulkan_capture_manager->GetMemoryTrackingMode(); - if ((tracking_mode == CaptureSettings::MemoryTrackingMode::kPageGuard || - tracking_mode == CaptureSettings::MemoryTrackingMode::kUserfaultfd) && - vulkan_capture_manager->GetPageGuardTrackAhbMemory()) - { - GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, allocation_size); - - util::PageGuardManager* manager = util::PageGuardManager::Get(); - assert(manager != nullptr); - - manager->AddTrackedMemory(memory_id, - data, - 0, - static_cast(allocation_size), - util::PageGuardManager::kNullShadowHandle, - false, // No shadow memory for the imported AHB memory. - false); // Write watch is not supported for this case. - } + command_writer->WriteFillMemoryCmd(format::ApiFamily_Vulkan, memory_id, 0, allocation_size, data); } result = AHardwareBuffer_unlock(hardware_buffer, nullptr); @@ -222,22 +103,25 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id { GFXRECON_LOG_ERROR("AHardwareBuffer_unlock failed"); } + + return data; } else { GFXRECON_LOG_ERROR( "AHardwareBuffer_lock failed: hardware buffer data will be omitted from the capture file"); - // Dump zeros for AHB payload. - std::vector zeros(allocation_size, 0); - CommonWriteFillMemoryCmd( - memory_id, zeros.size(), zeros.data(), vulkan_capture_manager, vulkan_state_writer); + if (command_writer != nullptr) + { + // Dump zeros for AHB payload. + std::vector zeros(allocation_size, 0); + command_writer->WriteFillMemoryCmd(format::ApiFamily_Vulkan, memory_id, 0, zeros.size(), zeros.data()); + } } } else { // The AHB is not CPU-readable, copy the data into a host visible buffer on the GPU - format::HandleId device_id = device_wrapper->handle_id; VkDevice device = device_wrapper->handle; auto physical_device_wrapper = device_wrapper->physical_device; auto physical_device = physical_device_wrapper->handle; @@ -266,14 +150,14 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id } if (device_queue_index == -1 || queue_family_index == -1) - return; - - auto queue_wrapper = device_wrapper->child_queues[device_queue_index]; - format::HandleId queue_id = queue_wrapper->handle_id; + return nullptr; - // Write CreateHardwareBufferCmd without the AHB payload - CommonWriteCreateHardwareBufferCmd( - thread_id, device_id, memory_id, hardware_buffer, plane_info, vulkan_capture_manager, vulkan_state_writer); + if (command_writer != nullptr) + { + // Write CreateHardwareBufferCmd without the AHB payload + command_writer->WriteCreateHardwareBufferCmd( + thread_id, device_wrapper->handle_id, memory_id, hardware_buffer, plane_info); + } VkResult vk_result = VK_SUCCESS; @@ -914,9 +798,9 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id if (vk_result == VK_SUCCESS) vk_result = device_table->MapMemory(device, host_image_memory, 0u, data_size, 0u, &data); - if (vk_result == VK_SUCCESS) + if (vk_result == VK_SUCCESS && command_writer != nullptr) { - CommonWriteFillMemoryCmd(memory_id, data_size, data, vulkan_capture_manager, vulkan_state_writer); + command_writer->WriteFillMemoryCmd(format::ApiFamily_Vulkan, memory_id, 0, data_size, data); } device_table->DestroyFence(device, fence, nullptr); @@ -936,12 +820,14 @@ void CommonProcessHardwareBuffer(format::ThreadId thread_id } #else GFXRECON_UNREFERENCED_PARAMETER(thread_id); + GFXRECON_UNREFERENCED_PARAMETER(device_wrapper); GFXRECON_UNREFERENCED_PARAMETER(memory_id); GFXRECON_UNREFERENCED_PARAMETER(hardware_buffer); GFXRECON_UNREFERENCED_PARAMETER(allocation_size); - GFXRECON_UNREFERENCED_PARAMETER(vulkan_capture_manager); - GFXRECON_UNREFERENCED_PARAMETER(vulkan_state_writer); + GFXRECON_UNREFERENCED_PARAMETER(command_writer); #endif + + return nullptr; } GFXRECON_END_NAMESPACE(encode) diff --git a/framework/encode/vulkan_capture_common.h b/framework/encode/vulkan_capture_common.h index 62e88b021d..b027d28999 100644 --- a/framework/encode/vulkan_capture_common.h +++ b/framework/encode/vulkan_capture_common.h @@ -33,13 +33,16 @@ GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(encode) -void CommonProcessHardwareBuffer(format::ThreadId thread_id, - const vulkan_wrappers::DeviceWrapper* device_wrapper, - format::HandleId memory_id, - AHardwareBuffer* hardware_buffer, - size_t allocation_size, - VulkanCaptureManager* vulkan_capture_manager, - VulkanStateWriter* vulkan_state_writer); +/** + * @param command_writer If valid, hardware buffer commands will be written to output stream. + * @return A pointer to the imported memory, if such memory is CPU visible. `nullptr` otherwise. + */ +void* CommonProcessHardwareBuffer(format::ThreadId thread_id, + const vulkan_wrappers::DeviceWrapper* device_wrapper, + format::HandleId memory_id, + AHardwareBuffer* hardware_buffer, + size_t allocation_size, + CommandWriter* command_writer); GFXRECON_END_NAMESPACE(encode) GFXRECON_END_NAMESPACE(gfxrecon) diff --git a/framework/encode/vulkan_capture_manager.cpp b/framework/encode/vulkan_capture_manager.cpp index d91b7bfa5d..ff8a12551a 100644 --- a/framework/encode/vulkan_capture_manager.cpp +++ b/framework/encode/vulkan_capture_manager.cpp @@ -1755,7 +1755,29 @@ void VulkanCaptureManager::ProcessHardwareBuffer(format::ThreadId thread_id, const size_t ahb_size = properties.allocationSize; assert(ahb_size); - CommonProcessHardwareBuffer(thread_id, device_wrapper, memory_id, hardware_buffer, ahb_size, this, nullptr); + auto* command_writer = IsCaptureModeWrite() ? GetCommandWriter() : nullptr; + auto* data = CommonProcessHardwareBuffer( + thread_id, device_wrapper, memory_id, hardware_buffer, ahb_size, command_writer); + if (data != nullptr) + { + // Track the memory with the PageGuardManager + const auto tracking_mode = GetMemoryTrackingMode(); + if ((tracking_mode == CaptureSettings::MemoryTrackingMode::kPageGuard || + tracking_mode == CaptureSettings::MemoryTrackingMode::kUserfaultfd) && + GetPageGuardTrackAhbMemory()) + { + util::PageGuardManager* manager = util::PageGuardManager::Get(); + GFXRECON_ASSERT(manager != nullptr); + + manager->AddTrackedMemory(memory_id, + data, + 0, + static_cast(ahb_size), + util::PageGuardManager::kNullShadowHandle, + false, // No shadow memory for the imported AHB memory. + false); // Write watch is not supported for this case. + } + } } else { diff --git a/framework/encode/vulkan_state_writer.cpp b/framework/encode/vulkan_state_writer.cpp index ac684d99e2..e17be77d2f 100644 --- a/framework/encode/vulkan_state_writer.cpp +++ b/framework/encode/vulkan_state_writer.cpp @@ -1372,8 +1372,7 @@ void VulkanStateWriter::WriteDeviceMemoryState(const VulkanStateTable& state_tab wrapper->hardware_buffer_memory_id, wrapper->hardware_buffer, wrapper->allocation_size, - nullptr, - this); + &command_writer_); ++blocks_written_; } diff --git a/framework/encode/vulkan_state_writer.h b/framework/encode/vulkan_state_writer.h index 1191487daa..85082ad6d5 100644 --- a/framework/encode/vulkan_state_writer.h +++ b/framework/encode/vulkan_state_writer.h @@ -62,6 +62,7 @@ class VulkanStateWriter VulkanStateWriter::AssetFileOffsetsInfo* asset_file_offsets = nullptr); util::ThreadData* GetThreadData() { return thread_data_; } + CommandWriter* GetCommandWriter() { return &command_writer_; } bool OutputStreamWrite(const void* data, size_t len); From f5bc3064dbd367f00ac8e9139639df7b42acb88a Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Tue, 4 Mar 2025 15:03:48 +0100 Subject: [PATCH 11/16] encode: Staging copy size for external format --- framework/encode/vulkan_state_writer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framework/encode/vulkan_state_writer.cpp b/framework/encode/vulkan_state_writer.cpp index e17be77d2f..d25b836bfb 100644 --- a/framework/encode/vulkan_state_writer.cpp +++ b/framework/encode/vulkan_state_writer.cpp @@ -2742,6 +2742,12 @@ void VulkanStateWriter::WriteImageMemoryState(const VulkanStateTable& state_tabl if (wrapper->external_format) { + // The original external format is not restored at replay time, but RGBA8 is used, meaning the + // image size at replay might be different than current size. + const VkDeviceSize rgba8_size = 4; + const VkDeviceSize replay_size = wrapper->extent.width * wrapper->extent.height * rgba8_size; + *max_staging_copy_size = std::max(*max_staging_copy_size, replay_size); + snapshot_info.resource_size = wrapper->size; snapshot_info.level_sizes.push_back(wrapper->size); } From a5458092bcf3179a70d4eefccc3d97e90bc1a2fa Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Tue, 4 Mar 2025 15:32:53 +0100 Subject: [PATCH 12/16] encode: Fix tracking image with external memory Do not query memory requirements before binding external memory to image. --- framework/encode/vulkan_state_tracker_initializers.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/framework/encode/vulkan_state_tracker_initializers.h b/framework/encode/vulkan_state_tracker_initializers.h index d4d274fce9..cbf193dc09 100644 --- a/framework/encode/vulkan_state_tracker_initializers.h +++ b/framework/encode/vulkan_state_tracker_initializers.h @@ -647,9 +647,18 @@ inline void InitializeStatequeue_family_index = create_info->pQueueFamilyIndices[0]; } + auto* external_memory = graphics::vulkan_struct_get_pnext(create_info); + bool external_handle_android = + (external_memory != nullptr) && + ((external_memory->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) == + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID); + auto* external_format_android = graphics::vulkan_struct_get_pnext(create_info); - if (external_format_android != nullptr && external_format_android->externalFormat != 0) + bool external_format = (external_format_android != nullptr) && (external_format_android->externalFormat != 0); + + if (external_handle_android || external_format) { + // Can not get image memory requirements before binding memory wrapper->external_format = true; wrapper->size = 0; } From 2ac2d25ab0be2c603deefa4507d8683b13bb8d94 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Thu, 20 Feb 2025 09:48:34 +0100 Subject: [PATCH 13/16] encode: Fix dedicated alloc info image VUID-VkMemoryDedicatedAllocateInfo-image-02964 If image is not VK_NULL_HANDLE and the memory is not an imported AHB or an imported QNX Screen buffer, VkMemoryAllocateInfo::allocationSize must equal the VkMemoryRequirements::size of the image. --- framework/encode/vulkan_capture_manager.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/framework/encode/vulkan_capture_manager.cpp b/framework/encode/vulkan_capture_manager.cpp index ff8a12551a..8af32c3936 100644 --- a/framework/encode/vulkan_capture_manager.cpp +++ b/framework/encode/vulkan_capture_manager.cpp @@ -1038,6 +1038,22 @@ VkResult VulkanCaptureManager::OverrideAllocateMemory(VkDevice } } +#if defined(VK_USE_PLATFORM_ANDROID_KHR) + // If image is not VK_NULL_HANDLE and the memory is not an imported Android Hardware Buffer + auto dedicated_alloc_info = + graphics::vulkan_struct_get_pnext(pAllocateInfo_unwrapped); + auto import_ahb_info = + graphics::vulkan_struct_get_pnext(pAllocateInfo_unwrapped); + if (dedicated_alloc_info != nullptr && dedicated_alloc_info->image != VK_NULL_HANDLE && import_ahb_info == nullptr) + { + // allocationSize needs to be equal to VkMemoryDedicatedAllocateInfo::image VkMemoryRequirements::size + VkMemoryRequirements memory_requirements = {}; + vulkan_wrappers::GetDeviceTable(device)->GetImageMemoryRequirements( + device, dedicated_alloc_info->image, &memory_requirements); + pAllocateInfo_unwrapped->allocationSize = memory_requirements.size; + } +#endif + if (IsPageGuardMemoryModeExternal()) { VkMemoryPropertyFlags properties = GetMemoryProperties(device_wrapper, pAllocateInfo->memoryTypeIndex); From 8af9a6d6a93bdef404e133fc7844bba3fa3443f3 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Thu, 20 Feb 2025 18:48:17 +0100 Subject: [PATCH 14/16] decode: Fix dedicated alloc info image VUID-VkMemoryDedicatedAllocateInfo-image-02964 If image is not VK_NULL_HANDLE and the memory is not an imported AHB or an imported QNX Screen buffer, VkMemoryAllocateInfo::allocationSize must equal the VkMemoryRequirements::size of the image. --- .../decode/vulkan_replay_consumer_base.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index 4a4f9a3add..76d2319e36 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -4713,6 +4713,24 @@ VkResult VulkanReplayConsumerBase::OverrideAllocateMemory( std::unique_ptr> external_memory_guard( nullptr, [&](void* memory) { util::platform::FreeRawMemory(memory, host_pointer_size); }); +#if defined(VK_USE_PLATFORM_ANDROID_KHR) + // If image is not VK_NULL_HANDLE and the memory is not an imported Android Hardware Buffer + auto dedicated_alloc_info = + graphics::vulkan_struct_get_pnext(modified_allocate_info); + auto import_ahb_info = + graphics::vulkan_struct_get_pnext(modified_allocate_info); + if (dedicated_alloc_info != nullptr && dedicated_alloc_info->image != VK_NULL_HANDLE && + import_ahb_info == nullptr) + { + // allocationSize needs to be equal to VkMemoryDedicatedAllocateInfo::image VkMemoryRequirements::size + VkMemoryRequirements memory_requirements = {}; + VkDevice device = device_info->handle; + GetDeviceTable(device)->GetImageMemoryRequirements( + device, dedicated_alloc_info->image, &memory_requirements); + modified_allocate_info->allocationSize = memory_requirements.size; + } +#endif + while (current_struct != nullptr) { if (current_struct->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO) From cd6f7e1d53a4e6d74f437a173dacbba57dbb87ab Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Fri, 28 Feb 2025 15:46:53 +0100 Subject: [PATCH 15/16] device: Fix AHB memory allocation size If memory is importing an Android Hardware Buffer, its allocation size should be equal to the AHB properties allocation size. --- framework/decode/vulkan_replay_consumer_base.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index 76d2319e36..73ae4cf4ab 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -4729,6 +4729,18 @@ VkResult VulkanReplayConsumerBase::OverrideAllocateMemory( device, dedicated_alloc_info->image, &memory_requirements); modified_allocate_info->allocationSize = memory_requirements.size; } + + // On the other hand, if it is importing an Android Hardware Buffer + if (import_ahb_info) + { + // allocationSize needs to be equal to VkAndroidHardwareBufferPropertiesANDROID::allocationSize + VkAndroidHardwareBufferPropertiesANDROID properties = {}; + properties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; + VkDevice device = device_info->handle; + GetDeviceTable(device)->GetAndroidHardwareBufferPropertiesANDROID( + device, import_ahb_info->buffer, &properties); + modified_allocate_info->allocationSize = properties.allocationSize; + } #endif while (current_struct != nullptr) From bbd750ecc15dcf7449e9c00e5e8bcd2860c4a7d3 Mon Sep 17 00:00:00 2001 From: Antonio Caggiano Date: Tue, 4 Mar 2025 17:49:04 +0100 Subject: [PATCH 16/16] trim: Skip images backed by AHBs Do not write the state of image memory backed by an AHB as the AHB has already been processed. At replay time the content of the image will clearly correspond to the content of the AHB. --- framework/decode/vulkan_object_info.h | 1 + .../decode/vulkan_replay_consumer_base.cpp | 29 +++++++++---------- framework/encode/vulkan_handle_wrappers.h | 1 + framework/encode/vulkan_state_tracker.cpp | 2 +- .../vulkan_state_tracker_initializers.h | 11 ++++--- framework/encode/vulkan_state_writer.cpp | 14 ++++++++- 6 files changed, 35 insertions(+), 23 deletions(-) diff --git a/framework/decode/vulkan_object_info.h b/framework/decode/vulkan_object_info.h index e5587fe82d..9b27b9720b 100644 --- a/framework/decode/vulkan_object_info.h +++ b/framework/decode/vulkan_object_info.h @@ -401,6 +401,7 @@ struct VulkanImageInfo : public VulkanObjectInfo VkImageType type{}; VkFormat format{}; bool external_format{ false }; + bool external_memory_android{ false }; VkExtent3D extent{ 0, 0, 0 }; VkImageTiling tiling{}; VkSampleCountFlagBits sample_count{}; diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index 73ae4cf4ab..cb218659ba 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -5126,7 +5126,7 @@ VkResult VulkanReplayConsumerBase::OverrideBindImageMemory(PFN_vkBindImageMemory } // Memory requirements for image with external format can only be queried after the memory is bound - if (image_info->external_format) + if (image_info->external_format || image_info->external_memory_android) { VkMemoryRequirements image_mem_reqs; GetDeviceTable(device_info->handle) @@ -5491,15 +5491,13 @@ VulkanReplayConsumerBase::OverrideCreateImage(PFN_vkCreateImage // The original image might be external. auto* external_memory = graphics::vulkan_struct_get_pnext(create_info); // The external memory might be an unknown format. - auto* external_format = graphics::vulkan_struct_get_pnext(create_info); - if (create_info->format == VK_FORMAT_UNDEFINED) + auto* external_format = graphics::vulkan_struct_get_pnext(create_info); + bool has_external_format = external_format != nullptr && external_format->externalFormat != 0; + if (create_info->format == VK_FORMAT_UNDEFINED && external_memory != nullptr && has_external_format) { - if (external_memory != nullptr && external_format != nullptr) - { - // In this case, the image has been sampled at capture time and format is now RGBA8_UNORM. - create_info->format = VK_FORMAT_R8G8B8A8_UNORM; - external_format->externalFormat = 0; - } + // In this case, the image has been sampled at capture time and format is now RGBA8_UNORM. + create_info->format = VK_FORMAT_R8G8B8A8_UNORM; + external_format->externalFormat = 0; } VkResult result = allocator->CreateImage( @@ -5535,15 +5533,16 @@ VulkanReplayConsumerBase::OverrideCreateImage(PFN_vkCreateImage image_info->queue_family_index = 0; } + image_info->external_format = has_external_format; + + image_info->external_memory_android = + (external_memory != nullptr && + (external_memory->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0); + // Memory requirements for image with external format can only be queried after the memory is bound // Also, if image was created with the VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID // external memory handle type, then image must be bound to memory - if (external_memory != nullptr && - (external_memory->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0) - { - image_info->external_format = true; - } - else + if (!image_info->external_memory_android && !image_info->external_format) { VkMemoryRequirements image_mem_reqs; GetDeviceTable(device_info->handle) diff --git a/framework/encode/vulkan_handle_wrappers.h b/framework/encode/vulkan_handle_wrappers.h index 8d68c871dd..04ce0252c5 100644 --- a/framework/encode/vulkan_handle_wrappers.h +++ b/framework/encode/vulkan_handle_wrappers.h @@ -220,6 +220,7 @@ struct ImageWrapper : public HandleWrapper, AssetWrapperBase VkImageType image_type{ VK_IMAGE_TYPE_2D }; VkFormat format{ VK_FORMAT_UNDEFINED }; bool external_format{ false }; + bool external_memory_android{ false }; VkExtent3D extent{ 0, 0, 0 }; uint32_t mip_levels{ 0 }; uint32_t array_layers{ 0 }; diff --git a/framework/encode/vulkan_state_tracker.cpp b/framework/encode/vulkan_state_tracker.cpp index e8ed6c424c..c0316fc7b3 100644 --- a/framework/encode/vulkan_state_tracker.cpp +++ b/framework/encode/vulkan_state_tracker.cpp @@ -606,7 +606,7 @@ void VulkanStateTracker::TrackImageMemoryBinding( } // AHB image memory requirements can only be queried after the memory is bound - if (wrapper->external_format) + if (wrapper->external_format || wrapper->external_memory_android) { const VulkanDeviceTable* device_table = vulkan_wrappers::GetDeviceTable(device); VkMemoryRequirements image_mem_reqs; diff --git a/framework/encode/vulkan_state_tracker_initializers.h b/framework/encode/vulkan_state_tracker_initializers.h index cbf193dc09..91595d9274 100644 --- a/framework/encode/vulkan_state_tracker_initializers.h +++ b/framework/encode/vulkan_state_tracker_initializers.h @@ -648,19 +648,18 @@ inline void InitializeState(create_info); - bool external_handle_android = + wrapper->external_memory_android = (external_memory != nullptr) && ((external_memory->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID); - auto* external_format_android = graphics::vulkan_struct_get_pnext(create_info); - bool external_format = (external_format_android != nullptr) && (external_format_android->externalFormat != 0); + auto* external_format = graphics::vulkan_struct_get_pnext(create_info); + wrapper->external_format = (external_format != nullptr) && (external_format->externalFormat != 0); - if (external_handle_android || external_format) + if (wrapper->external_memory_android || wrapper->external_format) { // Can not get image memory requirements before binding memory - wrapper->external_format = true; - wrapper->size = 0; + wrapper->size = 0; } else { diff --git a/framework/encode/vulkan_state_writer.cpp b/framework/encode/vulkan_state_writer.cpp index d25b836bfb..369b9bb2d2 100644 --- a/framework/encode/vulkan_state_writer.cpp +++ b/framework/encode/vulkan_state_writer.cpp @@ -2274,6 +2274,12 @@ void VulkanStateWriter::ProcessImageMemory(const vulkan_wrappers::DeviceWrapper* assert((image_wrapper != nullptr) && ((image_wrapper->is_swapchain_image && memory_wrapper == nullptr) || (!image_wrapper->is_swapchain_image && memory_wrapper != nullptr))); + if (image_wrapper->external_memory_android) + { + // No need to process this image memory as its corresponding AHB is processed instead + continue; + } + if (snapshot_entry.need_staging_copy) { std::vector subresource_offsets; @@ -2378,6 +2384,12 @@ void VulkanStateWriter::ProcessImageMemoryWithAssetFile(const vulkan_wrappers::D assert(image_wrapper != nullptr); + if (image_wrapper->external_memory_android) + { + // No need to process this image memory as its corresponding AHB is processed instead + continue; + } + if (image_wrapper->dirty) { assert((image_wrapper->is_swapchain_image && memory_wrapper == nullptr) || @@ -2740,7 +2752,7 @@ void VulkanStateWriter::WriteImageMemoryState(const VulkanStateTable& state_tabl snapshot_info.need_staging_copy = need_staging_copy; snapshot_info.aspect = aspect; - if (wrapper->external_format) + if (wrapper->external_format || wrapper->external_memory_android) { // The original external format is not restored at replay time, but RGBA8 is used, meaning the // image size at replay might be different than current size.