[graphite] Pass SkUniforms around as an SkSpan

Bug: skia:12701
Change-Id: Iee63650517a739029f81121cabd45dfcc2e8fa38
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/502698
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/experimental/graphite/src/ContextUtils.cpp b/experimental/graphite/src/ContextUtils.cpp
index 2a8f94d..0b9579f 100644
--- a/experimental/graphite/src/ContextUtils.cpp
+++ b/experimental/graphite/src/ContextUtils.cpp
@@ -70,21 +70,17 @@
 // that only defines a [[depth]] attribute but no color calculation.
 static const char* kNoneSkSL = "outColor = half4(0.0, 0.0, 1.0, 1.0);\n";
 
-sk_sp<SkUniformData> make_gradient_uniform_data_common(const void* srcs[kNumGradientUniforms]) {
+sk_sp<SkUniformData> make_gradient_uniform_data_common(SkSpan<const SkUniform> uniforms,
+                                                       const void* srcs[kNumGradientUniforms]) {
     UniformManager mgr(Layout::kMetal);
 
     // TODO: Given that, for the sprint, we always know the uniforms we could cache 'dataSize'
     // for each layout and skip the first call.
-    size_t dataSize = mgr.writeUniforms(SkSpan<const SkUniform>(kGradientUniforms,
-                                                                kNumGradientUniforms),
-                                        nullptr, nullptr, nullptr);
+    size_t dataSize = mgr.writeUniforms(uniforms, nullptr, nullptr, nullptr);
 
-    sk_sp<SkUniformData> result = SkUniformData::Make(kNumGradientUniforms,
-                                                      kGradientUniforms,
-                                                      dataSize);
+    sk_sp<SkUniformData> result = SkUniformData::Make(uniforms, dataSize);
 
-    mgr.writeUniforms(SkSpan<const SkUniform>(kGradientUniforms, kNumGradientUniforms),
-                      srcs, result->offsets(), result->data());
+    mgr.writeUniforms(result->uniforms(), srcs, result->offsets(), result->data());
     return result;
 }
 
@@ -92,8 +88,13 @@
                                                        SkPoint endPoint,
                                                        SkColor4f colors[GradientData::kMaxStops],
                                                        float offsets[GradientData::kMaxStops]) {
+    static constexpr size_t kExpectedNumUniforms = 6;
+
+    SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kLinearGradientShader);
+    SkASSERT(uniforms.size() == kExpectedNumUniforms);
+
     float unusedRadii[2] = { 0.0f, 0.0f };
-    const void* srcs[kNumGradientUniforms] = {
+    const void* srcs[kExpectedNumUniforms] = {
             colors,
             offsets,
             &startPoint,
@@ -102,17 +103,22 @@
             &unusedRadii[1],
     };
 
-    return make_gradient_uniform_data_common(srcs);
+    return make_gradient_uniform_data_common(uniforms, srcs);
 };
 
 sk_sp<SkUniformData> make_radial_gradient_uniform_data(SkPoint point,
                                                        float radius,
                                                        SkColor4f colors[GradientData::kMaxStops],
                                                        float offsets[GradientData::kMaxStops]) {
+    static constexpr size_t kExpectedNumUniforms = 6;
+
+    SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kRadialGradientShader);
+    SkASSERT(uniforms.size() == kExpectedNumUniforms);
+
     SkPoint unusedPoint = {0.0f, 0.0f};
     float unusedRadius = 0.0f;
 
-    const void* srcs[kNumGradientUniforms] = {
+    const void* srcs[kExpectedNumUniforms] = {
             colors,
             offsets,
             &point,
@@ -121,16 +127,21 @@
             &unusedRadius,
     };
 
-    return make_gradient_uniform_data_common(srcs);
+    return make_gradient_uniform_data_common(uniforms, srcs);
 };
 
 sk_sp<SkUniformData> make_sweep_gradient_uniform_data(SkPoint point,
                                                       SkColor4f colors[GradientData::kMaxStops],
                                                       float offsets[GradientData::kMaxStops]) {
+    static constexpr size_t kExpectedNumUniforms = 6;
+
+    SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kSweepGradientShader);
+    SkASSERT(uniforms.size() == kExpectedNumUniforms);
+
     SkPoint unusedPoint = {0.0f, 0.0f};
     float unusedRadii[2] = {0.0f, 0.0f};
 
