Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
impeller::AllocatedTextureSourceVK Class Referencefinal
Inheritance diagram for impeller::AllocatedTextureSourceVK:
impeller::TextureSourceVK

Public Member Functions

 AllocatedTextureSourceVK (const ContextVK &context, const TextureDescriptor &desc, VmaAllocator allocator, vk::Device device, bool supports_memoryless_textures)
 
 ~AllocatedTextureSourceVK ()=default
 
bool IsValid () const
 
vk::Image GetImage () const override
 Get the image handle for this texture source.
 
vk::ImageView GetImageView () const override
 Retrieve the image view used for sampling/blitting/compute with this texture source.
 
vk::ImageView GetRenderTargetView (uint32_t mip_level, uint32_t array_layer) const override
 Retrieve the image view used to attach a specific subresource of this texture as a render target.
 
bool IsSwapchainImage () const override
 Determines if swapchain image. That is, an image used as the root render target.
 
- Public Member Functions inherited from impeller::TextureSourceVK
virtual ~TextureSourceVK ()
 
const TextureDescriptorGetTextureDescriptor () const
 Gets the texture descriptor for this image source.
 
fml::Status SetLayout (const BarrierVK &barrier) const
 Encodes the layout transition barrier to barrier.cmd_buffer for the image.
 
vk::ImageLayout SetLayoutWithoutEncoding (vk::ImageLayout layout) const
 Store the layout of the image.
 
vk::ImageLayout GetLayout () const
 Get the last layout assigned to the TextureSourceVK.
 
virtual std::shared_ptr< YUVConversionVKGetYUVConversion () const
 When sampling from textures whose formats are not known to Vulkan, a custom conversion is necessary to setup custom samplers. This accessor provides this conversion if one is present. Most texture source have none.
 
void SetCachedFrameData (const FramebufferAndRenderPass &data, SampleCount sample_count, uint32_t mip_level=0u, uint32_t slice=0u)
 
FramebufferAndRenderPass GetCachedFrameData (SampleCount sample_count, uint32_t mip_level=0u, uint32_t slice=0u) const
 

Additional Inherited Members

- Protected Member Functions inherited from impeller::TextureSourceVK
 TextureSourceVK (TextureDescriptor desc)
 
- Protected Attributes inherited from impeller::TextureSourceVK
const TextureDescriptor desc_
 

Detailed Description

Definition at line 289 of file allocator_vk.cc.

Constructor & Destructor Documentation

◆ AllocatedTextureSourceVK()

impeller::AllocatedTextureSourceVK::AllocatedTextureSourceVK ( const ContextVK context,
const TextureDescriptor desc,
VmaAllocator  allocator,
vk::Device  device,
bool  supports_memoryless_textures 
)
inline

Definition at line 291 of file allocator_vk.cc.

