blob: 19b8f0a0ae6661e870ccfcfabb83b0f7d734f939 [file] [log] [blame]
/*
* 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 "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(tileModeLabels[static_cast<int>(samplerDesc.tileModeX())]);
label.append("Y").append(tileModeLabels[static_cast<int>(samplerDesc.tileModeY())]);
label.append(minMagFilterLabels[static_cast<int>(samplingOptions.filter)]);
label.append(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(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