blob: 7b7a8f386d99c8c0e9dbdc97542e78ade225f285 [file] [log] [blame]
/*
* 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<const SkColor4f>);
void writeArray(SkSpan<const SkPMColor4f>);
void writeArray(SkSpan<const float>);
void writeHalf(const SkMatrix&);
void writeHalfArray(SkSpan<const float>);
// Debug only utilities used for debug assertions and tests.
void checkReset() const;
void setExpectedUniforms(SkSpan<const Uniform>);
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<const Uniform> fExpectedUniforms;
int fExpectedUniformIndex = 0;
#endif // SK_DEBUG
SkTDArray<char> fStorage;
uint32_t fReqAlignment = 0;
};
} // namespace skgpu
#endif // skgpu_UniformManager_DEFINED