296 : TextureSourceVK(desc), resource_(context.GetResourceManager()) {
297 FML_DCHECK(desc.format != PixelFormat::kUnknown);
298 vk::StructureChain<vk::ImageCreateInfo, vk::ImageCompressionControlEXT>
299 image_info_chain;
300 auto& image_info = image_info_chain.get();
301 image_info.flags = ToVKImageCreateFlags(desc.type);
302 image_info.imageType = vk::ImageType::e2D;
303 image_info.format = ToVKImageFormat(desc.format);
304 image_info.extent = VkExtent3D{
305 static_cast<uint32_t>(desc.size.width), // width
306 static_cast<uint32_t>(desc.size.height), // height
307 1u // depth
308 };
309 image_info.samples = ToVKSampleCount(desc.sample_count);
310 image_info.mipLevels = desc.mip_count;
311 image_info.arrayLayers = ToArrayLayerCount(desc.type);
312 image_info.tiling = vk::ImageTiling::eOptimal;
313 image_info.initialLayout = vk::ImageLayout::eUndefined;
314 image_info.usage = AllocatorVK::ToVKImageUsageFlags(
315 desc.format, desc.usage, desc.storage_mode,
316 supports_memoryless_textures);
317 image_info.sharingMode = vk::SharingMode::eExclusive;
318
319 vk::ImageCompressionFixedRateFlagsEXT frc_rates[1] = {
320 vk::ImageCompressionFixedRateFlagBitsEXT::eNone};
321
322 const auto frc_rate =
323 CapabilitiesVK::Cast(*context.GetCapabilities())
324 .GetSupportedFRCRate(desc.compression_type,
325 FRCFormatDescriptor{image_info});
326 if (frc_rate.has_value()) {
327 // This array must not be in a temporary scope.
328 frc_rates[0] = frc_rate.value();
329
330 auto& compression_info =
331 image_info_chain.get<vk::ImageCompressionControlEXT>();
332 compression_info.pFixedRateFlags = frc_rates;
333 compression_info.compressionControlPlaneCount = 1u;
334 compression_info.flags =
335 vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
336 } else {
337 image_info_chain.unlink<vk::ImageCompressionControlEXT>();
338 }
339
340 VmaAllocationCreateInfo alloc_nfo = {};
341
342 alloc_nfo.usage = ToVMAMemoryUsage();
343 alloc_nfo.preferredFlags =
344 static_cast<VkMemoryPropertyFlags>(ToVKTextureMemoryPropertyFlags(
345 desc.storage_mode, supports_memoryless_textures));
346 alloc_nfo.flags = ToVmaAllocationCreateFlags(desc.storage_mode);
347
348 VkImage vk_image = VK_NULL_HANDLE;
349 VmaAllocation allocation = {};
350 VmaAllocationInfo allocation_info = {};
351
352 // Performs the VMA image allocation using the current create-info chain.
353 // The native create-info is re-derived from the chain on each call, so an
354 // unlink of the compression-control struct between calls is reflected.
355 const auto try_create_image = [&]() -> vk::Result {
356 vk::ImageCreateInfo::NativeType create_info_native =
357 static_cast<vk::ImageCreateInfo::NativeType>(
358 image_info_chain.get<vk::ImageCreateInfo>());
359 return vk::Result{::vmaCreateImage(allocator, //
360 &create_info_native, //
361 &alloc_nfo, //
362 &vk_image, //
363 &allocation, //
364 &allocation_info //
365 )};
366 };
367
368 // Fixed-rate compression was requested iff a rate was selected above.
369 const bool requested_compression = frc_rate.has_value();
370 vk::Result alloc_result = try_create_image();
371
372 // Some drivers (e.g. PowerVR) can return VK_ERROR_COMPRESSION_EXHAUSTED_EXT
373 // when fixed-rate compression resources are depleted. Per the Vulkan spec
374 // this error is only returned for fixed-rate compression requests, so
375 // retrying without compression is a valid recovery. Without it the
376 // allocation fails, the texture is invalid, and the resulting null render
377 // target crashes the raster thread.
378 if (alloc_result == vk::Result::eErrorCompressionExhaustedEXT &&
379 requested_compression) {
380 static std::once_flag warn_once;
381 std::call_once(warn_once, [] {
382 FML_LOG(WARNING)
383 << "Fixed-rate image compression exhausted; falling back to "
384 "uncompressed image allocation. (This message is logged once.)";
385 });
386 // The compression-control struct is only present here because compression
387 // was requested above, so unlinking it once is safe (no double-unlink).
388 image_info_chain.unlink<vk::ImageCompressionControlEXT>();
389 alloc_result = try_create_image();
390 }
391
392 if (alloc_result != vk::Result::eSuccess) {
393 VALIDATION_LOG << "Unable to allocate Vulkan Image: "
394 << vk::to_string(alloc_result)
395 << " Type: " << TextureTypeToString(desc.type)
396 << " Mode: " << StorageModeToString(desc.storage_mode)
397 << " Usage: " << TextureUsageMaskToString(desc.usage)
398 << " [VK]Flags: " << vk::to_string(image_info.flags)
399 << " [VK]Format: " << vk::to_string(image_info.format)
400 << " [VK]Usage: " << vk::to_string(image_info.usage)
401 << " [VK]Mem. Flags: "
402 << vk::to_string(
403 vk::MemoryPropertyFlags(alloc_nfo.preferredFlags));
404 return;
405 }
406
407 auto image = vk::Image{vk_image};
408
409 vk::ImageViewCreateInfo view_info = {};
410 view_info.image = image;
411 view_info.viewType = ToVKImageViewType(desc.type);
412 view_info.format = image_info.format;
413 view_info.subresourceRange.aspectMask = ToVKImageAspectFlags(desc.format);
414 view_info.subresourceRange.levelCount = image_info.mipLevels;
415 view_info.subresourceRange.layerCount = ToArrayLayerCount(desc.type);
416
417 // Vulkan does not have an image format that is equivalent to
418 // `MTLPixelFormatA8Unorm`, so we use `R8Unorm` instead. Given that the
419 // shaders expect that alpha channel to be set in the cases, we swizzle.
420 // See: https://github.com/flutter/flutter/issues/115461 for more details.
421 if (desc.format == PixelFormat::kA8UNormInt) {
422 view_info.components.a = vk::ComponentSwizzle::eR;
423 view_info.components.r = vk::ComponentSwizzle::eA;
424 }
425
426 auto [result, image_view] = device.createImageViewUnique(view_info);
427 if (result != vk::Result::eSuccess) {
428 VALIDATION_LOG << "Unable to create an image view for allocation: "
429 << vk::to_string(result);
430 return;
431 }
432 // Create one 2D attachment view per (mip level, array layer) so a
433 // specific subresource can be rendered into. Render targets are usually a
434 // single 2D mip (one view); cube and mipmapped render targets get the
435 // full set. Non-render-target textures only need the base view.
436 view_info.viewType = vk::ImageViewType::e2D;
437 view_info.subresourceRange.levelCount = 1u;
438 view_info.subresourceRange.layerCount = 1u;
439 const bool is_render_target = !!(desc.usage & TextureUsage::kRenderTarget);
440 const uint32_t rt_mip_count = is_render_target ? image_info.mipLevels : 1u;
441 const uint32_t rt_layer_count =
442 is_render_target ? ToArrayLayerCount(desc.type) : 1u;
443 std::vector<vk::UniqueImageView> rt_image_views;
444 rt_image_views.reserve(rt_mip_count * rt_layer_count);
445 for (uint32_t mip = 0; mip < rt_mip_count; mip++) {
446 for (uint32_t layer = 0; layer < rt_layer_count; layer++) {
447 view_info.subresourceRange.baseMipLevel = mip;
448 view_info.subresourceRange.baseArrayLayer = layer;
449 auto [rt_result, rt_image_view] =
450 device.createImageViewUnique(view_info);
451 if (rt_result != vk::Result::eSuccess) {
452 VALIDATION_LOG << "Unable to create a render target image view: "
453 << vk::to_string(rt_result);
454 return;
455 }
456 rt_image_views.push_back(std::move(rt_image_view));
457 }
458 }
459
460 resource_.Swap(ImageResource(
461 ImageVMA{allocator, allocation, image}, std::move(image_view),
462 std::move(rt_image_views), context.GetResourceAllocator(),
463 context.GetDeviceHolder()));
464 is_valid_ = true;
465 }
static vk::ImageUsageFlags ToVKImageUsageFlags(PixelFormat format, TextureUsageMask usage, StorageMode mode, bool supports_memoryless_textures)
static CapabilitiesVK & Cast(Capabilities &base)
std::optional< vk::ImageCompressionFixedRateFlagBitsEXT > GetSupportedFRCRate(CompressionType compression_type, const FRCFormatDescriptor &desc) const
Get the fixed compression rate supported by the context for the given format and usage.
TextureSourceVK(TextureDescriptor desc)
void Swap(ResourceType &&other)
Reclaims the existing resource, if any, and replaces it.
FlutterVulkanImage * image
VkDevice device
Definition main.cc:69
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DCHECK(condition)
Definition logging.h:122
std::shared_ptr< ImpellerAllocator > allocator
constexpr uint32_t ToArrayLayerCount(TextureType type)
Definition formats_vk.h:611
std::string TextureUsageMaskToString(TextureUsageMask mask)
Definition formats.cc:95
static constexpr vk::Flags< vk::MemoryPropertyFlagBits > ToVKTextureMemoryPropertyFlags(StorageMode mode, bool supports_memoryless_textures)
static constexpr VmaMemoryUsage ToVMAMemoryUsage()
constexpr vk::ImageViewType ToVKImageViewType(TextureType type)
Definition formats_vk.h:625
constexpr vk::SampleCountFlagBits ToVKSampleCount(SampleCount sample_count)
Definition formats_vk.h:250
constexpr vk::Format ToVKImageFormat(PixelFormat format)
Definition formats_vk.h:146
static VmaAllocationCreateFlags ToVmaAllocationCreateFlags(StorageMode mode)
constexpr const char * TextureTypeToString(TextureType type)
Definition formats.h:457
constexpr const char * StorageModeToString(StorageMode mode)
Definition formats.h:60
constexpr vk::ImageCreateFlags ToVKImageCreateFlags(TextureType type)
Definition formats_vk.h:639
constexpr vk::ImageAspectFlags ToVKImageAspectFlags(PixelFormat format)
Definition formats_vk.h:567
std::shared_ptr< ContextGLES > context
FlutterVulkanImageHandle image
Definition embedder.h:938
#define VALIDATION_LOG
Definition validation.h:91

