1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrContextThreadSafeProxy.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkNoncopyable.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkChecksum.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkLRUCache.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProgramDesc.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
22*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
23*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker class GrProgramInfo;
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker /**
30*c8dee2aaSAndroid Build Coastguard Worker * The DDL Context is the one in effect during DDL Recording. It isn't backed by a GrGPU and
31*c8dee2aaSAndroid Build Coastguard Worker * cannot allocate any GPU resources.
32*c8dee2aaSAndroid Build Coastguard Worker */
33*c8dee2aaSAndroid Build Coastguard Worker class GrDDLContext final : public GrRecordingContext {
34*c8dee2aaSAndroid Build Coastguard Worker public:
GrDDLContext(sk_sp<GrContextThreadSafeProxy> proxy)35*c8dee2aaSAndroid Build Coastguard Worker GrDDLContext(sk_sp<GrContextThreadSafeProxy> proxy)
36*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(std::move(proxy), true) {
37*c8dee2aaSAndroid Build Coastguard Worker }
38*c8dee2aaSAndroid Build Coastguard Worker
~GrDDLContext()39*c8dee2aaSAndroid Build Coastguard Worker ~GrDDLContext() override {}
40*c8dee2aaSAndroid Build Coastguard Worker
abandonContext()41*c8dee2aaSAndroid Build Coastguard Worker void abandonContext() override {
42*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(0); // abandoning in a DDL Recorder doesn't make a whole lot of sense
43*c8dee2aaSAndroid Build Coastguard Worker INHERITED::abandonContext();
44*c8dee2aaSAndroid Build Coastguard Worker }
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker private:
47*c8dee2aaSAndroid Build Coastguard Worker // Add to the set of unique program infos required by this DDL
recordProgramInfo(const GrProgramInfo * programInfo)48*c8dee2aaSAndroid Build Coastguard Worker void recordProgramInfo(const GrProgramInfo* programInfo) final {
49*c8dee2aaSAndroid Build Coastguard Worker if (!programInfo) {
50*c8dee2aaSAndroid Build Coastguard Worker return;
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = this->caps();
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker if (this->backend() == GrBackendApi::kMetal || this->backend() == GrBackendApi::kDirect3D) {
56*c8dee2aaSAndroid Build Coastguard Worker // Currently Metal and Direct3D require a live renderTarget to compute the key
57*c8dee2aaSAndroid Build Coastguard Worker return;
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker
60*c8dee2aaSAndroid Build Coastguard Worker GrProgramDesc desc = caps->makeDesc(nullptr, *programInfo);
61*c8dee2aaSAndroid Build Coastguard Worker if (!desc.isValid()) {
62*c8dee2aaSAndroid Build Coastguard Worker return;
63*c8dee2aaSAndroid Build Coastguard Worker }
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker fProgramInfoMap.add(desc, programInfo);
66*c8dee2aaSAndroid Build Coastguard Worker }
67*c8dee2aaSAndroid Build Coastguard Worker
detachProgramData(TArray<ProgramData> * dst)68*c8dee2aaSAndroid Build Coastguard Worker void detachProgramData(TArray<ProgramData>* dst) final {
69*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dst->empty());
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker fProgramInfoMap.toArray(dst);
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker private:
76*c8dee2aaSAndroid Build Coastguard Worker class ProgramInfoMap : public ::SkNoncopyable {
77*c8dee2aaSAndroid Build Coastguard Worker typedef const GrProgramDesc CacheKey;
78*c8dee2aaSAndroid Build Coastguard Worker typedef const GrProgramInfo* CacheValue;
79*c8dee2aaSAndroid Build Coastguard Worker
80*c8dee2aaSAndroid Build Coastguard Worker public:
81*c8dee2aaSAndroid Build Coastguard Worker // All the programInfo data should be stored in the record-time arena so there is no
82*c8dee2aaSAndroid Build Coastguard Worker // need to ref them here or to delete them in the destructor.
ProgramInfoMap()83*c8dee2aaSAndroid Build Coastguard Worker ProgramInfoMap() : fMap(10) {}
~ProgramInfoMap()84*c8dee2aaSAndroid Build Coastguard Worker ~ProgramInfoMap() {}
85*c8dee2aaSAndroid Build Coastguard Worker
86*c8dee2aaSAndroid Build Coastguard Worker // TODO: this is doing a lot of reallocating of the ProgramDesc! Once the program descs
87*c8dee2aaSAndroid Build Coastguard Worker // are allocated in the record-time area there won't be a problem.
add(CacheKey & desc,const GrProgramInfo * programInfo)88*c8dee2aaSAndroid Build Coastguard Worker void add(CacheKey& desc, const GrProgramInfo* programInfo) {
89*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desc.isValid());
90*c8dee2aaSAndroid Build Coastguard Worker
91*c8dee2aaSAndroid Build Coastguard Worker const CacheValue* preExisting = fMap.find(desc);
92*c8dee2aaSAndroid Build Coastguard Worker if (preExisting) {
93*c8dee2aaSAndroid Build Coastguard Worker return;
94*c8dee2aaSAndroid Build Coastguard Worker }
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker fMap.insert(desc, programInfo);
97*c8dee2aaSAndroid Build Coastguard Worker }
98*c8dee2aaSAndroid Build Coastguard Worker
toArray(TArray<ProgramData> * dst)99*c8dee2aaSAndroid Build Coastguard Worker void toArray(TArray<ProgramData>* dst) {
100*c8dee2aaSAndroid Build Coastguard Worker fMap.foreach([dst](CacheKey* programDesc, CacheValue* programInfo) {
101*c8dee2aaSAndroid Build Coastguard Worker // TODO: remove this allocation once the program descs are stored
102*c8dee2aaSAndroid Build Coastguard Worker // in the record-time arena.
103*c8dee2aaSAndroid Build Coastguard Worker dst->emplace_back(std::make_unique<const GrProgramDesc>(*programDesc),
104*c8dee2aaSAndroid Build Coastguard Worker *programInfo);
105*c8dee2aaSAndroid Build Coastguard Worker });
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker
108*c8dee2aaSAndroid Build Coastguard Worker private:
109*c8dee2aaSAndroid Build Coastguard Worker struct DescHash {
operator ()GrDDLContext::ProgramInfoMap::DescHash110*c8dee2aaSAndroid Build Coastguard Worker uint32_t operator()(CacheKey& desc) const {
111*c8dee2aaSAndroid Build Coastguard Worker return SkChecksum::Hash32(desc.asKey(), desc.keyLength());
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker };
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker SkLRUCache<CacheKey, CacheValue, DescHash> fMap;
116*c8dee2aaSAndroid Build Coastguard Worker };
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker ProgramInfoMap fProgramInfoMap;
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrRecordingContext;
121*c8dee2aaSAndroid Build Coastguard Worker };
122*c8dee2aaSAndroid Build Coastguard Worker
MakeDDL(sk_sp<GrContextThreadSafeProxy> proxy)123*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRecordingContext> GrRecordingContextPriv::MakeDDL(sk_sp<GrContextThreadSafeProxy> proxy) {
124*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRecordingContext> context(new GrDDLContext(std::move(proxy)));
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker if (!context->init()) {
127*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
128*c8dee2aaSAndroid Build Coastguard Worker }
129*c8dee2aaSAndroid Build Coastguard Worker return context;
130*c8dee2aaSAndroid Build Coastguard Worker }
131