blob: 1f77417a208f6c1240f65e5774f273392ac34590 [file] [log] [blame]
Robert Phillipsa3457b82018-03-08 11:30:12 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/gpu/GrContext.h"
Robert Phillips576b6a12019-12-06 13:05:49 -05009#include "src/core/SkLRUCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/GrCaps.h"
11#include "src/gpu/GrContextPriv.h"
12#include "src/gpu/GrContextThreadSafeProxyPriv.h"
Robert Phillips576b6a12019-12-06 13:05:49 -050013#include "src/gpu/GrProgramDesc.h"
14#include "src/gpu/GrProgramInfo.h"
Robert Phillips7f11fb52019-12-03 13:35:19 -050015#include "src/gpu/effects/GrSkSLFP.h"
Robert Phillipsa3457b82018-03-08 11:30:12 -050016
17/**
18 * The DDL Context is the one in effect during DDL Recording. It isn't backed by a GrGPU and
19 * cannot allocate any GPU resources.
20 */
Jim Van Verth861ac612019-11-27 09:41:43 -050021class GrDDLContext final : public GrContext {
Robert Phillipsa3457b82018-03-08 11:30:12 -050022public:
23 GrDDLContext(sk_sp<GrContextThreadSafeProxy> proxy)
Robert Phillipsc1541ae2019-02-04 12:05:37 -050024 : INHERITED(proxy->backend(), proxy->priv().options(), proxy->priv().contextID()) {
Robert Phillipsa3457b82018-03-08 11:30:12 -050025 fThreadSafeProxy = std::move(proxy);
26 }
27
Brian Salomon161c8ed2019-11-27 09:12:47 -050028 ~GrDDLContext() override {}
Robert Phillipsa3457b82018-03-08 11:30:12 -050029
Brian Salomon161c8ed2019-11-27 09:12:47 -050030 void abandonContext() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050031 SkASSERT(0); // abandoning in a DDL Recorder doesn't make a whole lot of sense
32 INHERITED::abandonContext();
33 }
34
Brian Salomon161c8ed2019-11-27 09:12:47 -050035 void releaseResourcesAndAbandonContext() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050036 SkASSERT(0); // abandoning in a DDL Recorder doesn't make a whole lot of sense
37 INHERITED::releaseResourcesAndAbandonContext();
38 }
39
Brian Salomon161c8ed2019-11-27 09:12:47 -050040 void freeGpuResources() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050041 SkASSERT(0); // freeing resources in a DDL Recorder doesn't make a whole lot of sense
42 INHERITED::freeGpuResources();
43 }
44
Robert Phillips933484f2019-11-26 09:38:55 -050045private:
Robert Phillipsa41c6852019-02-07 10:44:10 -050046 // TODO: Here we're pretending this isn't derived from GrContext. Switch this to be derived from
47 // GrRecordingContext!
Brian Salomon161c8ed2019-11-27 09:12:47 -050048 GrContext* asDirectContext() override { return nullptr; }
Robert Phillipsa41c6852019-02-07 10:44:10 -050049
Brian Osman7b1678a2019-12-16 09:17:25 -050050 bool init(sk_sp<const GrCaps> caps) override {
51 SkASSERT(caps);
Robert Phillipsa3457b82018-03-08 11:30:12 -050052 SkASSERT(fThreadSafeProxy); // should've been set in the ctor
53
Brian Osman7b1678a2019-12-16 09:17:25 -050054 if (!INHERITED::init(std::move(caps))) {
Robert Phillipsa3457b82018-03-08 11:30:12 -050055 return false;
56 }
57
Greg Danielf41b2bd2019-08-22 16:19:24 -040058 // DDL contexts/drawing managers always sort the oplists and attempt to reduce opsTask
Robert Phillips6db27c22019-05-01 10:43:56 -040059 // splitting.
60 this->setupDrawingManager(true, true);
Robert Phillips56181ba2019-03-08 12:00:45 -050061
Robert Phillipsbb606772019-02-04 17:50:57 -050062 SkASSERT(this->caps());
63
Robert Phillipsa3457b82018-03-08 11:30:12 -050064 return true;
65 }
66
Brian Salomon161c8ed2019-11-27 09:12:47 -050067 GrAtlasManager* onGetAtlasManager() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050068 SkASSERT(0); // the DDL Recorders should never invoke this
69 return nullptr;
70 }
71
Robert Phillips576b6a12019-12-06 13:05:49 -050072 // Add to the set of unique program infos required by this DDL
73 void recordProgramInfo(const GrProgramInfo* programInfo) final {
Robert Phillips345af252020-03-04 10:32:28 -050074 if (!programInfo) {
75 return;
76 }
77
Robert Phillips576b6a12019-12-06 13:05:49 -050078 const GrCaps* caps = this->caps();
79
Robert Phillipsf6a0b452020-02-18 14:26:46 -050080 if (this->backend() == GrBackendApi::kVulkan ||
Sean Gilhuly2cdad962020-03-13 11:58:05 -040081 this->backend() == GrBackendApi::kMetal ||
82 this->backend() == GrBackendApi::kDawn) {
83 // Currently, Vulkan, Metal and Dawn require a live renderTarget to
Robert Phillipsf6a0b452020-02-18 14:26:46 -050084 // compute the key
Robert Phillips576b6a12019-12-06 13:05:49 -050085 return;
86 }
87
88 if (programInfo->requestedFeatures() & GrProcessor::CustomFeatures::kSampleLocations) {
89 // Sample locations require a live renderTarget to compute the key
90 return;
91 }
92
93 GrProgramDesc desc = caps->makeDesc(nullptr, *programInfo);
Robert Phillipsf6a0b452020-02-18 14:26:46 -050094 if (!desc.isValid()) {
Robert Phillips576b6a12019-12-06 13:05:49 -050095 return;
96 }
97
98 fProgramInfoMap.add(desc, programInfo);
99 }
100
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500101 void detachProgramData(SkTArray<ProgramData>* dst) final {
102 SkASSERT(dst->empty());
Robert Phillips576b6a12019-12-06 13:05:49 -0500103
104 fProgramInfoMap.toArray(dst);
105 }
106
107
108private:
109 class ProgramInfoMap : public ::SkNoncopyable {
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500110 typedef const GrProgramDesc CacheKey;
Robert Phillips576b6a12019-12-06 13:05:49 -0500111 typedef const GrProgramInfo* CacheValue;
112
113 public:
114 // All the programInfo data should be stored in the record-time arena so there is no
115 // need to ref them here or to delete them in the destructor.
116 ProgramInfoMap() : fMap(10) {}
117 ~ProgramInfoMap() {}
118
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500119 // TODO: this is doing a lot of reallocating of the ProgramDesc! Once the program descs
120 // are allocated in the record-time area there won't be a problem.
121 void add(CacheKey& desc, const GrProgramInfo* programInfo) {
Robert Phillips576b6a12019-12-06 13:05:49 -0500122 SkASSERT(desc.isValid());
123
124 const CacheValue* preExisting = fMap.find(desc);
125 if (preExisting) {
126 return;
127 }
128
129 fMap.insert(desc, programInfo);
130 }
131
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500132 void toArray(SkTArray<ProgramData>* dst) {
133 fMap.foreach([dst](CacheKey* programDesc, CacheValue* programInfo) {
134 // TODO: remove this allocation once the program descs are stored
135 // in the record-time arena.
136 dst->emplace_back(std::make_unique<const GrProgramDesc>(*programDesc),
137 *programInfo);
Robert Phillips576b6a12019-12-06 13:05:49 -0500138 });
139 }
140
141 private:
142 struct DescHash {
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500143 uint32_t operator()(CacheKey& desc) const {
Robert Phillips576b6a12019-12-06 13:05:49 -0500144 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
145 }
146 };
147
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500148 SkLRUCache<CacheKey, CacheValue, DescHash> fMap;
Robert Phillips576b6a12019-12-06 13:05:49 -0500149 };
150
151 ProgramInfoMap fProgramInfoMap;
152
Robert Phillipsa3457b82018-03-08 11:30:12 -0500153 typedef GrContext INHERITED;
154};
155
Kevin Lubickb5502b22018-03-12 10:17:06 -0400156sk_sp<GrContext> GrContextPriv::MakeDDL(const sk_sp<GrContextThreadSafeProxy>& proxy) {
Robert Phillipsa3457b82018-03-08 11:30:12 -0500157 sk_sp<GrContext> context(new GrDDLContext(proxy));
158
Brian Osman7b1678a2019-12-16 09:17:25 -0500159 if (!context->init(proxy->priv().refCaps())) {
Robert Phillipsa3457b82018-03-08 11:30:12 -0500160 return nullptr;
161 }
162 return context;
163}