blob: 91a8177efb17605be29cef419468606fa15f973a [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"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/GrContextThreadSafeProxyPriv.h"
Robert Phillips576b6a12019-12-06 13:05:49 -050012#include "src/gpu/GrProgramDesc.h"
13#include "src/gpu/GrProgramInfo.h"
Robert Phillips07531a02020-07-15 15:11:09 -040014#include "src/gpu/GrRecordingContextPriv.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)
Adlai Hollere219d1c2020-06-02 11:23:16 -040024 : INHERITED(std::move(proxy)) {
Robert Phillipsa3457b82018-03-08 11:30:12 -050025 }
26
Brian Salomon161c8ed2019-11-27 09:12:47 -050027 ~GrDDLContext() override {}
Robert Phillipsa3457b82018-03-08 11:30:12 -050028
Brian Salomon161c8ed2019-11-27 09:12:47 -050029 void abandonContext() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050030 SkASSERT(0); // abandoning in a DDL Recorder doesn't make a whole lot of sense
31 INHERITED::abandonContext();
32 }
33
Brian Salomon161c8ed2019-11-27 09:12:47 -050034 void releaseResourcesAndAbandonContext() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050035 SkASSERT(0); // abandoning in a DDL Recorder doesn't make a whole lot of sense
36 INHERITED::releaseResourcesAndAbandonContext();
37 }
38
Brian Salomon161c8ed2019-11-27 09:12:47 -050039 void freeGpuResources() override {
Robert Phillips9977ab92020-06-19 15:01:47 -040040 // freeing resources in a DDL Recorder doesn't make a whole lot of sense but some of
41 // our tests do it anyways
Robert Phillipsa3457b82018-03-08 11:30:12 -050042 }
43
Robert Phillips933484f2019-11-26 09:38:55 -050044private:
Robert Phillipsa41c6852019-02-07 10:44:10 -050045 // TODO: Here we're pretending this isn't derived from GrContext. Switch this to be derived from
46 // GrRecordingContext!
Robert Phillips44333c52020-06-30 13:28:00 -040047 GrDirectContext* asDirectContext() override { return nullptr; }
Robert Phillipsa41c6852019-02-07 10:44:10 -050048
Adlai Hollere219d1c2020-06-02 11:23:16 -040049 bool init() override {
50 if (!INHERITED::init()) {
Robert Phillipsa3457b82018-03-08 11:30:12 -050051 return false;
52 }
53
Greg Danielf41b2bd2019-08-22 16:19:24 -040054 // DDL contexts/drawing managers always sort the oplists and attempt to reduce opsTask
Robert Phillips6db27c22019-05-01 10:43:56 -040055 // splitting.
56 this->setupDrawingManager(true, true);
Robert Phillips56181ba2019-03-08 12:00:45 -050057
Robert Phillipsa3457b82018-03-08 11:30:12 -050058 return true;
59 }
60
Brian Salomon161c8ed2019-11-27 09:12:47 -050061 GrAtlasManager* onGetAtlasManager() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050062 SkASSERT(0); // the DDL Recorders should never invoke this
63 return nullptr;
64 }
65
Robert Phillips576b6a12019-12-06 13:05:49 -050066 // Add to the set of unique program infos required by this DDL
67 void recordProgramInfo(const GrProgramInfo* programInfo) final {
Robert Phillips345af252020-03-04 10:32:28 -050068 if (!programInfo) {
69 return;
70 }
71
Robert Phillips576b6a12019-12-06 13:05:49 -050072 const GrCaps* caps = this->caps();
73
Robert Phillips24e2f6e2020-06-26 08:30:07 -040074 if (this->backend() == GrBackendApi::kMetal ||
Jim Van Verthde175ab2020-06-10 16:12:25 -040075 this->backend() == GrBackendApi::kDirect3D ||
Sean Gilhuly2cdad962020-03-13 11:58:05 -040076 this->backend() == GrBackendApi::kDawn) {
Robert Phillips24e2f6e2020-06-26 08:30:07 -040077 // Currently Metal, Direct3D, and Dawn require a live renderTarget to
Robert Phillipsf6a0b452020-02-18 14:26:46 -050078 // compute the key
Robert Phillips576b6a12019-12-06 13:05:49 -050079 return;
80 }
81
82 if (programInfo->requestedFeatures() & GrProcessor::CustomFeatures::kSampleLocations) {
83 // Sample locations require a live renderTarget to compute the key
84 return;
85 }
86
87 GrProgramDesc desc = caps->makeDesc(nullptr, *programInfo);
Robert Phillipsf6a0b452020-02-18 14:26:46 -050088 if (!desc.isValid()) {
Robert Phillips576b6a12019-12-06 13:05:49 -050089 return;
90 }
91
92 fProgramInfoMap.add(desc, programInfo);
93 }
94
Robert Phillipsf6a0b452020-02-18 14:26:46 -050095 void detachProgramData(SkTArray<ProgramData>* dst) final {
96 SkASSERT(dst->empty());
Robert Phillips576b6a12019-12-06 13:05:49 -050097
98 fProgramInfoMap.toArray(dst);
99 }
100
101
102private:
103 class ProgramInfoMap : public ::SkNoncopyable {
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500104 typedef const GrProgramDesc CacheKey;
Robert Phillips576b6a12019-12-06 13:05:49 -0500105 typedef const GrProgramInfo* CacheValue;
106
107 public:
108 // All the programInfo data should be stored in the record-time arena so there is no
109 // need to ref them here or to delete them in the destructor.
110 ProgramInfoMap() : fMap(10) {}
111 ~ProgramInfoMap() {}
112
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500113 // TODO: this is doing a lot of reallocating of the ProgramDesc! Once the program descs
114 // are allocated in the record-time area there won't be a problem.
115 void add(CacheKey& desc, const GrProgramInfo* programInfo) {
Robert Phillips576b6a12019-12-06 13:05:49 -0500116 SkASSERT(desc.isValid());
117
118 const CacheValue* preExisting = fMap.find(desc);
119 if (preExisting) {
120 return;
121 }
122
123 fMap.insert(desc, programInfo);
124 }
125
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500126 void toArray(SkTArray<ProgramData>* dst) {
127 fMap.foreach([dst](CacheKey* programDesc, CacheValue* programInfo) {
128 // TODO: remove this allocation once the program descs are stored
129 // in the record-time arena.
130 dst->emplace_back(std::make_unique<const GrProgramDesc>(*programDesc),
131 *programInfo);
Robert Phillips576b6a12019-12-06 13:05:49 -0500132 });
133 }
134
135 private:
136 struct DescHash {
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500137 uint32_t operator()(CacheKey& desc) const {
Robert Phillips576b6a12019-12-06 13:05:49 -0500138 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
139 }
140 };
141
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500142 SkLRUCache<CacheKey, CacheValue, DescHash> fMap;
Robert Phillips576b6a12019-12-06 13:05:49 -0500143 };
144
145 ProgramInfoMap fProgramInfoMap;
146
Robert Phillipsa3457b82018-03-08 11:30:12 -0500147 typedef GrContext INHERITED;
148};
149
Robert Phillips07531a02020-07-15 15:11:09 -0400150sk_sp<GrRecordingContext> GrRecordingContextPriv::MakeDDL(sk_sp<GrContextThreadSafeProxy> proxy) {
151 sk_sp<GrRecordingContext> context(new GrDDLContext(std::move(proxy)));
Robert Phillipsa3457b82018-03-08 11:30:12 -0500152
Adlai Hollere219d1c2020-06-02 11:23:16 -0400153 if (!context->init()) {
Robert Phillipsa3457b82018-03-08 11:30:12 -0500154 return nullptr;
155 }
156 return context;
157}