/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/ganesh/GrGeometryProcessor.h"

#include "include/core/SkSamplingOptions.h"
#include "include/core/SkString.h"
#include "include/private/SkSLSampleUsage.h"
#include "include/private/base/SkSafe32.h"
#include "src/core/SkMatrixPriv.h"
#include "src/gpu/KeyBuilder.h"
#include "src/gpu/ganesh/GrPipeline.h"
#include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h"
#include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
#include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
#include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"

#include <algorithm>
#include <queue>
#include <utility>
#include <vector>

GrGeometryProcessor::GrGeometryProcessor(ClassID classID) : GrProcessor(classID) {}

const GrGeometryProcessor::TextureSampler& GrGeometryProcessor::textureSampler(int i) const {
    SkASSERT(i >= 0 && i < this->numTextureSamplers());
    return this->onTextureSampler(i);
}

uint32_t GrGeometryProcessor::ComputeCoordTransformsKey(const GrFragmentProcessor& fp) {
    // This is highly coupled with the code in ProgramImpl::collectTransforms().
    uint32_t key = static_cast<uint32_t>(fp.sampleUsage().kind()) << 1;
    // This needs to be updated if GP starts specializing varyings on additional matrix types.
    if (fp.sampleUsage().hasPerspective()) {
        key |= 0b1;
    }
    return key;
}

