/*
 * 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 "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 <queue>

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);

    enum class BaseCoord { kNone, kLocal, kPosition };

    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(); }
