Home | History | Annotate | Download | only in mtl
      1 /*
      2  * Copyright 2018 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrMtlResourceProvider.h"
      9 
     10 #include "GrMtlCopyManager.h"
     11 #include "GrMtlGpu.h"
     12 #include "GrMtlPipelineState.h"
     13 #include "GrMtlUtil.h"
     14 
     15 #include "SkSLCompiler.h"
     16 
     17 
     18 GrMtlResourceProvider::GrMtlResourceProvider(GrMtlGpu* gpu)
     19     : fGpu(gpu) {
     20     fPipelineStateCache.reset(new PipelineStateCache(gpu));
     21 }
     22 
     23 GrMtlCopyPipelineState* GrMtlResourceProvider::findOrCreateCopyPipelineState(
     24         MTLPixelFormat dstPixelFormat,
     25         id<MTLFunction> vertexFunction,
     26         id<MTLFunction> fragmentFunction,
     27         MTLVertexDescriptor* vertexDescriptor) {
     28 
     29     for (const auto& copyPipelineState: fCopyPipelineStateCache) {
     30         if (GrMtlCopyManager::IsCompatible(copyPipelineState.get(), dstPixelFormat)) {
     31             return copyPipelineState.get();
     32         }
     33     }
     34 
     35     fCopyPipelineStateCache.emplace_back(GrMtlCopyPipelineState::CreateCopyPipelineState(
     36              fGpu, dstPixelFormat, vertexFunction, fragmentFunction, vertexDescriptor));
     37     return fCopyPipelineStateCache.back().get();
     38 }
     39 
     40 GrMtlPipelineState* GrMtlResourceProvider::findOrCreateCompatiblePipelineState(
     41         GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
     42         const GrPipeline& pipeline, const GrPrimitiveProcessor& proc,
     43         const GrTextureProxy* const primProcProxies[], GrPrimitiveType primType) {
     44     return fPipelineStateCache->refPipelineState(renderTarget, origin, proc, primProcProxies,
     45                                                  pipeline, primType);
     46 }
     47 
     48 ////////////////////////////////////////////////////////////////////////////////////////////////
     49 
     50 #ifdef GR_PIPELINE_STATE_CACHE_STATS
     51 // Display pipeline state cache usage
     52 static const bool c_DisplayMtlPipelineCache{false};
     53 #endif
     54 
     55 struct GrMtlResourceProvider::PipelineStateCache::Entry {
     56     Entry(GrMtlGpu* gpu, GrMtlPipelineState* pipelineState)
     57     : fGpu(gpu)
     58     , fPipelineState(pipelineState) {}
     59 
     60     GrMtlGpu* fGpu;
     61     std::unique_ptr<GrMtlPipelineState> fPipelineState;
     62 };
     63 
     64 GrMtlResourceProvider::PipelineStateCache::PipelineStateCache(GrMtlGpu* gpu)
     65     : fMap(kMaxEntries)
     66     , fGpu(gpu)
     67 #ifdef GR_PIPELINE_STATE_CACHE_STATS
     68     , fTotalRequests(0)
     69     , fCacheMisses(0)
     70 #endif
     71 {}
     72 
     73 GrMtlResourceProvider::PipelineStateCache::~PipelineStateCache() {
     74     // TODO: determine if we need abandon/release methods
     75     fMap.reset();
     76     // dump stats
     77 #ifdef GR_PIPELINE_STATE_CACHE_STATS
     78     if (c_DisplayMtlPipelineCache) {
     79         SkDebugf("--- Pipeline State Cache ---\n");
     80         SkDebugf("Total requests: %d\n", fTotalRequests);
     81         SkDebugf("Cache misses: %d\n", fCacheMisses);
     82         SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
     83                  100.f * fCacheMisses / fTotalRequests :
     84                  0.f);
     85         SkDebugf("---------------------\n");
     86     }
     87 #endif
     88 }
     89 
     90 GrMtlPipelineState* GrMtlResourceProvider::PipelineStateCache::refPipelineState(
     91         GrRenderTarget* renderTarget,
     92         GrSurfaceOrigin origin,
     93         const GrPrimitiveProcessor& primProc,
     94         const GrTextureProxy* const primProcProxies[],
     95         const GrPipeline& pipeline,
     96         GrPrimitiveType primType) {
     97 #ifdef GR_PIPELINE_STATE_CACHE_STATS
     98     ++fTotalRequests;
     99 #endif
    100     // Get GrMtlProgramDesc
    101     GrMtlPipelineStateBuilder::Desc desc;
    102     if (!GrMtlPipelineStateBuilder::Desc::Build(&desc, renderTarget, primProc, pipeline, primType,
    103                                                 fGpu)) {
    104         GrCapsDebugf(fGpu->caps(), "Failed to build mtl program descriptor!\n");
    105         return nullptr;
    106     }
    107 
    108     std::unique_ptr<Entry>* entry = fMap.find(desc);
    109     if (!entry) {
    110         // Didn't find an origin-independent version, check with the specific origin
    111         desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
    112         entry = fMap.find(desc);
    113     }
    114     if (!entry) {
    115 #ifdef GR_PIPELINE_STATE_CACHE_STATS
    116         ++fCacheMisses;
    117 #endif
    118         GrMtlPipelineState* pipelineState(GrMtlPipelineStateBuilder::CreatePipelineState(
    119                 fGpu, renderTarget, origin, primProc, primProcProxies, pipeline, &desc));
    120         if (nullptr == pipelineState) {
    121             return nullptr;
    122         }
    123         entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(fGpu, pipelineState)));
    124         return (*entry)->fPipelineState.get();
    125     }
    126     return (*entry)->fPipelineState.get();
    127 }
    128