-    const void* srcs[kNumGradientUniforms] = {
+    const void* srcs[kExpectedNumUniforms] = {
             colors,
             offsets,
             &point,
@@ -139,7 +150,7 @@
             &unusedRadii[1],
     };
 
-    return make_gradient_uniform_data_common(srcs);
+    return make_gradient_uniform_data_common(uniforms, srcs);
 };
 
 sk_sp<SkUniformData> make_conical_gradient_uniform_data(SkPoint point0,
@@ -148,8 +159,12 @@
                                                         float radius1,
                                                         SkColor4f colors[GradientData::kMaxStops],
                                                         float offsets[GradientData::kMaxStops]) {
+    static constexpr size_t kExpectedNumUniforms = 6;
 
-    const void* srcs[kNumGradientUniforms] = {
+    SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kConicalGradientShader);
+    SkASSERT(uniforms.size() == kExpectedNumUniforms);
+
+    const void* srcs[kExpectedNumUniforms] = {
             colors,
             offsets,
             &point0,
@@ -158,21 +173,24 @@
             &radius1,
     };
 
-    return make_gradient_uniform_data_common(srcs);
+    return make_gradient_uniform_data_common(uniforms, srcs);
 };
 
 sk_sp<SkUniformData> make_solid_uniform_data(SkColor4f color) {
+    static constexpr size_t kExpectedNumUniforms = 1;
+
+    SkSpan<const SkUniform> uniforms = skgpu::GetUniforms(CodeSnippetID::kSolidColorShader);
+    SkASSERT(uniforms.size() == kExpectedNumUniforms);
+
     UniformManager mgr(Layout::kMetal);
 
-    size_t dataSize = mgr.writeUniforms(SkSpan<const SkUniform>(kSolidUniforms, kNumSolidUniforms),
-                                        nullptr, nullptr, nullptr);
+    size_t dataSize = mgr.writeUniforms(uniforms, nullptr, nullptr, nullptr);
 
-    sk_sp<SkUniformData> result = SkUniformData::Make(kNumSolidUniforms, kSolidUniforms, dataSize);
+    sk_sp<SkUniformData> result = SkUniformData::Make(uniforms, dataSize);
 
-    const void* srcs[kNumSolidUniforms] = { &color };
+    const void* srcs[kExpectedNumUniforms] = { &color };
 
-    mgr.writeUniforms(SkSpan<const SkUniform>(kSolidUniforms, kNumSolidUniforms),
-                      srcs, result->offsets(), result->data());
+    mgr.writeUniforms(result->uniforms(), srcs, result->offsets(), result->data());
     return result;
 }
 
@@ -290,12 +308,12 @@
     switch (snippetID) {
         case CodeSnippetID::kDepthStencilOnlyDraw:
             return {nullptr, 0};
-        case CodeSnippetID::kLinearGradientShader:
+        case CodeSnippetID::kLinearGradientShader: [[fallthrough]];
+        case CodeSnippetID::kRadialGradientShader: [[fallthrough]];
+        case CodeSnippetID::kSweepGradientShader:  [[fallthrough]];
+        case CodeSnippetID::kConicalGradientShader:
             return SkMakeSpan(kGradientUniforms, kNumGradientUniforms);
         case CodeSnippetID::kSolidColorShader:
-        case CodeSnippetID::kRadialGradientShader:
-        case CodeSnippetID::kSweepGradientShader:
-        case CodeSnippetID::kConicalGradientShader:
         default:
             return SkMakeSpan(kSolidUniforms, kNumSolidUniforms);
     }
@@ -305,12 +323,12 @@
     switch (snippetID) {
         case CodeSnippetID::kDepthStencilOnlyDraw:
             return kNoneSkSL;
-        case CodeSnippetID::kLinearGradientShader:
+        case CodeSnippetID::kLinearGradientShader: [[fallthrough]];
+        case CodeSnippetID::kRadialGradientShader: [[fallthrough]];
+        case CodeSnippetID::kSweepGradientShader:  [[fallthrough]];
+        case CodeSnippetID::kConicalGradientShader:
             return kGradientSkSL;
         case CodeSnippetID::kSolidColorShader:
-        case CodeSnippetID::kRadialGradientShader:
-        case CodeSnippetID::kSweepGradientShader:
-        case CodeSnippetID::kConicalGradientShader:
         default:
             return kSolidColorSkSL;
     }
diff --git a/src/core/SkUniformData.cpp b/src/core/SkUniformData.cpp
index 4349fd5..c073ac0 100644
--- a/src/core/SkUniformData.cpp
+++ b/src/core/SkUniformData.cpp
@@ -9,24 +9,24 @@
 
 #include "src/core/SkOpts.h"
 
