Flutter Impeller
sampler_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 
10 
11 namespace impeller {
12 
13 static vk::UniqueSampler CreateSampler(
14  const vk::Device& device,
15  const SamplerDescriptor& desc,
16  const std::shared_ptr<YUVConversionVK>& yuv_conversion) {
17  const auto mip_map = ToVKSamplerMipmapMode(desc.mip_filter);
18 
19  const auto min_filter = ToVKSamplerMinMagFilter(desc.min_filter);
20  const auto mag_filter = ToVKSamplerMinMagFilter(desc.mag_filter);
21 
22  const auto address_mode_u = ToVKSamplerAddressMode(desc.width_address_mode);
23  const auto address_mode_v = ToVKSamplerAddressMode(desc.height_address_mode);
24  const auto address_mode_w = ToVKSamplerAddressMode(desc.depth_address_mode);
25 
26  vk::StructureChain<vk::SamplerCreateInfo,
27  // For VK_KHR_sampler_ycbcr_conversion
28  vk::SamplerYcbcrConversionInfo>
29  sampler_chain;
30 
31  auto& sampler_info = sampler_chain.get();
32 
33  sampler_info.magFilter = mag_filter;
34  sampler_info.minFilter = min_filter;
35  sampler_info.addressModeU = address_mode_u;
36  sampler_info.addressModeV = address_mode_v;
37  sampler_info.addressModeW = address_mode_w;
38  sampler_info.borderColor = vk::BorderColor::eFloatTransparentBlack;
39  sampler_info.mipmapMode = mip_map;
40 
41  if (yuv_conversion && yuv_conversion->IsValid()) {
42  sampler_chain.get<vk::SamplerYcbcrConversionInfo>().conversion =
43  yuv_conversion->GetConversion();
44 
45  //
46  // TL;DR: When using YUV conversion, our samplers are somewhat hobbled and
47  // not all options configurable in Impeller (especially the linear
48  // filtering which is by far the most used form of filtering) can be
49  // supported. Switch to safe defaults.
50  //
51  // Spec: If sampler Y'CBCR conversion is enabled and the potential format
52  // features of the sampler Y'CBCR conversion do not support or enable
53  // separate reconstruction filters, minFilter and magFilter must be equal to
54  // the sampler Y'CBCR conversion's chromaFilter.
55  //
56  // Thing is, we don't enable separate reconstruction filters. By the time we
57  // are here, we also don't have access to the descriptor used to create this
58  // conversion. So we don't yet know what the chromaFilter is. But eNearest
59  // is a safe bet since the `AndroidHardwareBufferTextureSourceVK` defaults
60  // to that safe value. So just use that.
61  //
62  // See the validation VUID-VkSamplerCreateInfo-minFilter-01645 for more.
63  //
64  sampler_info.magFilter = vk::Filter::eNearest;
65  sampler_info.minFilter = vk::Filter::eNearest;
66 
67  // Spec: If sampler Y′CBCR conversion is enabled, addressModeU,
68  // addressModeV, and addressModeW must be
69  // VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, anisotropyEnable must be VK_FALSE,
70  // and unnormalizedCoordinates must be VK_FALSE.
71  //
72  // See the validation VUID-VkSamplerCreateInfo-addressModeU-01646 for more.
73  //
74  sampler_info.addressModeU = vk::SamplerAddressMode::eClampToEdge;
75  sampler_info.addressModeV = vk::SamplerAddressMode::eClampToEdge;
76  sampler_info.addressModeW = vk::SamplerAddressMode::eClampToEdge;
77  sampler_info.anisotropyEnable = false;
78  sampler_info.unnormalizedCoordinates = false;
79  } else {
80  sampler_chain.unlink<vk::SamplerYcbcrConversionInfo>();
81  }
82 
83  auto sampler = device.createSamplerUnique(sampler_chain.get());
84  if (sampler.result != vk::Result::eSuccess) {
85  VALIDATION_LOG << "Could not create sampler: "
86  << vk::to_string(sampler.result);
87  return {};
88  }
89 
90  if (!desc.label.empty()) {
91  ContextVK::SetDebugName(device, sampler.value.get(), desc.label.c_str());
92  }
93 
94  return std::move(sampler.value);
95 }
96 
97 SamplerVK::SamplerVK(const vk::Device& device,
98  SamplerDescriptor desc,
99  std::shared_ptr<YUVConversionVK> yuv_conversion)
100  : Sampler(std::move(desc)),
101  device_(device),
102  sampler_(MakeSharedVK<vk::Sampler>(
103  CreateSampler(device, desc_, yuv_conversion))),
104  yuv_conversion_(std::move(yuv_conversion)) {
105  is_valid_ = sampler_ && !!sampler_->Get();
106 }
107 
108 SamplerVK::~SamplerVK() = default;
109 
110 vk::Sampler SamplerVK::GetSampler() const {
111  return *sampler_;
112 }
113 
114 std::shared_ptr<SamplerVK> SamplerVK::CreateVariantForConversion(
115  std::shared_ptr<YUVConversionVK> conversion) const {
116  if (!conversion || !is_valid_) {
117  return nullptr;
118  }
119  return std::make_shared<SamplerVK>(device_, desc_, std::move(conversion));
120 }
121 
122 const std::shared_ptr<YUVConversionVK>& SamplerVK::GetYUVConversion() const {
123  return yuv_conversion_;
124 }
125 
126 } // namespace impeller
impeller::SamplerVK::SamplerVK
SamplerVK(const vk::Device &device, SamplerDescriptor desc, std::shared_ptr< YUVConversionVK > yuv_conversion={})
Definition: sampler_vk.cc:97
impeller::SamplerVK::GetYUVConversion
const std::shared_ptr< YUVConversionVK > & GetYUVConversion() const
Definition: sampler_vk.cc:122
impeller::ToVKSamplerAddressMode
constexpr vk::SamplerAddressMode ToVKSamplerAddressMode(SamplerAddressMode mode)
Definition: formats_vk.h:236
impeller::CreateSampler
static vk::UniqueSampler CreateSampler(const vk::Device &device, const SamplerDescriptor &desc, const std::shared_ptr< YUVConversionVK > &yuv_conversion)
Definition: sampler_vk.cc:13
impeller::SamplerVK::CreateVariantForConversion
std::shared_ptr< SamplerVK > CreateVariantForConversion(std::shared_ptr< YUVConversionVK > conversion) const
Definition: sampler_vk.cc:114
impeller::ToVKSamplerMipmapMode
constexpr vk::SamplerMipmapMode ToVKSamplerMipmapMode(MipFilter filter)
Definition: formats_vk.h:225
formats_vk.h
impeller::SamplerDescriptor::mag_filter
MinMagFilter mag_filter
Definition: sampler_descriptor.h:17
impeller::SamplerDescriptor
Definition: sampler_descriptor.h:15
impeller::Sampler
Definition: sampler.h:15
impeller::SamplerDescriptor::min_filter
MinMagFilter min_filter
Definition: sampler_descriptor.h:16
impeller::SamplerDescriptor::width_address_mode
SamplerAddressMode width_address_mode
Definition: sampler_descriptor.h:20
impeller::SamplerDescriptor::depth_address_mode
SamplerAddressMode depth_address_mode
Definition: sampler_descriptor.h:22
impeller::SamplerVK::GetSampler
vk::Sampler GetSampler() const
Definition: sampler_vk.cc:110
impeller::ContextVK::SetDebugName
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:106
impeller::SamplerDescriptor::mip_filter
MipFilter mip_filter
Definition: sampler_descriptor.h:18
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::MakeSharedVK
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
Definition: shared_object_vk.h:43
impeller::ToVKSamplerMinMagFilter
constexpr vk::Filter ToVKSamplerMinMagFilter(MinMagFilter filter)
Definition: formats_vk.h:214
yuv_conversion_vk.h
std
Definition: comparable.h:95
impeller::SamplerDescriptor::label
std::string label
Definition: sampler_descriptor.h:24
sampler_vk.h
context_vk.h
impeller::SamplerVK::~SamplerVK
~SamplerVK() override
impeller::SamplerDescriptor::height_address_mode
SamplerAddressMode height_address_mode
Definition: sampler_descriptor.h:21
impeller
Definition: aiks_blur_unittests.cc:20
impeller::Sampler::desc_
SamplerDescriptor desc_
Definition: sampler.h:22