blob: fb4cfa8a61bc17e44a098451f33964cdccd829f5 [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,
Robert Phillips901aff02019-10-08 12:32:56 -040081 const GrProgramInfo& programInfo,
Brian Salomonff168d92018-06-23 15:17:27 -040082 GrPrimitiveType primitiveType,
Greg Daniel99b88e02018-10-03 15:31:20 -040083 VkRenderPass compatibleRenderPass) {
egdanielaf132772016-03-28 12:39:29 -070084#ifdef GR_PIPELINE_STATE_CACHE_STATS
egdaniel22281c12016-03-23 13:49:40 -070085 ++fTotalRequests;
86#endif
csmartdaltonc633abb2016-11-01 08:55:55 -070087 GrStencilSettings stencil;
Robert Phillips901aff02019-10-08 12:32:56 -040088 if (programInfo.pipeline().isStencilEnabled()) {
csmartdaltonc633abb2016-11-01 08:55:55 -070089 // TODO: attach stencil and create settings during render target flush.
Robert Phillipsd0fe8752019-01-31 14:13:59 -050090 SkASSERT(renderTarget->renderTargetPriv().getStencilAttachment());
Robert Phillips901aff02019-10-08 12:32:56 -040091 stencil.reset(*programInfo.pipeline().getUserStencil(),
92 programInfo.pipeline().hasStencilClip(),
Robert Phillipsd0fe8752019-01-31 14:13:59 -050093 renderTarget->renderTargetPriv().numStencilBits());
csmartdaltonc633abb2016-11-01 08:55:55 -070094 }
95
Robert Phillips901aff02019-10-08 12:32:56 -040096 // TODO: can this be unified between Vulkan and GL?
egdaniel22281c12016-03-23 13:49:40 -070097 // Get GrVkProgramDesc
Brian Salomon1471df92018-06-08 10:49:00 -040098 GrVkPipelineStateBuilder::Desc desc;
Robert Phillips901aff02019-10-08 12:32:56 -040099 if (!GrVkPipelineStateBuilder::Desc::Build(&desc, renderTarget, programInfo, stencil,
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500100 primitiveType, fGpu)) {
egdaniel22281c12016-03-23 13:49:40 -0700101 GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n");
egdanieldd97b852016-04-28 09:30:39 -0700102 return nullptr;
egdaniel22281c12016-03-23 13:49:40 -0700103 }
Brian Osmane11dfd32019-07-23 10:29:41 -0400104 // If we knew the shader won't depend on origin, we could skip this (and use the same program
105 // for both origins). Instrumenting all fragment processors would be difficult and error prone.
Robert Phillips901aff02019-10-08 12:32:56 -0400106 desc.setSurfaceOriginKey(
107 GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(programInfo.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 Phillips901aff02019-10-08 12:32:56 -0400115 fGpu, renderTarget, programInfo,
Robert Phillips65a77752019-10-02 15:22:24 -0400116 stencil, primitiveType, &desc, compatibleRenderPass));
Robert Phillips901aff02019-10-08 12:32:56 -0400117 if (!pipelineState) {
egdaniel22281c12016-03-23 13:49:40 -0700118 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}