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