[graphite] Add sampler creation

Bug: skia:12845
Change-Id: Iba4fcfe98adf6f0445958322d674ab3dfee87305
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/497280
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2022-01-24 15:55:31 -05:00 committed by SkCQ
parent a8ed76ac96
commit 84fecee879
9 changed files with 125 additions and 20 deletions

View File

@ -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<SkSL::ShaderCaps> fShaderCaps;
bool fClampToBorderSupport = true;
private:
virtual bool onIsTexturable(const TextureInfo&) const = 0;
virtual bool onAreColorTypeAndTextureInfoCompatible(SkColorType, const TextureInfo&) const = 0;

View File

@ -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<Texture> ResourceProvider::findOrCreateTexture(SkISize dimensions, const T
return this->createTexture(dimensions, info);
}
sk_sp<Sampler> ResourceProvider::findOrCreateCompatibleSampler(const SkSamplingOptions& smplOptions,
SkTileMode xTileMode,
SkTileMode yTileMode) {
return this->createSampler(smplOptions, xTileMode, yTileMode);
}
sk_sp<Buffer> ResourceProvider::findOrCreateBuffer(size_t size,
BufferType type,
PrioritizeGpuReads prioritizeGpuReads) {

View File

@ -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<Buffer> findOrCreateBuffer(size_t size, BufferType type, PrioritizeGpuReads);
sk_sp<Sampler> findOrCreateCompatibleSampler(const SkSamplingOptions&,
SkTileMode xTileMode,
SkTileMode yTileMode);
protected:
ResourceProvider(const Gpu* gpu);
@ -50,6 +58,10 @@ private:
virtual sk_sp<Texture> createTexture(SkISize, const TextureInfo&) = 0;
virtual sk_sp<Buffer> createBuffer(size_t size, BufferType type, PrioritizeGpuReads) = 0;
virtual sk_sp<Sampler> createSampler(const SkSamplingOptions&,
SkTileMode xTileMode,
SkTileMode yTileMode) = 0;
class GraphicsPipelineCache {
public:
GraphicsPipelineCache(ResourceProvider* resourceProvider);

View File

@ -229,6 +229,12 @@ void Caps::initCaps(const id<MTLDevice> device) {
} else {
fRequiredUniformBufferAlignment = 16;
}
if (@available(macOS 10.12, ios 14.0, *)) {
fClampToBorderSupport = (this->isMac() || fFamilyGroup >= 7);
} else {
fClampToBorderSupport = false;
}
}
void Caps::initShaderCaps() {

View File

@ -42,6 +42,10 @@ private:
sk_sp<skgpu::Texture> createTexture(SkISize, const skgpu::TextureInfo&) override;
sk_sp<skgpu::Buffer> createBuffer(size_t size, BufferType type, PrioritizeGpuReads) override;
sk_sp<skgpu::Sampler> createSampler(const SkSamplingOptions&,
SkTileMode xTileMode,
SkTileMode yTileMode) override;
SkTHashMap<DepthStencilSettings, sk_cfp<id<MTLDepthStencilState>>> fDepthStencilStates;
};

View File

@ -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 <Metal/Metal.h>
@ -60,6 +61,12 @@ sk_sp<skgpu::Buffer> ResourceProvider::createBuffer(size_t size,
return Buffer::Make(this->mtlGpu(), size, type, prioritizeGpuReads);
}
sk_sp<skgpu::Sampler> 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) {

View File

@ -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 <Metal/Metal.h>
struct SkSamplingOptions;
namespace skgpu::mtl {
class Gpu;
class Sampler : public skgpu::Sampler {
public:
static sk_cfp<id<MTLSamplerState>> MakeMtlSamplerState(const Gpu*);
static sk_sp<Sampler> Make(const Gpu*);
static sk_sp<Sampler> Make(const Gpu*,
const SkSamplingOptions& samplingOptions,
SkTileMode xTileMode,
SkTileMode yTileMode);
~Sampler() override {}

View File

@ -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<id<MTLSamplerState>> Sampler::MakeMtlSamplerState(const Gpu* gpu) {
sk_cfp<MTLSamplerDescriptor*> desc([[MTLSamplerDescriptor alloc] init]);
sk_cfp<id<MTLSamplerState>> 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<id<MTLSamplerState>> samplerState)
: skgpu::Sampler(gpu)
, fSamplerState(std::move(samplerState)) {}
sk_sp<Sampler> Sampler::Make(const Gpu* gpu) {
sk_cfp<id<MTLSamplerState>> 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> Sampler::Make(const Gpu* gpu,
const SkSamplingOptions& samplingOptions,
SkTileMode xTileMode,
SkTileMode yTileMode) {
sk_cfp<MTLSamplerDescriptor*> 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<id<MTLSamplerState>> sampler([gpu->device() newSamplerStateWithDescriptor:desc.get()]);
if (!sampler) {
return nullptr;
}
return sk_sp<Sampler>(new Sampler(gpu,
std::move(samplerState)));
return sk_sp<Sampler>(new Sampler(gpu, std::move(sampler)));
}
void Sampler::onFreeGpuData() {

View File

@ -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<Texture> depthStencilTexture =
gpu->resourceProvider()->findOrCreateTexture(textureSize, depthStencilInfo);
// Create Sampler -- for now, just to test creation
sk_sp<Sampler> sampler = gpu->resourceProvider()->findOrCreateCompatibleSampler(
SkSamplingOptions(SkFilterMode::kLinear), SkTileMode::kClamp, SkTileMode::kDecal);
REPORTER_ASSERT(reporter, sampler);
commandBuffer->beginRenderPass(renderPassDesc, target->refTexture(), nullptr,
depthStencilTexture);