Flutter Impeller
allocator_vk.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "flutter/fml/memory/ref_ptr.h"
11 #include "flutter/fml/trace_event.h"
13 #include "impeller/core/formats.h"
19 #include "vulkan/vulkan_enums.hpp"
20 
21 namespace impeller {
22 
23 static constexpr vk::Flags<vk::MemoryPropertyFlagBits>
25  switch (mode) {
27  return vk::MemoryPropertyFlagBits::eHostVisible;
29  return vk::MemoryPropertyFlagBits::eDeviceLocal;
31  return vk::MemoryPropertyFlagBits::eLazilyAllocated;
32  }
33  FML_UNREACHABLE();
34 }
35 
36 static VmaAllocationCreateFlags ToVmaAllocationBufferCreateFlags(
37  StorageMode mode,
38  bool readback) {
39  VmaAllocationCreateFlags flags = 0;
40  switch (mode) {
42  if (!readback) {
43  flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
44  } else {
45  flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
46  }
47  flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
48  return flags;
50  FML_DCHECK(!readback);
51  return flags;
53  FML_DCHECK(!readback);
54  return flags;
55  }
56  FML_UNREACHABLE();
57 }
58 
59 static PoolVMA CreateBufferPool(VmaAllocator allocator) {
60  vk::BufferCreateInfo buffer_info;
61  buffer_info.usage = vk::BufferUsageFlagBits::eVertexBuffer |
62  vk::BufferUsageFlagBits::eIndexBuffer |
63  vk::BufferUsageFlagBits::eUniformBuffer |
64  vk::BufferUsageFlagBits::eStorageBuffer |
65  vk::BufferUsageFlagBits::eTransferSrc |
66  vk::BufferUsageFlagBits::eTransferDst;
67  buffer_info.size = 1u; // doesn't matter
68  buffer_info.sharingMode = vk::SharingMode::eExclusive;
69  auto buffer_info_native =
70  static_cast<vk::BufferCreateInfo::NativeType>(buffer_info);
71 
72  VmaAllocationCreateInfo allocation_info = {};
73  allocation_info.usage = VMA_MEMORY_USAGE_AUTO;
74  allocation_info.preferredFlags = static_cast<VkMemoryPropertyFlags>(
76  allocation_info.flags = ToVmaAllocationBufferCreateFlags(
77  StorageMode::kHostVisible, /*readback=*/false);
78 
79  uint32_t memTypeIndex;
80  auto result = vk::Result{vmaFindMemoryTypeIndexForBufferInfo(
81  allocator, &buffer_info_native, &allocation_info, &memTypeIndex)};
82  if (result != vk::Result::eSuccess) {
83  return {};
84  }
85 
86  VmaPoolCreateInfo pool_create_info = {};
87  pool_create_info.memoryTypeIndex = memTypeIndex;
88  pool_create_info.flags = VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT;
89  pool_create_info.minBlockCount = 1;
90 
91  VmaPool pool = {};
92  result = vk::Result{::vmaCreatePool(allocator, &pool_create_info, &pool)};
93  if (result != vk::Result::eSuccess) {
94  return {};
95  }
96  return {allocator, pool};
97 }
98 
99 AllocatorVK::AllocatorVK(std::weak_ptr<Context> context,
100  uint32_t vulkan_api_version,
101  const vk::PhysicalDevice& physical_device,
102  const std::shared_ptr<DeviceHolderVK>& device_holder,
103  const vk::Instance& instance,
104  const CapabilitiesVK& capabilities)
105  : context_(std::move(context)), device_holder_(device_holder) {
106  auto limits = physical_device.getProperties().limits;
107  max_texture_size_.width = max_texture_size_.height =
108  limits.maxImageDimension2D;
109  physical_device.getMemoryProperties(&memory_properties_);
110 
111  VmaVulkanFunctions proc_table = {};
112 
113 #define BIND_VMA_PROC(x) proc_table.x = VULKAN_HPP_DEFAULT_DISPATCHER.x;
114 #define BIND_VMA_PROC_KHR(x) \
115  proc_table.x##KHR = VULKAN_HPP_DEFAULT_DISPATCHER.x \
116  ? VULKAN_HPP_DEFAULT_DISPATCHER.x \
117  : VULKAN_HPP_DEFAULT_DISPATCHER.x##KHR;
118  BIND_VMA_PROC(vkGetInstanceProcAddr);
119  BIND_VMA_PROC(vkGetDeviceProcAddr);
120  BIND_VMA_PROC(vkGetPhysicalDeviceProperties);
121  BIND_VMA_PROC(vkGetPhysicalDeviceMemoryProperties);
122  BIND_VMA_PROC(vkAllocateMemory);
123  BIND_VMA_PROC(vkFreeMemory);
124  BIND_VMA_PROC(vkMapMemory);
125  BIND_VMA_PROC(vkUnmapMemory);
126  BIND_VMA_PROC(vkFlushMappedMemoryRanges);
127  BIND_VMA_PROC(vkInvalidateMappedMemoryRanges);
128  BIND_VMA_PROC(vkBindBufferMemory);
129  BIND_VMA_PROC(vkBindImageMemory);
130  BIND_VMA_PROC(vkGetBufferMemoryRequirements);
131  BIND_VMA_PROC(vkGetImageMemoryRequirements);
132  BIND_VMA_PROC(vkCreateBuffer);
133  BIND_VMA_PROC(vkDestroyBuffer);
134  BIND_VMA_PROC(vkCreateImage);
135  BIND_VMA_PROC(vkDestroyImage);
136  BIND_VMA_PROC(vkCmdCopyBuffer);
137  BIND_VMA_PROC_KHR(vkGetBufferMemoryRequirements2);
138  BIND_VMA_PROC_KHR(vkGetImageMemoryRequirements2);
139  BIND_VMA_PROC_KHR(vkBindBufferMemory2);
140  BIND_VMA_PROC_KHR(vkBindImageMemory2);
141  BIND_VMA_PROC_KHR(vkGetPhysicalDeviceMemoryProperties2);
142 #undef BIND_VMA_PROC_KHR
143 #undef BIND_VMA_PROC
144 
145  VmaAllocatorCreateInfo allocator_info = {};
146  allocator_info.vulkanApiVersion = vulkan_api_version;
147  allocator_info.physicalDevice = physical_device;
148  allocator_info.device = device_holder->GetDevice();
149  allocator_info.instance = instance;
150  // 4 MB, matching the default used by Skia Vulkan.
151  allocator_info.preferredLargeHeapBlockSize = 4 * 1024 * 1024;
152  allocator_info.pVulkanFunctions = &proc_table;
153 
154  VmaAllocator allocator = {};
155  auto result = vk::Result{::vmaCreateAllocator(&allocator_info, &allocator)};
156  if (result != vk::Result::eSuccess) {
157  VALIDATION_LOG << "Could not create memory allocator";
158  return;
159  }
160  staging_buffer_pool_.reset(CreateBufferPool(allocator));
161  created_buffer_pool_ &= staging_buffer_pool_.is_valid();
162  allocator_.reset(allocator);
163  supports_memoryless_textures_ =
164  capabilities.SupportsDeviceTransientTextures();
165  is_valid_ = true;
166 }
167 
168 AllocatorVK::~AllocatorVK() = default;
169 
170 // |Allocator|
171 bool AllocatorVK::IsValid() const {
172  return is_valid_;
173 }
174 
175 // |Allocator|
176 ISize AllocatorVK::GetMaxTextureSizeSupported() const {
177  return max_texture_size_;
178 }
179 
180 int32_t AllocatorVK::FindMemoryTypeIndex(
181  uint32_t memory_type_bits_requirement,
182  vk::PhysicalDeviceMemoryProperties& memory_properties) {
183  int32_t type_index = -1;
184  vk::MemoryPropertyFlagBits required_properties =
185  vk::MemoryPropertyFlagBits::eDeviceLocal;
186 
187  const uint32_t memory_count = memory_properties.memoryTypeCount;
188  for (uint32_t memory_index = 0; memory_index < memory_count; ++memory_index) {
189  const uint32_t memory_type_bits = (1 << memory_index);
190  const bool is_required_memory_type =
191  memory_type_bits_requirement & memory_type_bits;
192 
193  const auto properties =
194  memory_properties.memoryTypes[memory_index].propertyFlags;
195  const bool has_required_properties =
196  (properties & required_properties) == required_properties;
197 
198  if (is_required_memory_type && has_required_properties) {
199  return static_cast<int32_t>(memory_index);
200  }
201  }
202 
203  return type_index;
204 }
205 
206 vk::ImageUsageFlags AllocatorVK::ToVKImageUsageFlags(
207  PixelFormat format,
208  TextureUsageMask usage,
209  StorageMode mode,
210  bool supports_memoryless_textures) {
211  vk::ImageUsageFlags vk_usage;
212 
213  switch (mode) {
214  case StorageMode::kHostVisible:
215  case StorageMode::kDevicePrivate:
216  break;
217  case StorageMode::kDeviceTransient:
218  if (supports_memoryless_textures) {
219  vk_usage |= vk::ImageUsageFlagBits::eTransientAttachment;
220  }
221  break;
222  }
223 
224  if (usage & TextureUsage::kRenderTarget) {
225  if (PixelFormatIsDepthStencil(format)) {
226  vk_usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
227  } else {
228  vk_usage |= vk::ImageUsageFlagBits::eColorAttachment;
229  vk_usage |= vk::ImageUsageFlagBits::eInputAttachment;
230  }
231  }
232 
233  if (usage & TextureUsage::kShaderRead) {
234  vk_usage |= vk::ImageUsageFlagBits::eSampled;
235  }
236 
237  if (usage & TextureUsage::kShaderWrite) {
238  vk_usage |= vk::ImageUsageFlagBits::eStorage;
239  }
240 
241  if (mode != StorageMode::kDeviceTransient) {
242  // Add transfer usage flags to support blit passes only if image isn't
243  // device transient.
244  vk_usage |= vk::ImageUsageFlagBits::eTransferSrc |
245  vk::ImageUsageFlagBits::eTransferDst;
246  }
247 
248  return vk_usage;
249 }
250 
251 static constexpr VmaMemoryUsage ToVMAMemoryUsage() {
252  return VMA_MEMORY_USAGE_AUTO;
253 }
254 
255 static constexpr vk::Flags<vk::MemoryPropertyFlagBits>
257  bool supports_memoryless_textures) {
258  switch (mode) {
259  case StorageMode::kHostVisible:
260  return vk::MemoryPropertyFlagBits::eHostVisible |
261  vk::MemoryPropertyFlagBits::eDeviceLocal;
262  case StorageMode::kDevicePrivate:
263  return vk::MemoryPropertyFlagBits::eDeviceLocal;
264  case StorageMode::kDeviceTransient:
265  if (supports_memoryless_textures) {
266  return vk::MemoryPropertyFlagBits::eLazilyAllocated |
267  vk::MemoryPropertyFlagBits::eDeviceLocal;
268  }
269  return vk::MemoryPropertyFlagBits::eDeviceLocal;
270  }
271  FML_UNREACHABLE();
272 }
273 
274 static VmaAllocationCreateFlags ToVmaAllocationCreateFlags(StorageMode mode) {
275  VmaAllocationCreateFlags flags = 0;
276  switch (mode) {
277  case StorageMode::kHostVisible:
278  return flags;
279  case StorageMode::kDevicePrivate:
280  return flags;
281  case StorageMode::kDeviceTransient:
282  return flags;
283  }
284  FML_UNREACHABLE();
285 }
286 
288  public:
290  const TextureDescriptor& desc,
291  VmaAllocator allocator,
292  vk::Device device,
293  bool supports_memoryless_textures)
294  : TextureSourceVK(desc), resource_(context.GetResourceManager()) {
295  FML_DCHECK(desc.format != PixelFormat::kUnknown);
296  vk::StructureChain<vk::ImageCreateInfo, vk::ImageCompressionControlEXT>
297  image_info_chain;
298  auto& image_info = image_info_chain.get();
299  image_info.flags = ToVKImageCreateFlags(desc.type);
300  image_info.imageType = vk::ImageType::e2D;
301  image_info.format = ToVKImageFormat(desc.format);
302  image_info.extent = VkExtent3D{
303  static_cast<uint32_t>(desc.size.width), // width
304  static_cast<uint32_t>(desc.size.height), // height
305  1u // depth
306  };
307  image_info.samples = ToVKSampleCount(desc.sample_count);
308  image_info.mipLevels = desc.mip_count;
309  image_info.arrayLayers = ToArrayLayerCount(desc.type);
310  image_info.tiling = vk::ImageTiling::eOptimal;
311  image_info.initialLayout = vk::ImageLayout::eUndefined;
312  image_info.usage = AllocatorVK::ToVKImageUsageFlags(
313  desc.format, desc.usage, desc.storage_mode,
314  supports_memoryless_textures);
315  image_info.sharingMode = vk::SharingMode::eExclusive;
316 
317  vk::ImageCompressionFixedRateFlagsEXT frc_rates[1] = {
318  vk::ImageCompressionFixedRateFlagBitsEXT::eNone};
319 
320  const auto frc_rate =
321  CapabilitiesVK::Cast(*context.GetCapabilities())
322  .GetSupportedFRCRate(desc.compression_type,
323  FRCFormatDescriptor{image_info});
324  if (frc_rate.has_value()) {
325  // This array must not be in a temporary scope.
326  frc_rates[0] = frc_rate.value();
327 
328  auto& compression_info =
329  image_info_chain.get<vk::ImageCompressionControlEXT>();
330  compression_info.pFixedRateFlags = frc_rates;
331  compression_info.compressionControlPlaneCount = 1u;
332  compression_info.flags =
333  vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
334  } else {
335  image_info_chain.unlink<vk::ImageCompressionControlEXT>();
336  }
337 
338  VmaAllocationCreateInfo alloc_nfo = {};
339 
340  alloc_nfo.usage = ToVMAMemoryUsage();
341  alloc_nfo.preferredFlags =
342  static_cast<VkMemoryPropertyFlags>(ToVKTextureMemoryPropertyFlags(
343  desc.storage_mode, supports_memoryless_textures));
344  alloc_nfo.flags = ToVmaAllocationCreateFlags(desc.storage_mode);
345 
346  auto create_info_native =
347  static_cast<vk::ImageCreateInfo::NativeType>(image_info);
348 
349  VkImage vk_image = VK_NULL_HANDLE;
350  VmaAllocation allocation = {};
351  VmaAllocationInfo allocation_info = {};
352  {
353  auto result = vk::Result{::vmaCreateImage(allocator, //
354  &create_info_native, //
355  &alloc_nfo, //
356  &vk_image, //
357  &allocation, //
358  &allocation_info //
359  )};
360  if (result != vk::Result::eSuccess) {
361  VALIDATION_LOG << "Unable to allocate Vulkan Image: "
362  << vk::to_string(result)
363  << " Type: " << TextureTypeToString(desc.type)
364  << " Mode: " << StorageModeToString(desc.storage_mode)
365  << " Usage: " << TextureUsageMaskToString(desc.usage)
366  << " [VK]Flags: " << vk::to_string(image_info.flags)
367  << " [VK]Format: " << vk::to_string(image_info.format)
368  << " [VK]Usage: " << vk::to_string(image_info.usage)
369  << " [VK]Mem. Flags: "
370  << vk::to_string(vk::MemoryPropertyFlags(
371  alloc_nfo.preferredFlags));
372  return;
373  }
374  }
375 
376  auto image = vk::Image{vk_image};
377 
378  vk::ImageViewCreateInfo view_info = {};
379  view_info.image = image;
380  view_info.viewType = ToVKImageViewType(desc.type);
381  view_info.format = image_info.format;
382  view_info.subresourceRange.aspectMask = ToVKImageAspectFlags(desc.format);
383  view_info.subresourceRange.levelCount = image_info.mipLevels;
384  view_info.subresourceRange.layerCount = ToArrayLayerCount(desc.type);
385 
386  // Vulkan does not have an image format that is equivalent to
387  // `MTLPixelFormatA8Unorm`, so we use `R8Unorm` instead. Given that the
388  // shaders expect that alpha channel to be set in the cases, we swizzle.
389  // See: https://github.com/flutter/flutter/issues/115461 for more details.
390  if (desc.format == PixelFormat::kA8UNormInt) {
391  view_info.components.a = vk::ComponentSwizzle::eR;
392  view_info.components.r = vk::ComponentSwizzle::eA;
393  }
394 
395  auto [result, image_view] = device.createImageViewUnique(view_info);
396  if (result != vk::Result::eSuccess) {
397  VALIDATION_LOG << "Unable to create an image view for allocation: "
398  << vk::to_string(result);
399  return;
400  }
401  // Create a specialized view for render target attachments.
402  view_info.subresourceRange.levelCount = 1u;
403  auto [rt_result, rt_image_view] = device.createImageViewUnique(view_info);
404  if (rt_result != vk::Result::eSuccess) {
405  VALIDATION_LOG << "Unable to create an image view for allocation: "
406  << vk::to_string(rt_result);
407  return;
408  }
409 
410  resource_.Swap(ImageResource(
411  ImageVMA{allocator, allocation, image}, std::move(image_view),
412  std::move(rt_image_view), context.GetResourceAllocator(),
413  context.GetDeviceHolder()));
414  is_valid_ = true;
415  }
416 
418 
419  bool IsValid() const { return is_valid_; }
420 
421  vk::Image GetImage() const override { return resource_->image.get().image; }
422 
423  vk::ImageView GetImageView() const override {
424  return resource_->image_view.get();
425  }
426 
427  vk::ImageView GetRenderTargetView() const override {
428  return resource_->rt_image_view.get();
429  }
430 
431  bool IsSwapchainImage() const override { return false; }
432 
433  private:
434  struct ImageResource {
435  std::shared_ptr<DeviceHolderVK> device_holder;
436  std::shared_ptr<Allocator> allocator;
437  UniqueImageVMA image;
438  vk::UniqueImageView image_view;
439  vk::UniqueImageView rt_image_view;
440 
441  ImageResource() = default;
442 
443  ImageResource(ImageVMA p_image,
444  vk::UniqueImageView p_image_view,
445  vk::UniqueImageView p_rt_image_view,
446  std::shared_ptr<Allocator> allocator,
447  std::shared_ptr<DeviceHolderVK> device_holder)
448  : device_holder(std::move(device_holder)),
449  allocator(std::move(allocator)),
450  image(p_image),
451  image_view(std::move(p_image_view)),
452  rt_image_view(std::move(p_rt_image_view)) {}
453 
454  ImageResource(ImageResource&& o) = default;
455 
456  ImageResource(const ImageResource&) = delete;
457 
458  ImageResource& operator=(const ImageResource&) = delete;
459  };
460 
461  UniqueResourceVKT<ImageResource> resource_;
462  bool is_valid_ = false;
463 
464  AllocatedTextureSourceVK(const AllocatedTextureSourceVK&) = delete;
465 
466  AllocatedTextureSourceVK& operator=(const AllocatedTextureSourceVK&) = delete;
467 };
468 
469 // |Allocator|
470 std::shared_ptr<Texture> AllocatorVK::OnCreateTexture(
471  const TextureDescriptor& desc) {
472  if (!IsValid()) {
473  return nullptr;
474  }
475  auto device_holder = device_holder_.lock();
476  if (!device_holder) {
477  return nullptr;
478  }
479  auto context = context_.lock();
480  if (!context) {
481  return nullptr;
482  }
483  auto source = std::make_shared<AllocatedTextureSourceVK>(
484  ContextVK::Cast(*context), //
485  desc, //
486  allocator_.get(), //
487  device_holder->GetDevice(), //
488  supports_memoryless_textures_ //
489  );
490  if (!source->IsValid()) {
491  return nullptr;
492  }
493  return std::make_shared<TextureVK>(context_, std::move(source));
494 }
495 
496 // |Allocator|
497 std::shared_ptr<DeviceBuffer> AllocatorVK::OnCreateBuffer(
498  const DeviceBufferDescriptor& desc) {
499  vk::BufferCreateInfo buffer_info;
500  buffer_info.usage = vk::BufferUsageFlagBits::eVertexBuffer |
501  vk::BufferUsageFlagBits::eIndexBuffer |
502  vk::BufferUsageFlagBits::eUniformBuffer |
503  vk::BufferUsageFlagBits::eStorageBuffer |
504  vk::BufferUsageFlagBits::eTransferSrc |
505  vk::BufferUsageFlagBits::eTransferDst;
506  buffer_info.size = desc.size;
507  buffer_info.sharingMode = vk::SharingMode::eExclusive;
508  auto buffer_info_native =
509  static_cast<vk::BufferCreateInfo::NativeType>(buffer_info);
510 
511  VmaAllocationCreateInfo allocation_info = {};
512  allocation_info.usage = ToVMAMemoryUsage();
513  allocation_info.preferredFlags = static_cast<VkMemoryPropertyFlags>(
514  ToVKBufferMemoryPropertyFlags(desc.storage_mode));
515  allocation_info.flags =
516  ToVmaAllocationBufferCreateFlags(desc.storage_mode, desc.readback);
517  if (created_buffer_pool_ && desc.storage_mode == StorageMode::kHostVisible &&
518  !desc.readback) {
519  allocation_info.pool = staging_buffer_pool_.get().pool;
520  }
521  VkBuffer buffer = {};
522  VmaAllocation buffer_allocation = {};
523  VmaAllocationInfo buffer_allocation_info = {};
524  auto result = vk::Result{::vmaCreateBuffer(allocator_.get(), //
525  &buffer_info_native, //
526  &allocation_info, //
527  &buffer, //
528  &buffer_allocation, //
529  &buffer_allocation_info //
530  )};
531 
532  auto type = memory_properties_.memoryTypes[buffer_allocation_info.memoryType];
533  bool is_host_coherent =
534  !!(type.propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent);
535 
536  if (result != vk::Result::eSuccess) {
537  VALIDATION_LOG << "Unable to allocate a device buffer: "
538  << vk::to_string(result);
539  return {};
540  }
541 
542  return std::make_shared<DeviceBufferVK>(
543  desc, //
544  context_, //
545  UniqueBufferVMA{BufferVMA{allocator_.get(), //
546  buffer_allocation, //
547  vk::Buffer{buffer}}}, //
548  buffer_allocation_info, //
549  is_host_coherent);
550 }
551 
552 Bytes AllocatorVK::DebugGetHeapUsage() const {
553  auto count = memory_properties_.memoryHeapCount;
554  std::vector<VmaBudget> budgets(count);
555  vmaGetHeapBudgets(allocator_.get(), budgets.data());
556  size_t total_usage = 0;
557  for (auto i = 0u; i < count; i++) {
558  const VmaBudget& budget = budgets[i];
559  total_usage += budget.usage;
560  }
561  return Bytes{static_cast<double>(total_usage)};
562 }
563 
564 void AllocatorVK::DebugTraceMemoryStatistics() const {
565 #ifdef IMPELLER_DEBUG
566  FML_TRACE_COUNTER("flutter", "AllocatorVK",
567  reinterpret_cast<int64_t>(this), // Trace Counter ID
568  "MemoryBudgetUsageMB",
569  DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize());
570 #endif // IMPELLER_DEBUG
571 }
572 
573 } // namespace impeller
#define BIND_VMA_PROC_KHR(x)
#define BIND_VMA_PROC(x)
GLenum type
vk::ImageView GetRenderTargetView() const override
Retrieve the image view used for render target attachments with this texture source.
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.
AllocatedTextureSourceVK(const ContextVK &context, const TextureDescriptor &desc, VmaAllocator allocator, vk::Device device, bool supports_memoryless_textures)
bool IsSwapchainImage() const override
Determines if swapchain image. That is, an image used as the root render target.
std::shared_ptr< Allocator > GetResourceAllocator() const override
Returns the allocator used to create textures and buffers on the device.
Definition: context_vk.cc:520
const std::shared_ptr< const Capabilities > & GetCapabilities() const override
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
Definition: context_vk.cc:614
std::shared_ptr< DeviceHolderVK > GetDeviceHolder() const
Definition: context_vk.h:191
Abstract base class that represents a vkImage and an vkImageView.
constexpr uint32_t ToArrayLayerCount(TextureType type)
Definition: formats_vk.h:539
static VmaAllocationCreateFlags ToVmaAllocationBufferCreateFlags(StorageMode mode, bool readback)
Definition: allocator_vk.cc:36
std::string TextureUsageMaskToString(TextureUsageMask mask)
Definition: formats.cc:81
StorageMode
Specified where the allocation resides and how it is used.
Definition: formats.h:32
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
constexpr const char * TextureTypeToString(TextureType type)
Definition: formats.h:269
constexpr bool PixelFormatIsDepthStencil(PixelFormat format)
Definition: formats_vk.h:414
static constexpr VmaMemoryUsage ToVMAMemoryUsage()
constexpr vk::ImageViewType ToVKImageViewType(TextureType type)
Definition: formats_vk.h:553
constexpr vk::SampleCountFlagBits ToVKSampleCount(SampleCount sample_count)
Definition: formats_vk.h:214
constexpr vk::Format ToVKImageFormat(PixelFormat format)
Definition: formats_vk.h:146
static VmaAllocationCreateFlags ToVmaAllocationCreateFlags(StorageMode mode)
static PoolVMA CreateBufferPool(VmaAllocator allocator)
Definition: allocator_vk.cc:59
fml::UniqueObject< ImageVMA, ImageVMATraits > UniqueImageVMA
Definition: vma.h:133
static constexpr vk::Flags< vk::MemoryPropertyFlagBits > ToVKTextureMemoryPropertyFlags(StorageMode mode, bool supports_memoryless_textures)
ISize64 ISize
Definition: size.h:162
constexpr const char * StorageModeToString(StorageMode mode)
Definition: formats.h:60
constexpr vk::ImageCreateFlags ToVKImageCreateFlags(TextureType type)
Definition: formats_vk.h:567
constexpr vk::ImageAspectFlags ToVKImageAspectFlags(PixelFormat format)
Definition: formats_vk.h:513
fml::UniqueObject< BufferVMA, BufferVMATraits > UniqueBufferVMA
Definition: vma.h:98
static constexpr vk::Flags< vk::MemoryPropertyFlagBits > ToVKBufferMemoryPropertyFlags(StorageMode mode)
Definition: allocator_vk.cc:24
Definition: comparable.h:95
A pixel format and usage that is sufficient to check if images of that format and usage are suitable ...
Type height
Definition: size.h:29
Type width
Definition: size.h:28
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
#define VALIDATION_LOG
Definition: validation.h:91