blob: c471f8cfe8e92fe7cc2f577a15fd9e05af762895 [file] [log] [blame]
joshualitt79f8fae2014-10-28 17:59:26 -07001/*
2 * Copyright 2014 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
8#ifndef GrProgramDesc_DEFINED
9#define GrProgramDesc_DEFINED
10
Brian Osmanf0de96f2021-02-26 13:54:11 -050011#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/private/GrTypesPriv.h"
13#include "include/private/SkTArray.h"
14#include "include/private/SkTo.h"
joshualitt79f8fae2014-10-28 17:59:26 -070015
Brian Osmanf0de96f2021-02-26 13:54:11 -050016#include <limits.h>
17
Robert Phillips03e4c952019-11-26 16:20:22 -050018class GrCaps;
Robert Phillips901aff02019-10-08 12:32:56 -040019class GrProgramInfo;
Robert Phillips03e4c952019-11-26 16:20:22 -050020class GrRenderTarget;
Brian Salomon94efbf52016-11-29 13:43:05 -050021class GrShaderCaps;
egdaniel5d8f69f2016-09-07 07:24:12 -070022
Brian Osmanef3725f2021-03-04 10:44:41 -050023class GrProcessorKeyBuilder {
Brian Osmanf0de96f2021-02-26 13:54:11 -050024public:
Brian Osmanef3725f2021-03-04 10:44:41 -050025 GrProcessorKeyBuilder() = default;
26 GrProcessorKeyBuilder(const GrProcessorKeyBuilder& other) = default;
Brian Osmanf0de96f2021-02-26 13:54:11 -050027
Brian Osmanef3725f2021-03-04 10:44:41 -050028 void reset() { *this = GrProcessorKeyBuilder{}; }
Brian Osmanf0de96f2021-02-26 13:54:11 -050029
30 void addBits(uint32_t numBits, uint32_t val, const char* label) {
31 SkASSERT(numBits > 0 && numBits <= 32);
32 SkASSERT(numBits == 32 || (val < (1u << numBits)));
33
34 SkDEBUGCODE(fDescription.appendf("%s: %u\n", label, val);)
35
36 fCurValue |= (val << fBitsUsed);
37 fBitsUsed += numBits;
38
39 if (fBitsUsed >= 32) {
40 // Overflow, start a new working value
41 fData.push_back(fCurValue);
42 uint32_t excess = fBitsUsed - 32;
43 fCurValue = excess ? (val >> (numBits - excess)) : 0;
44 fBitsUsed = excess;
45 }
46
47 SkASSERT(fCurValue < (1u << fBitsUsed));
48 }
49
50 void addBytes(uint32_t numBytes, const void* data, const char* label) {
51 // TODO: Make this smarter/faster?
52 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
53 for (; numBytes --> 0; bytes++) {
54 this->addBits(8, *bytes, label);
55 }
56 }
57
Brian Osmanef3725f2021-03-04 10:44:41 -050058 void addBool(bool b, const char* label) {
59 this->addBits(1, b, label);
60 }
61
62 void add32(uint32_t v, const char* label = "unknown") {
63 this->addBits(32, v, label);
64 }
65
Brian Osmanf0de96f2021-02-26 13:54:11 -050066 template <typename StringFunc>
67 void addString(StringFunc&& sf) {
68 #ifdef SK_DEBUG
69 fDescription.append(sf());
70 fDescription.append("\n");
71 #endif
72 }
73
Brian Osmanef3725f2021-03-04 10:44:41 -050074 // Introduces a word-boundary in the key. Must be called before using the key with any cache,
75 // but can also be called to create a break between generic data and backend-specific data.
Brian Osmanf0de96f2021-02-26 13:54:11 -050076 void flush() {
77 if (fBitsUsed) {
78 fData.push_back(fCurValue);
79 fCurValue = 0;
80 fBitsUsed = 0;
81 }
82 }
83
84 bool empty() const { return fData.empty() && !fBitsUsed; }
85
86 const uint32_t* data() const {
87 SkASSERT(fBitsUsed == 0); // flush() must be called when construction is complete
88 return fData.begin();
89 }
90
91 size_t size() const {
92 return (fData.count() + (fBitsUsed ? 1 : 0)) * sizeof(uint32_t);
93 }
94
95 size_t sizeInBits() const {
96 return (fData.count() * sizeof(uint32_t) * CHAR_BIT) + fBitsUsed;
97 }
98
Brian Osmanef3725f2021-03-04 10:44:41 -050099 GrProcessorKeyBuilder& operator=(const GrProcessorKeyBuilder& other) = default;
Brian Osmanf0de96f2021-02-26 13:54:11 -0500100
Brian Osmanef3725f2021-03-04 10:44:41 -0500101 bool operator==(const GrProcessorKeyBuilder& that) const {
Brian Osmanf0de96f2021-02-26 13:54:11 -0500102 return fBitsUsed == that.fBitsUsed &&
103 fCurValue == that.fCurValue &&
104 fData == that.fData;
105 }
106
Brian Osmanef3725f2021-03-04 10:44:41 -0500107 bool operator!= (const GrProcessorKeyBuilder& other) const {
Brian Osmanf0de96f2021-02-26 13:54:11 -0500108 return !(*this == other);
109 }
110
111 void setData(const void* data, size_t length) {
112 SkASSERT(SkIsAlign4(length));
113 fData.reset(length / 4);
114 memcpy(fData.begin(), data, length);
115 }
116
117 SkString description() const {
118 #ifdef SK_DEBUG
119 return fDescription;
120 #else
121 return SkString{};
122 #endif
123 }
124
125private:
126 enum {
127 kHeaderSize = 1, // "header" in ::Build
128 kMaxPreallocProcessors = 8,
129 kIntsPerProcessor = 4, // This is an overestimate of the average effect key size.
130 kPreAllocSize = kHeaderSize +
131 kMaxPreallocProcessors * kIntsPerProcessor,
132 };
133
134 SkSTArray<kPreAllocSize, uint32_t, true> fData;
135 uint32_t fCurValue = 0;
136 uint32_t fBitsUsed = 0; // ... in current value
137
138 SkDEBUGCODE(SkString fDescription;)
139};
140
Robert Phillips373bda62019-11-12 13:30:05 -0500141/** This class is used to generate a generic program cache key. The Dawn, Metal and Vulkan
142 * backends derive backend-specific versions which add additional information.
143 */
joshualitt79f8fae2014-10-28 17:59:26 -0700144class GrProgramDesc {
145public:
Brian Osman9b510a32021-02-26 14:29:39 -0500146 GrProgramDesc(const GrProgramDesc& other) = default;
Robert Phillipsf6a0b452020-02-18 14:26:46 -0500147
Robert Phillips03e4c952019-11-26 16:20:22 -0500148 bool isValid() const { return !fKey.empty(); }
Brian Osmaned58e002019-09-06 14:42:43 -0400149
joshualitt79f8fae2014-10-28 17:59:26 -0700150 // Returns this as a uint32_t array to be used as a key in the program cache.
151 const uint32_t* asKey() const {
Brian Osmanf0de96f2021-02-26 13:54:11 -0500152 return fKey.data();
joshualitt79f8fae2014-10-28 17:59:26 -0700153 }
154
Greg Daniel2d2c09f2019-01-07 16:14:12 -0500155 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value.
156 uint32_t keyLength() const {
Brian Osmanf0de96f2021-02-26 13:54:11 -0500157 SkASSERT(0 == (fKey.size() % 4));
158 return fKey.size();
Greg Daniel2d2c09f2019-01-07 16:14:12 -0500159 }
joshualitt79f8fae2014-10-28 17:59:26 -0700160
Brian Osmanf0de96f2021-02-26 13:54:11 -0500161 SkString description() const { return fKey.description(); }
162
163 GrProgramDesc& operator= (const GrProgramDesc& other) = default;
joshualitt79f8fae2014-10-28 17:59:26 -0700164
bsalomon89d59882015-06-04 15:34:34 -0700165 bool operator== (const GrProgramDesc& that) const {
Brian Osmanf0de96f2021-02-26 13:54:11 -0500166 return this->fKey == that.fKey;
joshualitt79f8fae2014-10-28 17:59:26 -0700167 }
168
169 bool operator!= (const GrProgramDesc& other) const {
170 return !(*this == other);
171 }
172
Brian Osman9b510a32021-02-26 14:29:39 -0500173 uint32_t initialKeyLength() const { return fInitialKeyLength; }
Robert Phillipsc15e8902019-11-26 14:26:36 -0500174
Robert Phillipsd5c1f342019-10-14 09:50:05 -0400175protected:
Robert Phillips03e4c952019-11-26 16:20:22 -0500176 friend class GrDawnCaps;
Jim Van Verthd2d4c5e2020-02-19 14:57:58 -0500177 friend class GrD3DCaps;
Robert Phillips03e4c952019-11-26 16:20:22 -0500178 friend class GrGLCaps;
179 friend class GrMockCaps;
180 friend class GrMtlCaps;
181 friend class GrVkCaps;
182
183 friend class GrGLGpu; // for ProgramCache to access BuildFromData
184
185 // Creates an uninitialized key that must be populated by Build
186 GrProgramDesc() {}
187
188 /**
189 * Builds a program descriptor.
190 *
191 * @param desc The built descriptor
192 * @param renderTarget The target of the draw
193 * @param programInfo Program information need to build the key
194 * @param caps the caps
195 **/
Brian Salomonf7f54332020-07-28 09:23:35 -0400196 static bool Build(GrProgramDesc*, GrRenderTarget*, const GrProgramInfo&, const GrCaps&);
Robert Phillips03e4c952019-11-26 16:20:22 -0500197
John Stilesd3feb6f2020-07-23 18:18:12 -0400198 // This is strictly an OpenGL call since the other backends have additional data in their keys.
Robert Phillips03e4c952019-11-26 16:20:22 -0500199 static bool BuildFromData(GrProgramDesc* desc, const void* keyData, size_t keyLength) {
200 if (!SkTFitsIn<int>(keyLength)) {
201 return false;
202 }
Brian Osmanf0de96f2021-02-26 13:54:11 -0500203 desc->fKey.setData(keyData, keyLength);
Robert Phillips03e4c952019-11-26 16:20:22 -0500204 return true;
205 }
206
Brian Osmanef3725f2021-03-04 10:44:41 -0500207 GrProcessorKeyBuilder* key() { return &fKey; }
joshualitt79f8fae2014-10-28 17:59:26 -0700208
jvanverthd1e72872015-04-20 12:29:37 -0700209private:
Brian Osmanef3725f2021-03-04 10:44:41 -0500210 GrProcessorKeyBuilder fKey;
Brian Osman9b510a32021-02-26 14:29:39 -0500211 uint32_t fInitialKeyLength = 0;
joshualitt79f8fae2014-10-28 17:59:26 -0700212};
213
214#endif