diff --git a/impeller/renderer/backend/vulkan/allocator_vk.cc b/impeller/renderer/backend/vulkan/allocator_vk.cc index ecbbc2f776ff8..b73e5457757da 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.cc +++ b/impeller/renderer/backend/vulkan/allocator_vk.cc @@ -170,6 +170,32 @@ ISize AllocatorVK::GetMaxTextureSizeSupported() const { return max_texture_size_; } +int32_t AllocatorVK::FindMemoryTypeIndex( + uint32_t memory_type_bits_requirement, + vk::PhysicalDeviceMemoryProperties& memory_properties) { + int32_t type_index = -1; + vk::MemoryPropertyFlagBits required_properties = + vk::MemoryPropertyFlagBits::eDeviceLocal; + + const uint32_t memory_count = memory_properties.memoryTypeCount; + for (uint32_t memory_index = 0; memory_index < memory_count; ++memory_index) { + const uint32_t memory_type_bits = (1 << memory_index); + const bool is_required_memory_type = + memory_type_bits_requirement & memory_type_bits; + + const auto properties = + memory_properties.memoryTypes[memory_index].propertyFlags; + const bool has_required_properties = + (properties & required_properties) == required_properties; + + if (is_required_memory_type && has_required_properties) { + return static_cast(memory_index); + } + } + + return type_index; +} + static constexpr vk::ImageUsageFlags ToVKImageUsageFlags( PixelFormat format, TextureUsageMask usage, diff --git a/impeller/renderer/backend/vulkan/allocator_vk.h b/impeller/renderer/backend/vulkan/allocator_vk.h index c16ce6bcf2f49..92b488c4b8c7c 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.h +++ b/impeller/renderer/backend/vulkan/allocator_vk.h @@ -5,15 +5,12 @@ #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_ALLOCATOR_VK_H_ #define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_ALLOCATOR_VK_H_ -#include "flutter/fml/macros.h" -#include "flutter/fml/memory/ref_ptr.h" #include "impeller/core/allocator.h" #include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/device_buffer_vk.h" #include "impeller/renderer/backend/vulkan/device_holder_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" -#include #include #include @@ -27,6 +24,14 @@ class AllocatorVK final : public Allocator { // Visible for testing size_t DebugGetHeapUsage() const; + /// @brief Select a matching memory type for the given + /// [memory_type_bits_requirement], or -1 if none is found. + /// + /// This only returns memory types with deviceLocal allocations. + static int32_t FindMemoryTypeIndex( + uint32_t memory_type_bits_requirement, + vk::PhysicalDeviceMemoryProperties& memory_properties); + private: friend class ContextVK; diff --git a/impeller/renderer/backend/vulkan/allocator_vk_unittests.cc b/impeller/renderer/backend/vulkan/allocator_vk_unittests.cc index 26856987e20de..1b0b85871231c 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk_unittests.cc +++ b/impeller/renderer/backend/vulkan/allocator_vk_unittests.cc @@ -13,6 +13,44 @@ namespace impeller { namespace testing { +TEST(AllocatorVKTest, MemoryTypeSelectionSingleHeap) { + vk::PhysicalDeviceMemoryProperties properties; + properties.memoryTypeCount = 1; + properties.memoryHeapCount = 1; + properties.memoryTypes[0].heapIndex = 0; + properties.memoryTypes[0].propertyFlags = + vk::MemoryPropertyFlagBits::eDeviceLocal; + properties.memoryHeaps[0].size = 1024 * 1024 * 1024; + properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal; + + EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), 0); + EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), -1); + EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 0); +} + +TEST(AllocatorVKTest, MemoryTypeSelectionTwoHeap) { + vk::PhysicalDeviceMemoryProperties properties; + properties.memoryTypeCount = 2; + properties.memoryHeapCount = 2; + properties.memoryTypes[0].heapIndex = 0; + properties.memoryTypes[0].propertyFlags = + vk::MemoryPropertyFlagBits::eHostVisible; + properties.memoryHeaps[0].size = 1024 * 1024 * 1024; + properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal; + + properties.memoryTypes[1].heapIndex = 1; + properties.memoryTypes[1].propertyFlags = + vk::MemoryPropertyFlagBits::eDeviceLocal; + properties.memoryHeaps[1].size = 1024 * 1024 * 1024; + properties.memoryHeaps[1].flags = vk::MemoryHeapFlagBits::eDeviceLocal; + + // First fails because this only looks for eDeviceLocal. + EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), -1); + EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), 1); + EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 1); + EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(4, properties), -1); +} + #ifdef IMPELLER_DEBUG TEST(AllocatorVKTest, RecreateSwapchainWhenSizeChanges) { diff --git a/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.cc b/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.cc index bea9958bd2b50..2ff45078fa5dc 100644 --- a/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.cc +++ b/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.cc @@ -4,6 +4,7 @@ #include "impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h" +#include "impeller/renderer/backend/vulkan/allocator_vk.h" #include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/texture_source_vk.h" #include "impeller/renderer/backend/vulkan/yuv_conversion_library_vk.h" @@ -88,27 +89,16 @@ static vk::UniqueImage CreateVKImageWrapperForAndroidHarwareBuffer( return std::move(image.value); } -// Returns -1 if not found. -static int FindMemoryTypeIndex( - const vk::AndroidHardwareBufferPropertiesANDROID& props) { - uint32_t memory_type_bits = props.memoryTypeBits; - int32_t type_index = -1; - for (uint32_t i = 0; memory_type_bits; - memory_type_bits = memory_type_bits >> 0x1, ++i) { - if (memory_type_bits & 0x1) { - type_index = i; - break; - } - } - return type_index; -} - static vk::UniqueDeviceMemory ImportVKDeviceMemoryFromAndroidHarwareBuffer( const vk::Device& device, + const vk::PhysicalDevice& physical_device, const vk::Image& image, struct AHardwareBuffer* hardware_buffer, const AHBProperties& ahb_props) { - const int memory_type_index = FindMemoryTypeIndex(ahb_props.get()); + vk::PhysicalDeviceMemoryProperties memory_properties; + physical_device.getMemoryProperties(&memory_properties); + int memory_type_index = AllocatorVK::FindMemoryTypeIndex( + ahb_props.get().memoryTypeBits, memory_properties); if (memory_type_index < 0) { VALIDATION_LOG << "Could not find memory type of external image."; return {}; @@ -300,6 +290,7 @@ AHBTextureSourceVK::AHBTextureSourceVK( } const auto& device = context->GetDevice(); + const auto& physical_device = context->GetPhysicalDevice(); AHBProperties ahb_props; @@ -322,7 +313,7 @@ AHBTextureSourceVK::AHBTextureSourceVK( // Create a device memory allocation to refer to our external image. auto device_memory = ImportVKDeviceMemoryFromAndroidHarwareBuffer( - device, image.get(), ahb, ahb_props); + device, physical_device, image.get(), ahb, ahb_props); if (!device_memory) { return; } diff --git a/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h b/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h index 14c027b901d89..c36a7c5652e4e 100644 --- a/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h +++ b/impeller/renderer/backend/vulkan/android/ahb_texture_source_vk.h @@ -58,10 +58,10 @@ class AHBTextureSourceVK final : public TextureSourceVK { std::shared_ptr GetYUVConversion() const override; private: - vk::UniqueDeviceMemory device_memory_; - vk::UniqueImage image_; - vk::UniqueImageView image_view_; - std::shared_ptr yuv_conversion_; + vk::UniqueDeviceMemory device_memory_ = {}; + vk::UniqueImage image_ = {}; + vk::UniqueImageView image_view_ = {}; + std::shared_ptr yuv_conversion_ = {}; bool needs_yuv_conversion_ = false; bool is_valid_ = false; diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index c8b94fb72d37b..ad00687b555ba 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -56,6 +56,10 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, auto texture_source = std::make_shared( impeller_context_, latest_hardware_buffer, hb_desc); + if (!texture_source->IsValid()) { + CloseHardwareBuffer(hardware_buffer); + return; + } auto texture = std::make_shared(impeller_context_, texture_source);