Rust Path Types
openinterpreter/openinterpreter
Rules for choosing Rust types for filesystem paths in new Codex code, covering protocol types, internal use and model tool arguments.
glslang SPIR-V Builder API for types, instructions, control flow, and decorations.
$ npx skills add LuisaGroup/LuisaCompute --skill glslang -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LuisaGroup/LuisaCompute glslang --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LuisaGroup/LuisaCompute.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/glslang .claude/skills/glslang && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "glslang" agent skill from https://github.com/LuisaGroup/LuisaCompute/tree/stable/.agents/skills/glslang into .claude/skills/glslang/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glslang", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LuisaGroup/LuisaCompute/tree/stable/.agents/skills/glslangType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LuisaGroup/LuisaCompute --skill glslang -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LuisaGroup/LuisaCompute glslang --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LuisaGroup/LuisaCompute.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/glslang .agents/skills/glslang && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "glslang" agent skill from https://github.com/LuisaGroup/LuisaCompute/tree/stable/.agents/skills/glslang into .agents/skills/glslang/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glslang", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LuisaGroup/LuisaCompute --skill glslang -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LuisaGroup/LuisaCompute glslang --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LuisaGroup/LuisaCompute.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/glslang .cursor/skills/glslang && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "glslang" agent skill from https://github.com/LuisaGroup/LuisaCompute/tree/stable/.agents/skills/glslang into .cursor/skills/glslang/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glslang", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LuisaGroup/LuisaCompute.git --path .agents/skills/glslang--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LuisaGroup/LuisaCompute --skill glslang -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LuisaGroup/LuisaCompute glslang --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LuisaGroup/LuisaCompute.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/glslang .gemini/skills/glslang && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "glslang" agent skill from https://github.com/LuisaGroup/LuisaCompute/tree/stable/.agents/skills/glslang into .gemini/skills/glslang/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glslang", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LuisaGroup/LuisaCompute glslangInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LuisaGroup/LuisaCompute --skill glslang -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LuisaGroup/LuisaCompute.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/glslang .github/skills/glslang && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "glslang" agent skill from https://github.com/LuisaGroup/LuisaCompute/tree/stable/.agents/skills/glslang into .github/skills/glslang/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glslang", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LuisaGroup/LuisaCompute --skill glslang -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LuisaGroup/LuisaCompute glslang --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LuisaGroup/LuisaCompute.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/glslang .opencode/skills/glslang && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "glslang" agent skill from https://github.com/LuisaGroup/LuisaCompute/tree/stable/.agents/skills/glslang into .opencode/skills/glslang/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "glslang", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
glslangglslang SPIR-V Builder API for types, instructions, control flow, and decorations.
Glslang is an agent skill from LuisaGroup/LuisaCompute. glslang SPIR-V Builder API for types, instructions, control flow, and decorations.
Its SKILL.md is about 6.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
The repository describes itself as: High-Performance Rendering Framework on Stream Architectures. The licence is Apache-2.0.
Read from SKILL.md and the folder at commit 0c84a1a. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are cpp).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Glslang loads about 6.4k tokens when it runs. Until then it costs about 23 tokens; SKILL.md has 441 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from LuisaGroup/LuisaCompute at commit 0c84a1a, republished under its Apache-2.0 licence (© LuisaGroup). 441 words, ~6,372 tokens.
.claude/skills/glslang/SKILL.md (or your agent's skills folder).Located in src/ext/glslang/SPIRV. Headers:
#include "SPIRV/SpvBuilder.h"
#include "SPIRV/spvIR.h"
#include "SPIRV/GlslangToSpv.h"
#include "SPIRV/disassemble.h"Code snippets follow glslang's own conventions (e.g.
camelCasebuilder methods). LuisaCompute project style rules apply to project code, whilesrc/ext/glslangis third-party code.
spv::Builder owns one SPIR-V module. Thread-safe internal IR.
spv::SpvBuildLogger logger;
spv::Builder builder(spv::Spv_1_5, 0, &logger);
builder.setSource(spv::SourceLanguage::GLSL, 450);
builder.setMemoryModel(spv::AddressingModel::Logical, spv::MemoryModel::GLSL450);
builder.addCapability(spv::Capability::Shader);
// ... build ...
std::vector<unsigned int> spirv;
builder.dump(spirv);builder.setSource(spv::SourceLanguage::GLSL, 450);
builder.setEmitSpirvDebugInfo(); // required before setting debug locations
builder.setDebugMainSourceFile("shader.frag");
builder.setDebugSourceLocation(10, "shader.frag");
builder.addCapability(spv::Capability::Shader);
builder.addExtension("SPV_KHR_ray_tracing");
builder.setMemoryModel(spv::AddressingModel::Logical, spv::MemoryModel::GLSL450);
spv::Id glsl450 = builder.import("GLSL.std.450");spv::Id voidTy = builder.makeVoidType();
spv::Id boolTy = builder.makeBoolType();
spv::Id int32Ty = builder.makeIntType(32);
spv::Id uint32Ty = builder.makeUintType(32);
spv::Id uint64Ty = builder.makeUintType(64);
spv::Id floatTy = builder.makeFloatType(32);
spv::Id doubleTy = builder.makeFloatType(64);
spv::Id halfTy = builder.makeFloatType(16);
spv::Id bfloat16 = builder.makeBFloat16Type();
spv::Id float8e5 = builder.makeFloatE5M2Type();
spv::Id float8e4 = builder.makeFloatE4M3Type();
spv::Id vec4Ty = builder.makeVectorType(floatTy, 4);
spv::Id mat4x4Ty = builder.makeMatrixType(floatTy, 4, 4);
spv::Id arrTy = builder.makeArrayType(floatTy, builder.makeUintConstant(16), 0);
spv::Id runArrTy = builder.makeRuntimeArray(floatTy);
std::vector<spv::Id> members = {floatTy, int32Ty};
// Second argument is member debug info; use {} when no per-member debug data is needed.
spv::Id structTy = builder.makeStructType(members, {}, "MyStruct", false);
spv::Id ptrTy = builder.makePointer(spv::StorageClass::Function, floatTy);
spv::Id fwdPtrTy = builder.makeForwardPointer(spv::StorageClass::PhysicalStorageBuffer);
// Resolve a forward pointer to its pointee type once the pointee is known.
spv::Id resolvedPtrTy = builder.makePointerFromForwardPointer(spv::StorageClass::PhysicalStorageBuffer, fwdPtrTy, floatTy);
spv::Id untypedPtr= builder.makeUntypedPointer(spv::StorageClass::StorageBuffer);
spv::Id fnTy = builder.makeFunctionType(voidTy, {floatTy, int32Ty});
spv::Id imgTy = builder.makeImageType(floatTy, spv::Dim::Dim2D, false, false, false, 1, spv::ImageFormat::Rgba32f, "texture2D");
spv::Id sampledImgTy= builder.makeSampledImageType(imgTy, "sampler2D");
spv::Id samplerTy = builder.makeSamplerType("sampler");
spv::Id asTy = builder.makeAccelerationStructureType();
spv::Id rqTy = builder.makeRayQueryType();
spv::Id hoTy = builder.makeHitObjectEXTType();
spv::Id coopMatTy = builder.makeCooperativeMatrixTypeKHR(floatTy, scopeId, rowsId, colsId, useId);
spv::Id coopVecTy = builder.makeCooperativeVectorTypeNV(floatTy, componentsId);
spv::Id tensorTy = builder.makeTensorTypeARM(floatTy, rankId);
// Generic
std::vector<spv::IdImmediate> ops = {{true, someId}};
spv::Id genericTy = builder.makeGenericType(spv::Op::OpType..., ops);spv::Id typeId = builder.getTypeId(resultId);
spv::Op opCode = builder.getOpCode(id);
spv::Op cls = builder.getTypeClass(typeId);
bool isPtr = builder.isPointer(id);
bool isScalar = builder.isScalar(id);
bool isVec = builder.isVector(id);
bool isMat = builder.isMatrix(id);
bool isArray = builder.isArrayType(typeId);
bool isStruct = builder.isStructType(typeId);
bool isImage = builder.isImageType(typeId);
bool isSampler = builder.isSamplerType(typeId);
int width = builder.getScalarTypeWidth(typeId);
spv::Id scalar = builder.getScalarTypeId(typeId);
spv::Id contained = builder.getContainedTypeId(typeId); // single
spv::Id contained = builder.getContainedTypeId(typeId, n); // nth
unsigned cols = builder.getNumColumns(id);
unsigned rows = builder.getNumRows(id);
unsigned comps= builder.getNumComponents(id);spv::Id t = builder.makeBoolConstant(true), f = builder.makeBoolConstant(false);
spv::Id i32 = builder.makeIntConstant(5), u32 = builder.makeUintConstant(7);
spv::Id i64 = builder.makeInt64Constant(9), u64 = builder.makeUint64Constant(11);
spv::Id i8 = builder.makeInt8Constant(1), u8 = builder.makeUint8Constant(2);
spv::Id i16 = builder.makeInt16Constant(3), u16 = builder.makeUint16Constant(4);
spv::Id f32 = builder.makeFloatConstant(1.0f), f64 = builder.makeDoubleConstant(2.0);
spv::Id f16 = builder.makeFloat16Constant(3.0f), bf16 = builder.makeBFloat16Constant(4.0f);
spv::Id fp = builder.makeFpConstant(floatTy, 1.5, false);
spv::Id null= builder.makeNullConstant(structTy);
// Composite
spv::Id vec4 = builder.makeCompositeConstant(vec4Ty, {f32, f32, f32, f32});
// Spec constants
spv::Id specI32 = builder.makeIntConstant(builder.makeIntType(32), 10, true);
spv::Id specVec = builder.makeCompositeConstant(vec4Ty, {f32, f32, f32, f32}, true);spv::Id global = builder.createVariable(spv::Decoration::NoPrecision, spv::StorageClass::Private, floatTy, "g", builder.makeFloatConstant(0.0f));
spv::Id local = builder.createVariable(spv::Decoration::NoPrecision, spv::StorageClass::Function, floatTy, "l");
spv::Id untyped= builder.createUntypedVariable(spv::Decoration::NoPrecision, spv::StorageClass::StorageBuffer, "u", dataTypeId, initId);
spv::Id undef = builder.createUndefined(floatTy);// Entry point
spv::Function* entry = builder.makeEntryPoint("main");
builder.addEntryPoint(spv::ExecutionModel::Fragment, entry, "main");
builder.addExecutionMode(entry, spv::ExecutionMode::OriginUpperLeft);
// Regular function
spv::Block* entryBlock = nullptr;
spv::Function* func = builder.makeFunctionEntry(
spv::Decoration::NoPrecision, floatTy, "myFunc", spv::LinkageType::Max,
{floatTy, int32Ty},
{{spv::Decoration::NoPrecision}, {spv::Decoration::NoPrecision}},
&entryBlock);
builder.enterFunction(func);
builder.setBuildPoint(entryBlock);
spv::Id p0 = func->getParamId(0);
spv::Id p1 = func->getParamId(1);
builder.makeReturn(false, resultId); // or makeReturn(false) for void
builder.leaveFunction();spv::Builder::If ifBuilder(cond, spv::SelectionControlMask::MaskNone, builder);
// then block
ifBuilder.makeBeginElse();
// else block
ifBuilder.makeEndIf();
// merge blockstd::vector<int> caseValues = {0, 1}, valueToSegment = {0, 1};
int defaultSegment = 2, numSegments = 3;
std::vector<Block*> segmentBB;
builder.makeSwitch(selectorId, spv::SelectionControlMask::MaskNone, numSegments, caseValues, valueToSegment, defaultSegment, segmentBB);
builder.nextSwitchSegment(segmentBB, 0); /* ... */ builder.addSwitchBreak(false);
builder.nextSwitchSegment(segmentBB, 1); /* ... */ builder.addSwitchBreak(false);
builder.nextSwitchSegment(segmentBB, 2); /* ... */ builder.addSwitchBreak(false);
builder.endSwitch(segmentBB);spv::Builder::LoopBlocks& loop = builder.makeNewLoop();
builder.setBuildPoint(&loop.head);
builder.createLoopMerge(&loop.merge, &loop.continue_target, spv::LoopControlMask::MaskNone, {});
builder.createConditionalBranch(cond, &loop.body, &loop.merge);
builder.setBuildPoint(&loop.body);
// loop body
builder.createLoopContinue();
builder.setBuildPoint(&loop.continue_target);
// loop increment (optional)
builder.createBranch(false, &loop.head);
builder.setBuildPoint(&loop.merge);
builder.closeLoop();
// break: builder.createLoopExit(); continue: builder.createLoopContinue();spv::Id neg = builder.createUnaryOp(spv::Op::OpSNegate, int32Ty, val);
spv::Id notb = builder.createUnaryOp(spv::Op::OpLogicalNot, boolTy, bval);
spv::Id add = builder.createBinOp(spv::Op::OpFAdd, floatTy, a, b);
spv::Id sub = builder.createBinOp(spv::Op::OpISub, int32Ty, a, b);
spv::Id mul = builder.createBinOp(spv::Op::OpIMul, int32Ty, a, b);
spv::Id div = builder.createBinOp(spv::Op::OpFDiv, floatTy, a, b);
spv::Id and_ = builder.createBinOp(spv::Op::OpBitwiseAnd, uint32Ty, a, b);
// ExtInst (ternary)
spv::Id fma = builder.createOp(spv::Op::OpExtInst, floatTy, {glsl450, GLSLstd450Fma, a, b, c});
// Generic n-ary
spv::Id r = builder.createOp(spv::Op::OpVectorTimesMatrix, vec4Ty, {a, b, c});
// Mixed ID/immediates
std::vector<spv::IdImmediate> mixed = {{true, idOp}, {false, (unsigned)spv::MemoryAccessMask::Aligned}};
spv::Id r = builder.createOp(spv::Op::Op..., typeId, mixed);
// SpecConstantOp
spv::Id specAdd = builder.createSpecConstantOp(spv::Op::OpIAdd, int32Ty, {specA, specB}, {});spv::Id loaded = builder.createLoad(ptrId, spv::Decoration::NoPrecision);
builder.createStore(valueId, ptrId);
builder.createStore(valueId, ptrId, spv::MemoryAccessMask::NonUniformPointerEXT, spv::Scope::Device, 4);
// Access chain
std::vector<spv::Id> indexes = {builder.makeUintConstant(0), builder.makeUintConstant(2)};
spv::Id chain = builder.createAccessChain(spv::StorageClass::Function, basePtr, indexes);
// Composite
spv::Id elem = builder.createCompositeExtract(composite, elemType, 2);
spv::Id elem = builder.createCompositeExtract(composite, elemType, std::vector<unsigned>{0, 1});
spv::Id ins = builder.createCompositeInsert(newVal, composite, compositeType, 0);
spv::Id dynEl = builder.createVectorExtractDynamic(vec, elemType, indexId);
spv::Id dynVec= builder.createVectorInsertDynamic(vec, vecType, newElem, indexId);
spv::Id comp = builder.createCompositeConstruct(vec4Ty, {a, b, c, d});
spv::Id vec4 = builder.createConstructor(spv::Decoration::NoPrecision, {scalarId}, vec4Ty);
spv::Id mat = builder.createMatrixConstructor(spv::Decoration::NoPrecision, srcs, mat4x4Ty);
// Swizzle
spv::Id swz = builder.createRvalueSwizzle(spv::Decoration::NoPrecision, vec4Ty, vec, {2, 1, 0, 3});
spv::Id lswz= builder.createLvalueSwizzle(vec4Ty, target, source, {2, 1, 0, 3});
// Scalar promotion (in-place)
builder.promoteScalar(spv::Decoration::NoPrecision, left, right);
spv::Id smeared = builder.smearScalar(spv::Decoration::NoPrecision, scalarId, vec4Ty);Builder maintains one active access chain for l-value/r-value tracking:
builder.clearAccessChain();
builder.setAccessChainLValue(ptrId); // base is pointer
builder.setAccessChainRValue(valueId); // base is r-value
builder.accessChainPush(indexId, coherentFlags, alignment);
builder.accessChainPushSwizzle(channels, preSwizzleBaseType, coherentFlags, alignment);
builder.accessChainPushComponent(componentId, preSwizzleBaseType, coherentFlags, alignment);
spv::Id result = builder.accessChainLoad(precision, lvalNonUniform, rvalNonUniform, resultType, memAccess, scope, n);
builder.accessChainStore(valueId, spv::Decoration::NonUniform,
spv::MemoryAccessMask::MaskNone, spv::Scope::Max, 0);
spv::Id lval = builder.accessChainGetLValue();
spv::Id inferred = builder.accessChainGetInferredType();
bool canBeLvalue = builder.isSpvLvalue(); // false for multi-component swizzles like .yx
// Save/restore
spv::Builder::AccessChain saved = builder.getAccessChain();
builder.setAccessChain(saved);spv::Builder::TextureParameters params = {};
params.sampler = sampledImageId;
params.coords = coordsId;
params.lod = lodId; // etc: bias, Dref, offset, gradX, gradY, component, sample, lodClamp, ...
// nonprivate, volatil, nontemporal = false
spv::Id tex = builder.createTextureCall(precision, resultType,
false/*sparse*/, false/*fetch*/, false/*proj*/, false/*gather*/, false/*noImplicit*/,
params, spv::ImageOperandsMask::MaskNone);builder.addName(id, "myVar");
builder.addMemberName(structTy, 0, "field0");
builder.addDecoration(id, spv::Decoration::Location, 0);
builder.addDecoration(id, spv::Decoration::Binding, 2);
builder.addDecoration(id, spv::Decoration::DescriptorSet, 0);
builder.addDecoration(id, spv::Decoration::NoContraction);
builder.addDecoration(id, spv::Decoration::RelaxedPrecision);
builder.addDecoration(id, spv::Decoration::BuiltIn, (int)spv::BuiltIn::Position);
builder.addMemberDecoration(structTy, 0, spv::Decoration::Offset, 0);
builder.addMemberDecoration(structTy, 1, spv::Decoration::Offset, 16);
builder.addDecoration(id, spv::Decoration::WorkgroupSize, std::vector<unsigned>{64, 1, 1});
builder.addDecorationId(id, spv::Decoration::ArrayStrideIdEXT, strideId);
builder.addLinkageDecoration(id, "myFunc", spv::LinkageType::Export);builder.createControlBarrier(spv::Scope::Workgroup, spv::Scope::Device,
spv::MemorySemanticsMask::UniformMemory | spv::MemorySemanticsMask::WorkgroupMemory);
builder.createMemoryBarrier(spv::Scope::Device, spv::MemorySemanticsMask::ImageMemory);builder.setEmitSpirvDebugInfo(); // enables OpLine/OpSource tracking
builder.setDebugMainSourceFile("shader.glsl");
builder.setDebugSourceLocation(42, "shader.glsl");
builder.setSourceText(sourceText);builder.setEmitNonSemanticShaderDebugInfo(true); // also enables OpLine-style tracking
spv::Id debugType = builder.getDebugType(spirvTypeId);
builder.enterLexicalBlock(line, column);
builder.leaveLexicalBlock();
builder.setupFunctionDebugInfo(func, "myFunc", paramTypes, paramNames);
spv::Id dbgGlobal = builder.createDebugGlobalVariable(debugType, "globalVar", varId);
spv::Id dbgLocal = builder.createDebugLocalVariable(debugType, "localVar", argNumber);
spv::Id dbgDecl = builder.makeDebugDeclare(dbgLocal, ptrId);
spv::Id dbgVal = builder.makeDebugValue(dbgLocal, valueId);spv::Id result = builder.createFunctionCall(calleeFunc, {arg0, arg1, arg2});
spv::Id sqrtVal = builder.createBuiltinCall(floatTy, glsl450, GLSLstd450Sqrt, {val});builder.postProcess(false); // prune + caps/extensions
builder.postProcessCFG(); // prune unreachable
builder.postProcessFeatures(); // add caps/extensions from instructions
builder.postProcessSamplers(); // move OpSampledImage near users
std::vector<unsigned int> spirv;
builder.dump(spirv);
spv::Disassemble(std::cout, spirv);
glslang::OutputSpvBin(spirv, "out.spv");
glslang::OutputSpvHex(spirv, "out.h", "g_spv");Both postProcessCFG() and Function::dump() traverse physical blocks with
inReadableOrder(), which assumes structured merge roles already nest. If an
outer selection merge is also an inner arm and then branches to the inner
merge, the physical graph exits the inner construct and re-enters it. The
traversal can initially mask that invalid topology by classifying the inner
merge as dead, replacing live code with OpUnreachable, and serializing it
before its dominator. Fix the producer's physical control-flow plan: preserve
the payload blocks but rotate the adjacent merge declarations so the inner
merge physically precedes the outer merge. Do not patch serialization order or
disable post-processing/validation around an invalid graph.
OpSwitch case literals are sized by the selector's OpTypeInt, not by the
generated operand-table class alone. A selector up to 32 bits uses one literal
word; a 64-bit selector uses two low-word-first literal words followed by one
target label ID. Disassemblers and binary walkers must resolve the selector
type and consume ceil(bit_width / 32) words per case before reading the label.
Never infer case boundaries by alternating one literal word and one ID.
Treat disassembly input as untrusted. Validate each instruction-local word
count before reading operands: reject zero, undersized, or module-truncated
instructions. When resolving an OpSwitch selector, also validate the mapped
defining instruction bounds and result ID; accept OpTypeInt only with its
exact four-word layout and a width of 8, 16, 32, or 64. Validate a directly
visited OpTypeInt before reading its width operand. The disassembler's fatal
path exits the process, so malformed-input regressions must run it in a child
process and assert the deterministic nonzero exit.
spvIR.h)spv::Instruction* inst = new spv::Instruction(resultId, typeId, spv::Op::OpIAdd);
inst->addIdOperand(opA);
inst->addIdOperand(opB);
spv::Block* block = new spv::Block(blockId, *function);
block->addInstruction(std::unique_ptr<spv::Instruction>(inst));
block->addLocalVariable(std::unique_ptr<spv::Instruction>(varInst));
bool terminated = block->isTerminated();
spv::Function* func = new spv::Function(funcId, retType, funcType, firstParamId, linkage, name, module);
func->addBlock(block);
func->setReturnPrecision(spv::Decoration::RelaxedPrecision);
func->addParamPrecision(0, spv::Decoration::RelaxedPrecision);
spv::Module module;
module.addFunction(func);
module.mapInstruction(inst);
spv::Instruction* found = module.getInstruction(id);
spv::Id typeId = module.getTypeId(resultId);| Type | Purpose |
|---|---|
spv::Builder | SPIR-V module construction |
spv::Instruction | Single SPIR-V instruction |
spv::Block | Basic block |
spv::Function | SPIR-V function |
spv::Module | Module root, ID→instruction map |
spv::Builder::If | Structured if-then-else helper |
spv::Builder::LoopBlocks | Structured loop blocks |
spv::Builder::AccessChain | L-value/R-value access chain |
spv::Builder::TextureParameters | Texture op parameters |
spv::IdImmediate | Operand: ID or immediate |
glslang::SpvOptions | GlslangToSpv options |
From TGlslangToSpvTraverser (src/ext/glslang/SPIRV/GlslangToSpv.cpp). Common pattern: clear access chain → traverse → load/store → set R-value.
builder.clearAccessChain();
// Treat spec constants, r-value parameters, and non-pointer/untyped values as r-values.
if (isRValue || rValueParameters.count(symbolId) ||
(!builder.isPointerType(builder.getTypeId(id)) && !builder.isUntypedPointer(id)))
builder.setAccessChainRValue(id);
else
builder.setAccessChainLValue(id);
spv::StorageClass sc = builder.getStorageClass(id);
if (builder.isGlobalVariable(id))
iOSet.insert(id);
builder.addExtension("SPV_GOOGLE_hlsl_functionality1");
builder.addDecorationId(id, spv::Decoration::HlslCounterBufferGOOGLE, counterId);builder.clearAccessChain(); node->getLeft()->traverse(this);
auto lValue = builder.getAccessChain();
builder.clearAccessChain(); node->getRight()->traverse(this);
spv::Id rValue = accessChainLoad(node->getRight()->getType());
builder.setAccessChain(lValue);
multiTypeStore(node->getLeft()->getType(), rValue);
builder.clearAccessChain(); builder.setAccessChainRValue(rValue);// zero-extend narrow uint indexes to 32-bit
if (builder.isUintType(indexType) && builder.getScalarTypeWidth(indexType) < 32)
index = builder.createUnaryOp(spv::Op::OpUConvert, builder.makeUintType(32), index);
builder.accessChainPush(index, coherentFlags, alignment);builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
coherentFlags, alignment);spv::Id operand = builder.accessChainGetLValue();
spv::Id one = builder.makeIntConstant(1);
spv::Id result = builder.createBinOp(op, type, operand, one);
builder.accessChainStore(result, ...);
builder.clearAccessChain(); builder.setAccessChainRValue(result);// Builtin
spv::Id result = builder.createBuiltinCall(resultType(), glsl450, opcode, {operand});
// No-result
builder.createNoResultOp(spv::Op::OpKill);
builder.createNoResultOp(spv::Op::OpTerminateInvocation);
builder.createNoResultOp(spv::Op::OpDemoteToHelperInvocationEXT);
builder.createNoResultOp(spv::Op::OpAssumeTrueKHR, operand);
// Array length
spv::Id len = builder.createArrayLength(builder.accessChainGetLValue(), member, bits);
len = builder.createUnaryOp(spv::Op::OpBitcast, builder.makeIntType(bits), len);
// Cooperative matrix/vector
spv::Id lenKHR = builder.createCooperativeMatrixLengthKHR(typeId);
spv::Id lenNV = builder.createCooperativeMatrixLengthNV(typeId);
spv::Id lenVec = builder.getCooperativeVectorNumComponents(typeId);
// Tensor
spv::Id layout = builder.createOp(spv::Op::OpCreateTensorLayoutNV, resultType(), {});
spv::Id view = builder.createOp(spv::Op::OpCreateTensorViewNV, resultType(), {});// Function entry/leave
builder.setBuildPoint(shaderEntry->getLastBlock());
builder.enterFunction(shaderEntry); /* body */ builder.leaveFunction();
// Function call
spv::Id result = builder.createFunctionCall(callee, arguments);
// Constructors
spv::Id c = builder.createConstructor(precision, arguments, resultType());
spv::Id m = builder.createMatrixConstructor(precision, arguments, resultType());
// Builtin
spv::Id r = builder.createBuiltinCall(resultType(), extInst, opcode, arguments);
// Texture
spv::Builder::TextureParameters params = {sampledImageId, coordsId, /*...*/};
spv::Id tex = builder.createTextureCall(precision, resultType(), sparse, fetch, proj, gather, noImplicit, params, mask);
// Sampled image
spv::Id sampled = builder.createOp(spv::Op::OpSampledImage, resultType(), {imageId, samplerId});
// Cooperative matrix conversion
spv::Id coop = builder.createCooperativeMatrixConversion(resultType(), arguments[0]);
// Variable
spv::Id var = builder.createVariable(precision, spv::StorageClass::Function, type, name, init);
// Load/store
spv::Id loaded = builder.createLoad(ptrId, precision);
builder.createStore(valueId, ptrId);
// Debug scopes
builder.enterLexicalBlock(loc.line, loc.column); /* body */ builder.leaveLexicalBlock();// Scalar ternary
spv::Id result = builder.createTriOp(spv::Op::OpSelect, resultType, cond, trueVal, falseVal);
// Vector selection: for SPIR-V < 1.4 smear the scalar condition to the vector width;
// for SPIR-V >= 1.4 OpSelect accepts a scalar condition directly.
if (builder.getSpvVersion() < spv::Spv_1_4 && builder.isVector(trueVal)) {
cond = builder.smearScalar(precision, cond,
builder.makeVectorType(builder.makeBoolType(),
builder.getNumComponents(trueVal)));
}
// If aggregate decorations cause type mismatches, normalize with OpCopyLogical.
if (builder.getTypeId(trueVal) != resultType)
trueVal = builder.createUnaryOp(spv::Op::OpCopyLogical, resultType, trueVal);
if (builder.getTypeId(falseVal) != resultType)
falseVal = builder.createUnaryOp(spv::Op::OpCopyLogical, resultType, falseVal);
spv::Id result = builder.createTriOp(spv::Op::OpSelect, resultType, cond, trueVal, falseVal);std::vector<int> caseValues = {0,1,2}, valueToSegment = {0,1,2};
builder.makeSwitch(selectorId, spv::SelectionControlMask::MaskNone, 4, caseValues, valueToSegment, 3, segmentBB);
builder.nextSwitchSegment(segmentBB, 0); /* case 0 */ builder.addSwitchBreak(false);
// ...
builder.endSwitch(segmentBB);spv::Builder::LoopBlocks& loop = builder.makeNewLoop();
builder.setBuildPoint(&loop.head);
builder.createLoopMerge(&loop.merge, &loop.continue_target, spv::LoopControlMask::MaskNone, {});
builder.createConditionalBranch(cond, &loop.body, &loop.merge);
builder.setBuildPoint(&loop.body); /* body */ builder.createLoopContinue();
builder.setBuildPoint(&loop.continue_target); /* increment */ builder.createBranch(false, &loop.head);
builder.setBuildPoint(&loop.merge);
builder.closeLoop();builder.makeReturn(false, returnValue); // with value
builder.makeReturn(false); // void
builder.createLoopExit(); // break
builder.createLoopContinue(); // continue
builder.makeStatementTerminator(spv::Op::OpKill, "post-discard");
builder.makeStatementTerminator(spv::Op::OpTerminateInvocation, "post-terminate");
builder.createNoResultOp(spv::Op::OpDemoteToHelperInvocationEXT);
builder.makeStatementTerminator(spv::Op::OpTerminateRayKHR, "post-terminate-ray");
builder.makeStatementTerminator(spv::Op::OpIgnoreIntersectionKHR, "post-ignore");spv::Id constantId = createSpvConstant(node);
builder.clearAccessChain();
builder.setAccessChainRValue(constantId);builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());// No direct builder usage; drives traversal of the translation unit.© LuisaGroup, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/glslang of LuisaGroup/LuisaCompute.
Open the folder on GitHubat commit 0c84a1a
Glslang next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Glslang this skillLuisaGroup/LuisaCompute | 1.1k | — | ~6.4k | Automated safety check: Pass | Apache-2.0 | |
| Rust Path Typesopeninterpreter/openinterpreter | 69k | 2 repos | ~605 | Automated safety check: Pass | Apache-2.0 | |
| Python Type Safetywshobson/agents | 40k | — | ~1.4k | Automated safety check: Pass | MIT | |
| Pyrefly Type Coveragepytorch/pytorch | 104k | — | ~3k | Automated safety check: Pass | Custom licence | |
| Typescript Advanced Typesrolling-scopes/rsschool-app | 10k | 25 repos | ~4.2k | Automated safety check: Pass | MPL-2.0 | |
| API Typessupabase/supabase | 111k | — | ~557 | Automated safety check: Pass | Apache-2.0 |
openinterpreter/openinterpreter
Rules for choosing Rust types for filesystem paths in new Codex code, covering protocol types, internal use and model tool arguments.
wshobson/agents
Python type safety with type hints, generics, protocols, and strict type checking.
pytorch/pytorch
Migrate a file to use stricter Pyrefly type checking with annotations required for all functions, classes, and attributes.
rolling-scopes/rsschool-app
Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications.
supabase/supabase
Maintain Supabase API types. An agent skill from supabase/supabase.
twentyhq/twenty
Walks through the first of six steps for adding a syncable entity to Twenty's server: metadata name, TypeORM entity, flat types and central constants.
LuisaGroup/LuisaCompute
Show uncommitted changes and commit history via git. An agent skill from LuisaGroup/LuisaCompute.
LuisaGroup/LuisaCompute
Manual AST construction with FunctionBuilder for kernels and callables without DSL sugar.
LuisaGroup/LuisaCompute
CMake build options, custom functions, and backend patterns for LuisaCompute.
LuisaGroup/LuisaCompute
C++ naming, formatting, static analysis, and RTTI rules for LuisaCompute.
LuisaGroup/LuisaCompute
Debug crashes and test failures via stack-traces, host/device logging, and DSL buffer inspection.
LuisaGroup/LuisaCompute
HLSL code generation, StringBuilder patterns, builtin headers, and DXIL embedding.
glslang SPIR-V Builder API for types, instructions, control flow, and decorations. Glslang is an agent skill from LuisaGroup/LuisaCompute. glslang SPIR-V Builder API for types, instructions, control flow, and decorations.
Run `npx skills add LuisaGroup/LuisaCompute --skill glslang -a claude-code`. Or copy the skill folder (.agents/skills/glslang in LuisaGroup/LuisaCompute) into .claude/skills/glslang in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LuisaGroup/LuisaCompute --skill glslang -a codex`. Or copy the skill folder (.agents/skills/glslang in LuisaGroup/LuisaCompute) into .agents/skills/glslang in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LuisaGroup/LuisaCompute --skill glslang -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/glslang, .gemini/skills/glslang, .github/skills/glslang and .opencode/skills/glslang in your project.
SKILL.md names no scripts, command-line tools or credentials: Glslang is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Glslang is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.4k tokens (SKILL.md is roughly 25k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Glslang: Rust Path Types (openinterpreter/openinterpreter, 69k stars), Python Type Safety (wshobson/agents, 40k stars), Pyrefly Type Coverage (pytorch/pytorch, 104k stars) and Typescript Advanced Types (rolling-scopes/rsschool-app, 10k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LuisaGroup (a GitHub organization) maintains it in LuisaGroup/LuisaCompute, which has 1,053 GitHub stars. The repository holds 12 skills in this directory. The repository was last updated on October 10, 2026.
Source: LuisaGroup/LuisaCompute on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.