blob: 68c0be1073775db6c65f81b9b2473d562d04a861 [file] [log] [blame]
egdaniel22281c12016-03-23 13:49:40 -07001/*
2 * Copyright 2016 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
Greg Daniel54bfb182018-11-20 17:12:36 -05008
Brian Osman172bb442019-09-06 10:16:02 -04009#include "include/gpu/GrContextOptions.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/core/SkOpts.h"
Brian Osman172bb442019-09-06 10:16:02 -040011#include "src/gpu/GrContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/GrProcessor.h"
13#include "src/gpu/GrRenderTargetPriv.h"
14#include "src/gpu/GrStencilSettings.h"
15#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
16#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
17#include "src/gpu/vk/GrVkGpu.h"
18#include "src/gpu/vk/GrVkPipelineState.h"
19#include "src/gpu/vk/GrVkPipelineStateBuilder.h"
20#include "src/gpu/vk/GrVkResourceProvider.h"
egdaniel22281c12016-03-23 13:49:40 -070021
egdanielaf132772016-03-28 12:39:29 -070022#ifdef GR_PIPELINE_STATE_CACHE_STATS
halcanary4e44efe2016-08-04 10:47:16 -070023// Display pipeline state cache usage
24static const bool c_DisplayVkPipelineCache{false};
egdaniel22281c12016-03-23 13:49:40 -070025#endif
26
egdaniel22281c12016-03-23 13:49:40 -070027struct GrVkResourceProvider::PipelineStateCache::Entry {
Greg Daniel09eeefb2017-10-16 15:15:02 -040028 Entry(GrVkGpu* gpu, GrVkPipelineState* pipelineState)
Ethan Nicholas87f340e2017-01-03 14:32:01 -050029 : fGpu(gpu)
30 , fPipelineState(pipelineState) {}
egdaniel22281c12016-03-23 13:49:40 -070031
Ethan Nicholas87f340e2017-01-03 14:32:01 -050032 ~Entry() {
33 if (fPipelineState) {
34 fPipelineState->freeGPUResources(fGpu);
35 }
egdaniel22281c12016-03-23 13:49:40 -070036 }
37
Ethan Nicholas87f340e2017-01-03 14:32:01 -050038 GrVkGpu* fGpu;
Greg Daniel09eeefb2017-10-16 15:15:02 -040039 std::unique_ptr<GrVkPipelineState> fPipelineState;
egdaniel22281c12016-03-23 13:49:40 -070040};
41
42GrVkResourceProvider::PipelineStateCache::PipelineStateCache(GrVkGpu* gpu)
Brian Osman172bb442019-09-06 10:16:02 -040043 : fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize)
egdaniel22281c12016-03-23 13:49:40 -070044 , fGpu(gpu)
egdanielaf132772016-03-28 12:39:29 -070045#ifdef GR_PIPELINE_STATE_CACHE_STATS
egdaniel22281c12016-03-23 13:49:40 -070046 , fTotalRequests(0)
47 , fCacheMisses(0)
egdaniel22281c12016-03-23 13:49:40 -070048#endif
egdanielaf132772016-03-28 12:39:29 -070049{}
egdaniel22281c12016-03-23 13:49:40 -070050
51GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() {
Ethan Nicholas87f340e2017-01-03 14:32:01 -050052 SkASSERT(0 == fMap.count());
egdaniel22281c12016-03-23 13:49:40 -070053 // dump stats
egdanielaf132772016-03-28 12:39:29 -070054#ifdef GR_PIPELINE_STATE_CACHE_STATS
55 if (c_DisplayVkPipelineCache) {
egdaniel22281c12016-03-23 13:49:40 -070056 SkDebugf("--- Pipeline State Cache ---\n");
57 SkDebugf("Total requests: %d\n", fTotalRequests);
58 SkDebugf("Cache misses: %d\n", fCacheMisses);
59 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
60 100.f * fCacheMisses / fTotalRequests :
61 0.f);
egdaniel22281c12016-03-23 13:49:40 -070062 SkDebugf("---------------------\n");
63 }
64#endif
65}
66
egdaniel22281c12016-03-23 13:49:40 -070067void GrVkResourceProvider::PipelineStateCache::abandon() {
Ethan Nicholas87f340e2017-01-03 14:32:01 -050068 fMap.foreach([](std::unique_ptr<Entry>* e) {
69 (*e)->fPipelineState->abandonGPUResources();
70 (*e)->fPipelineState = nullptr;
egdanielaf132772016-03-28 12:39:29 -070071 });
Ethan Nicholas87f340e2017-01-03 14:32:01 -050072 fMap.reset();
egdaniel22281c12016-03-23 13:49:40 -070073}
74
75void GrVkResourceProvider::PipelineStateCache::release() {
Ethan Nicholas87f340e2017-01-03 14:32:01 -050076 fMap.reset();
egdaniel22281c12016-03-23 13:49:40 -070077}
78
Greg Daniel09eeefb2017-10-16 15:15:02 -040079GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::refPipelineState(
Robert Phillipsd0fe8752019-01-31 14:13:59 -050080 GrRenderTarget* renderTarget,
81 GrSurfaceOrigin origin,
Brian Salomonff168d92018-06-23 15:17:27 -040082 const GrPrimitiveProcessor& primProc,
Greg Daniel9a51a862018-11-30 10:18:14 -050083 const GrTextureProxy* const primProcProxies[],
Brian Salomonff168d92018-06-23 15:17:27 -040084 const GrPipeline& pipeline,
85 GrPrimitiveType primitiveType,
Greg Daniel99b88e02018-10-03 15:31:20 -040086 VkRenderPass compatibleRenderPass) {
egdanielaf132772016-03-28 12:39:29 -070087#ifdef GR_PIPELINE_STATE_CACHE_STATS
egdaniel22281c12016-03-23 13:49:40 -070088 ++fTotalRequests;
89#endif
csmartdaltonc633abb2016-11-01 08:55:55 -070090 GrStencilSettings stencil;
91 if (pipeline.isStencilEnabled()) {
csmartdaltonc633abb2016-11-01 08:55:55 -070092 // TODO: attach stencil and create settings during render target flush.
Robert Phillipsd0fe8752019-01-31 14:13:59 -050093 SkASSERT(renderTarget->renderTargetPriv().getStencilAttachment());
csmartdaltonc633abb2016-11-01 08:55:55 -070094 stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
Robert Phillipsd0fe8752019-01-31 14:13:59 -050095 renderTarget->renderTargetPriv().numStencilBits());
csmartdaltonc633abb2016-11-01 08:55:55 -070096 }
97
egdaniel22281c12016-03-23 13:49:40 -070098 // Get GrVkProgramDesc
Brian Salomon1471df92018-06-08 10:49:00 -040099 GrVkPipelineStateBuilder::Desc desc;
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500100 if (!GrVkPipelineStateBuilder::Desc::Build(&desc, renderTarget, primProc, pipeline, stencil,
101 primitiveType, fGpu)) {
egdaniel22281c12016-03-23 13:49:40 -0700102 GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
egdanieldd97b852016-04-28 09:30:39 -0700103 return nullptr;
egdaniel22281c12016-03-23 13:49:40 -0700104 }
Brian Osmane11dfd32019-07-23 10:29:41 -0400105 // If we knew the shader won't depend on origin, we could skip this (and use the same program
106 // for both origins). Instrumenting all fragment processors would be difficult and error prone.
107 desc.setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(origin));
egdaniel22281c12016-03-23 13:49:40 -0700108
Ethan Nicholas87f340e2017-01-03 14:32:01 -0500109 std::unique_ptr<Entry>* entry = fMap.find(desc);
egdanielaf132772016-03-28 12:39:29 -0700110 if (!entry) {
111#ifdef GR_PIPELINE_STATE_CACHE_STATS
egdaniel22281c12016-03-23 13:49:40 -0700112 ++fCacheMisses;
113#endif
Brian Salomonff168d92018-06-23 15:17:27 -0400114 GrVkPipelineState* pipelineState(GrVkPipelineStateBuilder::CreatePipelineState(
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500115 fGpu, renderTarget, origin, primProc, primProcProxies, pipeline, stencil,
116 primitiveType, &desc, compatibleRenderPass));
egdaniel22281c12016-03-23 13:49:40 -0700117 if (nullptr == pipelineState) {
118 return nullptr;
119 }
Greg Daniel09eeefb2017-10-16 15:15:02 -0400120 entry = fMap.insert(desc, std::unique_ptr<Entry>(new Entry(fGpu, pipelineState)));
121 return (*entry)->fPipelineState.get();
egdaniel22281c12016-03-23 13:49:40 -0700122 }
Greg Daniel09eeefb2017-10-16 15:15:02 -0400123 return (*entry)->fPipelineState.get();
egdaniel22281c12016-03-23 13:49:40 -0700124}