void GrGeometryProcessor::getAttributeKey(skgpu::KeyBuilder* b) const {
    b->appendComment("vertex attributes");
    fVertexAttributes.addToKey(b);
    b->appendComment("instance attributes");
    fInstanceAttributes.addToKey(b);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

static inline GrSamplerState::Filter clamp_filter(GrTextureType type,
                                                  GrSamplerState::Filter requestedFilter) {
    if (GrTextureTypeHasRestrictedSampling(type)) {
        return std::min(requestedFilter, GrSamplerState::Filter::kLinear);
    }
    return requestedFilter;
}

GrGeometryProcessor::TextureSampler::TextureSampler(GrSamplerState samplerState,
                                                    const GrBackendFormat& backendFormat,
                                                    const skgpu::Swizzle& swizzle) {
    this->reset(samplerState, backendFormat, swizzle);
}

void GrGeometryProcessor::TextureSampler::reset(GrSamplerState samplerState,
                                                const GrBackendFormat& backendFormat,
                                                const skgpu::Swizzle& swizzle) {
    fSamplerState = samplerState;
    fSamplerState = GrSamplerState(samplerState.wrapModeX(),
                                   samplerState.wrapModeY(),
                                   clamp_filter(backendFormat.textureType(), samplerState.filter()),
                                   samplerState.mipmapMode());
    fBackendFormat = backendFormat;
    fSwizzle = swizzle;
    fIsInitialized = true;
}

//////////////////////////////////////////////////////////////////////////////

using ProgramImpl = GrGeometryProcessor::ProgramImpl;

std::tuple<ProgramImpl::FPCoordsMap, GrShaderVar>
ProgramImpl::emitCode(EmitArgs& args, const GrPipeline& pipeline) {
    GrGPArgs gpArgs;
    this->onEmitCode(args, &gpArgs);

    FPCoordsMap transformMap = this->collectTransforms(args.fVertBuilder,
                                                       args.fVaryingHandler,
                                                       args.fUniformHandler,
                                                       gpArgs.fLocalCoordShader,
                                                       gpArgs.fLocalCoordVar,
                                                       gpArgs.fPositionVar,
                                                       pipeline);

    GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
    // Emit the vertex position to the hardware in the normalized window coordinates it expects.
    SkASSERT(SkSLType::kFloat2 == gpArgs.fPositionVar.getType() ||
                SkSLType::kFloat3 == gpArgs.fPositionVar.getType());
    vBuilder->emitNormalizedSkPosition(gpArgs.fPositionVar.c_str(),
                                        gpArgs.fPositionVar.getType());
    if (SkSLType::kFloat2 == gpArgs.fPositionVar.getType()) {
        args.fVaryingHandler->setNoPerspective();
    }

    return {transformMap, gpArgs.fLocalCoordVar};
}

ProgramImpl::FPCoordsMap ProgramImpl::collectTransforms(GrGLSLVertexBuilder* vb,
                                                        GrGLSLVaryingHandler* varyingHandler,
                                                        GrGLSLUniformHandler* uniformHandler,
                                                        GrShaderType localCoordsShader,
                                                        const GrShaderVar& localCoordsVar,
                                                        const GrShaderVar& positionVar,
                                                        const GrPipeline& pipeline) {
    SkASSERT(localCoordsVar.getType() == SkSLType::kFloat2 ||
             localCoordsVar.getType() == SkSLType::kFloat3 ||
             localCoordsVar.getType() == SkSLType::kVoid);
    SkASSERT(positionVar.getType() == SkSLType::kFloat2 ||
             positionVar.getType() == SkSLType::kFloat3 ||
             positionVar.getType() == SkSLType::kVoid);

    auto baseLocalCoordFSVar = [&, baseLocalCoordVarying = GrGLSLVarying()]() mutable {
        if (localCoordsShader == kFragment_GrShaderType) {
            return localCoordsVar;
        }
        SkASSERT(localCoordsShader == kVertex_GrShaderType);
        SkASSERT(SkSLTypeIsFloatType(localCoordsVar.getType()));
        if (baseLocalCoordVarying.type() == SkSLType::kVoid) {
            // Initialize to the GP provided coordinate
            baseLocalCoordVarying = GrGLSLVarying(localCoordsVar.getType());
            varyingHandler->addVarying("LocalCoord", &baseLocalCoordVarying);
            vb->codeAppendf("%s = %s;\n",
                            baseLocalCoordVarying.vsOut(),
                            localCoordsVar.getName().c_str());
        }
        return baseLocalCoordVarying.fsInVar();
    };

    bool canUsePosition = positionVar.getType() != SkSLType::kVoid;

    FPCoordsMap result;
    // Performs a pre-order traversal of FP hierarchy rooted at fp and identifies FPs that are
    // sampled with a series of matrices applied to local coords. For each such FP a varying is
    // added to the varying handler and added to 'result'.
    auto liftTransforms = [&, traversalIndex = 0](
                                  auto& self,
                                  const GrFragmentProcessor& fp,
                                  bool hasPerspective,
                                  const GrFragmentProcessor* lastMatrixFP = nullptr,
                                  int lastMatrixTraversalIndex = -1,
                                  BaseCoord baseCoord = BaseCoord::kLocal) mutable -> void {
        ++traversalIndex;
        if (localCoordsShader == kVertex_GrShaderType) {
            switch (fp.sampleUsage().kind()) {
                case SkSL::SampleUsage::Kind::kNone:
                    // This should only happen at the root. Otherwise how did this FP get added?
                    SkASSERT(!fp.parent());
                    break;
                case SkSL::SampleUsage::Kind::kPassThrough:
                    break;
                case SkSL::SampleUsage::Kind::kUniformMatrix:
                    // Update tracking of last matrix and matrix props.
                    hasPerspective |= fp.sampleUsage().hasPerspective();
                    lastMatrixFP = &fp;
                    lastMatrixTraversalIndex = traversalIndex;
                    break;
                case SkSL::SampleUsage::Kind::kFragCoord:
                    hasPerspective = positionVar.getType() == SkSLType::kFloat3;
                    lastMatrixFP = nullptr;
                    lastMatrixTraversalIndex = -1;
                    baseCoord = BaseCoord::kPosition;
                    break;
                case SkSL::SampleUsage::Kind::kExplicit:
                    baseCoord = BaseCoord::kNone;
                    break;
            }
        } else {
            // If the GP doesn't provide an interpolatable local coord then there is no hope to
            // lift.
            baseCoord = BaseCoord::kNone;
        }

        auto& [varyingFSVar, hasCoordsParam] = result[&fp];
        hasCoordsParam = fp.usesSampleCoordsDirectly();

        // We add a varying if we're in a chain of matrices multiplied by local or device coords.
        // If the coord is the untransformed local coord we add a varying. We don't if it is
        // untransformed device coords since it doesn't save us anything over "sk_FragCoord.xy". Of
        // course, if the FP doesn't directly use its coords then we don't add a varying.
        if (fp.usesSampleCoordsDirectly() &&
            (baseCoord == BaseCoord::kLocal ||
             (baseCoord == BaseCoord::kPosition && lastMatrixFP && canUsePosition))) {
            // Associate the varying with the highest possible node in the FP tree that shares the
            // same coordinates so that multiple FPs in a subtree can share. If there are no matrix
            // sample nodes on the way up the tree then directly use the local coord.
            if (!lastMatrixFP) {
                varyingFSVar = baseLocalCoordFSVar();
            } else {
                // If there is an already a varying that incorporates all matrices from the root to
                // lastMatrixFP just use it. Otherwise, we add it.
                auto& [varying, inputCoords, varyingIdx] = fTransformVaryingsMap[lastMatrixFP];
                if (varying.type() == SkSLType::kVoid) {
                    varying = GrGLSLVarying(hasPerspective ? SkSLType::kFloat3 : SkSLType::kFloat2);
                    SkString strVaryingName = SkStringPrintf("TransformedCoords_%d",
                                                             lastMatrixTraversalIndex);
                    varyingHandler->addVarying(strVaryingName.c_str(), &varying);
                    inputCoords = baseCoord == BaseCoord::kLocal ? localCoordsVar : positionVar;
                    varyingIdx = lastMatrixTraversalIndex;
                }
                SkASSERT(varyingIdx == lastMatrixTraversalIndex);
                // The FP will use the varying in the fragment shader as its coords.
                varyingFSVar = varying.fsInVar();
            }
            hasCoordsParam = false;
        }

        for (int c = 0; c < fp.numChildProcessors(); ++c) {
            if (auto* child = fp.childProcessor(c)) {
                self(self,
                     *child,
                     hasPerspective,
                     lastMatrixFP,
                     lastMatrixTraversalIndex,
                     baseCoord);
                // If we have a varying then we never need a param. Otherwise, if one of our
                // children takes a non-explicit coord then we'll need our coord.
                hasCoordsParam |= varyingFSVar.getType() == SkSLType::kVoid &&
                                  !child->sampleUsage().isExplicit()        &&
                                  !child->sampleUsage().isFragCoord()       &&
                                  result[child].hasCoordsParam;
            }
        }
    };

    bool hasPerspective = SkSLTypeVecLength(localCoordsVar.getType()) == 3;
    for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
        liftTransforms(liftTransforms, pipeline.getFragmentProcessor(i), hasPerspective);
    }
    return result;
}

