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