From 84fecee87910a7d1e4237276dd9a0c44d70e313a Mon Sep 17 00:00:00 2001 From: Jim Van Verth Date: Mon, 24 Jan 2022 15:55:31 -0500 Subject: [PATCH] [graphite] Add sampler creation Bug: skia:12845 Change-Id: Iba4fcfe98adf6f0445958322d674ab3dfee87305 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/497280 Reviewed-by: Michael Ludwig Commit-Queue: Jim Van Verth --- experimental/graphite/src/Caps.h | 4 + .../graphite/src/ResourceProvider.cpp | 7 ++ experimental/graphite/src/ResourceProvider.h | 12 +++ experimental/graphite/src/mtl/MtlCaps.mm | 6 ++ .../graphite/src/mtl/MtlResourceProvider.h | 4 + .../graphite/src/mtl/MtlResourceProvider.mm | 7 ++ experimental/graphite/src/mtl/MtlSampler.h | 10 ++- experimental/graphite/src/mtl/MtlSampler.mm | 89 +++++++++++++++---- tests/graphite/CommandBufferTest.cpp | 6 ++ 9 files changed, 125 insertions(+), 20 deletions(-) diff --git a/experimental/graphite/src/Caps.h b/experimental/graphite/src/Caps.h index b66da85cca..e0a64c909e 100644 --- a/experimental/graphite/src/Caps.h +++ b/experimental/graphite/src/Caps.h @@ -56,6 +56,8 @@ public: // to a draw. size_t requiredUniformBufferAlignment() const { return fRequiredUniformBufferAlignment; } + bool clampToBorderSupport() const { return fClampToBorderSupport; } + protected: Caps(); @@ -64,6 +66,8 @@ protected: std::unique_ptr fShaderCaps; + bool fClampToBorderSupport = true; + private: virtual bool onIsTexturable(const TextureInfo&) const = 0; virtual bool onAreColorTypeAndTextureInfoCompatible(SkColorType, const TextureInfo&) const = 0; diff --git a/experimental/graphite/src/ResourceProvider.cpp b/experimental/graphite/src/ResourceProvider.cpp index 4376387d77..0361dd5e82 100644 --- a/experimental/graphite/src/ResourceProvider.cpp +++ b/experimental/graphite/src/ResourceProvider.cpp @@ -13,6 +13,7 @@ #include "experimental/graphite/src/ContextPriv.h" #include "experimental/graphite/src/Gpu.h" #include "experimental/graphite/src/GraphicsPipeline.h" +#include "experimental/graphite/src/Sampler.h" #include "experimental/graphite/src/Texture.h" namespace skgpu { @@ -74,6 +75,12 @@ sk_sp ResourceProvider::findOrCreateTexture(SkISize dimensions, const T return this->createTexture(dimensions, info); } +sk_sp ResourceProvider::findOrCreateCompatibleSampler(const SkSamplingOptions& smplOptions, + SkTileMode xTileMode, + SkTileMode yTileMode) { + return this->createSampler(smplOptions, xTileMode, yTileMode); +} + sk_sp ResourceProvider::findOrCreateBuffer(size_t size, BufferType type, PrioritizeGpuReads prioritizeGpuReads) { diff --git a/experimental/graphite/src/ResourceProvider.h b/experimental/graphite/src/ResourceProvider.h index 7bf3f6a5f6..b6016aa348 100644 --- a/experimental/graphite/src/ResourceProvider.h +++ b/experimental/graphite/src/ResourceProvider.h @@ -12,15 +12,19 @@ #include "experimental/graphite/src/GraphicsPipelineDesc.h" #include "experimental/graphite/src/ResourceTypes.h" #include "include/core/SkSize.h" +#include "include/core/SkTileMode.h" #include "src/core/SkLRUCache.h" #include "src/gpu/ResourceKey.h" +struct SkSamplingOptions; + namespace skgpu { class BackendTexture; class Buffer; class Gpu; class GraphicsPipeline; +class Sampler; class Texture; class TextureInfo; @@ -38,6 +42,10 @@ public: sk_sp findOrCreateBuffer(size_t size, BufferType type, PrioritizeGpuReads); + sk_sp findOrCreateCompatibleSampler(const SkSamplingOptions&, + SkTileMode xTileMode, + SkTileMode yTileMode); + protected: ResourceProvider(const Gpu* gpu); @@ -50,6 +58,10 @@ private: virtual sk_sp createTexture(SkISize, const TextureInfo&) = 0; virtual sk_sp createBuffer(size_t size, BufferType type, PrioritizeGpuReads) = 0; + virtual sk_sp createSampler(const SkSamplingOptions&, + SkTileMode xTileMode, + SkTileMode yTileMode) = 0; + class GraphicsPipelineCache { public: GraphicsPipelineCache(ResourceProvider* resourceProvider); diff --git a/experimental/graphite/src/mtl/MtlCaps.mm b/experimental/graphite/src/mtl/MtlCaps.mm index e2fa598060..ee741b4bf2 100644 --- a/experimental/graphite/src/mtl/MtlCaps.mm +++ b/experimental/graphite/src/mtl/MtlCaps.mm @@ -229,6 +229,12 @@ void Caps::initCaps(const id device) { } else { fRequiredUniformBufferAlignment = 16; } + + if (@available(macOS 10.12, ios 14.0, *)) { + fClampToBorderSupport = (this->isMac() || fFamilyGroup >= 7); + } else { + fClampToBorderSupport = false; + } } void Caps::initShaderCaps() { diff --git a/experimental/graphite/src/mtl/MtlResourceProvider.h b/experimental/graphite/src/mtl/MtlResourceProvider.h index 4f63b70187..50cb8e67b2 100644 --- a/experimental/graphite/src/mtl/MtlResourceProvider.h +++ b/experimental/graphite/src/mtl/MtlResourceProvider.h @@ -42,6 +42,10 @@ private: sk_sp createTexture(SkISize, const skgpu::TextureInfo&) override; sk_sp createBuffer(size_t size, BufferType type, PrioritizeGpuReads) override; + sk_sp createSampler(const SkSamplingOptions&, + SkTileMode xTileMode, + SkTileMode yTileMode) override; + SkTHashMap>> fDepthStencilStates; }; diff --git a/experimental/graphite/src/mtl/MtlResourceProvider.mm b/experimental/graphite/src/mtl/MtlResourceProvider.mm index cf7cdbe110..2c0c2ba462 100644 --- a/experimental/graphite/src/mtl/MtlResourceProvider.mm +++ b/experimental/graphite/src/mtl/MtlResourceProvider.mm @@ -13,6 +13,7 @@ #include "experimental/graphite/src/mtl/MtlCommandBuffer.h" #include "experimental/graphite/src/mtl/MtlGpu.h" #include "experimental/graphite/src/mtl/MtlGraphicsPipeline.h" +#include "experimental/graphite/src/mtl/MtlSampler.h" #include "experimental/graphite/src/mtl/MtlTexture.h" #import @@ -60,6 +61,12 @@ sk_sp ResourceProvider::createBuffer(size_t size, return Buffer::Make(this->mtlGpu(), size, type, prioritizeGpuReads); } +sk_sp ResourceProvider::createSampler(const SkSamplingOptions& samplingOptions, + SkTileMode xTileMode, + SkTileMode yTileMode) { + return Sampler::Make(this->mtlGpu(), samplingOptions, xTileMode, yTileMode); +} + namespace { MTLCompareFunction compare_op_to_mtl(CompareOp op) { switch (op) { diff --git a/experimental/graphite/src/mtl/MtlSampler.h b/experimental/graphite/src/mtl/MtlSampler.h index 1fcb853b9b..97f8cc22b1 100644 --- a/experimental/graphite/src/mtl/MtlSampler.h +++ b/experimental/graphite/src/mtl/MtlSampler.h @@ -11,19 +11,23 @@ #include "experimental/graphite/src/Sampler.h" #include "include/core/SkRefCnt.h" +#include "include/core/SkTileMode.h" #include "include/ports/SkCFObject.h" #import +struct SkSamplingOptions; + namespace skgpu::mtl { class Gpu; class Sampler : public skgpu::Sampler { public: - static sk_cfp> MakeMtlSamplerState(const Gpu*); - - static sk_sp Make(const Gpu*); + static sk_sp Make(const Gpu*, + const SkSamplingOptions& samplingOptions, + SkTileMode xTileMode, + SkTileMode yTileMode); ~Sampler() override {} diff --git a/experimental/graphite/src/mtl/MtlSampler.mm b/experimental/graphite/src/mtl/MtlSampler.mm index c59c1005ba..ccb19b1271 100644 --- a/experimental/graphite/src/mtl/MtlSampler.mm +++ b/experimental/graphite/src/mtl/MtlSampler.mm @@ -7,34 +7,89 @@ #include "experimental/graphite/src/mtl/MtlSampler.h" +#include "experimental/graphite/src/mtl/MtlCaps.h" #include "experimental/graphite/src/mtl/MtlGpu.h" +#include "include/core/SkSamplingOptions.h" namespace skgpu::mtl { -sk_cfp> Sampler::MakeMtlSamplerState(const Gpu* gpu) { - sk_cfp desc([[MTLSamplerDescriptor alloc] init]); - - sk_cfp> sampler([gpu->device() newSamplerStateWithDescriptor:desc.get()]); - // TODO: fill in fields -#ifdef SK_ENABLE_MTL_DEBUG_INFO - // TODO: add label -#endif - - return sampler; -} - Sampler::Sampler(const Gpu* gpu, sk_cfp> samplerState) : skgpu::Sampler(gpu) , fSamplerState(std::move(samplerState)) {} -sk_sp Sampler::Make(const Gpu* gpu) { - sk_cfp> samplerState = MakeMtlSamplerState(gpu); - if (!samplerState) { +static inline MTLSamplerAddressMode tile_mode_to_mtl_sampler_address(SkTileMode tileMode, + const Caps& caps) { + switch (tileMode) { + case SkTileMode::kClamp: + return MTLSamplerAddressModeClampToEdge; + case SkTileMode::kRepeat: + return MTLSamplerAddressModeRepeat; + case SkTileMode::kMirror: + return MTLSamplerAddressModeMirrorRepeat; + case SkTileMode::kDecal: + // For this tilemode, we should have checked that clamp-to-border support exists. + // If it doesn't we should have fallen back to a shader instead. + // TODO: for textures with alpha, we could use ClampToZero if there's no + // ClampToBorderColor as they'll clamp to (0,0,0,0). + // Unfortunately textures without alpha end up clamping to (0,0,0,1). + if (@available(macOS 10.12, iOS 14.0, *)) { + SkASSERT(caps.clampToBorderSupport()); + return MTLSamplerAddressModeClampToBorderColor; + } else { + SkASSERT(false); + return MTLSamplerAddressModeClampToZero; + } + } + SkUNREACHABLE; +} + +sk_sp Sampler::Make(const Gpu* gpu, + const SkSamplingOptions& samplingOptions, + SkTileMode xTileMode, + SkTileMode yTileMode) { + sk_cfp desc([[MTLSamplerDescriptor alloc] init]); + + MTLSamplerMinMagFilter minMagFilter = [&] { + switch (samplingOptions.filter) { + case SkFilterMode::kNearest: return MTLSamplerMinMagFilterNearest; + case SkFilterMode::kLinear: return MTLSamplerMinMagFilterLinear; + } + SkUNREACHABLE; + }(); + + MTLSamplerMipFilter mipFilter = [&] { + switch (samplingOptions.mipmap) { + case SkMipmapMode::kNone: return MTLSamplerMipFilterNotMipmapped; + case SkMipmapMode::kNearest: return MTLSamplerMipFilterNearest; + case SkMipmapMode::kLinear: return MTLSamplerMipFilterLinear; + } + SkUNREACHABLE; + }(); + + auto samplerDesc = [[MTLSamplerDescriptor alloc] init]; + samplerDesc.rAddressMode = MTLSamplerAddressModeClampToEdge; + samplerDesc.sAddressMode = tile_mode_to_mtl_sampler_address(xTileMode, gpu->mtlCaps()); + samplerDesc.tAddressMode = tile_mode_to_mtl_sampler_address(yTileMode, gpu->mtlCaps()); + samplerDesc.magFilter = minMagFilter; + samplerDesc.minFilter = minMagFilter; + samplerDesc.mipFilter = mipFilter; + samplerDesc.lodMinClamp = 0.0f; + samplerDesc.lodMaxClamp = FLT_MAX; // default value according to docs. + samplerDesc.maxAnisotropy = 1.0f; + samplerDesc.normalizedCoordinates = true; + if (@available(macOS 10.11, iOS 9.0, *)) { + samplerDesc.compareFunction = MTLCompareFunctionNever; + } +#ifdef SK_ENABLE_MTL_DEBUG_INFO + // TODO: add label? +#endif + + sk_cfp> sampler([gpu->device() newSamplerStateWithDescriptor:desc.get()]); + if (!sampler) { return nullptr; } - return sk_sp(new Sampler(gpu, - std::move(samplerState))); + return sk_sp(new Sampler(gpu, std::move(sampler))); } void Sampler::onFreeGpuData() { diff --git a/tests/graphite/CommandBufferTest.cpp b/tests/graphite/CommandBufferTest.cpp index 3b43e4a200..1df393b146 100644 --- a/tests/graphite/CommandBufferTest.cpp +++ b/tests/graphite/CommandBufferTest.cpp @@ -21,6 +21,7 @@ #include "experimental/graphite/src/GraphicsPipeline.h" #include "experimental/graphite/src/Renderer.h" #include "experimental/graphite/src/ResourceProvider.h" +#include "experimental/graphite/src/Sampler.h" #include "experimental/graphite/src/Texture.h" #include "experimental/graphite/src/TextureProxy.h" #include "experimental/graphite/src/UniformManager.h" @@ -281,6 +282,11 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) { sk_sp depthStencilTexture = gpu->resourceProvider()->findOrCreateTexture(textureSize, depthStencilInfo); + // Create Sampler -- for now, just to test creation + sk_sp sampler = gpu->resourceProvider()->findOrCreateCompatibleSampler( + SkSamplingOptions(SkFilterMode::kLinear), SkTileMode::kClamp, SkTileMode::kDecal); + REPORTER_ASSERT(reporter, sampler); + commandBuffer->beginRenderPass(renderPassDesc, target->refTexture(), nullptr, depthStencilTexture);