1/* 2 * Copyright 2011 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 <memory> 9 10#include "src/gpu/gl/GrGLGpu.h" 11 12#include "include/gpu/GrContextOptions.h" 13#include "include/gpu/GrDirectContext.h" 14#include "src/gpu/GrDirectContextPriv.h" 15#include "src/gpu/GrFragmentProcessor.h" 16#include "src/gpu/GrProcessor.h" 17#include "src/gpu/GrProgramDesc.h" 18#include "src/gpu/gl/builders/GrGLProgramBuilder.h" 19 20struct GrGLGpu::ProgramCache::Entry { 21 Entry(sk_sp<GrGLProgram> program) 22 : fProgram(std::move(program)) {} 23 24 Entry(const GrGLPrecompiledProgram& precompiledProgram) 25 : fPrecompiledProgram(precompiledProgram) {} 26 27 sk_sp<GrGLProgram> fProgram; 28 GrGLPrecompiledProgram fPrecompiledProgram; 29}; 30 31GrGLGpu::ProgramCache::ProgramCache(int runtimeProgramCacheSize) 32 : fMap(runtimeProgramCacheSize) { 33} 34 35GrGLGpu::ProgramCache::~ProgramCache() {} 36 37void GrGLGpu::ProgramCache::abandon() { 38 fMap.foreach([](GrProgramDesc*, std::unique_ptr<Entry>* e) { 39 if ((*e)->fProgram) { 40 (*e)->fProgram->abandon(); 41 } 42 }); 43 44 this->reset(); 45} 46 47void GrGLGpu::ProgramCache::reset() { 48 fMap.reset(); 49} 50 51sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrDirectContext* dContext, 52 const GrProgramInfo& programInfo) { 53 const GrCaps* caps = dContext->priv().caps(); 54 55 GrProgramDesc desc = caps->makeDesc(/*renderTarget*/nullptr, programInfo); 56 if (!desc.isValid()) { 57 GrCapsDebugf(caps, "Failed to gl program descriptor!\n"); 58 return nullptr; 59 } 60 61 Stats::ProgramCacheResult stat; 62 sk_sp<GrGLProgram> tmp = this->findOrCreateProgramImpl(dContext, desc, programInfo, &stat); 63 if (!tmp) { 64 fStats.incNumInlineCompilationFailures(); 65 } else { 66 fStats.incNumInlineProgramCacheResult(stat); 67 } 68 69 return tmp; 70} 71 72sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgram(GrDirectContext* dContext, 73 const GrProgramDesc& desc, 74 const GrProgramInfo& programInfo, 75 Stats::ProgramCacheResult* stat) { 76 sk_sp<GrGLProgram> tmp = this->findOrCreateProgramImpl(dContext, desc, programInfo, stat); 77 if (!tmp) { 78 fStats.incNumPreCompilationFailures(); 79 } else { 80 fStats.incNumPreProgramCacheResult(*stat); 81 } 82 83 return tmp; 84} 85 86sk_sp<GrGLProgram> GrGLGpu::ProgramCache::findOrCreateProgramImpl(GrDirectContext* dContext, 87 const GrProgramDesc& desc, 88 const GrProgramInfo& programInfo, 89 Stats::ProgramCacheResult* stat) { 90 *stat = Stats::ProgramCacheResult::kHit; 91 std::unique_ptr<Entry>* entry = fMap.find(desc); 92 if (entry && !(*entry)->fProgram) { 93 // We've pre-compiled the GL program, but don't have the GrGLProgram scaffolding 94 const GrGLPrecompiledProgram* precompiledProgram = &((*entry)->fPrecompiledProgram); 95 SkASSERT(precompiledProgram->fProgramID != 0); 96 (*entry)->fProgram = GrGLProgramBuilder::CreateProgram(dContext, desc, programInfo, 97 precompiledProgram); 98 if (!(*entry)->fProgram) { 99 // Should we purge the program ID from the cache at this point? 100 SkDEBUGFAIL("Couldn't create program from precompiled program"); 101 fStats.incNumCompilationFailures(); 102 return nullptr; 103 } 104 fStats.incNumPartialCompilationSuccesses(); 105 *stat = Stats::ProgramCacheResult::kPartial; 106 } else if (!entry) { 107 // We have a cache miss 108 sk_sp<GrGLProgram> program = GrGLProgramBuilder::CreateProgram(dContext, desc, programInfo); 109 if (!program) { 110 fStats.incNumCompilationFailures(); 111 return nullptr; 112 } 113 fStats.incNumCompilationSuccesses(); 114 entry = fMap.insert(desc, std::make_unique<Entry>(std::move(program))); 115 *stat = Stats::ProgramCacheResult::kMiss; 116 } 117 118 return (*entry)->fProgram; 119} 120 121bool GrGLGpu::ProgramCache::precompileShader(GrDirectContext* dContext, 122 const SkData& key, 123 const SkData& data) { 124 GrProgramDesc desc; 125 if (!GrProgramDesc::BuildFromData(&desc, key.data(), key.size())) { 126 return false; 127 } 128 129 std::unique_ptr<Entry>* entry = fMap.find(desc); 130 if (entry) { 131 // We've already seen/compiled this shader 132 return true; 133 } 134 135 GrGLPrecompiledProgram precompiledProgram; 136 if (!GrGLProgramBuilder::PrecompileProgram(dContext, &precompiledProgram, data)) { 137 return false; 138 } 139 140 fMap.insert(desc, std::make_unique<Entry>(precompiledProgram)); 141 return true; 142} 143