[graphite] Add instanced geometry for text.

Bug: skia:13118
Change-Id: Ifb738ffdefe489b08bfccedffa3d71c59818444c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/562761
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/gpu/graphite/DrawTypes.h b/src/gpu/graphite/DrawTypes.h
index e79e12c..9212c0b 100644
--- a/src/gpu/graphite/DrawTypes.h
+++ b/src/gpu/graphite/DrawTypes.h
@@ -71,7 +71,7 @@
     kInt,
     kUInt,
 
-    kUShort_norm,
+    kUShort_norm,  // unsigned short, e.g. depth, 0 -> 0.0f, 65535 -> 1.0f.
 
     kUShort4_norm, // vector of 4 unsigned shorts. 0 -> 0.0f, 65535 -> 1.0f.
 
diff --git a/src/gpu/graphite/render/TextDirectRenderStep.cpp b/src/gpu/graphite/render/TextDirectRenderStep.cpp
index 76ab4de..2f3e57b 100644
--- a/src/gpu/graphite/render/TextDirectRenderStep.cpp
+++ b/src/gpu/graphite/render/TextDirectRenderStep.cpp
@@ -41,13 +41,16 @@
                      "",
                      Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage,
                      /*uniforms=*/{{"atlasSizeInv", SkSLType::kFloat2}},
-                     PrimitiveType::kTriangles,
+                     PrimitiveType::kTriangleStrip,
                      kDirectShadingPass,
-                     /*vertexAttrs=*/
-                     {{"position", VertexAttribType::kFloat2, SkSLType::kFloat2},
-                      {"depth", VertexAttribType::kFloat, SkSLType::kFloat},
-                      {"texCoords", VertexAttribType::kUShort2, SkSLType::kUShort2}},
-                     /*instanceAttrs=*/{},
+                     /*vertexAttrs=*/ {},
+                     /*instanceAttrs=*/
+                     {{"mat0", VertexAttribType::kFloat3, SkSLType::kFloat3},
+                      {"mat1", VertexAttribType::kFloat3, SkSLType::kFloat3},
+                      {"mat2", VertexAttribType::kFloat3, SkSLType::kFloat3},
+                      {"uvScale", VertexAttribType::kUShort2, SkSLType::kUShort2},
+                      {"uvPos", VertexAttribType::kUShort2, SkSLType::kUShort2},
+                      {"depth", VertexAttribType::kUShort_norm, SkSLType::kFloat}},
                      /*varyings=*/
                      {{"textureCoords", SkSLType::kFloat2},
                       {"texIndex", SkSLType::kFloat}})
@@ -57,14 +60,16 @@
 
 const char* TextDirectRenderStep::vertexSkSL() const {
     return R"(
-        int2 coords = int2(texCoords.x, texCoords.y);
-        int texIdx = coords.x >> 13;
-        float2 unormTexCoords = float2(coords.x & 0x1FFF, coords.y);
+        float2 baseCoords = float2(float(sk_VertexID >> 1), float(sk_VertexID & 1));
+        baseCoords *= float2(uvScale);
+        float3 position = baseCoords.x*mat0 + baseCoords.y*mat1 + mat2;
+        int texIdx = (int)(uvPos.x >> 13);
+        float2 unormTexCoords = baseCoords + float2(uvPos.x & 0x1fff, uvPos.y);
 
         textureCoords = unormTexCoords * atlasSizeInv;
         texIndex = float(texIdx);
 
-        float4 devPosition = float4(position, depth, 1);
+        float4 devPosition = float4(position.xy, depth, position.z);
     )";
 }
 
