| /* | |
| * Copyright 2022 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "src/gpu/graphite/dawn/DawnSampler.h" | |
| #include "include/core/SkSamplingOptions.h" | |
| #include "include/private/SkAttributes.h" | |
| #include "src/gpu/graphite/dawn/DawnCaps.h" | |
| #include "src/gpu/graphite/dawn/DawnGraphiteUtils.h" | |
| #include "src/gpu/graphite/dawn/DawnSharedContext.h" | |
| #include <cfloat> | |
| namespace skgpu::graphite { | |
| namespace { | |
| wgpu::FilterMode filter_mode_to_dawn_filter_mode(SkFilterMode mode) { | |
| switch (mode) { | |
| case SkFilterMode::kNearest: | |
| return wgpu::FilterMode::Nearest; | |
| case SkFilterMode::kLinear: | |
| return wgpu::FilterMode::Linear; | |
| } | |
| SkUNREACHABLE; | |
| } | |
| wgpu::MipmapFilterMode mipmap_mode_to_dawn_filter_mode(SkMipmapMode mode) { | |
| switch (mode) { | |
| case SkMipmapMode::kNone: | |
| // Dawn doesn't have none filter mode. | |
| return wgpu::MipmapFilterMode::Nearest; | |
| case SkMipmapMode::kNearest: | |
| return wgpu::MipmapFilterMode::Nearest; | |
| case SkMipmapMode::kLinear: | |
| return wgpu::MipmapFilterMode::Linear; | |
| } | |
| SkUNREACHABLE; | |
| } | |
| } | |
| DawnSampler::DawnSampler(const DawnSharedContext* sharedContext, | |
| SamplerDesc samplerDesc, | |
| wgpu::Sampler sampler) | |
| : Sampler(sharedContext) | |
| , fSampler(std::move(sampler)) | |
| , fSamplerDesc(samplerDesc) {} | |
| static inline std::pair<wgpu::AddressMode, wgpu::AddressMode> | |
| tile_modes_to_dawn_address_modes(const SamplerDesc& samplerDesc) { | |
| auto to_dawn_mode = [](SkTileMode tm) -> wgpu::AddressMode { | |
| switch (tm) { | |
| case SkTileMode::kClamp: | |
| return wgpu::AddressMode::ClampToEdge; | |
| case SkTileMode::kRepeat: | |
| return wgpu::AddressMode::Repeat; | |
| case SkTileMode::kMirror: | |
| return wgpu::AddressMode::MirrorRepeat; | |
| case SkTileMode::kDecal: | |
| // Dawn doesn't support kDecal; considered an error if we reach this point. | |
| SkASSERT(false); | |
| return {}; | |
| } | |
| SkUNREACHABLE; | |
| }; | |
| return {to_dawn_mode(samplerDesc.tileModeX()), to_dawn_mode(samplerDesc.tileModeY())}; | |
| } | |
| sk_sp<DawnSampler> DawnSampler::Make(const DawnSharedContext* sharedContext, | |
| SamplerDesc samplerDesc) { | |
| wgpu::SamplerDescriptor desc; | |
| const SkSamplingOptions& samplingOptions = samplerDesc.samplingOptions(); | |
| std::tie(desc.addressModeU, desc.addressModeV) = tile_modes_to_dawn_address_modes(samplerDesc); | |
| desc.magFilter = filter_mode_to_dawn_filter_mode(samplingOptions.filter); | |
| desc.minFilter = desc.magFilter; | |
| desc.mipmapFilter = mipmap_mode_to_dawn_filter_mode(samplingOptions.mipmap); | |
| desc.lodMinClamp = 0.0f; | |
| if (samplingOptions.mipmap == SkMipmapMode::kNone) { | |
| // Disabling mipmap by clamping max lod to first level only. | |
| desc.lodMaxClamp = 0.0f; | |
| } else { | |
| desc.lodMaxClamp = FLT_MAX; | |
| } | |
| desc.maxAnisotropy = 1; | |
| desc.compare = wgpu::CompareFunction::Undefined; | |
| #if !defined(__EMSCRIPTEN__) | |
| wgpu::YCbCrVkDescriptor ycbcrDescriptor; | |
| if (samplerDesc.isImmutable()) { | |
| ycbcrDescriptor = | |
| DawnDescriptorFromImmutableSamplerInfo(samplerDesc.immutableSamplerInfo()); | |
| desc.nextInChain = &ycbcrDescriptor; | |
| } | |
| #endif | |
| std::string label; | |
| if (sharedContext->caps()->setBackendLabels()) { | |
| static const char* tileModeLabels[] = {"Clamp", "Repeat", "Mirror", "Decal"}; | |
| static const char* minMagFilterLabels[] = {"Nearest", "Linear"}; | |
| static const char* mipFilterLabels[] = {"MipNone", "MipNearest", "MipLinear"}; | |
| label.append("X").append( | |
| SK_UNSAFE_TODO(tileModeLabels[static_cast<int>(samplerDesc.tileModeX())])); | |
| label.append("Y").append( | |
| SK_UNSAFE_TODO(tileModeLabels[static_cast<int>(samplerDesc.tileModeY())])); | |
| label.append(SK_UNSAFE_TODO(minMagFilterLabels[static_cast<int>(samplingOptions.filter)])); | |
| label.append(SK_UNSAFE_TODO(mipFilterLabels[static_cast<int>(samplingOptions.mipmap)])); | |
| #if !defined(__EMSCRIPTEN__) | |
| if (DawnDescriptorIsValid(ycbcrDescriptor)) { | |
| label.append("YCbCr"); | |
| if (DawnDescriptorUsesExternalFormat(ycbcrDescriptor)) { | |
| label.append("ExternalFormat"); | |
| label.append(std::to_string(ycbcrDescriptor.externalFormat)); | |
| } else { | |
| label.append("KnownFormat").append(std::to_string(ycbcrDescriptor.vkFormat)); | |
| } | |
| label.append("Model").append(std::to_string(ycbcrDescriptor.vkYCbCrModel)); | |
| label.append("Range").append(std::to_string(ycbcrDescriptor.vkYCbCrRange)); | |
| label.append("ComponentSwizzleRGBA"); | |
| label.append(std::to_string(ycbcrDescriptor.vkComponentSwizzleRed)); | |
| label.append(std::to_string(ycbcrDescriptor.vkComponentSwizzleGreen)); | |
| label.append(std::to_string(ycbcrDescriptor.vkComponentSwizzleBlue)); | |
| label.append(std::to_string(ycbcrDescriptor.vkComponentSwizzleAlpha)); | |
| label.append("ChromaOffset"); | |
| label.append("X").append(std::to_string(ycbcrDescriptor.vkXChromaOffset)); | |
| label.append("Y").append(std::to_string(ycbcrDescriptor.vkYChromaOffset)); | |
| static const char* chromaFilterLabels[] = { | |
| "WGPU_Undefined", "WGPU_Nearest", "WGPU_Linear"}; | |
| label.append("ChromaFilter"); | |
| label.append(SK_UNSAFE_TODO( | |
| chromaFilterLabels[static_cast<int>(ycbcrDescriptor.vkChromaFilter)])); | |
| label.append("ForceExplicitReconstruct"); | |
| label.append(std::to_string(ycbcrDescriptor.forceExplicitReconstruction)); | |
| } | |
| #endif | |
| desc.label = label.c_str(); | |
| } | |
| auto sampler = sharedContext->device().CreateSampler(&desc); | |
| if (!sampler) { | |
| return {}; | |
| } | |
| return sk_sp<DawnSampler>(new DawnSampler(sharedContext, samplerDesc, std::move(sampler))); | |
| } | |
| void DawnSampler::freeGpuData() { | |
| fSampler = nullptr; | |
| } | |
| } // namespace skgpu::graphite |