{"id":13523379,"url":"https://github.com/brendan-duncan/wgsl_reflect","last_synced_at":"2025-05-15T07:05:05.330Z","repository":{"id":66114972,"uuid":"427828696","full_name":"brendan-duncan/wgsl_reflect","owner":"brendan-duncan","description":"A WebGPU Shading Language parser and reflection library for Javascript.","archived":false,"fork":false,"pushed_at":"2025-05-09T18:47:14.000Z","size":10957,"stargazers_count":219,"open_issues_count":5,"forks_count":22,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-05-09T19:46:36.222Z","etag":null,"topics":["javascript","webgpu","wgsl"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brendan-duncan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"brendan-duncan"}},"created_at":"2021-11-14T03:32:50.000Z","updated_at":"2025-05-09T18:47:17.000Z","dependencies_parsed_at":"2024-01-04T06:28:57.777Z","dependency_job_id":"42cc270d-323b-4d27-b6c8-06e02f2f322b","html_url":"https://github.com/brendan-duncan/wgsl_reflect","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brendan-duncan%2Fwgsl_reflect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brendan-duncan%2Fwgsl_reflect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brendan-duncan%2Fwgsl_reflect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brendan-duncan%2Fwgsl_reflect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brendan-duncan","download_url":"https://codeload.github.com/brendan-duncan/wgsl_reflect/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254043265,"owners_count":22004913,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","webgpu","wgsl"],"created_at":"2024-08-01T06:00:59.514Z","updated_at":"2025-05-15T07:05:00.319Z","avatar_url":"https://github.com/brendan-duncan.png","language":"TypeScript","funding_links":["https://github.com/sponsors/brendan-duncan"],"categories":["Libraries"],"sub_categories":["Safari"],"readme":"# WebGPU Shading Language Reflection Library\r\n\r\nA WebGPU Shading Language parser and reflection library for Typescript and Javascript.\r\n\r\n**wgsl_reflect** can parse a WGSL shader and analyze its contents, providing information about the shader. It can determine the bind group layout of the shader, resource bindings, uniform buffers, the members of a uniform buffer, their names, types, sizes, offsets into the buffer.\r\n\r\n## Usage\r\n\r\nFrom NPM\r\n```\r\nnpm install wgsl_reflect\r\n```\r\n\r\nThe _wgsl_reflect.module.js_ file is a self-contained roll-up of the library that can be included in your project and imported with:\r\n\r\n```javascript\r\nimport { WgslReflect } from \"wgsl_reflect/wgsl_reflect.module.js\";\r\nconst reflect = new WgslReflect(shader_code);\r\n```\r\n\r\n## Example\r\n\r\n[WGSL Reflect Example](https://brendan-duncan.github.io/wgsl_reflect/example.html)\r\n\r\n## Documentation\r\n\r\n```javascript\r\n// A collection of gathered reflection information about the shader.\r\nclass WgslReflect {\r\n  // All top-level uniform vars in the shader.\r\n  uniforms: Array\u003cVariableInfo\u003e;\r\n  // All top-level storage vars in the shader, including storage buffers and textures.\r\n  storage: Array\u003cVariableInfo\u003e;\r\n  // All top-level texture vars in the shader;\r\n  textures: Array\u003cVariableInfo\u003e;\r\n  // All top-level sampler vars in the shader.\r\n  samplers: Array\u003cVariableInfo\u003e;\r\n  // All top-level type aliases in the shader.\r\n  aliases: Array\u003cAliasInfo\u003e;\r\n  // All top-level overrides in the shader.\r\n  overrides: Array\u003cOverrideInfo\u003e = [];\r\n  // All top-level structs in the shader.\r\n  structs: Array\u003cStructInfo\u003e;\r\n  // All entry functions in the shader: vertex, fragment, and/or compute.\r\n  entry: EntryFunctions;\r\n  // All functions in the shader, including entry functions.\r\n  functions: Array\u003cFunctionInfo\u003e;\r\n\r\n  // Parse the given WGSL shader code, populating the info properties of this class.\r\n  constructor(shader?: string);\r\n\r\n  // Parse the given WGSL shader code, adding to the info properties of this class.\r\n  update(shader: string);\r\n\r\n  // Find a resource by its group and binding.\r\n  findResource(group: number, binding: number): VariableInfo | null;\r\n\r\n  // Get the bind groups used by the shader, bindGroups[group][binding].\r\n  getBindGroups(): Array\u003cArray\u003cVariableInfo\u003e\u003e;\r\n}\r\n\r\n// A variable can be a resource passed to the shader, of this type.\r\nenum ResourceType {\r\n  Uniform, // Uniform buffer\r\n  Storage, // Storage buffer\r\n  Texture, // Texture\r\n  Sampler, // Sampler to sample a Texture\r\n  StorageTexture // StorageTexture\r\n}\r\n\r\n// Information about a resource variable. This will be a uniform buffer,\r\n// storage buffer, texture, sampler, or storageTexture.\r\nclass VariableInfo {\r\n  // The name of the variable.\r\n  name: string;\r\n  // The type of the variable.\r\n  type: TypeInfo;\r\n  // The binding group of the variable.\r\n  group: number;\r\n  // The binding index of the variable.\r\n  binding: number;\r\n  // The resource type of the variable.\r\n  resourceType: ResourceType;\r\n  // The access mode of the variable, can be: \"\", \"read\", \"write\", or \"read_write\".\r\n  access: string;\r\n\r\n  // True if the type of the variable is an array.\r\n  get isArray(): boolean;\r\n  // True if the type of the variable is a struct.\r\n  get isStruct(): boolean;\r\n  // True if the type of the variable is a template.\r\n  get isTemplate(): boolean;\r\n  // Size of the data pointed to by the variable, in bytes.\r\n  get size(): number;\r\n  // The alignment size if the variable type is a struct, otherwise 0.\r\n  get align(): number;\r\n  // The list of members of the variable type if it's a struct, otherwise null.\r\n  get members(): Array\u003cMemberInfo\u003e | null;\r\n  // The format if the type is a template or array, otherwise null.\r\n  get format(): TypeInfo | null;\r\n  // The array size if it's an array, otherwise 0.\r\n  get count(): number;\r\n  // The array stride if it's an array, otherwise 0.\r\n  get stride(): number;\r\n}\r\n\r\n// Base class for variable types.\r\nclass TypeInfo {\r\n  // The name of the type declaration.\r\n  name: string;\r\n  // Size of the data used by this type, in bytes\r\n  size: number;\r\n\r\n  // True if this is an array type, can be cast to ArrayInfo.\r\n  get isArray(): boolean;\r\n  // True if this is a struct type, can be cast to StructInfo.\r\n  get isStruct(): boolean;\r\n  // True if this is a template type, can be cast to TemplateInfo.\r\n  get isTemplate(): boolean;\r\n}\r\n\r\n// Information about struct type declarations\r\nclass StructInfo extends TypeInfo {\r\n  // The list of members of the struct.\r\n  members: Array\u003cMemberInfo\u003e;\r\n  // The alignment, in bytes, for the structs data.\r\n  align: number;\r\n  // The line in the shader code the type declaration starts at.\r\n  startLine: number;\r\n  // The line in the shader code the type declaration ends at.\r\n  endLine: number;\r\n  // True if the struct is used by a uniform, storage, or directly or indirectly by an entry function.\r\n  inUse: boolean;\r\n}\r\n\r\n// Information about array type declarations\r\nclass ArrayInfo extends TypeInfo {\r\n  // The format for the data in the array\r\n  format: TypeInfo;\r\n  // The number of elements in the array\r\n  count: number;\r\n  // The stride, in bytes, of the array. This is the alignment of elements in the array data, including padding.\r\n  stride: number;\r\n}\r\n\r\n// Information about template type declarations\r\nclass TemplateInfo extends TypeInfo {\r\n  // The format type of the template\r\n  format: TypeInfo;\r\n  // Access mode of the template, which can be: \"\", \"read\", \"write\", or \"read_write\"\r\n  access: string;\r\n}\r\n\r\n// Information about a struct member declaration.\r\nclass MemberInfo {\r\n  // The name of the struct member.\r\n  name: string;\r\n  // The type of the struct member.\r\n  type: TypeInfo;\r\n  // The offset, in bytes, of the member from the start of the struct data.\r\n  offset: number;\r\n  // The size of the members data, in bytes.\r\n  size: number;\r\n\r\n  // True if the member type is an array and can be cast to ArrayInfo\r\n  get isArray(): boolean;\r\n  // True if the member type is a struct and can be cast to StructInfo.\r\n  get isStruct(): boolean;\r\n  // True if the member type is a template and can be cast to TemplateInfo.\r\n  get isTemplate(): boolean;\r\n  // If the member type is a struct, the alignment of the struct in bytes, otherwise 0.\r\n  get align(): number;\r\n  // If the member type is a struct, the members of the struct, otherwise null.\r\n  get members(): Array\u003cMemberInfo\u003e | null;\r\n  // If the member type is an array or template, the format of the type, otherwise null.\r\n  get format(): TypeInfo | null;\r\n  // If the member type is an array, the number of elements in the array, otherwise 0.\r\n  get count(): number;\r\n  // If the member type is an array, the stride of the array elements in bytes, otherwise 0.\r\n  get stride(): number;\r\n}\r\n\r\n// Information about type aliases declared in the shader.\r\nclass AliasInfo {\r\n  // The name of the alias type.\r\n  name: string;\r\n  // The information of the type being aliased.\r\n  type: TypeInfo;\r\n}\r\n\r\n// The lists of shader vertex, fragment, and/or compute entry functions.\r\nclass EntryFunctions {\r\n  // Any vertex entry points in the shader.\r\n  vertex: Array\u003cFunctionInfo\u003e;\r\n  // Any fragment entry points in the shader.\r\n  fragment: Array\u003cFunctionInfo\u003e;\r\n  // Any compute entry points in the shader.\r\n  compute: Array\u003cFunctionInfo\u003e;\r\n}\r\n\r\n// Information about a function in the shader.\r\nclass FunctionInfo {\r\n  // The name of the function.\r\n  name: string;\r\n  // If the function is an entry function, which stage is it for, either \"vertex\", \"fragment\", \"compute\", or null if none.\r\n  stage: string | null;\r\n  // The list of shader inputs used by the function, which includes vertex and index buffers.\r\n  inputs: Array\u003cInputInfo\u003e;\r\n  // The list of shader outputs updated by the function, such as inter-stage buffers.\r\n  outputs: Array\u003cOutputInfo\u003e;\r\n  // The arguments of the function.\r\n  arguments: Array\u003cArgumentInfo\u003e;\r\n  // The return type of the function, or null if the function returns void.\r\n  returnType: TypeInfo | null;\r\n  // The resources used by the function, including uniform buffers, storage buffers, textures,\r\n  // samplers, and storage textures.\r\n  resources: Array\u003cVariableInfo\u003e;\r\n  // The line in the shader the function definition starts at.\r\n  startLine: number;\r\n  // The line in the shader the function definition ends at.\r\n  endLine: number;\r\n  // True if called directly or indirectly by an entry function.\r\n  inUse: boolean;\r\n  // All custom functions called directly by this function.\r\n  calls: Set\u003cFunctionInfo\u003e;\r\n}\r\n\r\n// Information about a shader inputs.\r\nclass InputInfo {\r\n  // The name of the input variable\r\n  name: string;\r\n  // The type of the input variable.\r\n  type: TypeInfo | null;\r\n  // The location type of the input.\r\n  locationType: string;\r\n  // The location index or built-in location name.\r\n  location: number | string;\r\n  // The interpolation mode of the binding.\r\n  interpolation: string | null;\r\n}\r\n\r\n// Information about a shader output.\r\nclass OutputInfo {\r\n  // The name of the output variable.\r\n  name: string;\r\n  // The type of the output variable.\r\n  type: TypeInfo | null;\r\n  // The location type of the output.\r\n  locationType: string;\r\n  // The location index or built-in location name.\r\n  location: number | string;\r\n}\r\n\r\n// Information about override constants in the shader.\r\nclass OverrideInfo {\r\n  // The name of the override constant.\r\n  name: string;\r\n  // The type of the override constant.\r\n  type: TypeInfo | null;\r\n  // A unique ID given to the override constant.\r\n  id: number;\r\n}\r\n\r\n// Information about a function argument.\r\nclass ArgumentInfo {\r\n  // Then ame of the argument variable.\r\n  name: string;\r\n  // The type of the argument variable.\r\n  type: TypeInfo;\r\n}\r\n```\r\n\r\n## Examples\r\n\r\nCalculate the bind group information in the shader:\r\n\r\n```javascript\r\nimport { WgslReflect } from \"./wgsl_reflect.module.js\";\r\n\r\nconst shader = `\r\nstruct ViewUniforms {\r\n    viewProjection: mat4x4\u003cf32\u003e\r\n}\r\n\r\nstruct ModelUniforms {\r\n    model: mat4x4\u003cf32\u003e,\r\n    color: vec4\u003cf32\u003e,\r\n    intensity: f32\r\n}\r\n\r\n@binding(0) @group(0) var\u003cuniform\u003e viewUniforms: ViewUniforms;\r\n@binding(1) @group(0) var\u003cuniform\u003e modelUniforms: ModelUniforms;\r\n@binding(2) @group(0) var u_sampler: sampler;\r\n@binding(3) @group(0) var u_texture: texture_2d\u003cf32\u003e;\r\n\r\nstruct VertexInput {\r\n    @location(0) a_position: vec3\u003cf32\u003e,\r\n    @location(1) a_normal: vec3\u003cf32\u003e,\r\n    @location(2) a_color: vec4\u003cf32\u003e,\r\n    @location(3) a_uv: vec2\u003cf32\u003e\r\n}\r\n\r\nstruct VertexOutput {\r\n    @builtin(position) Position: vec4\u003cf32\u003e,\r\n    @location(0) v_position: vec4\u003cf32\u003e,\r\n    @location(1) v_normal: vec3\u003cf32\u003e,\r\n    @location(2) v_color: vec4\u003cf32\u003e,\r\n    @location(3) v_uv: vec2\u003cf32\u003e\r\n}\r\n\r\n@vertex\r\nfn main(input: VertexInput) -\u003e VertexOutput {\r\n    var output: VertexOutput;\r\n    output.Position = viewUniforms.viewProjection * modelUniforms.model * vec4\u003cf32\u003e(input.a_position, 1.0);\r\n    output.v_position = output.Position;\r\n    output.v_normal = input.a_normal;\r\n    output.v_color = input.a_color * modelUniforms.color * modelUniforms.intensity;\r\n    output.v_uv = input.a_uv;\r\n    return output;\r\n}`;\r\n\r\nconst reflect = new WgslReflect(shader);\r\n\r\nconsole.log(reflect.functions.length); // 1\r\nconsole.log(reflect.structs.length); // 4\r\nconsole.log(reflect.uniforms.length); // 2\r\n\r\n// Shader entry points\r\nconsole.log(reflect.entry.vertex.length); // 1, there is 1 vertex entry function.\r\nconsole.log(reflect.entry.fragment.length); // 0, there are no fragment entry functions.\r\nconsole.log(reflect.entry.compute.length); // 0, there are no compute entry functions.\r\n\r\nconsole.log(reflect.entry.vertex[0].name); // \"main\", the name of the vertex entry function.\r\n\r\nconsole.log(reflect.entry.vertex[0].resources.length); // 2, main uses modelUniforms and viewUniforms resource bindings.\r\nconsole.log(reflect.entry.vertex[0].resources[0].name); // viewUniforms\r\nconsole.log(reflect.entry.vertex[0].resources[1].name); // modelUniforms\r\n\r\n// Vertex shader inputs\r\nconsole.log(reflect.entry.vertex[0].inputs.length); // 4, inputs to \"main\"\r\nconsole.log(reflect.entry.vertex[0].inputs[0].name); // \"a_position\"\r\nconsole.log(reflect.entry.vertex[0].inputs[0].location); // 0\r\nconsole.log(reflect.entry.vertex[0].inputs[0].locationType); // \"location\" (can be \"builtin\")\r\nconsole.log(reflect.entry.vertex[0].inputs[0].type.name); // \"vec3\"\r\nconsole.log(reflect.entry.vertex[0].inputs[0].type.format.name); // \"f32\"\r\n\r\n// Gather the bind groups used by the shader.\r\nconst groups = reflect.getBindGroups();\r\nconsole.log(groups.length); // 1\r\nconsole.log(groups[0].length); // 4, bindings in group(0)\r\n\r\nconsole.log(groups[0][1].resourceType); // ResourceType.Uniform, the type of resource at group(0) binding(1)\r\nconsole.log(groups[0][1].size); // 96, the size of the uniform buffer.\r\nconsole.log(groups[0][1].members.length); // 3, members in ModelUniforms.\r\nconsole.log(groups[0][1].members[0].name); // \"model\", the name of the first member in the uniform buffer.\r\nconsole.log(groups[0][1].members[0].offset); // 0, the offset of 'model' in the uniform buffer.\r\nconsole.log(groups[0][1].members[0].size); // 64, the size of 'model'.\r\nconsole.log(groups[0][1].members[0].type.name); // \"mat4x4\", the type of 'model'.\r\nconsole.log(groups[0][1].members[0].type.format.name); // \"f32\", the format of the mat4x4.\r\n\r\nconsole.log(groups[0][2].resourceType); // ResourceType.Sampler\r\n\r\nconsole.log(groups[0][3].resourceType); // ResourceType.Texture\r\nconsole.log(groups[0][3].type.name); // \"texture_2d\"\r\nconsole.log(groups[0][3].type.format.name); // \"f32\"\r\n```\r\n\r\n---\r\n\r\nCalculate the member information for a uniform buffer block:\r\n\r\n```javascript\r\nimport { WgslReflect } from \"./wgsl_reflect.module.js\";\r\n\r\n// WgslReflect can calculate the size and offset for members of a uniform buffer block.\r\n\r\nconst shader = `\r\nstruct A {                                     //             align(8)  size(32)\r\n    u: f32,                                    // offset(0)   align(4)  size(4)\r\n    v: f32,                                    // offset(4)   align(4)  size(4)\r\n    w: vec2\u003cf32\u003e,                              // offset(8)   align(8)  size(8)\r\n    @size(16) x: f32                          // offset(16)  align(4)  size(16)\r\n}\r\n\r\nstruct B {                                     //             align(16) size(208)\r\n    a: vec2\u003cf32\u003e,                              // offset(0)   align(8)  size(8)\r\n    // -- implicit member alignment padding -- // offset(8)             size(8)\r\n    b: vec3\u003cf32\u003e,                              // offset(16)  align(16) size(12)\r\n    c: f32,                                    // offset(28)  align(4)  size(4)\r\n    d: f32,                                    // offset(32)  align(4)  size(4)\r\n    // -- implicit member alignment padding -- // offset(36)            size(12)\r\n    @align(16) e: A,                           // offset(48)  align(16) size(32)\r\n    f: vec3\u003cf32\u003e,                              // offset(80)  align(16) size(12)\r\n    // -- implicit member alignment padding -- // offset(92)            size(4)\r\n    g: @stride(32) array\u003cA, 3\u003e,                // offset(96)  align(8)  size(96)\r\n    h: i32,                                    // offset(192) align(4)  size(4)\r\n    // -- implicit struct size padding --      // offset(196)           size(12)\r\n}\r\n\r\n@group(0) @binding(0)\r\nvar\u003cuniform\u003e uniform_buffer: B;`;\r\n\r\nconst reflect = new WgslReflect(shader);\r\n\r\nconst u = reflect.uniforms[0];\r\nconsole.log(u.size); // 208, the size of the uniform buffer in bytes\r\nconsole.log(u.group); // 0\r\nconsole.log(u.binding); // 0\r\nconsole.log(u.members.length); // 8, members in B\r\nconsole.log(u.members[0].name); // \"a\"\r\nconsole.log(u.members[0].offset); // 0, the offset of 'a' in the buffer\r\nconsole.log(u.members[0].size); // 8, the size of 'a' in bytes\r\nconsole.log(u.members[0].type.name); // \"vec2\", the type of 'a'\r\nconsole.log(u.members[0].type.format.name); // \"f32\", the format of the vec2.\r\n\r\nconsole.log(u.members[4].name); // \"e\"\r\nconsole.log(u.members[4].offset); // 48, the offset of 'e' in the buffer\r\nconsole.log(u.members[4].size); // 32, the size of 'e' in the buffer\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrendan-duncan%2Fwgsl_reflect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrendan-duncan%2Fwgsl_reflect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrendan-duncan%2Fwgsl_reflect/lists"}