• 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/base/SkEnumBitMask.h"
20 #include "src/gpu/graphite/Caps.h"
21 #include "src/gpu/graphite/DrawTypes.h"
22 #include "src/gpu/graphite/TextureProxy.h"
23 #include "src/gpu/graphite/UniformManager.h"
24 
25 class SkArenaAlloc;
26 
27 namespace skgpu::graphite {
28 
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 Caps * caps,const SkSamplingOptions & sampling,const SkTileMode tileModes[2],sk_sp<TextureProxy> proxy)68     void add(const Caps* caps,
69              const SkSamplingOptions& sampling,
70              const SkTileMode tileModes[2],
71              sk_sp<TextureProxy> proxy) {
72         // Before relinquishing ownership of the proxy, query Caps to gather any relevant sampler
73         // conversion information for the SamplerDesc.
74         ImmutableSamplerInfo info = caps->getImmutableSamplerInfo(proxy);
75         fTextureData.push_back({std::move(proxy), SamplerDesc{sampling, tileModes, info}});
76     }
77 
reset()78     void reset() {
79         fTextureData.clear();
80     }
81 
82 private:
83     // TODO: Move this into a SkSpan that's managed by the gatherer or copied into the arena.
84     std::vector<SampledTexture> fTextureData;
85 };
86 
87 // The PipelineDataGatherer is just used to collect information for a given PaintParams object.
88 //   The UniformData is added to a cache and uniquified. Only that unique ID is passed around.
89 //   The TextureData is also added to a cache and uniquified. Only that ID is passed around.
90 
91 // TODO: The current plan for fixing uniform padding is for the PipelineDataGatherer to hold a
92 // persistent uniformManager. A stretch goal for this system would be for this combination
93 // to accumulate all the uniforms and then rearrange them to minimize padding. This would,
94 // obviously, vastly complicate uniform accumulation.
95 class PipelineDataGatherer {
96 public:
97     PipelineDataGatherer(const Caps* caps, Layout layout);
98 
99     void resetWithNewLayout(Layout layout);
100 
101     // Check that the gatherer has been reset to its initial state prior to collecting new data.
SkDEBUGCODE(void checkReset ();)102     SkDEBUGCODE(void checkReset();)
103 
104     void add(const SkSamplingOptions& sampling,
105              const SkTileMode tileModes[2],
106              sk_sp<TextureProxy> proxy) {
107         fTextureDataBlock.add(fCaps, sampling, tileModes, std::move(proxy));
108     }
hasTextures()109     bool hasTextures() const { return !fTextureDataBlock.empty(); }
110 
textureDataBlock()111     const TextureDataBlock& textureDataBlock() { return fTextureDataBlock; }
112 
113     // Mimic the type-safe API available in UniformManager
write(const T & t)114     template <typename T> void write(const T& t) { fUniformManager.write(t); }
writeHalf(const T & t)115     template <typename T> void writeHalf(const T& t) { fUniformManager.writeHalf(t); }
writeArray(SkSpan<const T> t)116     template <typename T> void writeArray(SkSpan<const T> t) { fUniformManager.writeArray(t); }
writeHalfArray(SkSpan<const T> t)117     template <typename T> void writeHalfArray(SkSpan<const T> t) {
118         fUniformManager.writeHalfArray(t);
119     }
120 
write(const Uniform & u,const void * data)121     void write(const Uniform& u, const void* data) { fUniformManager.write(u, data); }
122 
writePaintColor(const SkPMColor4f & color)123     void writePaintColor(const SkPMColor4f& color) { fUniformManager.writePaintColor(color); }
124 
hasUniforms()125     bool hasUniforms() const { return fUniformManager.size(); }
126 
hasGradientBufferData()127     bool hasGradientBufferData() const { return !fGradientStorage.empty(); }
128 
gradientBufferData()129     SkSpan<const float> gradientBufferData() const { return fGradientStorage; }
130 
131     // Returns the uniform data written so far. Will automatically pad the end of the data as needed
132     // to the overall required alignment, and so should only be called when all writing is done.
finishUniformDataBlock()133     UniformDataBlock finishUniformDataBlock() { return fUniformManager.finishUniformDataBlock(); }
134 
135     // Allocates the data for the requested number of stops and returns the
136     // pointer and buffer index offset the data will begin at.
allocateGradientData(int size)137     std::pair<float*, int> allocateGradientData(int size) {
138         int lastSize = fGradientStorage.size();
139         fGradientStorage.resize(lastSize + size);
140         float* startPtr = fGradientStorage.begin() + lastSize;
141 
142         return std::make_pair(startPtr, lastSize);
143     }
144 
145 private:
146 #ifdef SK_DEBUG
147     friend class UniformExpectationsValidator;
148 
149     void setExpectedUniforms(SkSpan<const Uniform> expectedUniforms);
doneWithExpectedUniforms()150     void doneWithExpectedUniforms() { fUniformManager.doneWithExpectedUniforms(); }
151 #endif // SK_DEBUG
152 
153     const Caps* const fCaps;
154     TextureDataBlock  fTextureDataBlock;
155     UniformManager    fUniformManager;
156 
157     SkTDArray<float>  fGradientStorage;
158 };
159 
160 #ifdef SK_DEBUG
161 class UniformExpectationsValidator {
162 public:
163     UniformExpectationsValidator(PipelineDataGatherer *gatherer,
164                                  SkSpan<const Uniform> expectedUniforms);
165 
~UniformExpectationsValidator()166     ~UniformExpectationsValidator() {
167         fGatherer->doneWithExpectedUniforms();
168     }
169 
170 private:
171     PipelineDataGatherer *fGatherer;
172 
173     UniformExpectationsValidator(UniformExpectationsValidator &&) = delete;
174     UniformExpectationsValidator(const UniformExpectationsValidator &) = delete;
175     UniformExpectationsValidator &operator=(UniformExpectationsValidator &&) = delete;
176     UniformExpectationsValidator &operator=(const UniformExpectationsValidator &) = delete;
177 };
178 #endif // SK_DEBUG
179 
180 } // namespace skgpu::graphite
181 
182 #endif // skgpu_graphite_PipelineData_DEFINED
183