void ProgramImpl::emitTransformCode(GrGLSLVertexBuilder* vb, GrGLSLUniformHandler* uniformHandler) {
    // Because descendant varyings may be computed using the varyings of ancestor FPs we make
    // sure to visit the varyings according to FP pre-order traversal by dumping them into a
    // priority queue.
    using FPAndInfo = std::tuple<const GrFragmentProcessor*, TransformInfo>;
    auto compare = [](const FPAndInfo& a, const FPAndInfo& b) {
        return std::get<1>(a).traversalOrder > std::get<1>(b).traversalOrder;
    };
    std::priority_queue<FPAndInfo, std::vector<FPAndInfo>, decltype(compare)> pq(compare);
    std::for_each(fTransformVaryingsMap.begin(), fTransformVaryingsMap.end(), [&pq](auto entry) {
        pq.push(entry);
    });
    for (; !pq.empty(); pq.pop()) {
        const auto& [fp, info] = pq.top();
        // If we recorded a transform info, its sample matrix must be uniform
        SkASSERT(fp->sampleUsage().isUniformMatrix());
        GrShaderVar uniform = uniformHandler->liftUniformToVertexShader(
                *fp->parent(), SkString(SkSL::SampleUsage::MatrixUniformName()));
        // Start with this matrix and accumulate additional matrices as we walk up the FP tree
        // to either the base coords or an ancestor FP that has an associated varying.
        SkString transformExpression = uniform.getName();

        // If we hit an ancestor with a varying on our walk up then save off the varying as the
        // input to our accumulated transformExpression. Start off assuming we'll reach the root.
        GrShaderVar inputCoords = info.inputCoords;

        for (const auto* base = fp->parent(); base; base = base->parent()) {
            if (auto iter = fTransformVaryingsMap.find(base); iter != fTransformVaryingsMap.end()) {
                // Can stop here, as this varying already holds all transforms from higher FPs
                // We'll apply the residual transformExpression we've accumulated up from our
                // starting FP to this varying.
                inputCoords = iter->second.varying.vsOutVar();
                break;
            } else if (base->sampleUsage().isUniformMatrix()) {
                // Accumulate any matrices along the path to either the original local/device coords
                // or a parent varying. Getting here means this FP was sampled with a uniform matrix
                // but all uses of coords below here in the FP hierarchy are beneath additional
                // matrix samples and thus this node wasn't assigned a varying.
                GrShaderVar parentUniform = uniformHandler->liftUniformToVertexShader(
                        *base->parent(), SkString(SkSL::SampleUsage::MatrixUniformName()));
                transformExpression.appendf(" * %s", parentUniform.getName().c_str());
            } else if (base->sampleUsage().isFragCoord()) {
                // Our chain of matrices starts here and is based on the device space position.
                break;
            } else {
                // This intermediate FP is just a pass through and doesn't need to be built
                // in to the expression, but we must visit its parents in case they add transforms.
                SkASSERT(base->sampleUsage().isPassThrough() || !base->sampleUsage().isSampled());
            }
        }

        SkString inputStr;
        if (inputCoords.getType() == SkSLType::kFloat2) {
            inputStr = SkStringPrintf("%s.xy1", inputCoords.getName().c_str());
        } else {
            SkASSERT(inputCoords.getType() == SkSLType::kFloat3);
            inputStr = inputCoords.getName();
        }

        vb->codeAppend("{\n");
        if (info.varying.type() == SkSLType::kFloat2) {
            if (vb->getProgramBuilder()->shaderCaps()->fNonsquareMatrixSupport) {
                vb->codeAppendf("%s = float3x2(%s) * %s",
                                info.varying.vsOut(),
                                transformExpression.c_str(),
                                inputStr.c_str());
            } else {
                vb->codeAppendf("%s = (%s * %s).xy",
                                info.varying.vsOut(),
                                transformExpression.c_str(),
                                inputStr.c_str());
            }
        } else {
            SkASSERT(info.varying.type() == SkSLType::kFloat3);
            vb->codeAppendf("%s = %s * %s",
                            info.varying.vsOut(),
                            transformExpression.c_str(),
                            inputStr.c_str());
        }
        vb->codeAppend(";\n");
        vb->codeAppend("}\n");
    }
    // We don't need this map anymore.
    fTransformVaryingsMap.clear();
}

