Cache some more Metal state.
Caches MTLSamplerStates and MTLDepthStencilStates. Bug: skia:8243 Change-Id: Id362507caedb3453b53d17f77dfbcee42ec52578 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209811 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
d425dee662
commit
75c5326bae
@ -706,6 +706,8 @@ skia_metal_sources = [
|
||||
"$_src/gpu/mtl/GrMtlCppUtil.h",
|
||||
"$_src/gpu/mtl/GrMtlCopyPipelineState.h",
|
||||
"$_src/gpu/mtl/GrMtlCopyPipelineState.mm",
|
||||
"$_src/gpu/mtl/GrMtlDepthStencil.h",
|
||||
"$_src/gpu/mtl/GrMtlDepthStencil.mm",
|
||||
"$_src/gpu/mtl/GrMtlGpu.h",
|
||||
"$_src/gpu/mtl/GrMtlGpu.mm",
|
||||
"$_src/gpu/mtl/GrMtlGpuCommandBuffer.h",
|
||||
|
63
src/gpu/mtl/GrMtlDepthStencil.h
Normal file
63
src/gpu/mtl/GrMtlDepthStencil.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrMtlDepthStencil_DEFINED
|
||||
#define GrMtlDepthStencil_DEFINED
|
||||
|
||||
#import <metal/metal.h>
|
||||
|
||||
#include "include/gpu/GrTypes.h"
|
||||
#include "src/core/SkOpts.h"
|
||||
#include <atomic>
|
||||
|
||||
class GrMtlGpu;
|
||||
class GrStencilSettings;
|
||||
|
||||
// A wrapper for a MTLDepthStencilState object with caching support.
|
||||
class GrMtlDepthStencil {
|
||||
public:
|
||||
static GrMtlDepthStencil* Create(const GrMtlGpu*, const GrStencilSettings&, GrSurfaceOrigin);
|
||||
|
||||
id<MTLDepthStencilState> mtlDepthStencil() const { return fMtlDepthStencilState; }
|
||||
|
||||
struct Key {
|
||||
struct Face {
|
||||
uint32_t fReadMask;
|
||||
uint32_t fWriteMask;
|
||||
uint32_t fOps;
|
||||
};
|
||||
Face fFront;
|
||||
Face fBack;
|
||||
|
||||
bool operator==(const Key& that) const {
|
||||
return this->fFront.fReadMask == that.fFront.fReadMask &&
|
||||
this->fFront.fWriteMask == that.fFront.fWriteMask &&
|
||||
this->fFront.fOps == that.fFront.fOps &&
|
||||
this->fBack.fReadMask == that.fBack.fReadMask &&
|
||||
this->fBack.fWriteMask == that.fBack.fWriteMask &&
|
||||
this->fBack.fOps == that.fBack.fOps;
|
||||
}
|
||||
};
|
||||
|
||||
// Helpers for hashing GrMtlSampler
|
||||
static Key GenerateKey(const GrStencilSettings&, GrSurfaceOrigin);
|
||||
|
||||
static const Key& GetKey(const GrMtlDepthStencil& depthStencil) { return depthStencil.fKey; }
|
||||
static uint32_t Hash(const Key& key) {
|
||||
return SkOpts::hash(reinterpret_cast<const uint32_t*>(&key), sizeof(Key));
|
||||
}
|
||||
|
||||
private:
|
||||
GrMtlDepthStencil(id<MTLDepthStencilState> mtlDepthStencilState, Key key)
|
||||
: fMtlDepthStencilState(mtlDepthStencilState)
|
||||
, fKey(key) {}
|
||||
|
||||
id<MTLDepthStencilState> fMtlDepthStencilState;
|
||||
Key fKey;
|
||||
};
|
||||
|
||||
#endif
|
122
src/gpu/mtl/GrMtlDepthStencil.mm
Normal file
122
src/gpu/mtl/GrMtlDepthStencil.mm
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/gpu/GrStencilSettings.h"
|
||||
#include "src/gpu/mtl/GrMtlDepthStencil.h"
|
||||
#include "src/gpu/mtl/GrMtlGpu.h"
|
||||
|
||||
MTLStencilOperation skia_stencil_op_to_mtl(GrStencilOp op) {
|
||||
switch (op) {
|
||||
case GrStencilOp::kKeep:
|
||||
return MTLStencilOperationKeep;
|
||||
case GrStencilOp::kZero:
|
||||
return MTLStencilOperationZero;
|
||||
case GrStencilOp::kReplace:
|
||||
return MTLStencilOperationReplace;
|
||||
case GrStencilOp::kInvert:
|
||||
return MTLStencilOperationInvert;
|
||||
case GrStencilOp::kIncWrap:
|
||||
return MTLStencilOperationIncrementWrap;
|
||||
case GrStencilOp::kDecWrap:
|
||||
return MTLStencilOperationDecrementWrap;
|
||||
case GrStencilOp::kIncClamp:
|
||||
return MTLStencilOperationIncrementClamp;
|
||||
case GrStencilOp::kDecClamp:
|
||||
return MTLStencilOperationDecrementClamp;
|
||||
}
|
||||
}
|
||||
|
||||
MTLStencilDescriptor* skia_stencil_to_mtl(GrStencilSettings::Face face) {
|
||||
MTLStencilDescriptor* result = [[MTLStencilDescriptor alloc] init];
|
||||
switch (face.fTest) {
|
||||
case GrStencilTest::kAlways:
|
||||
result.stencilCompareFunction = MTLCompareFunctionAlways;
|
||||
break;
|
||||
case GrStencilTest::kNever:
|
||||
result.stencilCompareFunction = MTLCompareFunctionNever;
|
||||
break;
|
||||
case GrStencilTest::kGreater:
|
||||
result.stencilCompareFunction = MTLCompareFunctionGreater;
|
||||
break;
|
||||
case GrStencilTest::kGEqual:
|
||||
result.stencilCompareFunction = MTLCompareFunctionGreaterEqual;
|
||||
break;
|
||||
case GrStencilTest::kLess:
|
||||
result.stencilCompareFunction = MTLCompareFunctionLess;
|
||||
break;
|
||||
case GrStencilTest::kLEqual:
|
||||
result.stencilCompareFunction = MTLCompareFunctionLessEqual;
|
||||
break;
|
||||
case GrStencilTest::kEqual:
|
||||
result.stencilCompareFunction = MTLCompareFunctionEqual;
|
||||
break;
|
||||
case GrStencilTest::kNotEqual:
|
||||
result.stencilCompareFunction = MTLCompareFunctionNotEqual;
|
||||
break;
|
||||
}
|
||||
result.readMask = face.fTestMask;
|
||||
result.writeMask = face.fWriteMask;
|
||||
result.depthStencilPassOperation = skia_stencil_op_to_mtl(face.fPassOp);
|
||||
result.stencilFailureOperation = skia_stencil_op_to_mtl(face.fFailOp);
|
||||
return result;
|
||||
}
|
||||
|
||||
GrMtlDepthStencil* GrMtlDepthStencil::Create(const GrMtlGpu* gpu,
|
||||
const GrStencilSettings& stencil,
|
||||
GrSurfaceOrigin origin) {
|
||||
MTLDepthStencilDescriptor* desc = [[MTLDepthStencilDescriptor alloc] init];
|
||||
if (!stencil.isDisabled()) {
|
||||
if (stencil.isTwoSided()) {
|
||||
desc.frontFaceStencil = skia_stencil_to_mtl(stencil.front(origin));
|
||||
desc.backFaceStencil = skia_stencil_to_mtl(stencil.back(origin));
|
||||
}
|
||||
else {
|
||||
desc.frontFaceStencil = skia_stencil_to_mtl(stencil.frontAndBack());
|
||||
desc.backFaceStencil = desc.frontFaceStencil;
|
||||
}
|
||||
}
|
||||
|
||||
return new GrMtlDepthStencil([gpu->device() newDepthStencilStateWithDescriptor: desc],
|
||||
GenerateKey(stencil, origin));
|
||||
}
|
||||
|
||||
void skia_stencil_to_key(GrStencilSettings::Face face, GrMtlDepthStencil::Key::Face* faceKey) {
|
||||
const int kPassOpShift = 3;
|
||||
const int kFailOpShift = 6;
|
||||
|
||||
faceKey->fReadMask = face.fTestMask;
|
||||
faceKey->fWriteMask = face.fWriteMask;
|
||||
|
||||
SkASSERT(static_cast<int>(face.fTest) <= 7);
|
||||
faceKey->fOps = static_cast<uint32_t>(face.fTest);
|
||||
|
||||
SkASSERT(static_cast<int>(face.fPassOp) <= 7);
|
||||
faceKey->fOps |= (static_cast<uint32_t>(face.fPassOp) << kPassOpShift);
|
||||
|
||||
SkASSERT(static_cast<int>(face.fFailOp) <= 7);
|
||||
faceKey->fOps |= (static_cast<uint32_t>(face.fFailOp) << kFailOpShift);
|
||||
}
|
||||
|
||||
GrMtlDepthStencil::Key GrMtlDepthStencil::GenerateKey(const GrStencilSettings& stencil,
|
||||
GrSurfaceOrigin origin) {
|
||||
Key depthStencilKey;
|
||||
|
||||
if (stencil.isDisabled()) {
|
||||
memset(&depthStencilKey, 0, sizeof(Key));
|
||||
} else {
|
||||
if (stencil.isTwoSided()) {
|
||||
skia_stencil_to_key(stencil.front(origin), &depthStencilKey.fFront);
|
||||
skia_stencil_to_key(stencil.back(origin), &depthStencilKey.fBack);
|
||||
}
|
||||
else {
|
||||
skia_stencil_to_key(stencil.frontAndBack(), &depthStencilKey.fFront);
|
||||
memcpy(&depthStencilKey.fBack, &depthStencilKey.fFront, sizeof(Key::Face));
|
||||
}
|
||||
}
|
||||
|
||||
return depthStencilKey;
|
||||
}
|
@ -227,7 +227,8 @@ private:
|
||||
GrMtlCommandBuffer* fCmdBuffer;
|
||||
|
||||
std::unique_ptr<SkSL::Compiler> fCompiler;
|
||||
GrMtlCopyManager fCopyManager;
|
||||
|
||||
GrMtlCopyManager fCopyManager;
|
||||
GrMtlResourceProvider fResourceProvider;
|
||||
GrMtlBufferManager fBufferManager;
|
||||
|
||||
|
@ -106,7 +106,7 @@ private:
|
||||
void setDepthStencilState(id<MTLRenderCommandEncoder> renderCmdEncoder);
|
||||
|
||||
struct SamplerBindings {
|
||||
id<MTLSamplerState> fSampler;
|
||||
GrMtlSampler* fSampler;
|
||||
id<MTLTexture> fTexture;
|
||||
|
||||
SamplerBindings(const GrSamplerState& state, GrTexture* texture, GrMtlGpu*);
|
||||
|
@ -18,17 +18,14 @@
|
||||
#include "src/gpu/glsl/GrGLSLXferProcessor.h"
|
||||
#include "src/gpu/mtl/GrMtlBuffer.h"
|
||||
#include "src/gpu/mtl/GrMtlGpu.h"
|
||||
#include "src/gpu/mtl/GrMtlSampler.h"
|
||||
#include "src/gpu/mtl/GrMtlTexture.h"
|
||||
|
||||
GrMtlPipelineState::SamplerBindings::SamplerBindings(const GrSamplerState& state,
|
||||
GrTexture* texture,
|
||||
GrMtlGpu* gpu)
|
||||
: fTexture(static_cast<GrMtlTexture*>(texture)->mtlTexture()) {
|
||||
// TODO: use resource provider to get sampler.
|
||||
std::unique_ptr<GrMtlSampler> sampler(
|
||||
GrMtlSampler::Create(gpu, state, texture->texturePriv().maxMipMapLevel()));
|
||||
fSampler = sampler->mtlSamplerState();
|
||||
uint32_t maxMipMapLevel = texture->texturePriv().maxMipMapLevel();
|
||||
fSampler = gpu->resourceProvider().findOrCreateCompatibleSampler(state, maxMipMapLevel);
|
||||
}
|
||||
|
||||
GrMtlPipelineState::GrMtlPipelineState(
|
||||
@ -126,7 +123,7 @@ void GrMtlPipelineState::bind(id<MTLRenderCommandEncoder> renderCmdEncoder) {
|
||||
for (int index = 0; index < fNumSamplers; ++index) {
|
||||
[renderCmdEncoder setFragmentTexture: fSamplerBindings[index].fTexture
|
||||
atIndex: index];
|
||||
[renderCmdEncoder setFragmentSamplerState: fSamplerBindings[index].fSampler
|
||||
[renderCmdEncoder setFragmentSamplerState: fSamplerBindings[index].fSampler->mtlSampler()
|
||||
atIndex: index];
|
||||
}
|
||||
}
|
||||
@ -188,85 +185,20 @@ void GrMtlPipelineState::setBlendConstants(id<MTLRenderCommandEncoder> renderCmd
|
||||
}
|
||||
}
|
||||
|
||||
MTLStencilOperation skia_stencil_op_to_mtl(GrStencilOp op) {
|
||||
switch (op) {
|
||||
case GrStencilOp::kKeep:
|
||||
return MTLStencilOperationKeep;
|
||||
case GrStencilOp::kZero:
|
||||
return MTLStencilOperationZero;
|
||||
case GrStencilOp::kReplace:
|
||||
return MTLStencilOperationReplace;
|
||||
case GrStencilOp::kInvert:
|
||||
return MTLStencilOperationInvert;
|
||||
case GrStencilOp::kIncWrap:
|
||||
return MTLStencilOperationIncrementWrap;
|
||||
case GrStencilOp::kDecWrap:
|
||||
return MTLStencilOperationDecrementWrap;
|
||||
case GrStencilOp::kIncClamp:
|
||||
return MTLStencilOperationIncrementClamp;
|
||||
case GrStencilOp::kDecClamp:
|
||||
return MTLStencilOperationDecrementClamp;
|
||||
}
|
||||
}
|
||||
|
||||
MTLStencilDescriptor* skia_stencil_to_mtl(GrStencilSettings::Face face) {
|
||||
MTLStencilDescriptor* result = [[MTLStencilDescriptor alloc] init];
|
||||
switch (face.fTest) {
|
||||
case GrStencilTest::kAlways:
|
||||
result.stencilCompareFunction = MTLCompareFunctionAlways;
|
||||
break;
|
||||
case GrStencilTest::kNever:
|
||||
result.stencilCompareFunction = MTLCompareFunctionNever;
|
||||
break;
|
||||
case GrStencilTest::kGreater:
|
||||
result.stencilCompareFunction = MTLCompareFunctionGreater;
|
||||
break;
|
||||
case GrStencilTest::kGEqual:
|
||||
result.stencilCompareFunction = MTLCompareFunctionGreaterEqual;
|
||||
break;
|
||||
case GrStencilTest::kLess:
|
||||
result.stencilCompareFunction = MTLCompareFunctionLess;
|
||||
break;
|
||||
case GrStencilTest::kLEqual:
|
||||
result.stencilCompareFunction = MTLCompareFunctionLessEqual;
|
||||
break;
|
||||
case GrStencilTest::kEqual:
|
||||
result.stencilCompareFunction = MTLCompareFunctionEqual;
|
||||
break;
|
||||
case GrStencilTest::kNotEqual:
|
||||
result.stencilCompareFunction = MTLCompareFunctionNotEqual;
|
||||
break;
|
||||
}
|
||||
result.readMask = face.fTestMask;
|
||||
result.writeMask = face.fWriteMask;
|
||||
result.depthStencilPassOperation = skia_stencil_op_to_mtl(face.fPassOp);
|
||||
result.stencilFailureOperation = skia_stencil_op_to_mtl(face.fFailOp);
|
||||
return result;
|
||||
}
|
||||
|
||||
void GrMtlPipelineState::setDepthStencilState(id<MTLRenderCommandEncoder> renderCmdEncoder) {
|
||||
if (fStencil.isDisabled()) {
|
||||
MTLDepthStencilDescriptor* desc = [[MTLDepthStencilDescriptor alloc] init];
|
||||
id<MTLDepthStencilState> state = [fGpu->device() newDepthStencilStateWithDescriptor:desc];
|
||||
[renderCmdEncoder setDepthStencilState:state];
|
||||
}
|
||||
else {
|
||||
MTLDepthStencilDescriptor* desc = [[MTLDepthStencilDescriptor alloc] init];
|
||||
GrSurfaceOrigin origin = fRenderTargetState.fRenderTargetOrigin;
|
||||
const GrSurfaceOrigin& origin = fRenderTargetState.fRenderTargetOrigin;
|
||||
GrMtlDepthStencil* state =
|
||||
fGpu->resourceProvider().findOrCreateCompatibleDepthStencilState(fStencil, origin);
|
||||
if (!fStencil.isDisabled()) {
|
||||
if (fStencil.isTwoSided()) {
|
||||
desc.frontFaceStencil = skia_stencil_to_mtl(fStencil.front(origin));
|
||||
desc.backFaceStencil = skia_stencil_to_mtl(fStencil.back(origin));
|
||||
[renderCmdEncoder setStencilFrontReferenceValue:fStencil.front(origin).fRef
|
||||
backReferenceValue:fStencil.back(origin).fRef];
|
||||
}
|
||||
else {
|
||||
desc.frontFaceStencil = skia_stencil_to_mtl(fStencil.frontAndBack());
|
||||
desc.backFaceStencil = desc.frontFaceStencil;
|
||||
[renderCmdEncoder setStencilReferenceValue:fStencil.frontAndBack().fRef];
|
||||
}
|
||||
id<MTLDepthStencilState> state = [fGpu->device() newDepthStencilStateWithDescriptor:desc];
|
||||
[renderCmdEncoder setDepthStencilState:state];
|
||||
}
|
||||
[renderCmdEncoder setDepthStencilState:state->mtlDepthStencil()];
|
||||
}
|
||||
|
||||
void GrMtlPipelineState::SetDynamicScissorRectState(id<MTLRenderCommandEncoder> renderCmdEncoder,
|
||||
|
@ -11,7 +11,9 @@
|
||||
#include "include/private/SkTArray.h"
|
||||
#include "src/core/SkLRUCache.h"
|
||||
#include "src/gpu/mtl/GrMtlCopyPipelineState.h"
|
||||
#include "src/gpu/mtl/GrMtlDepthStencil.h"
|
||||
#include "src/gpu/mtl/GrMtlPipelineStateBuilder.h"
|
||||
#include "src/gpu/mtl/GrMtlSampler.h"
|
||||
|
||||
#import <metal/metal.h>
|
||||
|
||||
@ -33,6 +35,13 @@ public:
|
||||
const GrTextureProxy* const primProcProxies[],
|
||||
GrPrimitiveType);
|
||||
|
||||
// Finds or creates a compatible MTLDepthStencilState based on the GrStencilSettings.
|
||||
GrMtlDepthStencil* findOrCreateCompatibleDepthStencilState(const GrStencilSettings&,
|
||||
GrSurfaceOrigin);
|
||||
|
||||
// Finds or creates a compatible MTLSamplerState based on the GrSamplerState.
|
||||
GrMtlSampler* findOrCreateCompatibleSampler(const GrSamplerState&, uint32_t maxMipLevel);
|
||||
|
||||
private:
|
||||
#ifdef SK_DEBUG
|
||||
#define GR_PIPELINE_STATE_CACHE_STATS
|
||||
@ -80,6 +89,9 @@ private:
|
||||
|
||||
// Cache of GrMtlPipelineStates
|
||||
std::unique_ptr<PipelineStateCache> fPipelineStateCache;
|
||||
|
||||
SkTDynamicHash<GrMtlSampler, GrMtlSampler::Key> fSamplers;
|
||||
SkTDynamicHash<GrMtlDepthStencil, GrMtlDepthStencil::Key> fDepthStencilStates;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include "src/sksl/SkSLCompiler.h"
|
||||
|
||||
|
||||
GrMtlResourceProvider::GrMtlResourceProvider(GrMtlGpu* gpu)
|
||||
: fGpu(gpu) {
|
||||
fPipelineStateCache.reset(new PipelineStateCache(gpu));
|
||||
@ -47,6 +46,33 @@ GrMtlPipelineState* GrMtlResourceProvider::findOrCreateCompatiblePipelineState(
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrMtlDepthStencil* GrMtlResourceProvider::findOrCreateCompatibleDepthStencilState(
|
||||
const GrStencilSettings& stencil, GrSurfaceOrigin origin) {
|
||||
GrMtlDepthStencil* depthStencilState;
|
||||
GrMtlDepthStencil::Key key = GrMtlDepthStencil::GenerateKey(stencil, origin);
|
||||
depthStencilState = fDepthStencilStates.find(key);
|
||||
if (!depthStencilState) {
|
||||
depthStencilState = GrMtlDepthStencil::Create(fGpu, stencil, origin);
|
||||
fDepthStencilStates.add(depthStencilState);
|
||||
}
|
||||
SkASSERT(depthStencilState);
|
||||
return depthStencilState;
|
||||
}
|
||||
|
||||
GrMtlSampler* GrMtlResourceProvider::findOrCreateCompatibleSampler(const GrSamplerState& params,
|
||||
uint32_t maxMipLevel) {
|
||||
GrMtlSampler* sampler;
|
||||
sampler = fSamplers.find(GrMtlSampler::GenerateKey(params, maxMipLevel));
|
||||
if (!sampler) {
|
||||
sampler = GrMtlSampler::Create(fGpu, params, maxMipLevel);
|
||||
fSamplers.add(sampler);
|
||||
}
|
||||
SkASSERT(sampler);
|
||||
return sampler;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef GR_PIPELINE_STATE_CACHE_STATS
|
||||
// Display pipeline state cache usage
|
||||
static const bool c_DisplayMtlPipelineCache{false};
|
||||
|
@ -10,21 +10,36 @@
|
||||
|
||||
#import <metal/metal.h>
|
||||
|
||||
#include "src/core/SkOpts.h"
|
||||
#include <atomic>
|
||||
|
||||
class GrSamplerState;
|
||||
class GrMtlGpu;
|
||||
|
||||
// This class only acts as a wrapper for a MTLSamplerState object for now, but will be more useful
|
||||
// once we start caching sampler states.
|
||||
// A wrapper for a MTLSamplerState object with caching support.
|
||||
class GrMtlSampler {
|
||||
public:
|
||||
static GrMtlSampler* Create(const GrMtlGpu* gpu, const GrSamplerState&, uint32_t maxMipLevel);
|
||||
|
||||
id<MTLSamplerState> mtlSamplerState() const { return fMtlSamplerState; }
|
||||
id<MTLSamplerState> mtlSampler() const { return fMtlSamplerState; }
|
||||
|
||||
typedef uint32_t Key;
|
||||
|
||||
// Helpers for hashing GrMtlSampler
|
||||
static Key GenerateKey(const GrSamplerState&, uint32_t maxMipLevel);
|
||||
|
||||
static const Key& GetKey(const GrMtlSampler& sampler) { return sampler.fKey; }
|
||||
static uint32_t Hash(const Key& key) {
|
||||
return SkOpts::hash(reinterpret_cast<const uint32_t*>(&key), sizeof(Key));
|
||||
}
|
||||
|
||||
private:
|
||||
GrMtlSampler(id<MTLSamplerState> mtlSamplerState) : fMtlSamplerState(mtlSamplerState) {}
|
||||
GrMtlSampler(id<MTLSamplerState> mtlSamplerState, Key key)
|
||||
: fMtlSamplerState(mtlSamplerState)
|
||||
, fKey(key) {}
|
||||
|
||||
id<MTLSamplerState> fMtlSamplerState;
|
||||
Key fKey;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -61,5 +61,27 @@ GrMtlSampler* GrMtlSampler::Create(const GrMtlGpu* gpu, const GrSamplerState& sa
|
||||
samplerDesc.normalizedCoordinates = true;
|
||||
samplerDesc.compareFunction = MTLCompareFunctionNever;
|
||||
|
||||
return new GrMtlSampler([gpu->device() newSamplerStateWithDescriptor: samplerDesc]);
|
||||
return new GrMtlSampler([gpu->device() newSamplerStateWithDescriptor: samplerDesc],
|
||||
GenerateKey(samplerState, maxMipLevel));
|
||||
}
|
||||
|
||||
GrMtlSampler::Key GrMtlSampler::GenerateKey(const GrSamplerState& samplerState,
|
||||
uint32_t maxMipLevel) {
|
||||
const int kTileModeXShift = 2;
|
||||
const int kTileModeYShift = 4;
|
||||
const int kMipLevelShift = 6;
|
||||
|
||||
SkASSERT(static_cast<int>(samplerState.filter()) <= 3);
|
||||
Key samplerKey = static_cast<uint16_t>(samplerState.filter());
|
||||
|
||||
SkASSERT(static_cast<int>(samplerState.wrapModeX()) <= 3);
|
||||
samplerKey |= (static_cast<uint16_t>(samplerState.wrapModeX()) << kTileModeXShift);
|
||||
|
||||
SkASSERT(static_cast<int>(samplerState.wrapModeY()) <= 3);
|
||||
samplerKey |= (static_cast<uint16_t>(samplerState.wrapModeY()) << kTileModeYShift);
|
||||
|
||||
bool useMipMaps = GrSamplerState::Filter::kMipMap == samplerState.filter() && maxMipLevel > 0;
|
||||
samplerKey |= (!useMipMaps ? 0 : (uint16_t) maxMipLevel) << kMipLevelShift;
|
||||
|
||||
return samplerKey;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user