1 /*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/graphite/dawn/DawnSampler.h"
9
10 #include "include/core/SkSamplingOptions.h"
11 #include "src/gpu/graphite/dawn/DawnCaps.h"
12 #include "src/gpu/graphite/dawn/DawnGraphiteUtilsPriv.h"
13 #include "src/gpu/graphite/dawn/DawnSharedContext.h"
14
15 #include <cfloat>
16
17 namespace skgpu::graphite {
18
19 namespace {
20
filter_mode_to_dawn_filter_mode(SkFilterMode mode)21 wgpu::FilterMode filter_mode_to_dawn_filter_mode(SkFilterMode mode) {
22 switch (mode) {
23 case SkFilterMode::kNearest:
24 return wgpu::FilterMode::Nearest;
25 case SkFilterMode::kLinear:
26 return wgpu::FilterMode::Linear;
27 }
28 SkUNREACHABLE;
29 }
30
mipmap_mode_to_dawn_filter_mode(SkMipmapMode mode)31 wgpu::MipmapFilterMode mipmap_mode_to_dawn_filter_mode(SkMipmapMode mode) {
32 switch (mode) {
33 case SkMipmapMode::kNone:
34 // Dawn doesn't have none filter mode.
35 return wgpu::MipmapFilterMode::Nearest;
36 case SkMipmapMode::kNearest:
37 return wgpu::MipmapFilterMode::Nearest;
38 case SkMipmapMode::kLinear:
39 return wgpu::MipmapFilterMode::Linear;
40 }
41 SkUNREACHABLE;
42 }
43 }
44
DawnSampler(const DawnSharedContext * sharedContext,wgpu::Sampler sampler)45 DawnSampler::DawnSampler(const DawnSharedContext* sharedContext,
46 wgpu::Sampler sampler)
47 : Sampler(sharedContext)
48 , fSampler(std::move(sampler)) {}
49
tile_mode_to_dawn_address_mode(SkTileMode tileMode)50 static inline wgpu::AddressMode tile_mode_to_dawn_address_mode(SkTileMode tileMode) {
51 switch (tileMode) {
52 case SkTileMode::kClamp:
53 return wgpu::AddressMode::ClampToEdge;
54 case SkTileMode::kRepeat:
55 return wgpu::AddressMode::Repeat;
56 case SkTileMode::kMirror:
57 return wgpu::AddressMode::MirrorRepeat;
58 case SkTileMode::kDecal:
59 // Dawn doesn't support this mode.
60 return wgpu::AddressMode::ClampToEdge;
61 }
62 SkUNREACHABLE;
63 }
64
65 #if !defined(__EMSCRIPTEN__)
66 namespace {
67 using namespace ycbcrUtils;
get_descriptor_from_sampler_desc(const SamplerDesc & samplerDesc)68 wgpu::YCbCrVkDescriptor get_descriptor_from_sampler_desc(const SamplerDesc& samplerDesc) {
69 wgpu::YCbCrVkDescriptor desc;
70 if (samplerDesc.isImmutable()) {
71 uint32_t nonFormatInfo =
72 (uint32_t)(samplerDesc.desc() >> SamplerDesc::kImmutableSamplerInfoShift);
73
74 desc.vkFormat = samplerDesc.usesExternalFormat() ? 0 : samplerDesc.format();
75 desc.vkYCbCrModel = (nonFormatInfo & ycbcrUtils::kYcbcrModelMask) >> kYcbcrModelShift;
76 desc.vkYCbCrRange = (nonFormatInfo & kYcbcrRangeMask) >> kYcbcrRangeShift;
77 desc.vkComponentSwizzleRed = (nonFormatInfo & kComponentRMask) >> kComponentRShift;
78 desc.vkComponentSwizzleGreen = (nonFormatInfo & kComponentGMask) >> kComponentGShift;
79 desc.vkComponentSwizzleBlue = (nonFormatInfo & kComponentBMask) >> kComponentBShift;
80 desc.vkComponentSwizzleAlpha = (nonFormatInfo & kComponentAMask) >> kComponentAShift;
81 desc.vkXChromaOffset = (nonFormatInfo & kXChromaOffsetMask) >> kXChromaOffsetShift;
82 desc.vkYChromaOffset = (nonFormatInfo & kYChromaOffsetMask) >> kYChromaOffsetShift;
83 desc.vkChromaFilter =
84 (wgpu::FilterMode)((nonFormatInfo & kChromaFilterMask) >> kChromaFilterShift);
85 desc.forceExplicitReconstruction =
86 (nonFormatInfo & kForceExplicitReconMask) >> kForceExplicitReconShift;
87 desc.externalFormat =
88 samplerDesc.usesExternalFormat()
89 ? (uint64_t)(samplerDesc.externalFormatMSBs()) << 32 | samplerDesc.format()
90 : 0;
91 }
92 return desc;
93 }
94 } // namespace
95 #endif
Make(const DawnSharedContext * sharedContext,const SamplerDesc & samplerDesc)96 sk_sp<DawnSampler> DawnSampler::Make(const DawnSharedContext* sharedContext,
97 const SamplerDesc& samplerDesc) {
98 wgpu::SamplerDescriptor desc;
99 const SkSamplingOptions& samplingOptions = samplerDesc.samplingOptions();
100 desc.addressModeU = tile_mode_to_dawn_address_mode(samplerDesc.tileModeX());
101 desc.addressModeV = tile_mode_to_dawn_address_mode(samplerDesc.tileModeY());
102 desc.magFilter = filter_mode_to_dawn_filter_mode(samplingOptions.filter);
103 desc.minFilter = desc.magFilter;
104 desc.mipmapFilter = mipmap_mode_to_dawn_filter_mode(samplingOptions.mipmap);
105 desc.lodMinClamp = 0.0f;
106 if (samplingOptions.mipmap == SkMipmapMode::kNone) {
107 // Disabling mipmap by clamping max lod to first level only.
108 desc.lodMaxClamp = 0.0f;
109 } else {
110 desc.lodMaxClamp = FLT_MAX;
111 }
112 desc.maxAnisotropy = 1;
113 desc.compare = wgpu::CompareFunction::Undefined;
114
115 #if !defined(__EMSCRIPTEN__)
116 wgpu::YCbCrVkDescriptor ycbcrDescriptor = get_descriptor_from_sampler_desc(samplerDesc);
117 if (samplerDesc.isImmutable()) {
118 desc.nextInChain = &ycbcrDescriptor;
119 }
120 #endif
121
122 std::string label;
123 if (sharedContext->caps()->setBackendLabels()) {
124 static const char* tileModeLabels[] = {"Clamp", "Repeat", "Mirror", "Decal"};
125 static const char* minMagFilterLabels[] = {"Nearest", "Linear"};
126 static const char* mipFilterLabels[] = {"MipNone", "MipNearest", "MipLinear"};
127 label.append("X").append(tileModeLabels[static_cast<int>(samplerDesc.tileModeX())]);
128 label.append("Y").append(tileModeLabels[static_cast<int>(samplerDesc.tileModeY())]);
129 label.append(minMagFilterLabels[static_cast<int>(samplingOptions.filter)]);
130 label.append(mipFilterLabels[static_cast<int>(samplingOptions.mipmap)]);
131 #if !defined(__EMSCRIPTEN__)
132 if (ycbcrUtils::DawnDescriptorIsValid(ycbcrDescriptor)) {
133 label.append("YCbCr");
134
135 if (ycbcrUtils::DawnDescriptorUsesExternalFormat(ycbcrDescriptor)) {
136 label.append("ExternalFormat");
137 label.append(std::to_string(ycbcrDescriptor.externalFormat));
138 } else {
139 label.append("KnownFormat").append(std::to_string(ycbcrDescriptor.vkFormat));
140 }
141
142 label.append("Model").append(std::to_string(ycbcrDescriptor.vkYCbCrModel));
143 label.append("Range").append(std::to_string(ycbcrDescriptor.vkYCbCrRange));
144
145 label.append("ComponentSwizzleRGBA");
146 label.append(std::to_string(ycbcrDescriptor.vkComponentSwizzleRed));
147 label.append(std::to_string(ycbcrDescriptor.vkComponentSwizzleGreen));
148 label.append(std::to_string(ycbcrDescriptor.vkComponentSwizzleBlue));
149 label.append(std::to_string(ycbcrDescriptor.vkComponentSwizzleAlpha));
150
151 label.append("ChromaOffset");
152 label.append("X").append(std::to_string(ycbcrDescriptor.vkXChromaOffset));
153 label.append("Y").append(std::to_string(ycbcrDescriptor.vkYChromaOffset));
154
155 static const char* chromaFilterLabels[] = {
156 "WGPU_Undefined", "WGPU_Nearest", "WGPU_Linear"};
157 label.append("ChromaFilter");
158 label.append(chromaFilterLabels[static_cast<int>(ycbcrDescriptor.vkChromaFilter)]);
159
160 label.append("ForceExplicitReconstruct");
161 label.append(std::to_string(ycbcrDescriptor.forceExplicitReconstruction));
162 }
163 #endif
164 desc.label = label.c_str();
165 }
166
167 auto sampler = sharedContext->device().CreateSampler(&desc);
168 if (!sampler) {
169 return {};
170 }
171 return sk_sp<DawnSampler>(new DawnSampler(sharedContext, std::move(sampler)));
172 }
173
freeGpuData()174 void DawnSampler::freeGpuData() {
175 fSampler = nullptr;
176 }
177
178 } // namespace skgpu::graphite
179
180