void ProgramImpl::setupUniformColor(GrGLSLFPFragmentBuilder* fragBuilder,
                                    GrGLSLUniformHandler* uniformHandler,
                                    const char* outputName,
                                    UniformHandle* colorUniform) {
    SkASSERT(colorUniform);
    const char* stagedLocalVarName;
    *colorUniform = uniformHandler->addUniform(nullptr,
                                               kFragment_GrShaderFlag,
                                               SkSLType::kHalf4,
                                               "Color",
                                               &stagedLocalVarName);
    fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
    if (fragBuilder->getProgramBuilder()->shaderCaps()->fMustObfuscateUniformColor) {
        fragBuilder->codeAppendf("%s = max(%s, half4(0));", outputName, outputName);
    }
}

void ProgramImpl::SetTransform(const GrGLSLProgramDataManager& pdman,
                               const GrShaderCaps& shaderCaps,
                               const UniformHandle& uniform,
                               const SkMatrix& matrix,
                               SkMatrix* state) {
    if (!uniform.isValid() || (state && SkMatrixPriv::CheapEqual(*state, matrix))) {
        // No update needed
        return;
    }
    if (state) {
        *state = matrix;
    }
    if (matrix.isScaleTranslate() && !shaderCaps.fReducedShaderMode) {
        // ComputeMatrixKey and writeX() assume the uniform is a float4 (can't assert since nothing
        // is exposed on a handle, but should be caught lower down).
        float values[4] = {matrix.getScaleX(), matrix.getTranslateX(),
                           matrix.getScaleY(), matrix.getTranslateY()};
        pdman.set4fv(uniform, 1, values);
    } else {
        pdman.setSkMatrix(uniform, matrix);
    }
}

