// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include <cstdint>

#include "flutter/fml/macros.h"
#include "impeller/base/validation.h"
#include "impeller/core/formats.h"
#include "impeller/core/shader_types.h"
#include "impeller/renderer/backend/vulkan/vk.h"
#include "vulkan/vulkan_enums.hpp"

namespace impeller {

constexpr vk::SampleCountFlagBits ToVKSampleCountFlagBits(SampleCount count) {
  switch (count) {
    case SampleCount::kCount1:
      return vk::SampleCountFlagBits::e1;
    case SampleCount::kCount4:
      return vk::SampleCountFlagBits::e4;
  }
  FML_UNREACHABLE();
}

constexpr vk::BlendFactor ToVKBlendFactor(BlendFactor factor) {
  switch (factor) {
    case BlendFactor::kZero:
      return vk::BlendFactor::eZero;
    case BlendFactor::kOne:
      return vk::BlendFactor::eOne;
    case BlendFactor::kSourceColor:
      return vk::BlendFactor::eSrcColor;
    case BlendFactor::kOneMinusSourceColor:
      return vk::BlendFactor::eOneMinusSrcColor;
    case BlendFactor::kSourceAlpha:
      return vk::BlendFactor::eSrcAlpha;
    case BlendFactor::kOneMinusSourceAlpha:
      return vk::BlendFactor::eOneMinusSrcAlpha;
    case BlendFactor::kDestinationColor:
      return vk::BlendFactor::eDstColor;
    case BlendFactor::kOneMinusDestinationColor:
      return vk::BlendFactor::eOneMinusDstColor;
    case BlendFactor::kDestinationAlpha:
      return vk::BlendFactor::eDstAlpha;
    case BlendFactor::kOneMinusDestinationAlpha:
      return vk::BlendFactor::eOneMinusDstAlpha;
    case BlendFactor::kSourceAlphaSaturated:
      return vk::BlendFactor::eSrcAlphaSaturate;
    case BlendFactor::kBlendColor:
      return vk::BlendFactor::eConstantColor;
    case BlendFactor::kOneMinusBlendColor:
      return vk::BlendFactor::eOneMinusConstantColor;
    case BlendFactor::kBlendAlpha:
      return vk::BlendFactor::eConstantAlpha;
    case BlendFactor::kOneMinusBlendAlpha:
      return vk::BlendFactor::eOneMinusConstantAlpha;
  }
  FML_UNREACHABLE();
}

constexpr vk::BlendOp ToVKBlendOp(BlendOperation op) {
  switch (op) {
    case BlendOperation::kAdd:
      return vk::BlendOp::eAdd;
    case BlendOperation::kSubtract:
      return vk::BlendOp::eSubtract;
    case BlendOperation::kReverseSubtract:
      return vk::BlendOp::eReverseSubtract;
  }
  FML_UNREACHABLE();
}

constexpr vk::ColorComponentFlags ToVKColorComponentFlags(
    std::underlying_type_t<ColorWriteMask> type) {
  using UnderlyingType = decltype(type);

  vk::ColorComponentFlags mask;

  if (type & static_cast<UnderlyingType>(ColorWriteMask::kRed)) {
    mask |= vk::ColorComponentFlagBits::eR;
  }

  if (type & static_cast<UnderlyingType>(ColorWriteMask::kGreen)) {
    mask |= vk::ColorComponentFlagBits::eG;
  }

  if (type & static_cast<UnderlyingType>(ColorWriteMask::kBlue)) {
    mask |= vk::ColorComponentFlagBits::eB;
  }

  if (type & static_cast<UnderlyingType>(ColorWriteMask::kAlpha)) {
    mask |= vk::ColorComponentFlagBits::eA;
  }

  return mask;
}

constexpr vk::PipelineColorBlendAttachmentState
ToVKPipelineColorBlendAttachmentState(const ColorAttachmentDescriptor& desc) {
  vk::PipelineColorBlendAttachmentState res;

  res.setBlendEnable(desc.blending_enabled);

  res.setSrcColorBlendFactor(ToVKBlendFactor(desc.src_color_blend_factor));
  res.setColorBlendOp(ToVKBlendOp(desc.color_blend_op));
  res.setDstColorBlendFactor(ToVKBlendFactor(desc.dst_color_blend_factor));

  res.setSrcAlphaBlendFactor(ToVKBlendFactor(desc.src_alpha_blend_factor));
  res.setAlphaBlendOp(ToVKBlendOp(desc.alpha_blend_op));
  res.setDstAlphaBlendFactor(ToVKBlendFactor(desc.dst_alpha_blend_factor));

  res.setColorWriteMask(ToVKColorComponentFlags(desc.write_mask));

  return res;
}

constexpr std::optional<vk::ShaderStageFlagBits> ToVKShaderStageFlagBits(
    ShaderStage stage) {
  switch (stage) {
    case ShaderStage::kUnknown:
      return std::nullopt;
    case ShaderStage::kVertex:
      return vk::ShaderStageFlagBits::eVertex;
    case ShaderStage::kFragment:
      return vk::ShaderStageFlagBits::eFragment;
    case ShaderStage::kCompute:
      return vk::ShaderStageFlagBits::eCompute;
  }
  FML_UNREACHABLE();
}

constexpr vk::Format ToVKImageFormat(PixelFormat format) {
  switch (format) {
    case PixelFormat::kUnknown:
    case PixelFormat::kB10G10R10XR:
    case PixelFormat::kB10G10R10A10XR:
    case PixelFormat::kB10G10R10XRSRGB:
      return vk::Format::eUndefined;
    case PixelFormat::kA8UNormInt:
      // TODO(csg): This is incorrect. Don't depend on swizzle support for GLES.
      return vk::Format::eR8Unorm;
    case PixelFormat::kR8G8B8A8UNormInt:
      return vk::Format::eR8G8B8A8Unorm;
    case PixelFormat::kR8G8B8A8UNormIntSRGB:
      return vk::Format::eR8G8B8A8Srgb;
    case PixelFormat::kB8G8R8A8UNormInt:
      return vk::Format::eB8G8R8A8Unorm;
    case PixelFormat::kB8G8R8A8UNormIntSRGB:
      return vk::Format::eB8G8R8A8Srgb;
    case PixelFormat::kR32G32B32A32Float:
      return vk::Format::eR32G32B32A32Sfloat;
    case PixelFormat::kR16G16B16A16Float:
      return vk::Format::eR16G16B16A16Sfloat;
    case PixelFormat::kS8UInt:
      return vk::Format::eS8Uint;
    case PixelFormat::kD24UnormS8Uint:
      return vk::Format::eD24UnormS8Uint;
    case PixelFormat::kD32FloatS8UInt:
      return vk::Format::eD32SfloatS8Uint;
    case PixelFormat::kR8UNormInt:
      return vk::Format::eR8Unorm;
    case PixelFormat::kR8G8UNormInt:
      return vk::Format::eR8G8Unorm;
  }

  FML_UNREACHABLE();
}

constexpr PixelFormat ToPixelFormat(vk::Format format) {
  switch (format) {
    case vk::Format::eUndefined:
      return PixelFormat::kUnknown;
    case vk::Format::eR8G8B8A8Unorm:
      return PixelFormat::kR8G8B8A8UNormInt;
    case vk::Format::eR8G8B8A8Srgb:
      return PixelFormat::kR8G8B8A8UNormIntSRGB;
    case vk::Format::eB8G8R8A8Unorm:
      return PixelFormat::kB8G8R8A8UNormInt;
    case vk::Format::eB8G8R8A8Srgb:
      return PixelFormat::kB8G8R8A8UNormIntSRGB;
    case vk::Format::eR32G32B32A32Sfloat:
      return PixelFormat::kR32G32B32A32Float;
    case vk::Format::eR16G16B16A16Sfloat:
      return PixelFormat::kR16G16B16A16Float;
    case vk::Format::eS8Uint:
      return PixelFormat::kS8UInt;
    case vk::Format::eD24UnormS8Uint:
      return PixelFormat::kD24UnormS8Uint;
    case vk::Format::eD32SfloatS8Uint:
      return PixelFormat::kD32FloatS8UInt;
    case vk::Format::eR8Unorm:
      return PixelFormat::kR8UNormInt;
    case vk::Format::eR8G8Unorm:
      return PixelFormat::kR8G8UNormInt;
    default:
      return PixelFormat::kUnknown;
  }
}

constexpr vk::SampleCountFlagBits ToVKSampleCount(SampleCount sample_count) {
  switch (sample_count) {
    case SampleCount::kCount1:
      return vk::SampleCountFlagBits::e1;
    case SampleCount::kCount4:
      return vk::SampleCountFlagBits::e4;
  }

  FML_UNREACHABLE();
}

constexpr vk::Filter ToVKSamplerMinMagFilter(MinMagFilter filter) {
  switch (filter) {
    case MinMagFilter::kNearest:
      return vk::Filter::eNearest;
    case MinMagFilter::kLinear:
      return vk::Filter::eLinear;
  }

  FML_UNREACHABLE();
}

constexpr vk::SamplerMipmapMode ToVKSamplerMipmapMode(MipFilter filter) {
  vk::SamplerCreateInfo sampler_info;
  switch (filter) {
    case MipFilter::kNearest:
      return vk::SamplerMipmapMode::eNearest;
    case MipFilter::kLinear:
      return vk::SamplerMipmapMode::eLinear;
  }

  FML_UNREACHABLE();
}

constexpr vk::SamplerAddressMode ToVKSamplerAddressMode(
    SamplerAddressMode mode) {
  switch (mode) {
    case SamplerAddressMode::kRepeat:
      return vk::SamplerAddressMode::eRepeat;
    case SamplerAddressMode::kMirror:
      return vk::SamplerAddressMode::eMirroredRepeat;
    case SamplerAddressMode::kClampToEdge:
      return vk::SamplerAddressMode::eClampToEdge;
    case SamplerAddressMode::kDecal:
      return vk::SamplerAddressMode::eClampToBorder;
  }

  FML_UNREACHABLE();
}

constexpr vk::ShaderStageFlags ToVkShaderStage(ShaderStage stage) {
  switch (stage) {
    case ShaderStage::kUnknown:
      return vk::ShaderStageFlagBits::eAll;
    case ShaderStage::kFragment:
      return vk::ShaderStageFlagBits::eFragment;
    case ShaderStage::kCompute:
      return vk::ShaderStageFlagBits::eCompute;
    case ShaderStage::kVertex:
      return vk::ShaderStageFlagBits::eVertex;
  }

  FML_UNREACHABLE();
}

constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type) {
  switch (type) {
    case DescriptorType::kSampledImage:
      return vk::DescriptorType::eCombinedImageSampler;
      break;
    case DescriptorType::kUniformBuffer:
      return vk::DescriptorType::eUniformBuffer;
      break;
    case DescriptorType::kStorageBuffer:
      return vk::DescriptorType::eStorageBuffer;
      break;
    case DescriptorType::kImage:
      return vk::DescriptorType::eSampledImage;
      break;
    case DescriptorType::kSampler:
      return vk::DescriptorType::eSampler;
      break;
    case DescriptorType::kInputAttachment:
      return vk::DescriptorType::eInputAttachment;
  }

  FML_UNREACHABLE();
}