References allocator, impeller::TextureDescriptor::compression_type, context, device, FML_DCHECK, FML_LOG, impeller::TextureDescriptor::format, impeller::TSize< T >::height, FlutterVulkanImage::image, image, impeller::TextureDescriptor::mip_count, impeller::TextureDescriptor::sample_count, impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, impeller::StorageModeToString(), impeller::TextureTypeToString(), impeller::TextureUsageMaskToString(), impeller::ToArrayLayerCount(), impeller::ToVKImageAspectFlags(), impeller::ToVKImageCreateFlags(), impeller::ToVKImageFormat(), impeller::ToVKImageViewType(), impeller::ToVKSampleCount(), impeller::ToVKTextureMemoryPropertyFlags(), impeller::ToVmaAllocationCreateFlags(), impeller::ToVMAMemoryUsage(), impeller::TextureDescriptor::type, impeller::TextureDescriptor::usage, VALIDATION_LOG, and impeller::TSize< T >::width.

◆ ~AllocatedTextureSourceVK()

impeller::AllocatedTextureSourceVK::~AllocatedTextureSourceVK ( )
default

Member Function Documentation

◆ GetImage()

vk::Image impeller::AllocatedTextureSourceVK::GetImage ( ) const
inlineoverridevirtual

Get the image handle for this texture source.

