xref: /aosp_15_r20/external/skia/src/gpu/graphite/dawn/DawnSampler.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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