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 #include "vulkan/vulkan_core.h"
11 
12 namespace impeller {
13 
14 static vk::UniqueSampler CreateSampler(
15  const vk::Device& device,
16  const SamplerDescriptor& desc,
17  const std::shared_ptr<YUVConversionVK>& yuv_conversion) {
18  const auto min_filter = ToVKSamplerMinMagFilter(desc.min_filter);
19  const auto mag_filter = ToVKSamplerMinMagFilter(desc.mag_filter);
20 
21  const auto address_mode_u = ToVKSamplerAddressMode(desc.width_address_mode);
22  const auto address_mode_v = ToVKSamplerAddressMode(desc.height_address_mode);
23  const auto address_mode_w = ToVKSamplerAddressMode(desc.depth_address_mode);
24 
25  vk::StructureChain<vk::SamplerCreateInfo,
26  // For VK_KHR_sampler_ycbcr_conversion
27  vk::SamplerYcbcrConversionInfo>
28  sampler_chain;
29 
30  auto& sampler_info = sampler_chain.get();
31 
32  sampler_info.magFilter = mag_filter;
33  sampler_info.minFilter = min_filter;
34  sampler_info.addressModeU = address_mode_u;
35  sampler_info.addressModeV = address_mode_v;
36  sampler_info.addressModeW = address_mode_w;
37  sampler_info.borderColor = vk::BorderColor::eFloatTransparentBlack;
38  sampler_info.maxLod = VK_LOD_CLAMP_NONE;
39 
40  // The descriptor's max anisotropy has already been clamped to the device
41  // limit by SamplerLibraryVK, and it remains 1 (disabled) when the
42  // samplerAnisotropy feature is unavailable.
43  sampler_info.anisotropyEnable = desc.max_anisotropy > 1;
44  sampler_info.maxAnisotropy = static_cast<float>(desc.max_anisotropy);
45 
46  // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkSamplerCreateInfo.html#_description
47  switch (desc.mip_filter) {
48  case MipFilter::kBase:
49  sampler_info.mipmapMode = vk::SamplerMipmapMode::eNearest;
50  sampler_info.minLod = sampler_info.maxLod = 0.0f;
51  break;
53  sampler_info.mipmapMode = vk::SamplerMipmapMode::eNearest;
54  break;
55  case MipFilter::kLinear:
56  sampler_info.mipmapMode = vk::SamplerMipmapMode::eLinear;
57  break;
58  }
59 
60  if (yuv_conversion && yuv_conversion->IsValid()) {
61  sampler_chain.get<vk::SamplerYcbcrConversionInfo>().conversion =
62  yuv_conversion->GetConversion();
63 
64  // Spec: If sampler Y'CBCR conversion is enabled and the potential format
65  // features of the sampler Y'CBCR conversion do not support or enable
66  // separate reconstruction filters, minFilter and magFilter must be equal to
67  // the sampler Y'CBCR conversion's chromaFilter.
68  //
69  // We don't enable separate reconstruction filters. So, just do what the
70  // spec. says and use the conversions chromaFilter.
71  //
72  // See the validation VUID-VkSamplerCreateInfo-minFilter-01645 for more.
73  //
74  sampler_info.minFilter = sampler_info.magFilter =
75  yuv_conversion->GetDescriptor().get().chromaFilter;
76 
77  // Spec: If sampler Y′CBCR conversion is enabled, addressModeU,
78  // addressModeV, and addressModeW must be
79  // VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, anisotropyEnable must be VK_FALSE,
80  // and unnormalizedCoordinates must be VK_FALSE.
81  //
82  // See the validation VUID-VkSamplerCreateInfo-addressModeU-01646 for more.
83  //
84  sampler_info.addressModeU = vk::SamplerAddressMode::eClampToEdge;
85  sampler_info.addressModeV = vk::SamplerAddressMode::eClampToEdge;
86  sampler_info.addressModeW = vk::SamplerAddressMode::eClampToEdge;
87  sampler_info.anisotropyEnable = false;
88  sampler_info.unnormalizedCoordinates = false;
89  } else {
90  sampler_chain.unlink<vk::SamplerYcbcrConversionInfo>();
91  }
92 
93  auto sampler = device.createSamplerUnique(sampler_chain.get());
94  if (sampler.result != vk::Result::eSuccess) {
95  VALIDATION_LOG << "Could not create sampler: "
96  << vk::to_string(sampler.result);
97  return {};
98  }
99 
100  if (!desc.label.empty()) {
101  ContextVK::SetDebugName(device, sampler.value.get(), desc.label.data());
102  }
103 
104  return std::move(sampler.value);
105 }
106 
107 SamplerVK::SamplerVK(const vk::Device& device,
108  const SamplerDescriptor& desc,
109  std::shared_ptr<YUVConversionVK> yuv_conversion)
110  : Sampler(desc),
111  device_(device),
112  sampler_(MakeSharedVK<vk::Sampler>(
113  CreateSampler(device, desc_, yuv_conversion))),
114  yuv_conversion_(std::move(yuv_conversion)) {
115  is_valid_ = sampler_ && !!sampler_->Get();
116 }
117 
118 SamplerVK::~SamplerVK() = default;
119 
120 vk::Sampler SamplerVK::GetSampler() const {
121  return *sampler_;
122 }
123 
124 std::shared_ptr<SamplerVK> SamplerVK::CreateVariantForConversion(
125  std::shared_ptr<YUVConversionVK> conversion) const {
126  if (!conversion || !is_valid_) {
127  return nullptr;
128  }
129  return std::make_shared<SamplerVK>(device_, desc_, std::move(conversion));
130 }
131 
132 const std::shared_ptr<YUVConversionVK>& SamplerVK::GetYUVConversion() const {
133  return yuv_conversion_;
134 }
135 
136 } // namespace impeller
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:151
SamplerDescriptor desc_
Definition: sampler.h:19
vk::Sampler GetSampler() const
Definition: sampler_vk.cc:120
~SamplerVK() override
SamplerVK(const vk::Device &device, const SamplerDescriptor &, std::shared_ptr< YUVConversionVK > yuv_conversion={})
Definition: sampler_vk.cc:107
std::shared_ptr< SamplerVK > CreateVariantForConversion(std::shared_ptr< YUVConversionVK > conversion) const
Definition: sampler_vk.cc:124
const std::shared_ptr< YUVConversionVK > & GetYUVConversion() const
Definition: sampler_vk.cc:132
std::optional< PipelineDescriptor > desc_
constexpr vk::SamplerAddressMode ToVKSamplerAddressMode(SamplerAddressMode mode)
Definition: formats_vk.h:284
constexpr vk::Filter ToVKSamplerMinMagFilter(MinMagFilter filter)
Definition: formats_vk.h:261
@ kLinear
Sample from the two nearest mip levels and linearly interpolate.
@ kBase
The texture is sampled as if it only had a single mipmap level.
@ kNearest
The nearst mipmap level is selected.
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
static vk::UniqueSampler CreateSampler(const vk::Device &device, const SamplerDescriptor &desc, const std::shared_ptr< YUVConversionVK > &yuv_conversion)
Definition: sampler_vk.cc:14
Definition: comparable.h:93
SamplerAddressMode depth_address_mode
SamplerAddressMode width_address_mode
SamplerAddressMode height_address_mode
#define VALIDATION_LOG
Definition: validation.h:91