@@ -119,9 +124,10 @@
 void TextDirectRenderStep::writeVertices(DrawWriter* dw, const DrawParams& params) const {
     const SubRunData& subRunData = params.geometry().subRunData();
     // TODO: pass through the color from the SkPaint via the SubRunData
-    subRunData.subRun()->fillVertexData(dw, subRunData.startGlyphIndex(), subRunData.glyphCount(),
-                                        params.order().depthAsFloat(),
-                                        params.transform());
+    uint16_t unormDepth = params.order().depth().bits();
+
+    subRunData.subRun()->fillInstanceData(dw, subRunData.startGlyphIndex(), subRunData.glyphCount(),
+                                          unormDepth, params.transform());
 }
 
 void TextDirectRenderStep::writeUniformsAndTextures(const DrawParams& params,
diff --git a/src/gpu/graphite/render/TextSDFRenderStep.cpp b/src/gpu/graphite/render/TextSDFRenderStep.cpp
index 29c2ee0..dfc5295 100644
--- a/src/gpu/graphite/render/TextSDFRenderStep.cpp
+++ b/src/gpu/graphite/render/TextSDFRenderStep.cpp
@@ -40,13 +40,16 @@
                      Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage,
                      /*uniforms=*/{{"atlasSizeInv", SkSLType::kFloat2},
                                    {"distanceAdjust", SkSLType::kFloat}},
-                     PrimitiveType::kTriangles,
+                     PrimitiveType::kTriangleStrip,
                      kDirectShadingPass,
-                     /*vertexAttrs=*/
-                     {{"position", VertexAttribType::kFloat2, SkSLType::kFloat2},
-                      {"depth", VertexAttribType::kFloat, SkSLType::kFloat},
-                      {"texCoords", VertexAttribType::kUShort2, SkSLType::kUShort2}},
-                     /*instanceAttrs=*/{},
+                     /*vertexAttrs=*/ {},
+                     /*instanceAttrs=*/
+                     {{"mat0", VertexAttribType::kFloat3, SkSLType::kFloat3},
+                      {"mat1", VertexAttribType::kFloat3, SkSLType::kFloat3},
+                      {"mat2", VertexAttribType::kFloat3, SkSLType::kFloat3},
+                      {"uvScale", VertexAttribType::kUShort2, SkSLType::kUShort2},
+                      {"uvPos", VertexAttribType::kUShort2, SkSLType::kUShort2},
+                      {"depth", VertexAttribType::kUShort_norm, SkSLType::kFloat}},
                      /*varyings=*/
                      {{"unormTexCoords", SkSLType::kFloat2},
                       {"textureCoords", SkSLType::kFloat2},
@@ -58,15 +61,18 @@
 
 const char* TextSDFRenderStep::vertexSkSL() const {
     return R"(
-        int2 coords = int2(texCoords.x, texCoords.y);
-        int texIdx = coords.x >> 13;
+        float2 baseCoords = float2(float(sk_VertexID >> 1), float(sk_VertexID & 1));
+        baseCoords *= float2(uvScale);
+        float3 position = baseCoords.x*mat0 + baseCoords.y*mat1 + mat2;
 
-        unormTexCoords = float2(coords.x & 0x1FFF, coords.y);
+        int texIdx = (int)(uvPos.x >> 13);
+        unormTexCoords = baseCoords + float2(uvPos.x & 0x1fff, uvPos.y);
+
         textureCoords = unormTexCoords * atlasSizeInv;
         texIndex = float(texIdx);
 
-        float4 devPosition = float4(position, depth, 1);
-        )";
+        float4 devPosition = float4(position.xy, depth, position.z);
+    )";
 }
 
 std::string TextSDFRenderStep::texturesAndSamplersSkSL(int binding) const {
@@ -141,8 +147,9 @@
 
 void TextSDFRenderStep::writeVertices(DrawWriter* dw, const DrawParams& params) const {
     const SubRunData& subRunData = params.geometry().subRunData();
-    subRunData.subRun()->fillVertexData(dw, subRunData.startGlyphIndex(), subRunData.glyphCount(),
-                                        params.order().depthAsFloat(), params.transform());
+    uint16_t unormDepth = params.order().depth().bits();
+    subRunData.subRun()->fillInstanceData(dw, subRunData.startGlyphIndex(), subRunData.glyphCount(),
+                                          unormDepth, params.transform());
 }
 
 void TextSDFRenderStep::writeUniformsAndTextures(const DrawParams& params,
diff --git a/src/text/gpu/SubRunContainer.cpp b/src/text/gpu/SubRunContainer.cpp
index 73ba8a5..60d74a0 100644
--- a/src/text/gpu/SubRunContainer.cpp
+++ b/src/text/gpu/SubRunContainer.cpp
@@ -63,6 +63,8 @@
 using namespace sktext::gpu;
 
 #if defined(SK_GRAPHITE_ENABLED)
+using BindBufferInfo = skgpu::graphite::BindBufferInfo;
+using BufferType = skgpu::graphite::BufferType;
 using Device = skgpu::graphite::Device;
 using DrawWriter = skgpu::graphite::DrawWriter;
 using Rect = skgpu::graphite::Rect;
@@ -130,6 +132,11 @@
                         SkSpan<const Glyph*> glyphs,
                         SkScalar depth,
                         const skgpu::graphite::Transform& toDevice) const;
+    void fillInstanceData(DrawWriter* dw,
+                          int offset, int count,
+                          SkSpan<const Glyph*> glyphs,
+                          uint16_t depth,
+                          const skgpu::graphite::Transform& toDevice) const;
 #endif
     SkRect deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const;
     MaskFormat grMaskType() const {return fMaskType;}
@@ -397,6 +404,36 @@
                         << SkPoint{devOut[1].x, devOut[1].y} << depth << AtlasPt{ar, at}; // R,T
     }
 }
