Make SkRuntimeShaderBuilder safe for reuse

Previously, if you snapped off a shader and then changed uniforms
(without drawing & flushing), we'd trigger the SkData assert about
calling writeable_data when not-uniquely-owned. Now we lazily copy the
SkData when necessary.

Includes unit test that previously failed.

Bug: skia:10667
Change-Id: If8d9dd8106d41e66560d760cb36ed83371791fc7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/313678
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
diff --git a/tests/SkRuntimeEffectTest.cpp b/tests/SkRuntimeEffectTest.cpp
index 281f4a6..2ddf507 100644
--- a/tests/SkRuntimeEffectTest.cpp
+++ b/tests/SkRuntimeEffectTest.cpp
@@ -161,7 +161,7 @@
                                           "Got     : [ %08x %08x %08x %08x ]\n"
                                           "SkSL:\n%s\n",
                                           TL, TR, BL, BR, actual[0], actual[1], actual[2],
-                                          actual[3], fBuilder->fEffect->source().c_str()));
+                                          actual[3], fBuilder->effect()->source().c_str()));
         }
     }
 
@@ -267,3 +267,21 @@
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRuntimeEffectSimple_GPU, r, ctxInfo) {
     test_RuntimeEffect_Shaders(r, ctxInfo.directContext());
 }
+
+DEF_TEST(SkRuntimeShaderBuilderReuse, r) {
+    const char* kSource = R"(
+        uniform half x;
+        half4 main() { return half4(x); }
+    )";
+
+    sk_sp<SkRuntimeEffect> effect = std::get<0>(SkRuntimeEffect::Make(SkString(kSource)));
+    REPORTER_ASSERT(r, effect);
+
+    // Test passes if this sequence doesn't assert.  skbug.com/10667
+    SkRuntimeShaderBuilder b(std::move(effect));
+    b.uniform("x") = 0.0f;
+    auto shader_0 = b.makeShader(nullptr, false);
+
+    b.uniform("x") = 1.0f;
+    auto shader_1 = b.makeShader(nullptr, true);
+}