/* * Copyright 2021 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef skgpu_UniformManager_DEFINED #define skgpu_UniformManager_DEFINED #include "include/core/SkRefCnt.h" #include "include/core/SkSpan.h" #include "include/private/SkColorData.h" #include "include/private/base/SkTDArray.h" #include "src/core/SkSLTypeShared.h" #include "src/gpu/graphite/ResourceTypes.h" #include "src/gpu/graphite/Uniform.h" class SkM44; class SkMatrix; struct SkPoint; struct SkRect; struct SkV2; struct SkV4; namespace skgpu::graphite { enum class CType : unsigned; class UniformDataBlock; class UniformOffsetCalculator { public: UniformOffsetCalculator(Layout layout, uint32_t startingOffset); size_t size() const { return fOffset; } // Calculates the correctly aligned offset to accommodate `count` instances of `type` and // advances the internal offset. Returns the correctly aligned start offset. // // After a call to this method, `size()` will return the offset to the end of `count` instances // of `type` (while the return value equals the aligned start offset). Subsequent calls will // calculate the new start offset starting at `size()`. size_t advanceOffset(SkSLType type, unsigned int count); protected: SkSLType getUniformTypeForLayout(SkSLType type); void setLayout(Layout); using WriteUniformFn = uint32_t (*)(SkSLType type, CType ctype, void *dest, int n, const void *src); WriteUniformFn fWriteUniform; Layout fLayout; // TODO: eventually 'fLayout' will not need to be stored uint32_t fOffset = 0; }; class UniformManager : public UniformOffsetCalculator { public: UniformManager(Layout layout) : UniformOffsetCalculator(layout, /*startingOffset=*/0) {} UniformDataBlock finishUniformDataBlock(); size_t size() const { return fStorage.size(); } void resetWithNewLayout(Layout); void reset(); // Write a single instance of `type` from the data block referenced by `src`. void write(SkSLType type, const void* src); // Write an array of `type` with `count` elements from the data block referenced by `src`. // Does nothing if `count` is 0. void writeArray(SkSLType type, const void* src, unsigned int count); // Copy from `src` using Uniform array-count semantics. void write(const Uniform&, const uint8_t* src); void write(const SkM44&); void write(const SkPMColor4f&); void write(const SkRect&); void write(const SkV2&); void write(const SkV4&); void write(const SkPoint&); void write(float f); void write(int); void writeArray(SkSpan); void writeArray(SkSpan); void writeArray(SkSpan); void writeHalf(const SkMatrix&); void writeHalfArray(SkSpan); // Debug only utilities used for debug assertions and tests. void checkReset() const; void setExpectedUniforms(SkSpan); void checkExpected(SkSLType, unsigned int count); void doneWithExpectedUniforms(); private: // Writes a single element of the given `type` if `count` == 0 (aka Uniform::kNonArray). // Writes an array of `count` elements if `count` > 0, obeying any array layout constraints. // // Do not call this method directly for any new write()/writeArray() overloads. Instead // call the write(SkSLType, const void*) and writeArray(SkSLType, const void*, unsigned int) // overloads which correctly abstract the array vs non-array semantics. void writeInternal(SkSLType type, unsigned int count, const void* src); #ifdef SK_DEBUG SkSpan fExpectedUniforms; int fExpectedUniformIndex = 0; #endif // SK_DEBUG SkTDArray fStorage; uint32_t fReqAlignment = 0; }; } // namespace skgpu #endif // skgpu_UniformManager_DEFINED