• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
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 skgpu_graphite_PipelineData_DEFINED
9 #define skgpu_graphite_PipelineData_DEFINED
10 
11 #include <vector>
12 #include "include/core/SkM44.h"
13 #include "include/core/SkPoint.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/core/SkSamplingOptions.h"
16 #include "include/core/SkSpan.h"
17 #include "include/core/SkTileMode.h"
18 #include "include/private/SkColorData.h"
19 #include "src/core/SkEnumBitMask.h"
20 #include "src/gpu/graphite/DrawTypes.h"
21 #include "src/gpu/graphite/TextureProxy.h"
22 #include "src/gpu/graphite/UniformManager.h"
23 
24 class SkArenaAlloc;
25 
26 namespace skgpu::graphite {
27 
28 enum class SnippetRequirementFlags : uint32_t;
29 class Uniform;
30 
31 class UniformDataBlock {
32 public:
33     static UniformDataBlock* Make(const UniformDataBlock&, SkArenaAlloc*);
34 
UniformDataBlock(SkSpan<const char> data)35     UniformDataBlock(SkSpan<const char> data) : fData(data) {}
36     UniformDataBlock() = default;
37 
data()38     const char* data() const { return fData.data(); }
size()39     size_t size() const { return fData.size(); }
40 
41     uint32_t hash() const;
42 
43     bool operator==(const UniformDataBlock& that) const {
44         return fData.size() == that.fData.size() &&
45                !memcmp(fData.data(), that.fData.data(), fData.size());
46     }
47     bool operator!=(const UniformDataBlock& that) const { return !(*this == that); }
48 
49 private:
50     SkSpan<const char> fData;
51 };
52 
53 class TextureDataBlock {
54 public:
55     using SampledTexture = std::pair<sk_sp<TextureProxy>, SamplerDesc>;
56 
57     static TextureDataBlock* Make(const TextureDataBlock&, SkArenaAlloc*);
58     TextureDataBlock() = default;
59 
empty()60     bool empty() const { return fTextureData.empty(); }
numTextures()61     int numTextures() const { return SkTo<int>(fTextureData.size()); }
texture(int index)62     const SampledTexture& texture(int index) const { return fTextureData[index]; }
63 
64     bool operator==(const TextureDataBlock&) const;
65     bool operator!=(const TextureDataBlock& other) const { return !(*this == other);  }
66     uint32_t hash() const;
67 
add(const SkSamplingOptions & sampling,const SkTileMode tileModes[2],sk_sp<TextureProxy> proxy)68     void add(const SkSamplingOptions& sampling,
69              const SkTileMode tileModes[2],
70              sk_sp<TextureProxy> proxy) {
71         fTextureData.push_back({std::move(proxy), {sampling, {tileModes[0], tileModes[1]}}});
72     }
73 
reset()74     void reset() {
75         fTextureData.clear();
76     }
77 
78 private:
79     // TODO: Move this into a SkSpan that's managed by the gatherer or copied into the arena.
80     std::vector<SampledTexture> fTextureData;
81 };
82 
83 // The PipelineDataGatherer is just used to collect information for a given PaintParams object.
84 //   The UniformData is added to a cache and uniquified. Only that unique ID is passed around.
85 //   The TextureData is also added to a cache and uniquified. Only that ID is passed around.
86 
87 // TODO: The current plan for fixing uniform padding is for the PipelineDataGatherer to hold a
88 // persistent uniformManager. A stretch goal for this system would be for this combination
89 // to accumulate all the uniforms and then rearrange them to minimize padding. This would,
90 // obviously, vastly complicate uniform accumulation.
91 class PipelineDataGatherer {
92 public:
93     PipelineDataGatherer(Layout layout);
94 
95     void resetWithNewLayout(Layout layout);
96 
97     // Check that the gatherer has been reset to its initial state prior to collecting new data.
SkDEBUGCODE(void checkReset ();)98     SkDEBUGCODE(void checkReset();)
99 
100     void add(const SkSamplingOptions& sampling,
101              const SkTileMode tileModes[2],
102              sk_sp<TextureProxy> proxy) {
103         fTextureDataBlock.add(sampling, tileModes, std::move(proxy));
104     }
hasTextures()105     bool hasTextures() const { return !fTextureDataBlock.empty(); }
106 
107     void addFlags(SkEnumBitMask<SnippetRequirementFlags> flags);
108     bool needsLocalCoords() const;
109 
textureDataBlock()110     const TextureDataBlock& textureDataBlock() { return fTextureDataBlock; }
111 
write(const SkM44 & mat)112     void write(const SkM44& mat) { fUniformManager.write(mat); }
write(const SkPMColor4f & premulColor)113     void write(const SkPMColor4f& premulColor) { fUniformManager.write(premulColor); }
write(const SkRect & rect)114     void write(const SkRect& rect) { fUniformManager.write(rect); }
write(const SkV2 & v)115     void write(const SkV2& v) { fUniformManager.write(v); }
write(const SkV4 & v)116     void write(const SkV4& v) { fUniformManager.write(v); }
write(const SkPoint & point)117     void write(const SkPoint& point) { fUniformManager.write(point); }
write(float f)118     void write(float f) { fUniformManager.write(f); }
write(int i)119     void write(int i) { fUniformManager.write(i); }
120 
121 
write(SkSLType t,const void * data)122     void write(SkSLType t, const void* data) { fUniformManager.write(t, data); }
write(const Uniform & u,const uint8_t * data)123     void write(const Uniform& u, const uint8_t* data) { fUniformManager.write(u, data); }
124 
writeArray(SkSpan<const SkColor4f> colors)125     void writeArray(SkSpan<const SkColor4f> colors) { fUniformManager.writeArray(colors); }
writeArray(SkSpan<const SkPMColor4f> colors)126     void writeArray(SkSpan<const SkPMColor4f> colors) { fUniformManager.writeArray(colors); }
writeArray(SkSpan<const float> floats)127     void writeArray(SkSpan<const float> floats) { fUniformManager.writeArray(floats); }
128 
writeHalf(const SkMatrix & mat)129     void writeHalf(const SkMatrix& mat) { fUniformManager.writeHalf(mat); }
writeHalfArray(SkSpan<const float> floats)130     void writeHalfArray(SkSpan<const float> floats) { fUniformManager.writeHalfArray(floats); }
131 
hasUniforms()132     bool hasUniforms() const { return fUniformManager.size(); }
133 
134     // Returns the uniform data written so far. Will automatically pad the end of the data as needed
135     // to the overall required alignment, and so should only be called when all writing is done.
finishUniformDataBlock()136     UniformDataBlock finishUniformDataBlock() { return fUniformManager.finishUniformDataBlock(); }
137 
138 private:
139 #ifdef SK_DEBUG
140     friend class UniformExpectationsValidator;
141 
142     void setExpectedUniforms(SkSpan<const Uniform> expectedUniforms);
doneWithExpectedUniforms()143     void doneWithExpectedUniforms() { fUniformManager.doneWithExpectedUniforms(); }
144 #endif // SK_DEBUG
145 
146     TextureDataBlock                       fTextureDataBlock;
147     UniformManager                         fUniformManager;
148     SkEnumBitMask<SnippetRequirementFlags> fSnippetRequirementFlags;
149 };
150 
151 #ifdef SK_DEBUG
152 class UniformExpectationsValidator {
153 public:
154     UniformExpectationsValidator(PipelineDataGatherer *gatherer,
155                                  SkSpan<const Uniform> expectedUniforms);
156 
~UniformExpectationsValidator()157     ~UniformExpectationsValidator() {
158         fGatherer->doneWithExpectedUniforms();
159     }
160 
161 private:
162     PipelineDataGatherer *fGatherer;
163 
164     UniformExpectationsValidator(UniformExpectationsValidator &&) = delete;
165     UniformExpectationsValidator(const UniformExpectationsValidator &) = delete;
166     UniformExpectationsValidator &operator=(UniformExpectationsValidator &&) = delete;
167     UniformExpectationsValidator &operator=(const UniformExpectationsValidator &) = delete;
168 };
169 #endif // SK_DEBUG
170 
171 } // namespace skgpu::graphite
172 
173 #endif // skgpu_graphite_PipelineData_DEFINED
174