Flutter Engine
The Flutter Engine
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
12namespace impeller {
13
14static vk::UniqueSampler CreateSampler(
15 const vk::Device& device,
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 // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkSamplerCreateInfo.html#_description
41 switch (desc.mip_filter) {
43 sampler_info.mipmapMode = vk::SamplerMipmapMode::eNearest;
44 sampler_info.minLod = sampler_info.maxLod = 0.0f;
45 break;
47 sampler_info.mipmapMode = vk::SamplerMipmapMode::eNearest;
48 break;
50 sampler_info.mipmapMode = vk::SamplerMipmapMode::eLinear;
51 break;
52 }
53
54 if (yuv_conversion && yuv_conversion->IsValid()) {
55 sampler_chain.get<vk::SamplerYcbcrConversionInfo>().conversion =
56 yuv_conversion->GetConversion();
57
58 //
59 // TL;DR: When using YUV conversion, our samplers are somewhat hobbled and
60 // not all options configurable in Impeller (especially the linear
61 // filtering which is by far the most used form of filtering) can be
62 // supported. Switch to safe defaults.
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 // Thing is, we don't enable separate reconstruction filters. By the time we
70 // are here, we also don't have access to the descriptor used to create this
71 // conversion. So we don't yet know what the chromaFilter is. But eNearest
72 // is a safe bet since the `AndroidHardwareBufferTextureSourceVK` defaults
73 // to that safe value. So just use that.
74 //
75 // See the validation VUID-VkSamplerCreateInfo-minFilter-01645 for more.
76 //
77 sampler_info.magFilter = vk::Filter::eNearest;
78 sampler_info.minFilter = vk::Filter::eNearest;
79
80 // Spec: If sampler Y′CBCR conversion is enabled, addressModeU,
81 // addressModeV, and addressModeW must be
82 // VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, anisotropyEnable must be VK_FALSE,
83 // and unnormalizedCoordinates must be VK_FALSE.
84 //
85 // See the validation VUID-VkSamplerCreateInfo-addressModeU-01646 for more.
86 //
87 sampler_info.addressModeU = vk::SamplerAddressMode::eClampToEdge;
88 sampler_info.addressModeV = vk::SamplerAddressMode::eClampToEdge;
89 sampler_info.addressModeW = vk::SamplerAddressMode::eClampToEdge;
90 sampler_info.anisotropyEnable = false;
91 sampler_info.unnormalizedCoordinates = false;
92 } else {
93 sampler_chain.unlink<vk::SamplerYcbcrConversionInfo>();
94 }
95
96 auto sampler = device.createSamplerUnique(sampler_chain.get());
97 if (sampler.result != vk::Result::eSuccess) {
98 VALIDATION_LOG << "Could not create sampler: "
99 << vk::to_string(sampler.result);
100 return {};
101 }
102
103 if (!desc.label.empty()) {
104 ContextVK::SetDebugName(device, sampler.value.get(), desc.label.c_str());
105 }
106
107 return std::move(sampler.value);
108}
109
110SamplerVK::SamplerVK(const vk::Device& device,
112 std::shared_ptr<YUVConversionVK> yuv_conversion)
113 : Sampler(std::move(desc)),
114 device_(device),
115 sampler_(MakeSharedVK<vk::Sampler>(
116 CreateSampler(device, desc_, yuv_conversion))),
117 yuv_conversion_(std::move(yuv_conversion)) {
118 is_valid_ = sampler_ && !!sampler_->Get();
119}
120
121SamplerVK::~SamplerVK() = default;
122
124 return *sampler_;
125}
126
127std::shared_ptr<SamplerVK> SamplerVK::CreateVariantForConversion(
128 std::shared_ptr<YUVConversionVK> conversion) const {
129 if (!conversion || !is_valid_) {
130 return nullptr;
131 }
132 return std::make_shared<SamplerVK>(device_, desc_, std::move(conversion));
133}
134
135const std::shared_ptr<YUVConversionVK>& SamplerVK::GetYUVConversion() const {
136 return yuv_conversion_;
137}
138
139} // namespace impeller
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:108
vk::Sampler GetSampler() const
Definition: sampler_vk.cc:123
~SamplerVK() override
SamplerVK(const vk::Device &device, SamplerDescriptor desc, std::shared_ptr< YUVConversionVK > yuv_conversion={})
Definition: sampler_vk.cc:110
std::shared_ptr< SamplerVK > CreateVariantForConversion(std::shared_ptr< YUVConversionVK > conversion) const
Definition: sampler_vk.cc:127
const std::shared_ptr< YUVConversionVK > & GetYUVConversion() const
Definition: sampler_vk.cc:135
SamplerDescriptor desc_
Definition: sampler.h:22
VkDevice device
Definition: main.cc:53
std::function< ProfileSample(void)> Sampler
Sampler is run during SamplingProfiler::SampleRepeatedly. Each platform should implement its version ...
constexpr vk::SamplerAddressMode ToVKSamplerAddressMode(SamplerAddressMode mode)
Definition: formats_vk.h:235
@ 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.
constexpr vk::Filter ToVKSamplerMinMagFilter(MinMagFilter filter)
Definition: formats_vk.h:212
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
vk
Definition: malisc.py:42
Definition: ref_ptr.h:256
static SkString to_string(int n)
Definition: nanobench.cpp:119
#define VALIDATION_LOG
Definition: validation.h:73
#define VK_LOD_CLAMP_NONE
Definition: vulkan_core.h:126