diff --git a/impeller/renderer/backend/gles/context_gles.cc b/impeller/renderer/backend/gles/context_gles.cc index 4f590e2b2d729..34b095d46ab48 100644 --- a/impeller/renderer/backend/gles/context_gles.cc +++ b/impeller/renderer/backend/gles/context_gles.cc @@ -76,6 +76,7 @@ ContextGLES::ContextGLES(std::unique_ptr gl, .SetSupportsReadFromResolve(false) .SetSupportsReadFromOnscreenTexture(false) .SetSupportsDecalTileMode(false) + .SetSupportsMemorylessTextures(false) .Build(); } diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index 223762608b153..db2c1fef0cc21 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -64,6 +64,7 @@ static bool DeviceSupportsComputeSubgroups(id device) { .SetSupportsComputeSubgroups(DeviceSupportsComputeSubgroups(device)) .SetSupportsReadFromResolve(true) .SetSupportsReadFromOnscreenTexture(true) + .SetSupportsMemorylessTextures(true) .Build(); } diff --git a/impeller/renderer/backend/vulkan/allocator_vk.cc b/impeller/renderer/backend/vulkan/allocator_vk.cc index be0674f82a9ec..4e106d2b9c98b 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.cc +++ b/impeller/renderer/backend/vulkan/allocator_vk.cc @@ -21,7 +21,8 @@ AllocatorVK::AllocatorVK(std::weak_ptr context, const std::shared_ptr& device_holder, const vk::Instance& instance, PFN_vkGetInstanceProcAddr get_instance_proc_address, - PFN_vkGetDeviceProcAddr get_device_proc_address) + PFN_vkGetDeviceProcAddr get_device_proc_address, + const CapabilitiesVK& capabilities) : context_(std::move(context)), device_holder_(device_holder) { vk_ = fml::MakeRefCounted(get_instance_proc_address); @@ -91,6 +92,7 @@ AllocatorVK::AllocatorVK(std::weak_ptr context, return; } allocator_ = allocator; + supports_memoryless_textures_ = capabilities.SupportsMemorylessTextures(); is_valid_ = true; } @@ -110,9 +112,11 @@ ISize AllocatorVK::GetMaxTextureSizeSupported() const { return max_texture_size_; } -static constexpr vk::ImageUsageFlags ToVKImageUsageFlags(PixelFormat format, - TextureUsageMask usage, - StorageMode mode) { +static constexpr vk::ImageUsageFlags ToVKImageUsageFlags( + PixelFormat format, + TextureUsageMask usage, + StorageMode mode, + bool supports_memoryless_textures) { vk::ImageUsageFlags vk_usage; switch (mode) { @@ -120,7 +124,9 @@ static constexpr vk::ImageUsageFlags ToVKImageUsageFlags(PixelFormat format, case StorageMode::kDevicePrivate: break; case StorageMode::kDeviceTransient: - vk_usage |= vk::ImageUsageFlagBits::eTransientAttachment; + if (supports_memoryless_textures) { + vk_usage |= vk::ImageUsageFlagBits::eTransientAttachment; + } break; } @@ -168,7 +174,25 @@ static constexpr VmaMemoryUsage ToVMAMemoryUsage() { return VMA_MEMORY_USAGE_AUTO; } -static constexpr VkMemoryPropertyFlags ToVKMemoryPropertyFlags( +static constexpr VkMemoryPropertyFlags ToVKTextureMemoryPropertyFlags( + StorageMode mode, + bool supports_memoryless_textures) { + switch (mode) { + case StorageMode::kHostVisible: + return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + case StorageMode::kDevicePrivate: + return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + case StorageMode::kDeviceTransient: + if (supports_memoryless_textures) { + return VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT | + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + FML_UNREACHABLE(); +} + +static constexpr VkMemoryPropertyFlags ToVKBufferMemoryPropertyFlags( StorageMode mode) { switch (mode) { case StorageMode::kHostVisible: @@ -196,9 +220,6 @@ static VmaAllocationCreateFlags ToVmaAllocationCreateFlags(StorageMode mode, } return flags; case StorageMode::kDevicePrivate: - if (is_texture) { - flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - } return flags; case StorageMode::kDeviceTransient: return flags; @@ -210,7 +231,8 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { public: AllocatedTextureSourceVK(const TextureDescriptor& desc, VmaAllocator allocator, - vk::Device device) + vk::Device device, + bool supports_memoryless_textures) : TextureSourceVK(desc) { vk::ImageCreateInfo image_info; image_info.flags = ToVKImageCreateFlags(desc.type); @@ -227,13 +249,15 @@ class AllocatedTextureSourceVK final : public TextureSourceVK { image_info.tiling = vk::ImageTiling::eOptimal; image_info.initialLayout = vk::ImageLayout::eUndefined; image_info.usage = - ToVKImageUsageFlags(desc.format, desc.usage, desc.storage_mode); + ToVKImageUsageFlags(desc.format, desc.usage, desc.storage_mode, + supports_memoryless_textures); image_info.sharingMode = vk::SharingMode::eExclusive; VmaAllocationCreateInfo alloc_nfo = {}; alloc_nfo.usage = ToVMAMemoryUsage(); - alloc_nfo.preferredFlags = ToVKMemoryPropertyFlags(desc.storage_mode); + alloc_nfo.preferredFlags = ToVKTextureMemoryPropertyFlags( + desc.storage_mode, supports_memoryless_textures); alloc_nfo.flags = ToVmaAllocationCreateFlags(desc.storage_mode, true); auto create_info_native = @@ -336,11 +360,12 @@ std::shared_ptr AllocatorVK::OnCreateTexture( if (!device_holder) { return nullptr; } - auto source = - std::make_shared(desc, // - allocator_, // - device_holder->GetDevice() // - ); + auto source = std::make_shared( + desc, // + allocator_, // + device_holder->GetDevice(), // + supports_memoryless_textures_ // + ); if (!source->IsValid()) { return nullptr; } @@ -365,7 +390,8 @@ std::shared_ptr AllocatorVK::OnCreateBuffer( VmaAllocationCreateInfo allocation_info = {}; allocation_info.usage = ToVMAMemoryUsage(); - allocation_info.preferredFlags = ToVKMemoryPropertyFlags(desc.storage_mode); + allocation_info.preferredFlags = + ToVKBufferMemoryPropertyFlags(desc.storage_mode); allocation_info.flags = ToVmaAllocationCreateFlags(desc.storage_mode, false); VkBuffer buffer = {}; diff --git a/impeller/renderer/backend/vulkan/allocator_vk.h b/impeller/renderer/backend/vulkan/allocator_vk.h index 64b9ba4c2ac5c..fba13f2b7cf12 100644 --- a/impeller/renderer/backend/vulkan/allocator_vk.h +++ b/impeller/renderer/backend/vulkan/allocator_vk.h @@ -31,6 +31,7 @@ class AllocatorVK final : public Allocator { std::weak_ptr device_holder_; ISize max_texture_size_; bool is_valid_ = false; + bool supports_memoryless_textures_ = false; AllocatorVK(std::weak_ptr context, uint32_t vulkan_api_version, @@ -38,7 +39,8 @@ class AllocatorVK final : public Allocator { const std::shared_ptr& device_holder, const vk::Instance& instance, PFN_vkGetInstanceProcAddr get_instance_proc_address, - PFN_vkGetDeviceProcAddr get_device_proc_address); + PFN_vkGetDeviceProcAddr get_device_proc_address, + const CapabilitiesVK& capabilities); // |Allocator| bool IsValid() const; diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.cc b/impeller/renderer/backend/vulkan/capabilities_vk.cc index 84585b84ec33f..a09c13b568e43 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.cc +++ b/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -348,6 +348,21 @@ bool CapabilitiesVK::SetPhysicalDevice(const vk::PhysicalDevice& device) { .supportedOperations & vk::SubgroupFeatureFlagBits::eArithmetic); + { + // Query texture support. + // TODO(jonahwilliams): + // https://github.com/flutter/flutter/issues/129784 + vk::PhysicalDeviceMemoryProperties memory_properties; + device.getMemoryProperties(&memory_properties); + + for (auto i = 0u; i < memory_properties.memoryTypeCount; i++) { + if (memory_properties.memoryTypes[i].propertyFlags & + vk::MemoryPropertyFlagBits::eLazilyAllocated) { + supports_memoryless_textures_ = true; + } + } + } + // Determine the optional device extensions this physical device supports. { optional_device_extensions_.clear(); @@ -422,6 +437,11 @@ bool CapabilitiesVK::SupportsDecalTileMode() const { return true; } +// |Capabilities| +bool CapabilitiesVK::SupportsMemorylessTextures() const { + return supports_memoryless_textures_; +} + // |Capabilities| PixelFormat CapabilitiesVK::GetDefaultColorFormat() const { return color_format_; diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.h b/impeller/renderer/backend/vulkan/capabilities_vk.h index 98614011206ff..ffa96d46bc98e 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.h +++ b/impeller/renderer/backend/vulkan/capabilities_vk.h @@ -90,6 +90,9 @@ class CapabilitiesVK final : public Capabilities, // |Capabilities| bool SupportsDecalTileMode() const override; + // |Capabilities| + bool SupportsMemorylessTextures() const override; + // |Capabilities| PixelFormat GetDefaultColorFormat() const override; @@ -104,6 +107,7 @@ class CapabilitiesVK final : public Capabilities, PixelFormat depth_stencil_format_ = PixelFormat::kUnknown; vk::PhysicalDeviceProperties device_properties_; bool supports_compute_subgroups_ = false; + bool supports_memoryless_textures_ = false; bool is_valid_ = false; bool HasExtension(const std::string& ext) const; diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 3af8a62fbbce3..0b1fc69001e33 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -332,7 +332,8 @@ void ContextVK::Setup(Settings settings) { device_holder, // device_holder->instance.get(), // dispatcher.vkGetInstanceProcAddr, // - dispatcher.vkGetDeviceProcAddr // + dispatcher.vkGetDeviceProcAddr, // + *caps // )); if (!allocator->IsValid()) { diff --git a/impeller/renderer/capabilities.cc b/impeller/renderer/capabilities.cc index 9e2c9201bb603..d0c9f62348066 100644 --- a/impeller/renderer/capabilities.cc +++ b/impeller/renderer/capabilities.cc @@ -76,6 +76,10 @@ class StandardCapabilities final : public Capabilities { return default_stencil_format_; } + bool SupportsMemorylessTextures() const override { + return supports_memoryless_textures_; + } + private: StandardCapabilities(bool has_threading_restrictions, bool supports_offscreen_msaa, @@ -88,6 +92,7 @@ class StandardCapabilities final : public Capabilities { bool supports_read_from_onscreen_texture, bool supports_read_from_resolve, bool supports_decal_tile_mode, + bool supports_memoryless_textures, PixelFormat default_color_format, PixelFormat default_stencil_format) : has_threading_restrictions_(has_threading_restrictions), @@ -102,6 +107,7 @@ class StandardCapabilities final : public Capabilities { supports_read_from_onscreen_texture), supports_read_from_resolve_(supports_read_from_resolve), supports_decal_tile_mode_(supports_decal_tile_mode), + supports_memoryless_textures_(supports_memoryless_textures), default_color_format_(default_color_format), default_stencil_format_(default_stencil_format) {} @@ -118,6 +124,7 @@ class StandardCapabilities final : public Capabilities { bool supports_read_from_onscreen_texture_ = false; bool supports_read_from_resolve_ = false; bool supports_decal_tile_mode_ = false; + bool supports_memoryless_textures_ = false; PixelFormat default_color_format_ = PixelFormat::kUnknown; PixelFormat default_stencil_format_ = PixelFormat::kUnknown; @@ -202,6 +209,12 @@ CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsDecalTileMode(bool value) { return *this; } +CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsMemorylessTextures( + bool value) { + supports_memoryless_textures_ = value; + return *this; +} + std::unique_ptr CapabilitiesBuilder::Build() { return std::unique_ptr(new StandardCapabilities( // has_threading_restrictions_, // @@ -215,6 +228,7 @@ std::unique_ptr CapabilitiesBuilder::Build() { supports_read_from_onscreen_texture_, // supports_read_from_resolve_, // supports_decal_tile_mode_, // + supports_memoryless_textures_, // default_color_format_.value_or(PixelFormat::kUnknown), // default_stencil_format_.value_or(PixelFormat::kUnknown) // )); diff --git a/impeller/renderer/capabilities.h b/impeller/renderer/capabilities.h index 6fb1118dd7c95..87a7f9df08892 100644 --- a/impeller/renderer/capabilities.h +++ b/impeller/renderer/capabilities.h @@ -37,6 +37,8 @@ class Capabilities { virtual bool SupportsDecalTileMode() const = 0; + virtual bool SupportsMemorylessTextures() const = 0; + virtual PixelFormat GetDefaultColorFormat() const = 0; virtual PixelFormat GetDefaultStencilFormat() const = 0; @@ -79,6 +81,8 @@ class CapabilitiesBuilder { CapabilitiesBuilder& SetSupportsDecalTileMode(bool value); + CapabilitiesBuilder& SetSupportsMemorylessTextures(bool value); + std::unique_ptr Build(); private: @@ -93,6 +97,7 @@ class CapabilitiesBuilder { bool supports_read_from_onscreen_texture_ = false; bool supports_read_from_resolve_ = false; bool supports_decal_tile_mode_ = false; + bool supports_memoryless_textures_ = false; std::optional default_color_format_ = std::nullopt; std::optional default_stencil_format_ = std::nullopt; diff --git a/impeller/renderer/capabilities_unittests.cc b/impeller/renderer/capabilities_unittests.cc index 1dc9d17e3c678..9d8a9f386273d 100644 --- a/impeller/renderer/capabilities_unittests.cc +++ b/impeller/renderer/capabilities_unittests.cc @@ -29,6 +29,7 @@ CAPABILITY_TEST(SupportsComputeSubgroups, false); CAPABILITY_TEST(SupportsReadFromOnscreenTexture, false); CAPABILITY_TEST(SupportsReadFromResolve, false); CAPABILITY_TEST(SupportsDecalTileMode, false); +CAPABILITY_TEST(SupportsMemorylessTextures, false); } // namespace testing } // namespace impeller