static void write_passthrough_vertex_position(GrGLSLVertexBuilder* vertBuilder,
                                              const GrShaderVar& inPos,
                                              GrShaderVar* outPos) {
    SkASSERT(inPos.getType() == SkSLType::kFloat3 || inPos.getType() == SkSLType::kFloat2);
    SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str());
    outPos->set(inPos.getType(), outName.c_str());
    vertBuilder->codeAppendf("float%d %s = %s;",
                             SkSLTypeVecLength(inPos.getType()),
                             outName.c_str(),
                             inPos.getName().c_str());
}

static void write_vertex_position(GrGLSLVertexBuilder* vertBuilder,
                                  GrGLSLUniformHandler* uniformHandler,
                                  const GrShaderCaps& shaderCaps,
                                  const GrShaderVar& inPos,
                                  const SkMatrix& matrix,
                                  const char* matrixName,
                                  GrShaderVar* outPos,
                                  ProgramImpl::UniformHandle* matrixUniform) {
    SkASSERT(inPos.getType() == SkSLType::kFloat3 || inPos.getType() == SkSLType::kFloat2);
    SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str());

    if (matrix.isIdentity() && !shaderCaps.fReducedShaderMode) {
        write_passthrough_vertex_position(vertBuilder, inPos, outPos);
        return;
    }
    SkASSERT(matrixUniform);

    bool useCompactTransform = matrix.isScaleTranslate() && !shaderCaps.fReducedShaderMode;
    const char* mangledMatrixName;
    *matrixUniform = uniformHandler->addUniform(nullptr,
                                                kVertex_GrShaderFlag,
                                                useCompactTransform ? SkSLType::kFloat4
                                                                    : SkSLType::kFloat3x3,
                                                matrixName,
                                                &mangledMatrixName);

    if (inPos.getType() == SkSLType::kFloat3) {
        // A float3 stays a float3 whether or not the matrix adds perspective
        if (useCompactTransform) {
            vertBuilder->codeAppendf("float3 %s = %s.xz1 * %s + %s.yw0;\n",
                                     outName.c_str(),
                                     mangledMatrixName,
                                     inPos.getName().c_str(),
                                     mangledMatrixName);
        } else {
            vertBuilder->codeAppendf("float3 %s = %s * %s;\n",
                                     outName.c_str(),
                                     mangledMatrixName,
                                     inPos.getName().c_str());
        }
        outPos->set(SkSLType::kFloat3, outName.c_str());
        return;
    }
    if (matrix.hasPerspective()) {
        // A float2 is promoted to a float3 if we add perspective via the matrix
        SkASSERT(!useCompactTransform);
        vertBuilder->codeAppendf("float3 %s = (%s * %s.xy1);",
                                 outName.c_str(),
                                 mangledMatrixName,
                                 inPos.getName().c_str());
        outPos->set(SkSLType::kFloat3, outName.c_str());
        return;
    }
    if (useCompactTransform) {
        vertBuilder->codeAppendf("float2 %s = %s.xz * %s + %s.yw;\n",
                                 outName.c_str(),
                                 mangledMatrixName,
                                 inPos.getName().c_str(),
                                 mangledMatrixName);
    } else if (shaderCaps.fNonsquareMatrixSupport) {
        vertBuilder->codeAppendf("float2 %s = float3x2(%s) * %s.xy1;\n",
                                 outName.c_str(),
                                 mangledMatrixName,
                                 inPos.getName().c_str());
    } else {
        vertBuilder->codeAppendf("float2 %s = (%s * %s.xy1).xy;\n",
                                 outName.c_str(),
                                 mangledMatrixName,
                                 inPos.getName().c_str());
    }
    outPos->set(SkSLType::kFloat2, outName.c_str());
}

void ProgramImpl::WriteOutputPosition(GrGLSLVertexBuilder* vertBuilder,
                                      GrGPArgs* gpArgs,
                                      const char* posName) {
    // writeOutputPosition assumes the incoming pos name points to a float2 variable
    GrShaderVar inPos(posName, SkSLType::kFloat2);
    write_passthrough_vertex_position(vertBuilder, inPos, &gpArgs->fPositionVar);
}

void ProgramImpl::WriteOutputPosition(GrGLSLVertexBuilder* vertBuilder,
                                      GrGLSLUniformHandler* uniformHandler,
                                      const GrShaderCaps& shaderCaps,
                                      GrGPArgs* gpArgs,
                                      const char* posName,
                                      const SkMatrix& mat,
                                      UniformHandle* viewMatrixUniform) {
    GrShaderVar inPos(posName, SkSLType::kFloat2);
    write_vertex_position(vertBuilder,
                          uniformHandler,
                          shaderCaps,
                          inPos,
                          mat,
                          "viewMatrix",
                          &gpArgs->fPositionVar,
                          viewMatrixUniform);
}