-sk_sp<SkUniformData> SkUniformData::Make(int count,
-                                         const SkUniform* uniforms,
+sk_sp<SkUniformData> SkUniformData::Make(SkSpan<const SkUniform> uniforms,
                                          size_t dataSize) {
     // TODO: the offsets and data should just be allocated right after UniformData in an arena
-    uint32_t* offsets = new uint32_t[count];
+    uint32_t* offsets = new uint32_t[uniforms.size()];
     char* data = new char[dataSize];
 
-    return sk_sp<SkUniformData>(new SkUniformData(count, uniforms, offsets, data, dataSize));
+    return sk_sp<SkUniformData>(new SkUniformData(uniforms, offsets, data, dataSize));
 }
 
 bool SkUniformData::operator==(const SkUniformData& other) const {
-    if (this->count() != other.count() ||
-        this->uniforms() != other.uniforms() ||
+    if (this->uniforms().size() != other.uniforms().size() ||
         this->dataSize() != other.dataSize()) {
         return false;
     }
 
-    return !memcmp(this->data(), other.data(), this->dataSize()) &&
+    return !memcmp(this->uniforms().data(), other.uniforms().data(),
+                   this->uniforms().size_bytes()) &&
+           !memcmp(this->data(), other.data(), this->dataSize()) &&
            !memcmp(this->offsets(), other.offsets(), this->count()*sizeof(uint32_t));
 }
 
diff --git a/src/core/SkUniformData.h b/src/core/SkUniformData.h
index 1392479..d0398b6 100644
--- a/src/core/SkUniformData.h
+++ b/src/core/SkUniformData.h
@@ -9,10 +9,10 @@
 #define SkUniformData_DEFINED
 
 #include "include/core/SkRefCnt.h"
+#include "include/core/SkSpan.h"
+#include "src/core/SkUniform.h"
 #include <vector>
 
-class SkUniform;
-
 /*
  * TODO: Here is the plan of record for SkUniformData
  *    allocate them (and their ancillary data (offsets & data)) in an arena - and rm SkRefCnt
@@ -33,9 +33,7 @@
 
     // TODO: should we require a name (e.g., "gradient_uniforms") for each uniform block so
     // we can better name the Metal FS uniform struct?
-    static sk_sp<SkUniformData> Make(int count,
-                                     const SkUniform* uniforms,
-                                     size_t dataSize);
+    static sk_sp<SkUniformData> Make(SkSpan<const SkUniform>, size_t dataSize);
 
     ~SkUniformData() override {
         // TODO: fOffsets and fData should just be allocated right after UniformData in an arena
@@ -43,12 +41,12 @@
         delete [] fData;
     }
 
-    int count() const { return fCount; }
-    const SkUniform* uniforms() const { return fUniforms; }
+    int count() const { return static_cast<unsigned int>(fUniforms.size()); }
+    SkSpan<const SkUniform>  uniforms() const { return fUniforms; }
     uint32_t* offsets() { return fOffsets; }
     const uint32_t* offsets() const { return fOffsets; }
     uint32_t offset(int index) {
-        SkASSERT(index >= 0 && index < fCount);
+        SkASSERT(index >= 0 && static_cast<size_t>(index) < fUniforms.size());
         return fOffsets[index];
     }
     char* data() { return fData; }
@@ -59,20 +57,17 @@
     bool operator!=(const SkUniformData& other) const { return !(*this == other);  }
 
 private:
-    SkUniformData(int count,
-                  const SkUniform* uniforms,
+    SkUniformData(SkSpan<const SkUniform> uniforms,
                   uint32_t* offsets,
                   char* data,
                   size_t dataSize)
-            : fCount(count)
-            , fUniforms(uniforms)
+            : fUniforms(uniforms)
             , fOffsets(offsets)
             , fData(data)
             , fDataSize(dataSize) {
     }
 
-    const int fCount;
-    const SkUniform* fUniforms;
+    SkSpan<const SkUniform> fUniforms;
     uint32_t* fOffsets; // offset of each uniform in 'fData'
     char* fData;
     const size_t fDataSize;
diff --git a/tests/graphite/CommandBufferTest.cpp b/tests/graphite/CommandBufferTest.cpp
index c64cffc..c1a453a 100644
--- a/tests/graphite/CommandBufferTest.cpp
+++ b/tests/graphite/CommandBufferTest.cpp
@@ -84,8 +84,7 @@
         SkASSERT(shape.isRect());
         // TODO: A << API for uniforms would be nice, particularly if it could take pre-computed
         // offsets for each uniform.
-        auto uniforms = SkUniformData::Make(this->numUniforms(), this->uniforms().data(),
-                                            sizeof(float) * 4);
+        auto uniforms = SkUniformData::Make(this->uniforms(), sizeof(float) * 4);
         float2 scale = shape.rect().size();
         float2 translate = shape.rect().topLeft();
         memcpy(uniforms->data(), &scale, sizeof(float2));
@@ -147,8 +146,7 @@
                                        const SkIRect&,
                                        const Transform&,
                                        const Shape&) const override {
-        auto uniforms = SkUniformData::Make(this->numUniforms(), this->uniforms().data(),
-                                          sizeof(float) * 4);
+        auto uniforms = SkUniformData::Make(this->uniforms(), sizeof(float) * 4);
         float data[4] = {2.f, 2.f, -1.f, -1.f};
         memcpy(uniforms->data(), data, 4 * sizeof(float));
         return uniforms;
diff --git a/tests/graphite/UniformCacheTest.cpp b/tests/graphite/UniformCacheTest.cpp
index 952252a..709bedf 100644
--- a/tests/graphite/UniformCacheTest.cpp
+++ b/tests/graphite/UniformCacheTest.cpp
@@ -28,7 +28,8 @@
 
     SkASSERT(numUniforms <= kMaxUniforms);
 
-    sk_sp<SkUniformData> ud = SkUniformData::Make(numUniforms, kUniforms, dataSize);
+    sk_sp<SkUniformData> ud = SkUniformData::Make(SkSpan<const SkUniform>(kUniforms, numUniforms),
+                                                  dataSize);
     for (int i = 0; i < numUniforms; ++i) {
         ud->offsets()[i] = i;
     }