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