Validate per-vertex vertices data against effect in SkCanvas

Updates the vertices_data GM to work on the GPU backend, too. For now,
it still works on the CPU via the original hack.

Bug: skia:9984
Change-Id: I2e11bd01e3cc953d2837ecd6ca8b2305b060e5fc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/278857
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/gm/vertices.cpp b/gm/vertices.cpp
index 5950263..715ee0d 100644
--- a/gm/vertices.cpp
+++ b/gm/vertices.cpp
@@ -297,7 +297,14 @@
 
     auto vert = builder.detach();
     SkPaint paint;
-    // paint.setShader(sksl_shader);
+    const char* gProg = R"(
+        varying float4 vtx_color;
+        void main(float2 p, inout half4 color) {
+            color = half4(vtx_color);
+        }
+    )";
+    auto [effect, errorText] = SkRuntimeEffect::Make(SkString(gProg));
+    paint.setShader(effect->makeShader(nullptr, nullptr, 0, nullptr, true));
     canvas->drawVertices(vert, paint);
 }
 
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 01ca4b0..61e7b89 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -17,6 +17,7 @@
 #include "include/core/SkString.h"
 #include "include/core/SkTextBlob.h"
 #include "include/core/SkVertices.h"
+#include "include/effects/SkRuntimeEffect.h"
 #include "include/private/SkNx.h"
 #include "include/private/SkTo.h"
 #include "include/utils/SkNoDrawCanvas.h"
@@ -1984,8 +1985,20 @@
 void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
     TRACE_EVENT0("skia", TRACE_FUNC);
     RETURN_ON_NULL(vertices);
+
+    SkVertices::Info info;
+    vertices->getInfo(&info);
+
     // We expect fans to be converted to triangles when building or deserializing SkVertices.
-    SkASSERT(SkVerticesPriv::Mode(vertices) != SkVertices::kTriangleFan_VertexMode);
+    SkASSERT(info.fMode != SkVertices::kTriangleFan_VertexMode);
+
+    // If the vertices contain custom attributes, ensure they line up with the paint's shader
+    const SkRuntimeEffect* effect =
+            paint.getShader() ? as_SB(paint.getShader())->asRuntimeEffect() : nullptr;
+    if (info.fPerVertexDataCount != (effect ? effect->varyingCount() : 0)) {
+        return;
+    }
+
     this->onDrawVerticesObject(vertices, mode, paint);
 }
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 22ee64f..6ce878d 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1039,12 +1039,7 @@
 
     const SkRuntimeEffect* effect =
             paint.getShader() ? as_SB(paint.getShader())->asRuntimeEffect() : nullptr;
-    int shaderVaryingCount = effect ? effect->varyingCount() : 0;
-
-    // TODO: Hoist this check up to SkCanvas
-    if (shaderVaryingCount != info.fPerVertexDataCount) {
-        return;
-    }
+    SkASSERT(info.fPerVertexDataCount == (effect ? effect->varyingCount() : 0));
 
     // Pretend that we have tex coords when using custom per-vertex data. The shader is going to
     // use those (rather than local coords), but our paint conversion remains the same.