constexpr vk::DescriptorSetLayoutBinding ToVKDescriptorSetLayoutBinding(
    const DescriptorSetLayout& layout) {
  vk::DescriptorSetLayoutBinding binding;
  binding.binding = layout.binding;
  binding.descriptorCount = 1u;
  binding.descriptorType = ToVKDescriptorType(layout.descriptor_type);
  binding.stageFlags = ToVkShaderStage(layout.shader_stage);
  return binding;
}

constexpr vk::AttachmentLoadOp ToVKAttachmentLoadOp(LoadAction load_action) {
  switch (load_action) {
    case LoadAction::kLoad:
      return vk::AttachmentLoadOp::eLoad;
    case LoadAction::kClear:
      return vk::AttachmentLoadOp::eClear;
    case LoadAction::kDontCare:
      return vk::AttachmentLoadOp::eDontCare;
  }

  FML_UNREACHABLE();
}

constexpr vk::AttachmentStoreOp ToVKAttachmentStoreOp(
    StoreAction store_action) {
  switch (store_action) {
    case StoreAction::kStore:
      return vk::AttachmentStoreOp::eStore;
    case StoreAction::kDontCare:
      return vk::AttachmentStoreOp::eDontCare;
    case StoreAction::kMultisampleResolve:
    case StoreAction::kStoreAndMultisampleResolve:
      return vk::AttachmentStoreOp::eDontCare;
  }

  FML_UNREACHABLE();
}