+
+void TransformedMaskVertexFiller::fillInstanceData(DrawWriter* dw,
+                                                   int offset, int count,
+                                                   SkSpan<const Glyph*> glyphs,
+                                                   uint16_t depth,
+                                                   const Transform& toDevice) const {
+    auto quadData = [&]() {
+        return SkMakeZip(glyphs.subspan(offset, count),
+                         fLeftTop.subspan(offset, count));
+    };
+
+    DrawWriter::Instances instances{*dw, {}, {}, 4};
+    instances.reserve(count);
+    const SkM44& m44(toDevice);
+    skvx::float4 c0 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m44) + 0);
+    skvx::float4 c1 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m44) + 4);
+    skvx::float4 c3 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m44) + 12);
+    skvx::float4 newC0 = fStrikeToSourceScale*c0;
+    skvx::float4 newC1 = fStrikeToSourceScale*c1;
+    for (auto [glyph, leftTop]: quadData()) {
+        auto[al, at, ar, ab] = glyph->fAtlasLocator.getUVs();
+        skvx::float4 newC3 = leftTop.x()*c0 + leftTop.y()*c1 + c3;
+        instances.append(1) << newC0.x() << newC0.y() << newC0.w()
+                            << newC1.x() << newC1.y() << newC1.w()
+                            << newC3.x() << newC3.y() << newC3.w()
+                            << AtlasPt{uint16_t(ar-al), uint16_t(ab-at)} << AtlasPt{al, at}
+                            << depth;
+    }
+}
+
 #endif
 
 
@@ -1206,6 +1243,10 @@
                         int offset, int count,
                         SkScalar depth,
                         const skgpu::graphite::Transform& transform) const override;
+    void fillInstanceData(skgpu::graphite::DrawWriter*,
+                          int offset, int count,
+                          uint16_t depth,
+                          const skgpu::graphite::Transform& transform) const override;
 
     MaskFormat maskFormat() const override { return fMaskFormat; }
 #endif
@@ -1652,6 +1693,33 @@
         transformed_direct_dw(dw, quadData(), depth, toDevice);
     }
 }
+
+void DirectMaskSubRun::fillInstanceData(DrawWriter* dw,
+                                        int offset, int count,
+                                        uint16_t depth,
+                                        const skgpu::graphite::Transform& toDevice) const {
+    auto quadData = [&]() {
+        return SkMakeZip(fGlyphs.glyphs().subspan(offset, count),
+                         fLeftTopDevicePos.subspan(offset, count));
+    };
+
+    DrawWriter::Instances instances{*dw, {}, {}, 4};
+    instances.reserve(count);
+    const SkM44& m44(toDevice);
+    skvx::float4 c0 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m44) + 0);
+    skvx::float4 c1 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m44) + 4);
+    skvx::float4 c3 = skvx::float4::Load(SkMatrixPriv::M44ColMajor(m44) + 12);
+    for (auto [glyph, leftTop]: quadData()) {
+        auto[al, at, ar, ab] = glyph->fAtlasLocator.getUVs();
+        skvx::float4 newC3 = leftTop.x()*c0 + leftTop.y()*c1 + c3;
+        instances.append(1) << c0.x() << c0.y() << c0.w()
+                            << c1.x() << c1.y() << c1.w()
+                            << newC3.x() << newC3.y() << newC3.w()
+                            << AtlasPt{uint16_t(ar-al), uint16_t(ab-at)} << AtlasPt{al, at}
+                            << depth;
+    }
+}
+
 #endif
 
 // true if only need to translate by integer amount, device rect.
@@ -1755,6 +1823,10 @@
                         int offset, int count,
                         SkScalar depth,
                         const skgpu::graphite::Transform& transform) const override;
+    void fillInstanceData(DrawWriter*,
+                          int offset, int count,
+                          uint16_t depth,
+                          const skgpu::graphite::Transform& transform) const override;
 
     MaskFormat maskFormat() const override { return fVertexFiller.grMaskType(); }
 #endif
@@ -1945,6 +2017,18 @@
                                  depth,
                                  transform);
 }
+
+void TransformedMaskSubRun::fillInstanceData(DrawWriter* dw,
+                                             int offset, int count,
+                                             uint16_t depth,
+                                             const Transform& transform) const {
+    fVertexFiller.fillInstanceData(dw,
+                                   offset, count,
+                                   fGlyphs.glyphs(),
+                                   depth,
+                                   transform);
+}
+
 #endif
 
 int TransformedMaskSubRun::glyphCount() const {
@@ -2036,6 +2120,10 @@
                         int offset, int count,
                         SkScalar depth,
                         const skgpu::graphite::Transform& transform) const override;
+    void fillInstanceData(DrawWriter*,
+                          int offset, int count,
+                          uint16_t depth,
+                          const skgpu::graphite::Transform& transform) const override;
 
     MaskFormat maskFormat() const override { return fVertexFiller.grMaskType(); }
 #endif
@@ -2283,13 +2371,24 @@
 void SDFTSubRun::fillVertexData(DrawWriter* dw,
                                 int offset, int count,
                                 SkScalar depth,
-                                const skgpu::graphite::Transform& transform) const {
+                                const Transform& transform) const {
     fVertexFiller.fillVertexData(dw,
                                  offset, count,
                                  fGlyphs.glyphs(),
                                  depth,
                                  transform);
 }
+
+void SDFTSubRun::fillInstanceData(DrawWriter* dw,
+                                  int offset, int count,
+                                  uint16_t depth,
+                                  const Transform& transform) const {
+    fVertexFiller.fillInstanceData(dw,
+                                   offset, count,
+                                   fGlyphs.glyphs(),
+                                   depth,
+                                   transform);
+}
 #endif
 
 int SDFTSubRun::glyphCount() const {
diff --git a/src/text/gpu/SubRunContainer.h b/src/text/gpu/SubRunContainer.h
index d0467b3..789dcf0 100644
--- a/src/text/gpu/SubRunContainer.h
+++ b/src/text/gpu/SubRunContainer.h
@@ -117,6 +117,11 @@
             int offset, int count,
             SkScalar depth,
             const skgpu::graphite::Transform& transform) const = 0;
+    virtual void fillInstanceData(
+            skgpu::graphite::DrawWriter*,
+            int offset, int count,
+            uint16_t depth,
+            const skgpu::graphite::Transform& transform) const = 0;
 
     virtual skgpu::MaskFormat maskFormat() const = 0;
 #endif