void ProgramImpl::WriteLocalCoord(GrGLSLVertexBuilder* vertBuilder,
                                  GrGLSLUniformHandler* uniformHandler,
                                  const GrShaderCaps& shaderCaps,
                                  GrGPArgs* gpArgs,
                                  GrShaderVar localVar,
                                  const SkMatrix& localMatrix,
                                  UniformHandle* localMatrixUniform) {
    write_vertex_position(vertBuilder,
                          uniformHandler,
                          shaderCaps,
                          localVar,
                          localMatrix,
                          "localMatrix",
                          &gpArgs->fLocalCoordVar,
                          localMatrixUniform);
}

//////////////////////////////////////////////////////////////////////////////

using Attribute    = GrGeometryProcessor::Attribute;
using AttributeSet = GrGeometryProcessor::AttributeSet;

GrGeometryProcessor::Attribute AttributeSet::Iter::operator*() const {
    if (fCurr->offset().has_value()) {
        return *fCurr;
    }
    return Attribute(fCurr->name(), fCurr->cpuType(), fCurr->gpuType(), fImplicitOffset);
}

void AttributeSet::Iter::operator++() {
    if (fRemaining) {
        fRemaining--;
        fImplicitOffset += Attribute::AlignOffset(fCurr->size());
        fCurr++;
        this->skipUninitialized();
    }
}

void AttributeSet::Iter::skipUninitialized() {
    if (!fRemaining) {
        fCurr = nullptr;
    } else {
        while (!fCurr->isInitialized()) {
            ++fCurr;
        }
    }
}

void AttributeSet::initImplicit(const Attribute* attrs, int count) {
    fAttributes = attrs;
    fRawCount   = count;
    fCount      = 0;
    fStride     = 0;
    for (int i = 0; i < count; ++i) {
        if (attrs[i].isInitialized()) {
            fCount++;
            fStride += Attribute::AlignOffset(attrs[i].size());
        }
    }
}

void AttributeSet::initExplicit(const Attribute* attrs, int count, size_t stride) {
    fAttributes = attrs;
    fRawCount   = count;
    fCount      = count;
    fStride     = stride;
    SkASSERT(Attribute::AlignOffset(fStride) == fStride);
    for (int i = 0; i < count; ++i) {
        SkASSERT(attrs[i].isInitialized());
        SkASSERT(attrs[i].offset().has_value());
        SkASSERT(Attribute::AlignOffset(*attrs[i].offset()) == *attrs[i].offset());
        SkASSERT(*attrs[i].offset() + attrs[i].size() <= fStride);
    }
}

void AttributeSet::addToKey(skgpu::KeyBuilder* b) const {
    int rawCount = SkAbs32(fRawCount);
    b->addBits(16, SkToU16(this->stride()), "stride");
    b->addBits(16, rawCount, "attribute count");
    size_t implicitOffset = 0;
    for (int i = 0; i < rawCount; ++i) {
        const Attribute& attr = fAttributes[i];
        b->appendComment(attr.isInitialized() ? attr.name() : "unusedAttr");
        static_assert(kGrVertexAttribTypeCount < (1 << 8), "");
        static_assert(kSkSLTypeCount           < (1 << 8), "");
        b->addBits(8,  attr.isInitialized() ? attr.cpuType() : 0xff, "attrType");
        b->addBits(8 , attr.isInitialized() ? static_cast<int>(attr.gpuType()) : 0xff,
                   "attrGpuType");
        int16_t offset = -1;
        if (attr.isInitialized()) {
            if (attr.offset().has_value()) {
                offset = *attr.offset();
            } else {
                offset = implicitOffset;
                implicitOffset += Attribute::AlignOffset(attr.size());
            }
        }
        b->addBits(16, static_cast<uint16_t>(offset), "attrOffset");
    }
}

AttributeSet::Iter AttributeSet::begin() const { return Iter(fAttributes, fCount); }
AttributeSet::Iter AttributeSet::end() const { return Iter(); }