Returns
The image.

Implements impeller::TextureSourceVK.

Definition at line 471 of file allocator_vk.cc.

471{ return resource_->image.get().image; }

◆ GetImageView()

vk::ImageView impeller::AllocatedTextureSourceVK::GetImageView ( ) const
inlineoverridevirtual

Retrieve the image view used for sampling/blitting/compute with this texture source.

Returns
The image view.

Implements impeller::TextureSourceVK.

Definition at line 473 of file allocator_vk.cc.

473 {
474 return resource_->image_view.get();
475 }

◆ GetRenderTargetView()

vk::ImageView impeller::AllocatedTextureSourceVK::GetRenderTargetView ( uint32_t  mip_level,
uint32_t  array_layer 
) const
inlineoverridevirtual

Retrieve the image view used to attach a specific subresource of this texture as a render target.

The returned view covers a single mip level and a single array layer (or cube map face), since attachment views cannot span multiple levels or layers.

Parameters
[in]mip_levelThe mip level to attach.
[in]array_layerThe array layer or cube map face to attach.
Returns
The render target view.

Implements impeller::TextureSourceVK.

Definition at line 477 of file allocator_vk.cc.

478 {
479 const auto& views = resource_->rt_image_views;
480 if (views.empty()) {
481 return VK_NULL_HANDLE;
482 }
483 const uint32_t layer_count = ToArrayLayerCount(GetTextureDescriptor().type);
484 const size_t index =
485 static_cast<size_t>(mip_level) * layer_count + array_layer;
486 return index < views.size() ? views[index].get() : views[0].get();
487 }
const TextureDescriptor & GetTextureDescriptor() const
Gets the texture descriptor for this image source.
impeller::ShaderType type

References impeller::ToArrayLayerCount(), and type.

◆ IsSwapchainImage()

bool impeller::AllocatedTextureSourceVK::IsSwapchainImage ( ) const
inlineoverridevirtual

Determines if swapchain image. That is, an image used as the root render target.

Returns
Whether or not this is a swapchain image.

Implements impeller::TextureSourceVK.

Definition at line 489 of file allocator_vk.cc.

489{ return false; }

◆ IsValid()

bool impeller::AllocatedTextureSourceVK::IsValid ( ) const
inline

Definition at line 469 of file allocator_vk.cc.

469{ return is_valid_; }

The documentation for this class was generated from the following file: