Revert "Change how vertex/instance attributes are handled in geometry processors."

This reverts commit 19c1233c447f625c2522e7ecd0a0adecc629bb2f.

Reason for revert: want to make sure Google3 can roll

Original change's description:
> Change how vertex/instance attributes are handled in geometry processors.
> 
> * No longer register vertex/instance attributes on base class, just counts
> 
> * Separate instance and vertex attributes and remove InputRate and offset
> 
> * Make attributes constexpr where possible
> 
> Change-Id: I1f1d5e772fa177a96d2aeb805aab7b69f35bfae6
> Reviewed-on: https://skia-review.googlesource.com/132405
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Chris Dalton <csmartdalton@google.com>

TBR=egdaniel@google.com,bsalomon@google.com,csmartdalton@google.com

Change-Id: I4800632515e14fbf54af52826928ac915657b59f
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/135661
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index bfc1e74..c75f13c 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -40,22 +40,23 @@
  */
 class GrPrimitiveProcessor : public GrResourceIOProcessor, public GrProgramElement {
 public:
-    /** Describes a vertex or instance attribute. */
     class Attribute {
     public:
+        enum class InputRate : bool {
+            kPerVertex,
+            kPerInstance
+        };
+
         constexpr Attribute() = default;
-        constexpr Attribute(const char* name, GrVertexAttribType type) : fName(name), fType(type) {}
-        constexpr Attribute(const Attribute&) = default;
+        constexpr Attribute(const char* name, GrVertexAttribType type, int offset, InputRate rate)
+                : fName(name), fType(type), fOffsetInRecord(offset), fInputRate(rate) {}
 
-        Attribute& operator=(const Attribute&) = default;
+        bool isInitialized() const { return SkToBool(fName); }
 
-        constexpr bool isInitialized() const { return SkToBool(fName); }
-
-        constexpr const char* name() const { return fName; }
-        constexpr GrVertexAttribType type() const { return fType; }
-
-        constexpr size_t size() const { return GrVertexAttribTypeSize(fType); }
-        constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); }
+        const char* name() const { return fName; }
+        GrVertexAttribType type() const { return fType; }
+        int offsetInRecord() const { return fOffsetInRecord; }
+        InputRate inputRate() const { return fInputRate; }
 
         GrShaderVar asShaderVar() const {
             return {fName, GrVertexAttribTypeToSLType(fType), GrShaderVar::kIn_TypeModifier};
@@ -64,34 +65,35 @@
     private:
         const char* fName = nullptr;
         GrVertexAttribType fType = kFloat_GrVertexAttribType;
+        int fOffsetInRecord = 0;
+        InputRate fInputRate = InputRate::kPerVertex;
     };
 
-    GrPrimitiveProcessor(ClassID);
+    GrPrimitiveProcessor(ClassID classID)
+    : GrResourceIOProcessor(classID) {}
 
-    int numVertexAttributes() const { return fVertexAttributeCnt; }
-    const Attribute& vertexAttribute(int i) const;
-    int numInstanceAttributes() const { return fInstanceAttributeCnt; }
-    const Attribute& instanceAttribute(int i) const;
+    int numAttribs() const { return fAttribs.count(); }
+    const Attribute& getAttrib(int index) const { return fAttribs[index]; }
 
-    bool hasVertexAttributes() const { return SkToBool(fVertexAttributeCnt); }
-    bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributeCnt); }
+    bool hasVertexAttribs() const { return SkToBool(fVertexStride); }
+    bool hasInstanceAttribs() const { return SkToBool(fInstanceStride); }
 
-#ifdef SK_DEBUG
     /**
-     * A common practice is to populate the the vertex/instance's memory using an implicit array of
-     * structs. In this case, it is best to assert that:
-     *     debugOnly_stride == sizeof(struct) and
-     *     offsetof(struct, field[i]) == debugOnly_AttributeOffset(i)
-     * In general having Op subclasses assert that attribute offsets and strides agree with their
-     * tessellation code's expectations is good practice.
-     * However, these functions walk the attributes to compute offsets and call virtual functions
-     * to access the attributes. Thus, they are only available in debug builds.
+     * These return the strides of the vertex and instance buffers. Attributes are expected to be
+     * laid out interleaved in their corresponding buffer (vertex or instance). fOffsetInRecord
+     * indicates an attribute's location in bytes relative to the first attribute. (These are padded
+     * to the nearest 4 bytes for performance reasons.)
+     *
+     * A common practice is to populate the buffer's memory using an implicit array of structs. In
+     * this case, it is best to assert:
+     *
+     *     stride == sizeof(struct) and
+     *     offsetof(struct, field[i]) == attrib[i].fOffsetInRecord
+     *
+     * NOTE: for instanced draws the vertex buffer has a single record that each instance reuses.
      */
-    size_t debugOnly_vertexStride() const;
-    size_t debugOnly_instanceStride() const;
-    size_t debugOnly_vertexAttributeOffset(int) const;
-    size_t debugOnly_instanceAttributeOffset(int) const;
-#endif
+    int getVertexStride() const { return fVertexStride; }
+    int getInstanceStride() const { return fInstanceStride; }
 
     // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but
     // we put these calls on the base class to prevent having to cast
@@ -127,11 +129,24 @@
      */
     virtual const char* getDestColorOverride() const { return nullptr; }
 
-    virtual float getSampleShading() const { return 0.0; }
+    virtual float getSampleShading() const {
+        return 0.0;
+    }
 
 protected:
-    void setVertexAttributeCnt(int cnt) { fVertexAttributeCnt = cnt; }
-    void setInstanceAttributeCnt(int cnt) { fInstanceAttributeCnt = cnt; }
+    /**
+     * Subclasses call these from their constructor to register vertex and instance attributes.
+     */
+    const Attribute& addVertexAttrib(const char* name, GrVertexAttribType type) {
+        fAttribs.push_back() = {name, type, fVertexStride, Attribute::InputRate::kPerVertex};
+        fVertexStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type)));
+        return fAttribs.back();
+    }
+    const Attribute& addInstanceAttrib(const char* name, GrVertexAttribType type) {
+        fAttribs.push_back() = {name, type, fInstanceStride, Attribute::InputRate::kPerInstance};
+        fInstanceStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type)));
+        return fAttribs.back();
+    }
 
 private:
     void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); }
@@ -139,11 +154,10 @@
     void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); }
     void notifyRefCntIsZero() const final {}
 
-    virtual const Attribute& onVertexAttribute(int) const = 0;
-    virtual const Attribute& onInstanceAttribute(int) const = 0;
+    SkSTArray<8, Attribute> fAttribs;
+    int fVertexStride = 0;
+    int fInstanceStride = 0;
 
-    int fVertexAttributeCnt = 0;
-    int fInstanceAttributeCnt = 0;
     typedef GrProcessor INHERITED;
 };