constexpr vk::IndexType ToVKIndexType(IndexType index_type) {
  switch (index_type) {
    case IndexType::k16bit:
      return vk::IndexType::eUint16;
    case IndexType::k32bit:
      return vk::IndexType::eUint32;
    case IndexType::kUnknown:
      return vk::IndexType::eUint32;
    case IndexType::kNone:
      FML_UNREACHABLE();
  }

  FML_UNREACHABLE();
}

constexpr vk::PolygonMode ToVKPolygonMode(PolygonMode mode) {
  switch (mode) {
    case PolygonMode::kFill:
      return vk::PolygonMode::eFill;
    case PolygonMode::kLine:
      return vk::PolygonMode::eLine;
  }
  FML_UNREACHABLE();
}

constexpr vk::PrimitiveTopology ToVKPrimitiveTopology(PrimitiveType primitive) {
  switch (primitive) {
    case PrimitiveType::kTriangle:
      return vk::PrimitiveTopology::eTriangleList;
    case PrimitiveType::kTriangleStrip:
      return vk::PrimitiveTopology::eTriangleStrip;
    case PrimitiveType::kLine:
      return vk::PrimitiveTopology::eLineList;
    case PrimitiveType::kLineStrip:
      return vk::PrimitiveTopology::eLineStrip;
    case PrimitiveType::kPoint:
      return vk::PrimitiveTopology::ePointList;
  }

  FML_UNREACHABLE();
}

constexpr bool PixelFormatIsDepthStencil(PixelFormat format) {
  switch (format) {
    case PixelFormat::kUnknown:
    case PixelFormat::kA8UNormInt:
    case PixelFormat::kR8UNormInt:
    case PixelFormat::kR8G8UNormInt:
    case PixelFormat::kR8G8B8A8UNormInt:
    case PixelFormat::kR8G8B8A8UNormIntSRGB:
    case PixelFormat::kB8G8R8A8UNormInt:
    case PixelFormat::kB8G8R8A8UNormIntSRGB:
    case PixelFormat::kR32G32B32A32Float:
    case PixelFormat::kR16G16B16A16Float:
    case PixelFormat::kB10G10R10XR:
    case PixelFormat::kB10G10R10XRSRGB:
    case PixelFormat::kB10G10R10A10XR:
      return false;
    case PixelFormat::kS8UInt:
    case PixelFormat::kD24UnormS8Uint:
    case PixelFormat::kD32FloatS8UInt:
      return true;
  }
  return false;
}

enum class AttachmentKind {
  kColor,
  kDepth,
  kStencil,
  kDepthStencil,
};

constexpr AttachmentKind AttachmentKindFromFormat(PixelFormat format) {
  switch (format) {
    case PixelFormat::kUnknown:
    case PixelFormat::kA8UNormInt:
    case PixelFormat::kR8UNormInt:
    case PixelFormat::kR8G8UNormInt:
    case PixelFormat::kR8G8B8A8UNormInt:
    case PixelFormat::kR8G8B8A8UNormIntSRGB:
    case PixelFormat::kB8G8R8A8UNormInt:
    case PixelFormat::kB8G8R8A8UNormIntSRGB:
    case PixelFormat::kR32G32B32A32Float:
    case PixelFormat::kR16G16B16A16Float:
    case PixelFormat::kB10G10R10XR:
    case PixelFormat::kB10G10R10XRSRGB:
    case PixelFormat::kB10G10R10A10XR:
      return AttachmentKind::kColor;
    case PixelFormat::kS8UInt:
      return AttachmentKind::kStencil;
    case PixelFormat::kD24UnormS8Uint:
    case PixelFormat::kD32FloatS8UInt:
      return AttachmentKind::kDepthStencil;
  }
  FML_UNREACHABLE();
}

constexpr vk::AttachmentDescription CreateAttachmentDescription(
    PixelFormat format,
    SampleCount sample_count,
    LoadAction load_action,
    StoreAction store_action,
    vk::ImageLayout current_layout,
    bool supports_framebuffer_fetch) {
  vk::AttachmentDescription vk_attachment;

  vk_attachment.format = ToVKImageFormat(format);
  vk_attachment.samples = ToVKSampleCount(sample_count);

  // The Vulkan spec has somewhat complicated rules for when these ops are used
  // and ignored. Just set safe defaults.
  vk_attachment.loadOp = vk::AttachmentLoadOp::eDontCare;
  vk_attachment.storeOp = vk::AttachmentStoreOp::eDontCare;
  vk_attachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
  vk_attachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;

  const auto kind = AttachmentKindFromFormat(format);

  switch (kind) {
    case AttachmentKind::kColor:
      // If the attachment uses a color format, then loadOp and storeOp are
      // used, and stencilLoadOp and stencilStoreOp are ignored.
      vk_attachment.loadOp = ToVKAttachmentLoadOp(load_action);
      vk_attachment.storeOp = ToVKAttachmentStoreOp(store_action);
      break;
    case AttachmentKind::kDepth:
    case AttachmentKind::kDepthStencil:
      // If the format has depth and/or stencil components, loadOp and storeOp
      // apply only to the depth data, while stencilLoadOp and stencilStoreOp
      // define how the stencil data is handled.
      vk_attachment.loadOp = ToVKAttachmentLoadOp(load_action);
      vk_attachment.storeOp = ToVKAttachmentStoreOp(store_action);
      [[fallthrough]];
    case AttachmentKind::kStencil:
      vk_attachment.stencilLoadOp = ToVKAttachmentLoadOp(load_action);
      vk_attachment.stencilStoreOp = ToVKAttachmentStoreOp(store_action);
      break;
  }

  switch (kind) {
    case AttachmentKind::kColor:
      vk_attachment.initialLayout = current_layout;
      if (supports_framebuffer_fetch) {
        vk_attachment.finalLayout = vk::ImageLayout::eGeneral;
      } else {
        vk_attachment.finalLayout = vk::ImageLayout::eColorAttachmentOptimal;
      }
      break;
    case AttachmentKind::kDepth:
    case AttachmentKind::kStencil:
    case AttachmentKind::kDepthStencil:
      // Separate depth stencil layouts feature is only available in Vulkan 1.2.
      vk_attachment.initialLayout = current_layout;
      vk_attachment.finalLayout =
          vk::ImageLayout::eDepthStencilAttachmentOptimal;
      break;
  }

  return vk_attachment;
}

static constexpr vk::AttachmentReference kUnusedAttachmentReference = {
    VK_ATTACHMENT_UNUSED, vk::ImageLayout::eUndefined};

constexpr vk::CullModeFlags ToVKCullModeFlags(CullMode mode) {
  switch (mode) {
    case CullMode::kNone:
      return vk::CullModeFlagBits::eNone;
    case CullMode::kFrontFace:
      return vk::CullModeFlagBits::eFront;
    case CullMode::kBackFace:
      return vk::CullModeFlagBits::eBack;
  }
  FML_UNREACHABLE();
}

constexpr vk::CompareOp ToVKCompareOp(CompareFunction op) {
  switch (op) {
    case CompareFunction::kNever:
      return vk::CompareOp::eNever;
    case CompareFunction::kAlways:
      return vk::CompareOp::eAlways;
    case CompareFunction::kLess:
      return vk::CompareOp::eLess;
    case CompareFunction::kEqual:
      return vk::CompareOp::eEqual;
    case CompareFunction::kLessEqual:
      return vk::CompareOp::eLessOrEqual;
    case CompareFunction::kGreater:
      return vk::CompareOp::eGreater;
    case CompareFunction::kNotEqual:
      return vk::CompareOp::eNotEqual;
    case CompareFunction::kGreaterEqual:
      return vk::CompareOp::eGreaterOrEqual;
  }
  FML_UNREACHABLE();
}

constexpr vk::StencilOp ToVKStencilOp(StencilOperation op) {
  switch (op) {
    case StencilOperation::kKeep:
      return vk::StencilOp::eKeep;
    case StencilOperation::kZero:
      return vk::StencilOp::eZero;
    case StencilOperation::kSetToReferenceValue:
      return vk::StencilOp::eReplace;
    case StencilOperation::kIncrementClamp:
      return vk::StencilOp::eIncrementAndClamp;
    case StencilOperation::kDecrementClamp:
      return vk::StencilOp::eDecrementAndClamp;
    case StencilOperation::kInvert:
      return vk::StencilOp::eInvert;
    case StencilOperation::kIncrementWrap:
      return vk::StencilOp::eIncrementAndWrap;
    case StencilOperation::kDecrementWrap:
      return vk::StencilOp::eDecrementAndWrap;
      break;
  }
  FML_UNREACHABLE();
}

constexpr vk::StencilOpState ToVKStencilOpState(
    const StencilAttachmentDescriptor& desc) {
  vk::StencilOpState state;
  state.failOp = ToVKStencilOp(desc.stencil_failure);
  state.passOp = ToVKStencilOp(desc.depth_stencil_pass);
  state.depthFailOp = ToVKStencilOp(desc.depth_failure);
  state.compareOp = ToVKCompareOp(desc.stencil_compare);
  state.compareMask = desc.read_mask;
  state.writeMask = desc.write_mask;
  // This is irrelevant as the stencil references are always dynamic state and
  // will be set in the render pass.
  state.reference = 1988;
  return state;
}

constexpr vk::ImageAspectFlags ToVKImageAspectFlags(PixelFormat format) {
  switch (format) {
    case PixelFormat::kUnknown:
    case PixelFormat::kA8UNormInt:
    case PixelFormat::kR8UNormInt:
    case PixelFormat::kR8G8UNormInt:
    case PixelFormat::kR8G8B8A8UNormInt:
    case PixelFormat::kR8G8B8A8UNormIntSRGB:
    case PixelFormat::kB8G8R8A8UNormInt:
    case PixelFormat::kB8G8R8A8UNormIntSRGB:
    case PixelFormat::kR32G32B32A32Float:
    case PixelFormat::kR16G16B16A16Float:
    case PixelFormat::kB10G10R10XR:
    case PixelFormat::kB10G10R10XRSRGB:
    case PixelFormat::kB10G10R10A10XR:
      return vk::ImageAspectFlagBits::eColor;
    case PixelFormat::kS8UInt:
      return vk::ImageAspectFlagBits::eStencil;
    case PixelFormat::kD24UnormS8Uint:
    case PixelFormat::kD32FloatS8UInt:
      return vk::ImageAspectFlagBits::eDepth |
             vk::ImageAspectFlagBits::eStencil;
  }
  FML_UNREACHABLE();
}

constexpr uint32_t ToArrayLayerCount(TextureType type) {
  switch (type) {
    case TextureType::kTexture2D:
    case TextureType::kTexture2DMultisample:
      return 1u;
    case TextureType::kTextureCube:
      return 6u;
    case TextureType::kTextureExternalOES:
      VALIDATION_LOG
          << "kTextureExternalOES can not be used with the Vulkan backend.";
  }
  FML_UNREACHABLE();
}

constexpr vk::ImageViewType ToVKImageViewType(TextureType type) {
  switch (type) {
    case TextureType::kTexture2D:
    case TextureType::kTexture2DMultisample:
      return vk::ImageViewType::e2D;
    case TextureType::kTextureCube:
      return vk::ImageViewType::eCube;
    case TextureType::kTextureExternalOES:
      VALIDATION_LOG
          << "kTextureExternalOES can not be used with the Vulkan backend.";
  }
  FML_UNREACHABLE();
}

constexpr vk::ImageCreateFlags ToVKImageCreateFlags(TextureType type) {
  switch (type) {
    case TextureType::kTexture2D:
    case TextureType::kTexture2DMultisample:
      return {};
    case TextureType::kTextureCube:
      return vk::ImageCreateFlagBits::eCubeCompatible;
    case TextureType::kTextureExternalOES:
      VALIDATION_LOG
          << "kTextureExternalOES can not be used with the Vulkan backend.";
  }
  FML_UNREACHABLE();
}

vk::PipelineDepthStencilStateCreateInfo ToVKPipelineDepthStencilStateCreateInfo(
    std::optional<DepthAttachmentDescriptor> depth,
    std::optional<StencilAttachmentDescriptor> front,
    std::optional<StencilAttachmentDescriptor> back);

constexpr vk::ImageAspectFlags ToImageAspectFlags(PixelFormat format) {
  switch (format) {
    case PixelFormat::kUnknown:
      return {};
    case PixelFormat::kA8UNormInt:
    case PixelFormat::kR8UNormInt:
    case PixelFormat::kR8G8UNormInt:
    case PixelFormat::kR8G8B8A8UNormInt:
    case PixelFormat::kR8G8B8A8UNormIntSRGB:
    case PixelFormat::kB8G8R8A8UNormInt:
    case PixelFormat::kB8G8R8A8UNormIntSRGB:
    case PixelFormat::kR32G32B32A32Float:
    case PixelFormat::kR16G16B16A16Float:
    case PixelFormat::kB10G10R10XR:
    case PixelFormat::kB10G10R10XRSRGB:
    case PixelFormat::kB10G10R10A10XR:
      return vk::ImageAspectFlagBits::eColor;
    case PixelFormat::kS8UInt:
      return vk::ImageAspectFlagBits::eStencil;
    case PixelFormat::kD24UnormS8Uint:
    case PixelFormat::kD32FloatS8UInt:
      return vk::ImageAspectFlagBits::eDepth |
             vk::ImageAspectFlagBits::eStencil;
  }
  FML_UNREACHABLE();
}

}  // namespace impeller
