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 SkUniformData_DEFINED 9 #define SkUniformData_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "include/core/SkSpan.h" 13 #include "src/core/SkUniform.h" 14 #include <vector> 15 16 /* 17 * TODO: Here is the plan of record for SkUniformData 18 * allocate them (and their ancillary data (offsets & data)) in an arena - and rm SkRefCnt 19 * remove the offsets - these should be recomputable as/if needed 20 * allow a scratch buffer to be used to collect the uniform data when processing a PaintParams 21 * - this can be reset for each draw and be copied into a cache if it needs to be preserved 22 * if possible, clear out the cache (and delete the arena) once the DrawPass is created/the 23 * uniforms are copied into a buffer 24 * - this will mean we'll get w/in DrawPass reuse but not cross-DrawPass reuse 25 * - we could also explore getting w/in a Recording (i.e. cross-DrawPass) and w/in a 26 * Recorder reuse (i.e., cross-Recordings, but single-threaded) 27 * have the SkUniformData's data layout match what is required by the DrawList so we can just 28 * copy it into the buffer 29 */ 30 31 class SkUniformData : public SkRefCnt { 32 public: 33 34 // TODO: should we require a name (e.g., "gradient_uniforms") for each uniform block so 35 // we can better name the Metal FS uniform struct? 36 static sk_sp<SkUniformData> Make(SkSpan<const SkUniform>, size_t dataSize); 37 ~SkUniformData()38 ~SkUniformData() override { 39 // TODO: fOffsets and fData should just be allocated right after UniformData in an arena 40 delete [] fOffsets; 41 delete [] fData; 42 } 43 count()44 int count() const { return static_cast<unsigned int>(fUniforms.size()); } uniforms()45 SkSpan<const SkUniform> uniforms() const { return fUniforms; } offsets()46 uint32_t* offsets() { return fOffsets; } offsets()47 const uint32_t* offsets() const { return fOffsets; } offset(int index)48 uint32_t offset(int index) { 49 SkASSERT(index >= 0 && static_cast<size_t>(index) < fUniforms.size()); 50 return fOffsets[index]; 51 } data()52 char* data() { return fData; } data()53 const char* data() const { return fData; } dataSize()54 size_t dataSize() const { return fDataSize; } 55 56 bool operator==(const SkUniformData&) const; 57 bool operator!=(const SkUniformData& other) const { return !(*this == other); } 58 59 private: SkUniformData(SkSpan<const SkUniform> uniforms,uint32_t * offsets,char * data,size_t dataSize)60 SkUniformData(SkSpan<const SkUniform> uniforms, 61 uint32_t* offsets, 62 char* data, 63 size_t dataSize) 64 : fUniforms(uniforms) 65 , fOffsets(offsets) 66 , fData(data) 67 , fDataSize(dataSize) { 68 } 69 70 SkSpan<const SkUniform> fUniforms; 71 uint32_t* fOffsets; // offset of each uniform in 'fData' 72 char* fData; 73 const size_t fDataSize; 74 }; 75 76 class SkUniformBlock { 77 public: 78 SkUniformBlock() = default; SkUniformBlock(sk_sp<SkUniformData> initial)79 SkUniformBlock(sk_sp<SkUniformData> initial) { 80 fUniformData.push_back(std::move(initial)); 81 } 82 83 void add(sk_sp<SkUniformData>); 84 empty()85 bool empty() const { return fUniformData.empty(); } 86 size_t totalSize() const; // TODO: cache this? 87 int count() const; // TODO: cache this? 88 89 bool operator==(const SkUniformBlock&) const; 90 bool operator!=(const SkUniformBlock& other) const { return !(*this == other); } 91 size_t hash() const; 92 93 using container = std::vector<sk_sp<SkUniformData>>; 94 using iterator = container::iterator; 95 using const_iterator = container::const_iterator; 96 begin()97 inline iterator begin() noexcept { return fUniformData.begin(); } cbegin()98 inline const_iterator cbegin() const noexcept { return fUniformData.cbegin(); } end()99 inline iterator end() noexcept { return fUniformData.end(); } cend()100 inline const_iterator cend() const noexcept { return fUniformData.cend(); } 101 102 private: 103 // TODO: SkUniformData should be held uniquely 104 std::vector<sk_sp<SkUniformData>> fUniformData; 105 }; 106 107 #endif // SkUniformData_DEFINED 108