This commit is contained in:
Akko
2025-08-04 18:57:35 +02:00
parent 8cf6e78a79
commit 9495868c2e
5030 changed files with 518594 additions and 17609 deletions

View File

@@ -0,0 +1,75 @@
import type { BindResource } from './BindResource';
/**
* A bind group is a collection of resources that are bound together for use by a shader.
* They are essentially a wrapper for the WebGPU BindGroup class. But with the added bonus
* that WebGL can also work with them.
* @see https://gpuweb.github.io/gpuweb/#dictdef-gpubindgroupdescriptor
* @example
* // Create a bind group with a single texture and sampler
* const bindGroup = new BindGroup({
* uTexture: texture.source,
* uTexture: texture.style,
* });
*
* Bind groups resources must implement the {@link BindResource} interface.
* The following resources are supported:
* - {@link TextureSource}
* - {@link TextureStyle}
* - {@link Buffer}
* - {@link BufferResource}
* - {@link UniformGroup}
*
* The keys in the bind group must correspond to the names of the resources in the GPU program.
*
* This bind group class will also watch for changes in its resources ensuring that the changes
* are reflected in the WebGPU BindGroup.
* @memberof rendering
*/
export declare class BindGroup {
/** The resources that are bound together for use by a shader. */
resources: Record<string, BindResource>;
/**
* a key used internally to match it up to a WebGPU Bindgroup
* @internal
* @ignore
*/
_key: string;
private _dirty;
/**
* Create a new instance eof the Bind Group.
* @param resources - The resources that are bound together for use by a shader.
*/
constructor(resources?: Record<string, BindResource>);
/**
* Updates the key if its flagged as dirty. This is used internally to
* match this bind group to a WebGPU BindGroup.
* @internal
* @ignore
*/
_updateKey(): void;
/**
* Set a resource at a given index. this function will
* ensure that listeners will be removed from the current resource
* and added to the new resource.
* @param resource - The resource to set.
* @param index - The index to set the resource at.
*/
setResource(resource: BindResource, index: number): void;
/**
* Returns the resource at the current specified index.
* @param index - The index of the resource to get.
* @returns - The resource at the specified index.
*/
getResource(index: number): BindResource;
/**
* Used internally to 'touch' each resource, to ensure that the GC
* knows that all resources in this bind group are still being used.
* @param tick - The current tick.
* @internal
* @ignore
*/
_touch(tick: number): void;
/** Destroys this bind group and removes all listeners. */
destroy(): void;
protected onResourceChange(resource: BindResource): void;
}

View File

@@ -0,0 +1,101 @@
'use strict';
"use strict";
class BindGroup {
/**
* Create a new instance eof the Bind Group.
* @param resources - The resources that are bound together for use by a shader.
*/
constructor(resources) {
/** The resources that are bound together for use by a shader. */
this.resources = /* @__PURE__ */ Object.create(null);
this._dirty = true;
let index = 0;
for (const i in resources) {
const resource = resources[i];
this.setResource(resource, index++);
}
this._updateKey();
}
/**
* Updates the key if its flagged as dirty. This is used internally to
* match this bind group to a WebGPU BindGroup.
* @internal
* @ignore
*/
_updateKey() {
if (!this._dirty)
return;
this._dirty = false;
const keyParts = [];
let index = 0;
for (const i in this.resources) {
keyParts[index++] = this.resources[i]._resourceId;
}
this._key = keyParts.join("|");
}
/**
* Set a resource at a given index. this function will
* ensure that listeners will be removed from the current resource
* and added to the new resource.
* @param resource - The resource to set.
* @param index - The index to set the resource at.
*/
setResource(resource, index) {
const currentResource = this.resources[index];
if (resource === currentResource)
return;
if (currentResource) {
resource.off?.("change", this.onResourceChange, this);
}
resource.on?.("change", this.onResourceChange, this);
this.resources[index] = resource;
this._dirty = true;
}
/**
* Returns the resource at the current specified index.
* @param index - The index of the resource to get.
* @returns - The resource at the specified index.
*/
getResource(index) {
return this.resources[index];
}
/**
* Used internally to 'touch' each resource, to ensure that the GC
* knows that all resources in this bind group are still being used.
* @param tick - The current tick.
* @internal
* @ignore
*/
_touch(tick) {
const resources = this.resources;
for (const i in resources) {
resources[i]._touched = tick;
}
}
/** Destroys this bind group and removes all listeners. */
destroy() {
const resources = this.resources;
for (const i in resources) {
const resource = resources[i];
resource.off?.("change", this.onResourceChange, this);
}
this.resources = null;
}
onResourceChange(resource) {
this._dirty = true;
if (resource.destroyed) {
const resources = this.resources;
for (const i in resources) {
if (resources[i] === resource) {
resources[i] = null;
}
}
} else {
this._updateKey();
}
}
}
exports.BindGroup = BindGroup;
//# sourceMappingURL=BindGroup.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,99 @@
"use strict";
class BindGroup {
/**
* Create a new instance eof the Bind Group.
* @param resources - The resources that are bound together for use by a shader.
*/
constructor(resources) {
/** The resources that are bound together for use by a shader. */
this.resources = /* @__PURE__ */ Object.create(null);
this._dirty = true;
let index = 0;
for (const i in resources) {
const resource = resources[i];
this.setResource(resource, index++);
}
this._updateKey();
}
/**
* Updates the key if its flagged as dirty. This is used internally to
* match this bind group to a WebGPU BindGroup.
* @internal
* @ignore
*/
_updateKey() {
if (!this._dirty)
return;
this._dirty = false;
const keyParts = [];
let index = 0;
for (const i in this.resources) {
keyParts[index++] = this.resources[i]._resourceId;
}
this._key = keyParts.join("|");
}
/**
* Set a resource at a given index. this function will
* ensure that listeners will be removed from the current resource
* and added to the new resource.
* @param resource - The resource to set.
* @param index - The index to set the resource at.
*/
setResource(resource, index) {
const currentResource = this.resources[index];
if (resource === currentResource)
return;
if (currentResource) {
resource.off?.("change", this.onResourceChange, this);
}
resource.on?.("change", this.onResourceChange, this);
this.resources[index] = resource;
this._dirty = true;
}
/**
* Returns the resource at the current specified index.
* @param index - The index of the resource to get.
* @returns - The resource at the specified index.
*/
getResource(index) {
return this.resources[index];
}
/**
* Used internally to 'touch' each resource, to ensure that the GC
* knows that all resources in this bind group are still being used.
* @param tick - The current tick.
* @internal
* @ignore
*/
_touch(tick) {
const resources = this.resources;
for (const i in resources) {
resources[i]._touched = tick;
}
}
/** Destroys this bind group and removes all listeners. */
destroy() {
const resources = this.resources;
for (const i in resources) {
const resource = resources[i];
resource.off?.("change", this.onResourceChange, this);
}
this.resources = null;
}
onResourceChange(resource) {
this._dirty = true;
if (resource.destroyed) {
const resources = this.resources;
for (const i in resources) {
if (resources[i] === resource) {
resources[i] = null;
}
}
} else {
this._updateKey();
}
}
}
export { BindGroup };
//# sourceMappingURL=BindGroup.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
import type { BindGroup } from './BindGroup';
/**
* an interface that allows a resource to be bound to the gpu in a bind group
* @memberof rendering
*/
export interface BindResource {
/**
* The type of resource this is
* @ignore
*/
_resourceType: string;
/**
* Unique id for this resource this can change and is used to link the gpu
* @ignore
*/
_resourceId: number;
_touched: number;
/**
* a boolean that indicates if the resource has been destroyed.
* If true, the resource should not be used and any bind groups
* that will release any references to this resource.
* @ignore
*/
destroyed: boolean;
/**
* event dispatch whenever the underlying resource needs to change
* this could be a texture or buffer that has been resized.
* This is important as it allows the renderer to know that it needs to rebind the resource
*/
on?(event: 'change', listenerFunction: (resource: BindResource) => void, listener: BindGroup): void;
/** @todo */
off?(event: 'change', listenerFunction: (resource: BindResource) => void, listener: BindGroup): void;
}

View File

@@ -0,0 +1,4 @@
'use strict';
"use strict";
//# sourceMappingURL=BindResource.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BindResource.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}

View File

@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=BindResource.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BindResource.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}

View File

@@ -0,0 +1,148 @@
/// <reference types="@webgpu/types" />
import type { ExtractedAttributeData } from '../../gl/shader/program/extractAttributesFromGlProgram';
import type { StructsAndGroups } from './utils/extractStructAndGroups';
/**
* a WebGPU descriptions of how the program is laid out
* @see https://gpuweb.github.io/gpuweb/#gpupipelinelayout
* @memberof rendering
*/
export type ProgramPipelineLayoutDescription = GPUBindGroupLayoutEntry[][];
/**
* a map the maps names of uniforms to group indexes
* @memberof rendering
*/
export type ProgramLayout = Record<string, number>[];
/**
* the program source
* @memberof rendering
*/
export interface ProgramSource {
/** The wgsl source code of the shader. */
source: string;
/** The main function to run in this shader */
entryPoint?: string;
}
/**
* The options for the gpu program
* @memberof rendering
*/
export interface GpuProgramOptions {
/**
* the name of the program, this is added to the label of the GPU Program created
* under the hood. Makes it much easier to debug!
*/
name?: string;
/** The fragment glsl shader source. */
fragment?: ProgramSource;
/** The vertex glsl shader source. */
vertex?: ProgramSource;
/** The layout of the program. If not provided, it will be generated from the shader sources. */
layout?: ProgramLayout;
/** The gpu layout of the program. If not provided, it will be generated from the shader sources. */
gpuLayout?: ProgramPipelineLayoutDescription;
}
/**
* A wrapper for a WebGPU Program, specifically designed for the WebGPU renderer.
* This class facilitates the creation and management of shader code that integrates with the WebGPU pipeline.
*
* To leverage the full capabilities of this class, familiarity with WGSL shaders is recommended.
* @see https://gpuweb.github.io/gpuweb/#index
* @example
*
* // Create a new program
* const program = new GpuProgram({
* vertex: {
* source: '...',
* entryPoint: 'main',
* },
* fragment:{
* source: '...',
* entryPoint: 'main',
* },
* });
*
*
* Note: Both fragment and vertex shader sources can coexist within a single WGSL source file
* this can make things a bit simpler.
*
* For optimal usage and best performance, it help to reuse programs whenever possible.
* The {@link GpuProgram.from} helper function is designed for this purpose, utilizing an
* internal cache to efficiently manage and retrieve program instances.
* By leveraging this function, you can significantly reduce overhead and enhance the performance of your rendering pipeline.
*
* An important distinction between WebGL and WebGPU regarding program data retrieval:
* While WebGL allows extraction of program information directly from its compiled state,
* WebGPU does not offer such a capability. Therefore, in the context of WebGPU, we're required
* to manually extract the program layout information from the source code itself.
* @memberof rendering
*/
export declare class GpuProgram {
/** The fragment glsl shader source. */
readonly fragment?: ProgramSource;
/** The vertex glsl shader source */
readonly vertex?: ProgramSource;
/**
* Mapping of uniform names to group indexes for organizing shader program uniforms.
* Automatically generated from shader sources if not provided.
* @example
* // Assuming a shader with two uniforms, `u_time` and `u_resolution`, grouped respectively:
* [
* { "u_time": 0 },
* { "u_resolution": 1 }
* ]
*/
readonly layout: ProgramLayout;
/**
* Configuration for the WebGPU bind group layouts, detailing resource organization for the shader.
* Generated from shader sources if not explicitly provided.
* @example
* // Assuming a shader program that requires two bind groups:
* [
* // First bind group layout entries
* [{ binding: 0, visibility: GPUShaderStage.VERTEX, type: "uniform-buffer" }],
* // Second bind group layout entries
* [{ binding: 1, visibility: GPUShaderStage.FRAGMENT, type: "sampler" },
* { binding: 2, visibility: GPUShaderStage.FRAGMENT, type: "sampled-texture" }]
* ]
*/
readonly gpuLayout: ProgramPipelineLayoutDescription;
/**
* @internal
* @ignore
*/
_layoutKey: number;
/**
* @internal
* @ignore
*/
_attributeLocationsKey: number;
/** the structs and groups extracted from the shader sources */
readonly structsAndGroups: StructsAndGroups;
/**
* the name of the program, this is added to the label of the GPU Program created under the hood.
* Makes it much easier to debug!
*/
readonly name: string;
private _attributeData;
/** if true, the program will automatically assign global uniforms to group[0] */
autoAssignGlobalUniforms: boolean;
/** if true, the program will automatically assign local uniforms to group[1] */
autoAssignLocalUniforms: boolean;
/**
* Create a new GpuProgram
* @param options - The options for the gpu program
*/
constructor(options: GpuProgramOptions);
private _generateProgramKey;
get attributeData(): Record<string, ExtractedAttributeData>;
/** destroys the program */
destroy(): void;
/**
* Helper function that creates a program for a given source.
* It will check the program cache if the program has already been created.
* If it has that one will be returned, if not a new one will be created and cached.
* @param options - The options for the program.
* @returns A program using the same source
*/
static from(options: GpuProgramOptions): GpuProgram;
}

View File

@@ -0,0 +1,81 @@
'use strict';
var createIdFromString = require('../../shared/utils/createIdFromString.js');
var extractAttributesFromGpuProgram = require('./utils/extractAttributesFromGpuProgram.js');
var extractStructAndGroups = require('./utils/extractStructAndGroups.js');
var generateGpuLayoutGroups = require('./utils/generateGpuLayoutGroups.js');
var generateLayoutHash = require('./utils/generateLayoutHash.js');
var removeStructAndGroupDuplicates = require('./utils/removeStructAndGroupDuplicates.js');
"use strict";
const programCache = /* @__PURE__ */ Object.create(null);
class GpuProgram {
/**
* Create a new GpuProgram
* @param options - The options for the gpu program
*/
constructor(options) {
/**
* @internal
* @ignore
*/
this._layoutKey = 0;
/**
* @internal
* @ignore
*/
this._attributeLocationsKey = 0;
const { fragment, vertex, layout, gpuLayout, name } = options;
this.name = name;
this.fragment = fragment;
this.vertex = vertex;
if (fragment.source === vertex.source) {
const structsAndGroups = extractStructAndGroups.extractStructAndGroups(fragment.source);
this.structsAndGroups = structsAndGroups;
} else {
const vertexStructsAndGroups = extractStructAndGroups.extractStructAndGroups(vertex.source);
const fragmentStructsAndGroups = extractStructAndGroups.extractStructAndGroups(fragment.source);
this.structsAndGroups = removeStructAndGroupDuplicates.removeStructAndGroupDuplicates(vertexStructsAndGroups, fragmentStructsAndGroups);
}
this.layout = layout ?? generateLayoutHash.generateLayoutHash(this.structsAndGroups);
this.gpuLayout = gpuLayout ?? generateGpuLayoutGroups.generateGpuLayoutGroups(this.structsAndGroups);
this.autoAssignGlobalUniforms = !!(this.layout[0]?.globalUniforms !== void 0);
this.autoAssignLocalUniforms = !!(this.layout[1]?.localUniforms !== void 0);
this._generateProgramKey();
}
// TODO maker this pure
_generateProgramKey() {
const { vertex, fragment } = this;
const bigKey = vertex.source + fragment.source + vertex.entryPoint + fragment.entryPoint;
this._layoutKey = createIdFromString.createIdFromString(bigKey, "program");
}
get attributeData() {
this._attributeData ?? (this._attributeData = extractAttributesFromGpuProgram.extractAttributesFromGpuProgram(this.vertex));
return this._attributeData;
}
/** destroys the program */
destroy() {
this.gpuLayout = null;
this.layout = null;
this.structsAndGroups = null;
this.fragment = null;
this.vertex = null;
}
/**
* Helper function that creates a program for a given source.
* It will check the program cache if the program has already been created.
* If it has that one will be returned, if not a new one will be created and cached.
* @param options - The options for the program.
* @returns A program using the same source
*/
static from(options) {
const key = `${options.vertex.source}:${options.fragment.source}:${options.fragment.entryPoint}:${options.vertex.entryPoint}`;
if (!programCache[key]) {
programCache[key] = new GpuProgram(options);
}
return programCache[key];
}
}
exports.GpuProgram = GpuProgram;
//# sourceMappingURL=GpuProgram.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,79 @@
import { createIdFromString } from '../../shared/utils/createIdFromString.mjs';
import { extractAttributesFromGpuProgram } from './utils/extractAttributesFromGpuProgram.mjs';
import { extractStructAndGroups } from './utils/extractStructAndGroups.mjs';
import { generateGpuLayoutGroups } from './utils/generateGpuLayoutGroups.mjs';
import { generateLayoutHash } from './utils/generateLayoutHash.mjs';
import { removeStructAndGroupDuplicates } from './utils/removeStructAndGroupDuplicates.mjs';
"use strict";
const programCache = /* @__PURE__ */ Object.create(null);
class GpuProgram {
/**
* Create a new GpuProgram
* @param options - The options for the gpu program
*/
constructor(options) {
/**
* @internal
* @ignore
*/
this._layoutKey = 0;
/**
* @internal
* @ignore
*/
this._attributeLocationsKey = 0;
const { fragment, vertex, layout, gpuLayout, name } = options;
this.name = name;
this.fragment = fragment;
this.vertex = vertex;
if (fragment.source === vertex.source) {
const structsAndGroups = extractStructAndGroups(fragment.source);
this.structsAndGroups = structsAndGroups;
} else {
const vertexStructsAndGroups = extractStructAndGroups(vertex.source);
const fragmentStructsAndGroups = extractStructAndGroups(fragment.source);
this.structsAndGroups = removeStructAndGroupDuplicates(vertexStructsAndGroups, fragmentStructsAndGroups);
}
this.layout = layout ?? generateLayoutHash(this.structsAndGroups);
this.gpuLayout = gpuLayout ?? generateGpuLayoutGroups(this.structsAndGroups);
this.autoAssignGlobalUniforms = !!(this.layout[0]?.globalUniforms !== void 0);
this.autoAssignLocalUniforms = !!(this.layout[1]?.localUniforms !== void 0);
this._generateProgramKey();
}
// TODO maker this pure
_generateProgramKey() {
const { vertex, fragment } = this;
const bigKey = vertex.source + fragment.source + vertex.entryPoint + fragment.entryPoint;
this._layoutKey = createIdFromString(bigKey, "program");
}
get attributeData() {
this._attributeData ?? (this._attributeData = extractAttributesFromGpuProgram(this.vertex));
return this._attributeData;
}
/** destroys the program */
destroy() {
this.gpuLayout = null;
this.layout = null;
this.structsAndGroups = null;
this.fragment = null;
this.vertex = null;
}
/**
* Helper function that creates a program for a given source.
* It will check the program cache if the program has already been created.
* If it has that one will be returned, if not a new one will be created and cached.
* @param options - The options for the program.
* @returns A program using the same source
*/
static from(options) {
const key = `${options.vertex.source}:${options.fragment.source}:${options.fragment.entryPoint}:${options.vertex.entryPoint}`;
if (!programCache[key]) {
programCache[key] = new GpuProgram(options);
}
return programCache[key];
}
}
export { GpuProgram };
//# sourceMappingURL=GpuProgram.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,27 @@
/// <reference types="@webgpu/types" />
import { ExtensionType } from '../../../../extensions/Extensions';
import type { ShaderSystem } from '../../shared/shader/ShaderSystem';
import type { GPU } from '../GpuDeviceSystem';
import type { GpuProgram } from './GpuProgram';
export interface GPUProgramData {
bindGroups: GPUBindGroupLayout[];
pipeline: GPUPipelineLayout;
}
/**
* A system that manages the rendering of GpuPrograms.
* @memberof rendering
*/
export declare class GpuShaderSystem implements ShaderSystem {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGPUSystem];
readonly name: "shader";
};
maxTextures: number;
private _gpu;
private readonly _gpuProgramData;
protected contextChange(gpu: GPU): void;
getProgramData(program: GpuProgram): GPUProgramData;
private _createGPUProgramData;
destroy(): void;
}

View File

@@ -0,0 +1,41 @@
'use strict';
var Extensions = require('../../../../extensions/Extensions.js');
"use strict";
class GpuShaderSystem {
constructor() {
this._gpuProgramData = /* @__PURE__ */ Object.create(null);
}
contextChange(gpu) {
this._gpu = gpu;
this.maxTextures = gpu.device.limits.maxSampledTexturesPerShaderStage;
}
getProgramData(program) {
return this._gpuProgramData[program._layoutKey] || this._createGPUProgramData(program);
}
_createGPUProgramData(program) {
const device = this._gpu.device;
const bindGroups = program.gpuLayout.map((group) => device.createBindGroupLayout({ entries: group }));
const pipelineLayoutDesc = { bindGroupLayouts: bindGroups };
this._gpuProgramData[program._layoutKey] = {
bindGroups,
pipeline: device.createPipelineLayout(pipelineLayoutDesc)
};
return this._gpuProgramData[program._layoutKey];
}
destroy() {
this._gpu = null;
this._gpuProgramData = null;
}
}
/** @ignore */
GpuShaderSystem.extension = {
type: [
Extensions.ExtensionType.WebGPUSystem
],
name: "shader"
};
exports.GpuShaderSystem = GpuShaderSystem;
//# sourceMappingURL=GpuShaderSystem.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"GpuShaderSystem.js","sources":["../../../../../src/rendering/renderers/gpu/shader/GpuShaderSystem.ts"],"sourcesContent":["import { ExtensionType } from '../../../../extensions/Extensions';\n\nimport type { ShaderSystem } from '../../shared/shader/ShaderSystem';\nimport type { GPU } from '../GpuDeviceSystem';\nimport type { GpuProgram } from './GpuProgram';\n\nexport interface GPUProgramData\n{\n bindGroups: GPUBindGroupLayout[]\n pipeline: GPUPipelineLayout\n}\n\n/**\n * A system that manages the rendering of GpuPrograms.\n * @memberof rendering\n */\nexport class GpuShaderSystem implements ShaderSystem\n{\n /** @ignore */\n public static extension = {\n type: [\n ExtensionType.WebGPUSystem,\n ],\n name: 'shader',\n } as const;\n\n public maxTextures: number;\n\n private _gpu: GPU;\n\n private readonly _gpuProgramData: Record<number, GPUProgramData> = Object.create(null);\n\n protected contextChange(gpu: GPU): void\n {\n this._gpu = gpu;\n\n this.maxTextures = gpu.device.limits.maxSampledTexturesPerShaderStage;\n }\n\n public getProgramData(program: GpuProgram)\n {\n return this._gpuProgramData[program._layoutKey] || this._createGPUProgramData(program);\n }\n\n private _createGPUProgramData(program: GpuProgram)\n {\n const device = this._gpu.device;\n\n const bindGroups = program.gpuLayout.map((group) => device.createBindGroupLayout({ entries: group }));\n\n const pipelineLayoutDesc = { bindGroupLayouts: bindGroups };\n\n this._gpuProgramData[program._layoutKey] = {\n bindGroups,\n pipeline: device.createPipelineLayout(pipelineLayoutDesc),\n };\n\n // generally we avoid having to make this automatically\n // keeping this for a reminder, if any issues popup\n // program._gpuLayout = {\n // bindGroups: null,\n // pipeline: 'auto',\n // };\n\n return this._gpuProgramData[program._layoutKey];\n }\n\n public destroy(): void\n {\n // TODO destroy the _gpuProgramData\n this._gpu = null;\n (this._gpuProgramData as null) = null;\n }\n}\n"],"names":["ExtensionType"],"mappings":";;;;;AAgBO,MAAM,eACb,CAAA;AAAA,EADO,WAAA,GAAA;AAcH,IAAiB,IAAA,CAAA,eAAA,mBAAyD,MAAA,CAAA,MAAA,CAAO,IAAI,CAAA,CAAA;AAAA,GAAA;AAAA,EAE3E,cAAc,GACxB,EAAA;AACI,IAAA,IAAA,CAAK,IAAO,GAAA,GAAA,CAAA;AAEZ,IAAK,IAAA,CAAA,WAAA,GAAc,GAAI,CAAA,MAAA,CAAO,MAAO,CAAA,gCAAA,CAAA;AAAA,GACzC;AAAA,EAEO,eAAe,OACtB,EAAA;AACI,IAAA,OAAO,KAAK,eAAgB,CAAA,OAAA,CAAQ,UAAU,CAAK,IAAA,IAAA,CAAK,sBAAsB,OAAO,CAAA,CAAA;AAAA,GACzF;AAAA,EAEQ,sBAAsB,OAC9B,EAAA;AACI,IAAM,MAAA,MAAA,GAAS,KAAK,IAAK,CAAA,MAAA,CAAA;AAEzB,IAAA,MAAM,UAAa,GAAA,OAAA,CAAQ,SAAU,CAAA,GAAA,CAAI,CAAC,KAAA,KAAU,MAAO,CAAA,qBAAA,CAAsB,EAAE,OAAA,EAAS,KAAM,EAAC,CAAC,CAAA,CAAA;AAEpG,IAAM,MAAA,kBAAA,GAAqB,EAAE,gBAAA,EAAkB,UAAW,EAAA,CAAA;AAE1D,IAAK,IAAA,CAAA,eAAA,CAAgB,OAAQ,CAAA,UAAU,CAAI,GAAA;AAAA,MACvC,UAAA;AAAA,MACA,QAAA,EAAU,MAAO,CAAA,oBAAA,CAAqB,kBAAkB,CAAA;AAAA,KAC5D,CAAA;AASA,IAAO,OAAA,IAAA,CAAK,eAAgB,CAAA,OAAA,CAAQ,UAAU,CAAA,CAAA;AAAA,GAClD;AAAA,EAEO,OACP,GAAA;AAEI,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAA;AACZ,IAAC,KAAK,eAA2B,GAAA,IAAA,CAAA;AAAA,GACrC;AACJ,CAAA;AAAA;AAzDa,eAAA,CAGK,SAAY,GAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACFA,wBAAc,CAAA,YAAA;AAAA,GAClB;AAAA,EACA,IAAM,EAAA,QAAA;AACV,CAAA;;;;"}

View File

@@ -0,0 +1,39 @@
import { ExtensionType } from '../../../../extensions/Extensions.mjs';
"use strict";
class GpuShaderSystem {
constructor() {
this._gpuProgramData = /* @__PURE__ */ Object.create(null);
}
contextChange(gpu) {
this._gpu = gpu;
this.maxTextures = gpu.device.limits.maxSampledTexturesPerShaderStage;
}
getProgramData(program) {
return this._gpuProgramData[program._layoutKey] || this._createGPUProgramData(program);
}
_createGPUProgramData(program) {
const device = this._gpu.device;
const bindGroups = program.gpuLayout.map((group) => device.createBindGroupLayout({ entries: group }));
const pipelineLayoutDesc = { bindGroupLayouts: bindGroups };
this._gpuProgramData[program._layoutKey] = {
bindGroups,
pipeline: device.createPipelineLayout(pipelineLayoutDesc)
};
return this._gpuProgramData[program._layoutKey];
}
destroy() {
this._gpu = null;
this._gpuProgramData = null;
}
}
/** @ignore */
GpuShaderSystem.extension = {
type: [
ExtensionType.WebGPUSystem
],
name: "shader"
};
export { GpuShaderSystem };
//# sourceMappingURL=GpuShaderSystem.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"GpuShaderSystem.mjs","sources":["../../../../../src/rendering/renderers/gpu/shader/GpuShaderSystem.ts"],"sourcesContent":["import { ExtensionType } from '../../../../extensions/Extensions';\n\nimport type { ShaderSystem } from '../../shared/shader/ShaderSystem';\nimport type { GPU } from '../GpuDeviceSystem';\nimport type { GpuProgram } from './GpuProgram';\n\nexport interface GPUProgramData\n{\n bindGroups: GPUBindGroupLayout[]\n pipeline: GPUPipelineLayout\n}\n\n/**\n * A system that manages the rendering of GpuPrograms.\n * @memberof rendering\n */\nexport class GpuShaderSystem implements ShaderSystem\n{\n /** @ignore */\n public static extension = {\n type: [\n ExtensionType.WebGPUSystem,\n ],\n name: 'shader',\n } as const;\n\n public maxTextures: number;\n\n private _gpu: GPU;\n\n private readonly _gpuProgramData: Record<number, GPUProgramData> = Object.create(null);\n\n protected contextChange(gpu: GPU): void\n {\n this._gpu = gpu;\n\n this.maxTextures = gpu.device.limits.maxSampledTexturesPerShaderStage;\n }\n\n public getProgramData(program: GpuProgram)\n {\n return this._gpuProgramData[program._layoutKey] || this._createGPUProgramData(program);\n }\n\n private _createGPUProgramData(program: GpuProgram)\n {\n const device = this._gpu.device;\n\n const bindGroups = program.gpuLayout.map((group) => device.createBindGroupLayout({ entries: group }));\n\n const pipelineLayoutDesc = { bindGroupLayouts: bindGroups };\n\n this._gpuProgramData[program._layoutKey] = {\n bindGroups,\n pipeline: device.createPipelineLayout(pipelineLayoutDesc),\n };\n\n // generally we avoid having to make this automatically\n // keeping this for a reminder, if any issues popup\n // program._gpuLayout = {\n // bindGroups: null,\n // pipeline: 'auto',\n // };\n\n return this._gpuProgramData[program._layoutKey];\n }\n\n public destroy(): void\n {\n // TODO destroy the _gpuProgramData\n this._gpu = null;\n (this._gpuProgramData as null) = null;\n }\n}\n"],"names":[],"mappings":";;;AAgBO,MAAM,eACb,CAAA;AAAA,EADO,WAAA,GAAA;AAcH,IAAiB,IAAA,CAAA,eAAA,mBAAyD,MAAA,CAAA,MAAA,CAAO,IAAI,CAAA,CAAA;AAAA,GAAA;AAAA,EAE3E,cAAc,GACxB,EAAA;AACI,IAAA,IAAA,CAAK,IAAO,GAAA,GAAA,CAAA;AAEZ,IAAK,IAAA,CAAA,WAAA,GAAc,GAAI,CAAA,MAAA,CAAO,MAAO,CAAA,gCAAA,CAAA;AAAA,GACzC;AAAA,EAEO,eAAe,OACtB,EAAA;AACI,IAAA,OAAO,KAAK,eAAgB,CAAA,OAAA,CAAQ,UAAU,CAAK,IAAA,IAAA,CAAK,sBAAsB,OAAO,CAAA,CAAA;AAAA,GACzF;AAAA,EAEQ,sBAAsB,OAC9B,EAAA;AACI,IAAM,MAAA,MAAA,GAAS,KAAK,IAAK,CAAA,MAAA,CAAA;AAEzB,IAAA,MAAM,UAAa,GAAA,OAAA,CAAQ,SAAU,CAAA,GAAA,CAAI,CAAC,KAAA,KAAU,MAAO,CAAA,qBAAA,CAAsB,EAAE,OAAA,EAAS,KAAM,EAAC,CAAC,CAAA,CAAA;AAEpG,IAAM,MAAA,kBAAA,GAAqB,EAAE,gBAAA,EAAkB,UAAW,EAAA,CAAA;AAE1D,IAAK,IAAA,CAAA,eAAA,CAAgB,OAAQ,CAAA,UAAU,CAAI,GAAA;AAAA,MACvC,UAAA;AAAA,MACA,QAAA,EAAU,MAAO,CAAA,oBAAA,CAAqB,kBAAkB,CAAA;AAAA,KAC5D,CAAA;AASA,IAAO,OAAA,IAAA,CAAK,eAAgB,CAAA,OAAA,CAAQ,UAAU,CAAA,CAAA;AAAA,GAClD;AAAA,EAEO,OACP,GAAA;AAEI,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAA;AACZ,IAAC,KAAK,eAA2B,GAAA,IAAA,CAAA;AAAA,GACrC;AACJ,CAAA;AAAA;AAzDa,eAAA,CAGK,SAAY,GAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACF,aAAc,CAAA,YAAA;AAAA,GAClB;AAAA,EACA,IAAM,EAAA,QAAA;AACV,CAAA;;;;"}

View File

@@ -0,0 +1,6 @@
import type { UboLayout, UNIFORM_TYPES, UniformData } from '../../../shared/shader/types';
export declare const WGSL_ALIGN_SIZE_DATA: Record<UNIFORM_TYPES | string, {
align: number;
size: number;
}>;
export declare function createUboElementsWGSL(uniformData: UniformData[]): UboLayout;

View File

@@ -0,0 +1,68 @@
'use strict';
"use strict";
const WGSL_ALIGN_SIZE_DATA = {
i32: { align: 4, size: 4 },
u32: { align: 4, size: 4 },
f32: { align: 4, size: 4 },
f16: { align: 2, size: 2 },
"vec2<i32>": { align: 8, size: 8 },
"vec2<u32>": { align: 8, size: 8 },
"vec2<f32>": { align: 8, size: 8 },
"vec2<f16>": { align: 4, size: 4 },
"vec3<i32>": { align: 16, size: 12 },
"vec3<u32>": { align: 16, size: 12 },
"vec3<f32>": { align: 16, size: 12 },
"vec3<f16>": { align: 8, size: 6 },
"vec4<i32>": { align: 16, size: 16 },
"vec4<u32>": { align: 16, size: 16 },
"vec4<f32>": { align: 16, size: 16 },
"vec4<f16>": { align: 8, size: 8 },
"mat2x2<f32>": { align: 8, size: 16 },
"mat2x2<f16>": { align: 4, size: 8 },
"mat3x2<f32>": { align: 8, size: 24 },
"mat3x2<f16>": { align: 4, size: 12 },
"mat4x2<f32>": { align: 8, size: 32 },
"mat4x2<f16>": { align: 4, size: 16 },
"mat2x3<f32>": { align: 16, size: 32 },
"mat2x3<f16>": { align: 8, size: 16 },
"mat3x3<f32>": { align: 16, size: 48 },
"mat3x3<f16>": { align: 8, size: 24 },
"mat4x3<f32>": { align: 16, size: 64 },
"mat4x3<f16>": { align: 8, size: 32 },
"mat2x4<f32>": { align: 16, size: 32 },
"mat2x4<f16>": { align: 8, size: 16 },
"mat3x4<f32>": { align: 16, size: 48 },
"mat3x4<f16>": { align: 8, size: 24 },
"mat4x4<f32>": { align: 16, size: 64 },
"mat4x4<f16>": { align: 8, size: 32 }
};
function createUboElementsWGSL(uniformData) {
const uboElements = uniformData.map((data) => ({
data,
offset: 0,
size: 0
}));
let offset = 0;
for (let i = 0; i < uboElements.length; i++) {
const uboElement = uboElements[i];
let size = WGSL_ALIGN_SIZE_DATA[uboElement.data.type].size;
const align = WGSL_ALIGN_SIZE_DATA[uboElement.data.type].align;
if (!WGSL_ALIGN_SIZE_DATA[uboElement.data.type]) {
throw new Error(`[Pixi.js] WebGPU UniformBuffer: Unknown type ${uboElement.data.type}`);
}
if (uboElement.data.size > 1) {
size = Math.max(size, align) * uboElement.data.size;
}
offset = Math.ceil(offset / align) * align;
uboElement.size = size;
uboElement.offset = offset;
offset += size;
}
offset = Math.ceil(offset / 16) * 16;
return { uboElements, size: offset };
}
exports.WGSL_ALIGN_SIZE_DATA = WGSL_ALIGN_SIZE_DATA;
exports.createUboElementsWGSL = createUboElementsWGSL;
//# sourceMappingURL=createUboElementsWGSL.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,65 @@
"use strict";
const WGSL_ALIGN_SIZE_DATA = {
i32: { align: 4, size: 4 },
u32: { align: 4, size: 4 },
f32: { align: 4, size: 4 },
f16: { align: 2, size: 2 },
"vec2<i32>": { align: 8, size: 8 },
"vec2<u32>": { align: 8, size: 8 },
"vec2<f32>": { align: 8, size: 8 },
"vec2<f16>": { align: 4, size: 4 },
"vec3<i32>": { align: 16, size: 12 },
"vec3<u32>": { align: 16, size: 12 },
"vec3<f32>": { align: 16, size: 12 },
"vec3<f16>": { align: 8, size: 6 },
"vec4<i32>": { align: 16, size: 16 },
"vec4<u32>": { align: 16, size: 16 },
"vec4<f32>": { align: 16, size: 16 },
"vec4<f16>": { align: 8, size: 8 },
"mat2x2<f32>": { align: 8, size: 16 },
"mat2x2<f16>": { align: 4, size: 8 },
"mat3x2<f32>": { align: 8, size: 24 },
"mat3x2<f16>": { align: 4, size: 12 },
"mat4x2<f32>": { align: 8, size: 32 },
"mat4x2<f16>": { align: 4, size: 16 },
"mat2x3<f32>": { align: 16, size: 32 },
"mat2x3<f16>": { align: 8, size: 16 },
"mat3x3<f32>": { align: 16, size: 48 },
"mat3x3<f16>": { align: 8, size: 24 },
"mat4x3<f32>": { align: 16, size: 64 },
"mat4x3<f16>": { align: 8, size: 32 },
"mat2x4<f32>": { align: 16, size: 32 },
"mat2x4<f16>": { align: 8, size: 16 },
"mat3x4<f32>": { align: 16, size: 48 },
"mat3x4<f16>": { align: 8, size: 24 },
"mat4x4<f32>": { align: 16, size: 64 },
"mat4x4<f16>": { align: 8, size: 32 }
};
function createUboElementsWGSL(uniformData) {
const uboElements = uniformData.map((data) => ({
data,
offset: 0,
size: 0
}));
let offset = 0;
for (let i = 0; i < uboElements.length; i++) {
const uboElement = uboElements[i];
let size = WGSL_ALIGN_SIZE_DATA[uboElement.data.type].size;
const align = WGSL_ALIGN_SIZE_DATA[uboElement.data.type].align;
if (!WGSL_ALIGN_SIZE_DATA[uboElement.data.type]) {
throw new Error(`[Pixi.js] WebGPU UniformBuffer: Unknown type ${uboElement.data.type}`);
}
if (uboElement.data.size > 1) {
size = Math.max(size, align) * uboElement.data.size;
}
offset = Math.ceil(offset / align) * align;
uboElement.size = size;
uboElement.offset = offset;
offset += size;
}
offset = Math.ceil(offset / 16) * 16;
return { uboElements, size: offset };
}
export { WGSL_ALIGN_SIZE_DATA, createUboElementsWGSL };
//# sourceMappingURL=createUboElementsWGSL.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
import type { UboElement, UniformsSyncCallback } from '../../../shared/shader/types';
export declare function createUboSyncFunctionWGSL(uboElements: UboElement[]): UniformsSyncCallback;

View File

@@ -0,0 +1,18 @@
'use strict';
var createUboSyncFunction = require('../../../shared/shader/utils/createUboSyncFunction.js');
var uboSyncFunctions = require('../../../shared/shader/utils/uboSyncFunctions.js');
var generateArraySyncWGSL = require('./generateArraySyncWGSL.js');
"use strict";
function createUboSyncFunctionWGSL(uboElements) {
return createUboSyncFunction.createUboSyncFunction(
uboElements,
"uboWgsl",
generateArraySyncWGSL.generateArraySyncWGSL,
uboSyncFunctions.uboSyncFunctionsWGSL
);
}
exports.createUboSyncFunctionWGSL = createUboSyncFunctionWGSL;
//# sourceMappingURL=createUboSyncFunctionWGSL.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"createUboSyncFunctionWGSL.js","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/createUboSyncFunctionWGSL.ts"],"sourcesContent":["/* eslint-disable quote-props */\nimport { createUboSyncFunction } from '../../../shared/shader/utils/createUboSyncFunction';\nimport { uboSyncFunctionsWGSL } from '../../../shared/shader/utils/uboSyncFunctions';\nimport { generateArraySyncWGSL } from './generateArraySyncWGSL';\n\nimport type { UboElement, UniformsSyncCallback } from '../../../shared/shader/types';\n\nexport function createUboSyncFunctionWGSL(\n uboElements: UboElement[],\n): UniformsSyncCallback\n{\n return createUboSyncFunction(\n uboElements,\n 'uboWgsl',\n generateArraySyncWGSL,\n uboSyncFunctionsWGSL,\n );\n}\n"],"names":["createUboSyncFunction","generateArraySyncWGSL","uboSyncFunctionsWGSL"],"mappings":";;;;;;;AAOO,SAAS,0BACZ,WAEJ,EAAA;AACI,EAAO,OAAAA,2CAAA;AAAA,IACH,WAAA;AAAA,IACA,SAAA;AAAA,IACAC,2CAAA;AAAA,IACAC,qCAAA;AAAA,GACJ,CAAA;AACJ;;;;"}

View File

@@ -0,0 +1,16 @@
import { createUboSyncFunction } from '../../../shared/shader/utils/createUboSyncFunction.mjs';
import { uboSyncFunctionsWGSL } from '../../../shared/shader/utils/uboSyncFunctions.mjs';
import { generateArraySyncWGSL } from './generateArraySyncWGSL.mjs';
"use strict";
function createUboSyncFunctionWGSL(uboElements) {
return createUboSyncFunction(
uboElements,
"uboWgsl",
generateArraySyncWGSL,
uboSyncFunctionsWGSL
);
}
export { createUboSyncFunctionWGSL };
//# sourceMappingURL=createUboSyncFunctionWGSL.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"createUboSyncFunctionWGSL.mjs","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/createUboSyncFunctionWGSL.ts"],"sourcesContent":["/* eslint-disable quote-props */\nimport { createUboSyncFunction } from '../../../shared/shader/utils/createUboSyncFunction';\nimport { uboSyncFunctionsWGSL } from '../../../shared/shader/utils/uboSyncFunctions';\nimport { generateArraySyncWGSL } from './generateArraySyncWGSL';\n\nimport type { UboElement, UniformsSyncCallback } from '../../../shared/shader/types';\n\nexport function createUboSyncFunctionWGSL(\n uboElements: UboElement[],\n): UniformsSyncCallback\n{\n return createUboSyncFunction(\n uboElements,\n 'uboWgsl',\n generateArraySyncWGSL,\n uboSyncFunctionsWGSL,\n );\n}\n"],"names":[],"mappings":";;;;;AAOO,SAAS,0BACZ,WAEJ,EAAA;AACI,EAAO,OAAA,qBAAA;AAAA,IACH,WAAA;AAAA,IACA,SAAA;AAAA,IACA,qBAAA;AAAA,IACA,oBAAA;AAAA,GACJ,CAAA;AACJ;;;;"}

View File

@@ -0,0 +1,3 @@
import type { ExtractedAttributeData } from '../../../gl/shader/program/extractAttributesFromGlProgram';
import type { ProgramSource } from '../GpuProgram';
export declare function extractAttributesFromGpuProgram({ source, entryPoint }: ProgramSource): Record<string, ExtractedAttributeData>;

View File

@@ -0,0 +1,53 @@
'use strict';
var getAttributeInfoFromFormat = require('../../../shared/geometry/utils/getAttributeInfoFromFormat.js');
"use strict";
const WGSL_TO_VERTEX_TYPES = {
f32: "float32",
"vec2<f32>": "float32x2",
"vec3<f32>": "float32x3",
"vec4<f32>": "float32x4",
vec2f: "float32x2",
vec3f: "float32x3",
vec4f: "float32x4",
i32: "sint32",
"vec2<i32>": "sint32x2",
"vec3<i32>": "sint32x3",
"vec4<i32>": "sint32x4",
u32: "uint32",
"vec2<u32>": "uint32x2",
"vec3<u32>": "uint32x3",
"vec4<u32>": "uint32x4",
bool: "uint32",
"vec2<bool>": "uint32x2",
"vec3<bool>": "uint32x3",
"vec4<bool>": "uint32x4"
};
function extractAttributesFromGpuProgram({ source, entryPoint }) {
const results = {};
const mainVertStart = source.indexOf(`fn ${entryPoint}`);
if (mainVertStart !== -1) {
const arrowFunctionStart = source.indexOf("->", mainVertStart);
if (arrowFunctionStart !== -1) {
const functionArgsSubstring = source.substring(mainVertStart, arrowFunctionStart);
const inputsRegex = /@location\((\d+)\)\s+([a-zA-Z0-9_]+)\s*:\s*([a-zA-Z0-9_<>]+)(?:,|\s|$)/g;
let match;
while ((match = inputsRegex.exec(functionArgsSubstring)) !== null) {
const format = WGSL_TO_VERTEX_TYPES[match[3]] ?? "float32";
results[match[2]] = {
location: parseInt(match[1], 10),
format,
stride: getAttributeInfoFromFormat.getAttributeInfoFromFormat(format).stride,
offset: 0,
instance: false,
start: 0
};
}
}
}
return results;
}
exports.extractAttributesFromGpuProgram = extractAttributesFromGpuProgram;
//# sourceMappingURL=extractAttributesFromGpuProgram.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractAttributesFromGpuProgram.js","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/extractAttributesFromGpuProgram.ts"],"sourcesContent":["import { getAttributeInfoFromFormat } from '../../../shared/geometry/utils/getAttributeInfoFromFormat';\n\nimport type { ExtractedAttributeData } from '../../../gl/shader/program/extractAttributesFromGlProgram';\nimport type { VertexFormat } from '../../../shared/geometry/const';\nimport type { ProgramSource } from '../GpuProgram';\n\nconst WGSL_TO_VERTEX_TYPES: Record<string, VertexFormat> = {\n\n f32: 'float32',\n 'vec2<f32>': 'float32x2',\n 'vec3<f32>': 'float32x3',\n 'vec4<f32>': 'float32x4',\n vec2f: 'float32x2',\n vec3f: 'float32x3',\n vec4f: 'float32x4',\n\n i32: 'sint32',\n 'vec2<i32>': 'sint32x2',\n 'vec3<i32>': 'sint32x3',\n 'vec4<i32>': 'sint32x4',\n\n u32: 'uint32',\n 'vec2<u32>': 'uint32x2',\n 'vec3<u32>': 'uint32x3',\n 'vec4<u32>': 'uint32x4',\n\n bool: 'uint32',\n 'vec2<bool>': 'uint32x2',\n 'vec3<bool>': 'uint32x3',\n 'vec4<bool>': 'uint32x4',\n};\n\nexport function extractAttributesFromGpuProgram(\n { source, entryPoint }: ProgramSource\n): Record<string, ExtractedAttributeData>\n{\n const results: Record<string, ExtractedAttributeData> = {};\n\n // Step 1: Find the start of the mainVert function using string methods\n const mainVertStart = source.indexOf(`fn ${entryPoint}`);\n\n if (mainVertStart !== -1)\n {\n // Step 2: Find the index of the next '->' after the start of the mainVert function\n const arrowFunctionStart = source.indexOf('->', mainVertStart);\n\n if (arrowFunctionStart !== -1)\n {\n const functionArgsSubstring = source.substring(mainVertStart, arrowFunctionStart);\n\n // Apply the inputs regex directly to the trimmed string\n const inputsRegex = /@location\\((\\d+)\\)\\s+([a-zA-Z0-9_]+)\\s*:\\s*([a-zA-Z0-9_<>]+)(?:,|\\s|$)/g;\n let match;\n\n while ((match = inputsRegex.exec(functionArgsSubstring)) !== null)\n {\n const format = WGSL_TO_VERTEX_TYPES[match[3] as VertexFormat] ?? 'float32';\n\n results[match[2]] = {\n location: parseInt(match[1], 10),\n format,\n stride: getAttributeInfoFromFormat(format).stride,\n offset: 0,\n instance: false,\n start: 0,\n };\n }\n }\n }\n\n return results;\n}\n"],"names":["getAttributeInfoFromFormat"],"mappings":";;;;;AAMA,MAAM,oBAAqD,GAAA;AAAA,EAEvD,GAAM,EAAA,SAAA;AAAA,EACN,WAAa,EAAA,WAAA;AAAA,EACb,WAAa,EAAA,WAAA;AAAA,EACb,WAAa,EAAA,WAAA;AAAA,EACb,KAAO,EAAA,WAAA;AAAA,EACP,KAAO,EAAA,WAAA;AAAA,EACP,KAAO,EAAA,WAAA;AAAA,EAEP,GAAK,EAAA,QAAA;AAAA,EACL,WAAa,EAAA,UAAA;AAAA,EACb,WAAa,EAAA,UAAA;AAAA,EACb,WAAa,EAAA,UAAA;AAAA,EAEb,GAAK,EAAA,QAAA;AAAA,EACL,WAAa,EAAA,UAAA;AAAA,EACb,WAAa,EAAA,UAAA;AAAA,EACb,WAAa,EAAA,UAAA;AAAA,EAEb,IAAM,EAAA,QAAA;AAAA,EACN,YAAc,EAAA,UAAA;AAAA,EACd,YAAc,EAAA,UAAA;AAAA,EACd,YAAc,EAAA,UAAA;AAClB,CAAA,CAAA;AAEO,SAAS,+BACZ,CAAA,EAAE,MAAQ,EAAA,UAAA,EAEd,EAAA;AACI,EAAA,MAAM,UAAkD,EAAC,CAAA;AAGzD,EAAA,MAAM,aAAgB,GAAA,MAAA,CAAO,OAAQ,CAAA,CAAA,GAAA,EAAM,UAAU,CAAE,CAAA,CAAA,CAAA;AAEvD,EAAA,IAAI,kBAAkB,CACtB,CAAA,EAAA;AAEI,IAAA,MAAM,kBAAqB,GAAA,MAAA,CAAO,OAAQ,CAAA,IAAA,EAAM,aAAa,CAAA,CAAA;AAE7D,IAAA,IAAI,uBAAuB,CAC3B,CAAA,EAAA;AACI,MAAA,MAAM,qBAAwB,GAAA,MAAA,CAAO,SAAU,CAAA,aAAA,EAAe,kBAAkB,CAAA,CAAA;AAGhF,MAAA,MAAM,WAAc,GAAA,yEAAA,CAAA;AACpB,MAAI,IAAA,KAAA,CAAA;AAEJ,MAAA,OAAA,CAAQ,KAAQ,GAAA,WAAA,CAAY,IAAK,CAAA,qBAAqB,OAAO,IAC7D,EAAA;AACI,QAAA,MAAM,MAAS,GAAA,oBAAA,CAAqB,KAAM,CAAA,CAAC,CAAiB,CAAK,IAAA,SAAA,CAAA;AAEjE,QAAQ,OAAA,CAAA,KAAA,CAAM,CAAC,CAAC,CAAI,GAAA;AAAA,UAChB,QAAU,EAAA,QAAA,CAAS,KAAM,CAAA,CAAC,GAAG,EAAE,CAAA;AAAA,UAC/B,MAAA;AAAA,UACA,MAAA,EAAQA,qDAA2B,CAAA,MAAM,CAAE,CAAA,MAAA;AAAA,UAC3C,MAAQ,EAAA,CAAA;AAAA,UACR,QAAU,EAAA,KAAA;AAAA,UACV,KAAO,EAAA,CAAA;AAAA,SACX,CAAA;AAAA,OACJ;AAAA,KACJ;AAAA,GACJ;AAEA,EAAO,OAAA,OAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,51 @@
import { getAttributeInfoFromFormat } from '../../../shared/geometry/utils/getAttributeInfoFromFormat.mjs';
"use strict";
const WGSL_TO_VERTEX_TYPES = {
f32: "float32",
"vec2<f32>": "float32x2",
"vec3<f32>": "float32x3",
"vec4<f32>": "float32x4",
vec2f: "float32x2",
vec3f: "float32x3",
vec4f: "float32x4",
i32: "sint32",
"vec2<i32>": "sint32x2",
"vec3<i32>": "sint32x3",
"vec4<i32>": "sint32x4",
u32: "uint32",
"vec2<u32>": "uint32x2",
"vec3<u32>": "uint32x3",
"vec4<u32>": "uint32x4",
bool: "uint32",
"vec2<bool>": "uint32x2",
"vec3<bool>": "uint32x3",
"vec4<bool>": "uint32x4"
};
function extractAttributesFromGpuProgram({ source, entryPoint }) {
const results = {};
const mainVertStart = source.indexOf(`fn ${entryPoint}`);
if (mainVertStart !== -1) {
const arrowFunctionStart = source.indexOf("->", mainVertStart);
if (arrowFunctionStart !== -1) {
const functionArgsSubstring = source.substring(mainVertStart, arrowFunctionStart);
const inputsRegex = /@location\((\d+)\)\s+([a-zA-Z0-9_]+)\s*:\s*([a-zA-Z0-9_<>]+)(?:,|\s|$)/g;
let match;
while ((match = inputsRegex.exec(functionArgsSubstring)) !== null) {
const format = WGSL_TO_VERTEX_TYPES[match[3]] ?? "float32";
results[match[2]] = {
location: parseInt(match[1], 10),
format,
stride: getAttributeInfoFromFormat(format).stride,
offset: 0,
instance: false,
start: 0
};
}
}
}
return results;
}
export { extractAttributesFromGpuProgram };
//# sourceMappingURL=extractAttributesFromGpuProgram.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractAttributesFromGpuProgram.mjs","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/extractAttributesFromGpuProgram.ts"],"sourcesContent":["import { getAttributeInfoFromFormat } from '../../../shared/geometry/utils/getAttributeInfoFromFormat';\n\nimport type { ExtractedAttributeData } from '../../../gl/shader/program/extractAttributesFromGlProgram';\nimport type { VertexFormat } from '../../../shared/geometry/const';\nimport type { ProgramSource } from '../GpuProgram';\n\nconst WGSL_TO_VERTEX_TYPES: Record<string, VertexFormat> = {\n\n f32: 'float32',\n 'vec2<f32>': 'float32x2',\n 'vec3<f32>': 'float32x3',\n 'vec4<f32>': 'float32x4',\n vec2f: 'float32x2',\n vec3f: 'float32x3',\n vec4f: 'float32x4',\n\n i32: 'sint32',\n 'vec2<i32>': 'sint32x2',\n 'vec3<i32>': 'sint32x3',\n 'vec4<i32>': 'sint32x4',\n\n u32: 'uint32',\n 'vec2<u32>': 'uint32x2',\n 'vec3<u32>': 'uint32x3',\n 'vec4<u32>': 'uint32x4',\n\n bool: 'uint32',\n 'vec2<bool>': 'uint32x2',\n 'vec3<bool>': 'uint32x3',\n 'vec4<bool>': 'uint32x4',\n};\n\nexport function extractAttributesFromGpuProgram(\n { source, entryPoint }: ProgramSource\n): Record<string, ExtractedAttributeData>\n{\n const results: Record<string, ExtractedAttributeData> = {};\n\n // Step 1: Find the start of the mainVert function using string methods\n const mainVertStart = source.indexOf(`fn ${entryPoint}`);\n\n if (mainVertStart !== -1)\n {\n // Step 2: Find the index of the next '->' after the start of the mainVert function\n const arrowFunctionStart = source.indexOf('->', mainVertStart);\n\n if (arrowFunctionStart !== -1)\n {\n const functionArgsSubstring = source.substring(mainVertStart, arrowFunctionStart);\n\n // Apply the inputs regex directly to the trimmed string\n const inputsRegex = /@location\\((\\d+)\\)\\s+([a-zA-Z0-9_]+)\\s*:\\s*([a-zA-Z0-9_<>]+)(?:,|\\s|$)/g;\n let match;\n\n while ((match = inputsRegex.exec(functionArgsSubstring)) !== null)\n {\n const format = WGSL_TO_VERTEX_TYPES[match[3] as VertexFormat] ?? 'float32';\n\n results[match[2]] = {\n location: parseInt(match[1], 10),\n format,\n stride: getAttributeInfoFromFormat(format).stride,\n offset: 0,\n instance: false,\n start: 0,\n };\n }\n }\n }\n\n return results;\n}\n"],"names":[],"mappings":";;;AAMA,MAAM,oBAAqD,GAAA;AAAA,EAEvD,GAAM,EAAA,SAAA;AAAA,EACN,WAAa,EAAA,WAAA;AAAA,EACb,WAAa,EAAA,WAAA;AAAA,EACb,WAAa,EAAA,WAAA;AAAA,EACb,KAAO,EAAA,WAAA;AAAA,EACP,KAAO,EAAA,WAAA;AAAA,EACP,KAAO,EAAA,WAAA;AAAA,EAEP,GAAK,EAAA,QAAA;AAAA,EACL,WAAa,EAAA,UAAA;AAAA,EACb,WAAa,EAAA,UAAA;AAAA,EACb,WAAa,EAAA,UAAA;AAAA,EAEb,GAAK,EAAA,QAAA;AAAA,EACL,WAAa,EAAA,UAAA;AAAA,EACb,WAAa,EAAA,UAAA;AAAA,EACb,WAAa,EAAA,UAAA;AAAA,EAEb,IAAM,EAAA,QAAA;AAAA,EACN,YAAc,EAAA,UAAA;AAAA,EACd,YAAc,EAAA,UAAA;AAAA,EACd,YAAc,EAAA,UAAA;AAClB,CAAA,CAAA;AAEO,SAAS,+BACZ,CAAA,EAAE,MAAQ,EAAA,UAAA,EAEd,EAAA;AACI,EAAA,MAAM,UAAkD,EAAC,CAAA;AAGzD,EAAA,MAAM,aAAgB,GAAA,MAAA,CAAO,OAAQ,CAAA,CAAA,GAAA,EAAM,UAAU,CAAE,CAAA,CAAA,CAAA;AAEvD,EAAA,IAAI,kBAAkB,CACtB,CAAA,EAAA;AAEI,IAAA,MAAM,kBAAqB,GAAA,MAAA,CAAO,OAAQ,CAAA,IAAA,EAAM,aAAa,CAAA,CAAA;AAE7D,IAAA,IAAI,uBAAuB,CAC3B,CAAA,EAAA;AACI,MAAA,MAAM,qBAAwB,GAAA,MAAA,CAAO,SAAU,CAAA,aAAA,EAAe,kBAAkB,CAAA,CAAA;AAGhF,MAAA,MAAM,WAAc,GAAA,yEAAA,CAAA;AACpB,MAAI,IAAA,KAAA,CAAA;AAEJ,MAAA,OAAA,CAAQ,KAAQ,GAAA,WAAA,CAAY,IAAK,CAAA,qBAAqB,OAAO,IAC7D,EAAA;AACI,QAAA,MAAM,MAAS,GAAA,oBAAA,CAAqB,KAAM,CAAA,CAAC,CAAiB,CAAK,IAAA,SAAA,CAAA;AAEjE,QAAQ,OAAA,CAAA,KAAA,CAAM,CAAC,CAAC,CAAI,GAAA;AAAA,UAChB,QAAU,EAAA,QAAA,CAAS,KAAM,CAAA,CAAC,GAAG,EAAE,CAAA;AAAA,UAC/B,MAAA;AAAA,UACA,MAAA,EAAQ,0BAA2B,CAAA,MAAM,CAAE,CAAA,MAAA;AAAA,UAC3C,MAAQ,EAAA,CAAA;AAAA,UACR,QAAU,EAAA,KAAA;AAAA,UACV,KAAO,EAAA,CAAA;AAAA,SACX,CAAA;AAAA,OACJ;AAAA,KACJ;AAAA,GACJ;AAEA,EAAO,OAAA,OAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,14 @@
export interface StructsAndGroups {
groups: {
group: number;
binding: number;
name: string;
isUniform: boolean;
type: string;
}[];
structs: {
name: string;
members: Record<string, string>;
}[];
}
export declare function extractStructAndGroups(wgsl: string): StructsAndGroups;

View File

@@ -0,0 +1,45 @@
'use strict';
"use strict";
function extractStructAndGroups(wgsl) {
const linePattern = /(^|[^/])@(group|binding)\(\d+\)[^;]+;/g;
const groupPattern = /@group\((\d+)\)/;
const bindingPattern = /@binding\((\d+)\)/;
const namePattern = /var(<[^>]+>)? (\w+)/;
const typePattern = /:\s*(\w+)/;
const structPattern = /struct\s+(\w+)\s*{([^}]+)}/g;
const structMemberPattern = /(\w+)\s*:\s*([\w\<\>]+)/g;
const structName = /struct\s+(\w+)/;
const groups = wgsl.match(linePattern)?.map((item) => ({
group: parseInt(item.match(groupPattern)[1], 10),
binding: parseInt(item.match(bindingPattern)[1], 10),
name: item.match(namePattern)[2],
isUniform: item.match(namePattern)[1] === "<uniform>",
type: item.match(typePattern)[1]
}));
if (!groups) {
return {
groups: [],
structs: []
};
}
const structs = wgsl.match(structPattern)?.map((struct) => {
const name = struct.match(structName)[1];
const members = struct.match(structMemberPattern).reduce((acc, member) => {
const [name2, type] = member.split(":");
acc[name2.trim()] = type.trim();
return acc;
}, {});
if (!members) {
return null;
}
return { name, members };
}).filter(({ name }) => groups.some((group) => group.type === name)) ?? [];
return {
groups,
structs
};
}
exports.extractStructAndGroups = extractStructAndGroups;
//# sourceMappingURL=extractStructAndGroups.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractStructAndGroups.js","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/extractStructAndGroups.ts"],"sourcesContent":["export interface StructsAndGroups\n{\n groups: {\n group: number;\n binding: number;\n name: string;\n isUniform: boolean;\n type: string;\n }[];\n structs: {\n name: string;\n members: Record<string, string>;\n }[];\n}\n\nexport function extractStructAndGroups(wgsl: string): StructsAndGroups\n{\n // Patterns for parsing the WGSL file\n const linePattern = /(^|[^/])@(group|binding)\\(\\d+\\)[^;]+;/g;\n const groupPattern = /@group\\((\\d+)\\)/;\n const bindingPattern = /@binding\\((\\d+)\\)/;\n const namePattern = /var(<[^>]+>)? (\\w+)/;\n const typePattern = /:\\s*(\\w+)/;\n const structPattern = /struct\\s+(\\w+)\\s*{([^}]+)}/g;\n const structMemberPattern = /(\\w+)\\s*:\\s*([\\w\\<\\>]+)/g;\n const structName = /struct\\s+(\\w+)/;\n\n // Find the @group and @binding annotations\n const groups = wgsl.match(linePattern)?.map((item) => ({\n group: parseInt(item.match(groupPattern)[1], 10),\n binding: parseInt(item.match(bindingPattern)[1], 10),\n name: item.match(namePattern)[2],\n isUniform: item.match(namePattern)[1] === '<uniform>',\n type: item.match(typePattern)[1],\n }));\n\n if (!groups)\n {\n return {\n groups: [],\n structs: [],\n };\n }\n\n // Find the structs\n const structs = wgsl\n .match(structPattern)\n ?.map((struct) =>\n {\n const name = struct.match(structName)[1];\n const members = struct.match(structMemberPattern).reduce((acc: Record<string, string>, member) =>\n {\n const [name, type] = member.split(':');\n\n acc[name.trim()] = type.trim();\n\n return acc;\n }, {});\n\n if (!members)\n {\n return null;\n }\n\n return { name, members };\n // Only include the structs mentioned in the @group/@binding annotations\n })\n .filter(({ name }) => groups.some((group) => group.type === name)) ?? [];\n\n return {\n groups,\n structs,\n };\n}\n"],"names":["name"],"mappings":";;;AAeO,SAAS,uBAAuB,IACvC,EAAA;AAEI,EAAA,MAAM,WAAc,GAAA,wCAAA,CAAA;AACpB,EAAA,MAAM,YAAe,GAAA,iBAAA,CAAA;AACrB,EAAA,MAAM,cAAiB,GAAA,mBAAA,CAAA;AACvB,EAAA,MAAM,WAAc,GAAA,qBAAA,CAAA;AACpB,EAAA,MAAM,WAAc,GAAA,WAAA,CAAA;AACpB,EAAA,MAAM,aAAgB,GAAA,6BAAA,CAAA;AACtB,EAAA,MAAM,mBAAsB,GAAA,0BAAA,CAAA;AAC5B,EAAA,MAAM,UAAa,GAAA,gBAAA,CAAA;AAGnB,EAAA,MAAM,SAAS,IAAK,CAAA,KAAA,CAAM,WAAW,CAAG,EAAA,GAAA,CAAI,CAAC,IAAU,MAAA;AAAA,IACnD,KAAA,EAAO,SAAS,IAAK,CAAA,KAAA,CAAM,YAAY,CAAE,CAAA,CAAC,GAAG,EAAE,CAAA;AAAA,IAC/C,OAAA,EAAS,SAAS,IAAK,CAAA,KAAA,CAAM,cAAc,CAAE,CAAA,CAAC,GAAG,EAAE,CAAA;AAAA,IACnD,IAAM,EAAA,IAAA,CAAK,KAAM,CAAA,WAAW,EAAE,CAAC,CAAA;AAAA,IAC/B,WAAW,IAAK,CAAA,KAAA,CAAM,WAAW,CAAA,CAAE,CAAC,CAAM,KAAA,WAAA;AAAA,IAC1C,IAAM,EAAA,IAAA,CAAK,KAAM,CAAA,WAAW,EAAE,CAAC,CAAA;AAAA,GACjC,CAAA,CAAA,CAAA;AAEF,EAAA,IAAI,CAAC,MACL,EAAA;AACI,IAAO,OAAA;AAAA,MACH,QAAQ,EAAC;AAAA,MACT,SAAS,EAAC;AAAA,KACd,CAAA;AAAA,GACJ;AAGA,EAAA,MAAM,UAAU,IACX,CAAA,KAAA,CAAM,aAAa,CAClB,EAAA,GAAA,CAAI,CAAC,MACP,KAAA;AACI,IAAA,MAAM,IAAO,GAAA,MAAA,CAAO,KAAM,CAAA,UAAU,EAAE,CAAC,CAAA,CAAA;AACvC,IAAM,MAAA,OAAA,GAAU,OAAO,KAAM,CAAA,mBAAmB,EAAE,MAAO,CAAA,CAAC,KAA6B,MACvF,KAAA;AACI,MAAA,MAAM,CAACA,KAAM,EAAA,IAAI,CAAI,GAAA,MAAA,CAAO,MAAM,GAAG,CAAA,CAAA;AAErC,MAAA,GAAA,CAAIA,KAAK,CAAA,IAAA,EAAM,CAAA,GAAI,KAAK,IAAK,EAAA,CAAA;AAE7B,MAAO,OAAA,GAAA,CAAA;AAAA,KACX,EAAG,EAAE,CAAA,CAAA;AAEL,IAAA,IAAI,CAAC,OACL,EAAA;AACI,MAAO,OAAA,IAAA,CAAA;AAAA,KACX;AAEA,IAAO,OAAA,EAAE,MAAM,OAAQ,EAAA,CAAA;AAAA,GAE1B,CACA,CAAA,MAAA,CAAO,CAAC,EAAE,MAAW,KAAA,MAAA,CAAO,IAAK,CAAA,CAAC,UAAU,KAAM,CAAA,IAAA,KAAS,IAAI,CAAC,KAAK,EAAC,CAAA;AAE3E,EAAO,OAAA;AAAA,IACH,MAAA;AAAA,IACA,OAAA;AAAA,GACJ,CAAA;AACJ;;;;"}

View File

@@ -0,0 +1,43 @@
"use strict";
function extractStructAndGroups(wgsl) {
const linePattern = /(^|[^/])@(group|binding)\(\d+\)[^;]+;/g;
const groupPattern = /@group\((\d+)\)/;
const bindingPattern = /@binding\((\d+)\)/;
const namePattern = /var(<[^>]+>)? (\w+)/;
const typePattern = /:\s*(\w+)/;
const structPattern = /struct\s+(\w+)\s*{([^}]+)}/g;
const structMemberPattern = /(\w+)\s*:\s*([\w\<\>]+)/g;
const structName = /struct\s+(\w+)/;
const groups = wgsl.match(linePattern)?.map((item) => ({
group: parseInt(item.match(groupPattern)[1], 10),
binding: parseInt(item.match(bindingPattern)[1], 10),
name: item.match(namePattern)[2],
isUniform: item.match(namePattern)[1] === "<uniform>",
type: item.match(typePattern)[1]
}));
if (!groups) {
return {
groups: [],
structs: []
};
}
const structs = wgsl.match(structPattern)?.map((struct) => {
const name = struct.match(structName)[1];
const members = struct.match(structMemberPattern).reduce((acc, member) => {
const [name2, type] = member.split(":");
acc[name2.trim()] = type.trim();
return acc;
}, {});
if (!members) {
return null;
}
return { name, members };
}).filter(({ name }) => groups.some((group) => group.type === name)) ?? [];
return {
groups,
structs
};
}
export { extractStructAndGroups };
//# sourceMappingURL=extractStructAndGroups.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractStructAndGroups.mjs","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/extractStructAndGroups.ts"],"sourcesContent":["export interface StructsAndGroups\n{\n groups: {\n group: number;\n binding: number;\n name: string;\n isUniform: boolean;\n type: string;\n }[];\n structs: {\n name: string;\n members: Record<string, string>;\n }[];\n}\n\nexport function extractStructAndGroups(wgsl: string): StructsAndGroups\n{\n // Patterns for parsing the WGSL file\n const linePattern = /(^|[^/])@(group|binding)\\(\\d+\\)[^;]+;/g;\n const groupPattern = /@group\\((\\d+)\\)/;\n const bindingPattern = /@binding\\((\\d+)\\)/;\n const namePattern = /var(<[^>]+>)? (\\w+)/;\n const typePattern = /:\\s*(\\w+)/;\n const structPattern = /struct\\s+(\\w+)\\s*{([^}]+)}/g;\n const structMemberPattern = /(\\w+)\\s*:\\s*([\\w\\<\\>]+)/g;\n const structName = /struct\\s+(\\w+)/;\n\n // Find the @group and @binding annotations\n const groups = wgsl.match(linePattern)?.map((item) => ({\n group: parseInt(item.match(groupPattern)[1], 10),\n binding: parseInt(item.match(bindingPattern)[1], 10),\n name: item.match(namePattern)[2],\n isUniform: item.match(namePattern)[1] === '<uniform>',\n type: item.match(typePattern)[1],\n }));\n\n if (!groups)\n {\n return {\n groups: [],\n structs: [],\n };\n }\n\n // Find the structs\n const structs = wgsl\n .match(structPattern)\n ?.map((struct) =>\n {\n const name = struct.match(structName)[1];\n const members = struct.match(structMemberPattern).reduce((acc: Record<string, string>, member) =>\n {\n const [name, type] = member.split(':');\n\n acc[name.trim()] = type.trim();\n\n return acc;\n }, {});\n\n if (!members)\n {\n return null;\n }\n\n return { name, members };\n // Only include the structs mentioned in the @group/@binding annotations\n })\n .filter(({ name }) => groups.some((group) => group.type === name)) ?? [];\n\n return {\n groups,\n structs,\n };\n}\n"],"names":["name"],"mappings":";AAeO,SAAS,uBAAuB,IACvC,EAAA;AAEI,EAAA,MAAM,WAAc,GAAA,wCAAA,CAAA;AACpB,EAAA,MAAM,YAAe,GAAA,iBAAA,CAAA;AACrB,EAAA,MAAM,cAAiB,GAAA,mBAAA,CAAA;AACvB,EAAA,MAAM,WAAc,GAAA,qBAAA,CAAA;AACpB,EAAA,MAAM,WAAc,GAAA,WAAA,CAAA;AACpB,EAAA,MAAM,aAAgB,GAAA,6BAAA,CAAA;AACtB,EAAA,MAAM,mBAAsB,GAAA,0BAAA,CAAA;AAC5B,EAAA,MAAM,UAAa,GAAA,gBAAA,CAAA;AAGnB,EAAA,MAAM,SAAS,IAAK,CAAA,KAAA,CAAM,WAAW,CAAG,EAAA,GAAA,CAAI,CAAC,IAAU,MAAA;AAAA,IACnD,KAAA,EAAO,SAAS,IAAK,CAAA,KAAA,CAAM,YAAY,CAAE,CAAA,CAAC,GAAG,EAAE,CAAA;AAAA,IAC/C,OAAA,EAAS,SAAS,IAAK,CAAA,KAAA,CAAM,cAAc,CAAE,CAAA,CAAC,GAAG,EAAE,CAAA;AAAA,IACnD,IAAM,EAAA,IAAA,CAAK,KAAM,CAAA,WAAW,EAAE,CAAC,CAAA;AAAA,IAC/B,WAAW,IAAK,CAAA,KAAA,CAAM,WAAW,CAAA,CAAE,CAAC,CAAM,KAAA,WAAA;AAAA,IAC1C,IAAM,EAAA,IAAA,CAAK,KAAM,CAAA,WAAW,EAAE,CAAC,CAAA;AAAA,GACjC,CAAA,CAAA,CAAA;AAEF,EAAA,IAAI,CAAC,MACL,EAAA;AACI,IAAO,OAAA;AAAA,MACH,QAAQ,EAAC;AAAA,MACT,SAAS,EAAC;AAAA,KACd,CAAA;AAAA,GACJ;AAGA,EAAA,MAAM,UAAU,IACX,CAAA,KAAA,CAAM,aAAa,CAClB,EAAA,GAAA,CAAI,CAAC,MACP,KAAA;AACI,IAAA,MAAM,IAAO,GAAA,MAAA,CAAO,KAAM,CAAA,UAAU,EAAE,CAAC,CAAA,CAAA;AACvC,IAAM,MAAA,OAAA,GAAU,OAAO,KAAM,CAAA,mBAAmB,EAAE,MAAO,CAAA,CAAC,KAA6B,MACvF,KAAA;AACI,MAAA,MAAM,CAACA,KAAM,EAAA,IAAI,CAAI,GAAA,MAAA,CAAO,MAAM,GAAG,CAAA,CAAA;AAErC,MAAA,GAAA,CAAIA,KAAK,CAAA,IAAA,EAAM,CAAA,GAAI,KAAK,IAAK,EAAA,CAAA;AAE7B,MAAO,OAAA,GAAA,CAAA;AAAA,KACX,EAAG,EAAE,CAAA,CAAA;AAEL,IAAA,IAAI,CAAC,OACL,EAAA;AACI,MAAO,OAAA,IAAA,CAAA;AAAA,KACX;AAEA,IAAO,OAAA,EAAE,MAAM,OAAQ,EAAA,CAAA;AAAA,GAE1B,CACA,CAAA,MAAA,CAAO,CAAC,EAAE,MAAW,KAAA,MAAA,CAAO,IAAK,CAAA,CAAC,UAAU,KAAM,CAAA,IAAA,KAAS,IAAI,CAAC,KAAK,EAAC,CAAA;AAE3E,EAAO,OAAA;AAAA,IACH,MAAA;AAAA,IACA,OAAA;AAAA,GACJ,CAAA;AACJ;;;;"}

View File

@@ -0,0 +1,9 @@
import type { UboElement } from '../../../shared/shader/types';
/**
* This generates a function that will sync an array to the uniform buffer
* following the wgsl layout
* @param uboElement - the element to generate the array sync for
* @param offsetToAdd - the offset to append at the start of the code
* @returns - the generated code
*/
export declare function generateArraySyncWGSL(uboElement: UboElement, offsetToAdd: number): string;

View File

@@ -0,0 +1,29 @@
'use strict';
var createUboElementsWGSL = require('./createUboElementsWGSL.js');
"use strict";
function generateArraySyncWGSL(uboElement, offsetToAdd) {
const { size, align } = createUboElementsWGSL.WGSL_ALIGN_SIZE_DATA[uboElement.data.type];
const remainder = (align - size) / 4;
return `
v = uv.${uboElement.data.name};
${offsetToAdd !== 0 ? `offset += ${offsetToAdd};` : ""}
arrayOffset = offset;
t = 0;
for(var i=0; i < ${uboElement.data.size * (size / 4)}; i++)
{
for(var j = 0; j < ${size / 4}; j++)
{
data[arrayOffset++] = v[t++];
}
${remainder !== 0 ? `arrayOffset += ${remainder};` : ""}
}
`;
}
exports.generateArraySyncWGSL = generateArraySyncWGSL;
//# sourceMappingURL=generateArraySyncWGSL.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateArraySyncWGSL.js","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/generateArraySyncWGSL.ts"],"sourcesContent":["import { WGSL_ALIGN_SIZE_DATA } from './createUboElementsWGSL';\n\nimport type { UboElement } from '../../../shared/shader/types';\n\n/**\n * This generates a function that will sync an array to the uniform buffer\n * following the wgsl layout\n * @param uboElement - the element to generate the array sync for\n * @param offsetToAdd - the offset to append at the start of the code\n * @returns - the generated code\n */\nexport function generateArraySyncWGSL(uboElement: UboElement, offsetToAdd: number): string\n{\n // this is in byte..\n const { size, align } = WGSL_ALIGN_SIZE_DATA[uboElement.data.type];\n\n const remainder = (align - size) / 4;\n\n return `\n v = uv.${uboElement.data.name};\n ${offsetToAdd !== 0 ? `offset += ${offsetToAdd};` : ''}\n\n arrayOffset = offset;\n\n t = 0;\n\n for(var i=0; i < ${uboElement.data.size * (size / 4)}; i++)\n {\n for(var j = 0; j < ${size / 4}; j++)\n {\n data[arrayOffset++] = v[t++];\n }\n ${remainder !== 0 ? `arrayOffset += ${remainder};` : ''}\n }\n `;\n}\n"],"names":["WGSL_ALIGN_SIZE_DATA"],"mappings":";;;;;AAWgB,SAAA,qBAAA,CAAsB,YAAwB,WAC9D,EAAA;AAEI,EAAA,MAAM,EAAE,IAAM,EAAA,KAAA,KAAUA,0CAAqB,CAAA,UAAA,CAAW,KAAK,IAAI,CAAA,CAAA;AAEjE,EAAM,MAAA,SAAA,GAAA,CAAa,QAAQ,IAAQ,IAAA,CAAA,CAAA;AAEnC,EAAO,OAAA,CAAA;AAAA,gBACO,EAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA,SAAA,EAC3B,WAAgB,KAAA,CAAA,GAAI,CAAa,UAAA,EAAA,WAAW,MAAM,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAA,EAMnC,UAAW,CAAA,IAAA,CAAK,IAAQ,IAAA,IAAA,GAAO,CAAE,CAAA,CAAA;AAAA;AAAA,gCAAA,EAE3B,OAAO,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA,aAAA,EAI3B,SAAc,KAAA,CAAA,GAAI,CAAkB,eAAA,EAAA,SAAS,MAAM,EAAE,CAAA;AAAA;AAAA,KAAA,CAAA,CAAA;AAGpE;;;;"}

View File

@@ -0,0 +1,27 @@
import { WGSL_ALIGN_SIZE_DATA } from './createUboElementsWGSL.mjs';
"use strict";
function generateArraySyncWGSL(uboElement, offsetToAdd) {
const { size, align } = WGSL_ALIGN_SIZE_DATA[uboElement.data.type];
const remainder = (align - size) / 4;
return `
v = uv.${uboElement.data.name};
${offsetToAdd !== 0 ? `offset += ${offsetToAdd};` : ""}
arrayOffset = offset;
t = 0;
for(var i=0; i < ${uboElement.data.size * (size / 4)}; i++)
{
for(var j = 0; j < ${size / 4}; j++)
{
data[arrayOffset++] = v[t++];
}
${remainder !== 0 ? `arrayOffset += ${remainder};` : ""}
}
`;
}
export { generateArraySyncWGSL };
//# sourceMappingURL=generateArraySyncWGSL.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateArraySyncWGSL.mjs","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/generateArraySyncWGSL.ts"],"sourcesContent":["import { WGSL_ALIGN_SIZE_DATA } from './createUboElementsWGSL';\n\nimport type { UboElement } from '../../../shared/shader/types';\n\n/**\n * This generates a function that will sync an array to the uniform buffer\n * following the wgsl layout\n * @param uboElement - the element to generate the array sync for\n * @param offsetToAdd - the offset to append at the start of the code\n * @returns - the generated code\n */\nexport function generateArraySyncWGSL(uboElement: UboElement, offsetToAdd: number): string\n{\n // this is in byte..\n const { size, align } = WGSL_ALIGN_SIZE_DATA[uboElement.data.type];\n\n const remainder = (align - size) / 4;\n\n return `\n v = uv.${uboElement.data.name};\n ${offsetToAdd !== 0 ? `offset += ${offsetToAdd};` : ''}\n\n arrayOffset = offset;\n\n t = 0;\n\n for(var i=0; i < ${uboElement.data.size * (size / 4)}; i++)\n {\n for(var j = 0; j < ${size / 4}; j++)\n {\n data[arrayOffset++] = v[t++];\n }\n ${remainder !== 0 ? `arrayOffset += ${remainder};` : ''}\n }\n `;\n}\n"],"names":[],"mappings":";;;AAWgB,SAAA,qBAAA,CAAsB,YAAwB,WAC9D,EAAA;AAEI,EAAA,MAAM,EAAE,IAAM,EAAA,KAAA,KAAU,oBAAqB,CAAA,UAAA,CAAW,KAAK,IAAI,CAAA,CAAA;AAEjE,EAAM,MAAA,SAAA,GAAA,CAAa,QAAQ,IAAQ,IAAA,CAAA,CAAA;AAEnC,EAAO,OAAA,CAAA;AAAA,gBACO,EAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA,SAAA,EAC3B,WAAgB,KAAA,CAAA,GAAI,CAAa,UAAA,EAAA,WAAW,MAAM,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAA,EAMnC,UAAW,CAAA,IAAA,CAAK,IAAQ,IAAA,IAAA,GAAO,CAAE,CAAA,CAAA;AAAA;AAAA,gCAAA,EAE3B,OAAO,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA,aAAA,EAI3B,SAAc,KAAA,CAAA,GAAI,CAAkB,eAAA,EAAA,SAAS,MAAM,EAAE,CAAA;AAAA;AAAA,KAAA,CAAA,CAAA;AAGpE;;;;"}

View File

@@ -0,0 +1,3 @@
import type { ProgramPipelineLayoutDescription } from '../GpuProgram';
import type { StructsAndGroups } from './extractStructAndGroups';
export declare function generateGpuLayoutGroups({ groups }: StructsAndGroups): ProgramPipelineLayoutDescription;

View File

@@ -0,0 +1,45 @@
'use strict';
var _const = require('../../../shared/shader/const.js');
"use strict";
function generateGpuLayoutGroups({ groups }) {
const layout = [];
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
if (!layout[group.group]) {
layout[group.group] = [];
}
if (group.isUniform) {
layout[group.group].push({
binding: group.binding,
visibility: _const.ShaderStage.VERTEX | _const.ShaderStage.FRAGMENT,
buffer: {
type: "uniform"
}
});
} else if (group.type === "sampler") {
layout[group.group].push({
binding: group.binding,
visibility: _const.ShaderStage.FRAGMENT,
sampler: {
type: "filtering"
}
});
} else if (group.type === "texture_2d") {
layout[group.group].push({
binding: group.binding,
visibility: _const.ShaderStage.FRAGMENT,
texture: {
sampleType: "float",
viewDimension: "2d",
multisampled: false
}
});
}
}
return layout;
}
exports.generateGpuLayoutGroups = generateGpuLayoutGroups;
//# sourceMappingURL=generateGpuLayoutGroups.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateGpuLayoutGroups.js","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/generateGpuLayoutGroups.ts"],"sourcesContent":["import { ShaderStage } from '../../../shared/shader/const';\n\nimport type { ProgramPipelineLayoutDescription } from '../GpuProgram';\nimport type { StructsAndGroups } from './extractStructAndGroups';\n\nexport function generateGpuLayoutGroups({ groups }: StructsAndGroups): ProgramPipelineLayoutDescription\n{\n const layout: ProgramPipelineLayoutDescription = [];\n\n for (let i = 0; i < groups.length; i++)\n {\n const group = groups[i];\n\n if (!layout[group.group])\n {\n layout[group.group] = [];\n }\n\n if (group.isUniform)\n {\n layout[group.group].push({\n binding: group.binding,\n visibility: ShaderStage.VERTEX | ShaderStage.FRAGMENT,\n buffer: {\n type: 'uniform'\n }\n });\n }\n else if (group.type === 'sampler')\n {\n layout[group.group].push({\n binding: group.binding,\n visibility: ShaderStage.FRAGMENT,\n sampler: {\n type: 'filtering'\n }\n });\n }\n else if (group.type === 'texture_2d')\n {\n layout[group.group].push({\n binding: group.binding,\n visibility: ShaderStage.FRAGMENT,\n texture: {\n sampleType: 'float',\n viewDimension: '2d',\n multisampled: false,\n }\n });\n }\n }\n\n return layout;\n}\n"],"names":["ShaderStage"],"mappings":";;;;;AAKgB,SAAA,uBAAA,CAAwB,EAAE,MAAA,EAC1C,EAAA;AACI,EAAA,MAAM,SAA2C,EAAC,CAAA;AAElD,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,MAAA,CAAO,QAAQ,CACnC,EAAA,EAAA;AACI,IAAM,MAAA,KAAA,GAAQ,OAAO,CAAC,CAAA,CAAA;AAEtB,IAAA,IAAI,CAAC,MAAA,CAAO,KAAM,CAAA,KAAK,CACvB,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,GAAI,EAAC,CAAA;AAAA,KAC3B;AAEA,IAAA,IAAI,MAAM,SACV,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,CAAE,IAAK,CAAA;AAAA,QACrB,SAAS,KAAM,CAAA,OAAA;AAAA,QACf,UAAA,EAAYA,kBAAY,CAAA,MAAA,GAASA,kBAAY,CAAA,QAAA;AAAA,QAC7C,MAAQ,EAAA;AAAA,UACJ,IAAM,EAAA,SAAA;AAAA,SACV;AAAA,OACH,CAAA,CAAA;AAAA,KACL,MAAA,IACS,KAAM,CAAA,IAAA,KAAS,SACxB,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,CAAE,IAAK,CAAA;AAAA,QACrB,SAAS,KAAM,CAAA,OAAA;AAAA,QACf,YAAYA,kBAAY,CAAA,QAAA;AAAA,QACxB,OAAS,EAAA;AAAA,UACL,IAAM,EAAA,WAAA;AAAA,SACV;AAAA,OACH,CAAA,CAAA;AAAA,KACL,MAAA,IACS,KAAM,CAAA,IAAA,KAAS,YACxB,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,CAAE,IAAK,CAAA;AAAA,QACrB,SAAS,KAAM,CAAA,OAAA;AAAA,QACf,YAAYA,kBAAY,CAAA,QAAA;AAAA,QACxB,OAAS,EAAA;AAAA,UACL,UAAY,EAAA,OAAA;AAAA,UACZ,aAAe,EAAA,IAAA;AAAA,UACf,YAAc,EAAA,KAAA;AAAA,SAClB;AAAA,OACH,CAAA,CAAA;AAAA,KACL;AAAA,GACJ;AAEA,EAAO,OAAA,MAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,43 @@
import { ShaderStage } from '../../../shared/shader/const.mjs';
"use strict";
function generateGpuLayoutGroups({ groups }) {
const layout = [];
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
if (!layout[group.group]) {
layout[group.group] = [];
}
if (group.isUniform) {
layout[group.group].push({
binding: group.binding,
visibility: ShaderStage.VERTEX | ShaderStage.FRAGMENT,
buffer: {
type: "uniform"
}
});
} else if (group.type === "sampler") {
layout[group.group].push({
binding: group.binding,
visibility: ShaderStage.FRAGMENT,
sampler: {
type: "filtering"
}
});
} else if (group.type === "texture_2d") {
layout[group.group].push({
binding: group.binding,
visibility: ShaderStage.FRAGMENT,
texture: {
sampleType: "float",
viewDimension: "2d",
multisampled: false
}
});
}
}
return layout;
}
export { generateGpuLayoutGroups };
//# sourceMappingURL=generateGpuLayoutGroups.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateGpuLayoutGroups.mjs","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/generateGpuLayoutGroups.ts"],"sourcesContent":["import { ShaderStage } from '../../../shared/shader/const';\n\nimport type { ProgramPipelineLayoutDescription } from '../GpuProgram';\nimport type { StructsAndGroups } from './extractStructAndGroups';\n\nexport function generateGpuLayoutGroups({ groups }: StructsAndGroups): ProgramPipelineLayoutDescription\n{\n const layout: ProgramPipelineLayoutDescription = [];\n\n for (let i = 0; i < groups.length; i++)\n {\n const group = groups[i];\n\n if (!layout[group.group])\n {\n layout[group.group] = [];\n }\n\n if (group.isUniform)\n {\n layout[group.group].push({\n binding: group.binding,\n visibility: ShaderStage.VERTEX | ShaderStage.FRAGMENT,\n buffer: {\n type: 'uniform'\n }\n });\n }\n else if (group.type === 'sampler')\n {\n layout[group.group].push({\n binding: group.binding,\n visibility: ShaderStage.FRAGMENT,\n sampler: {\n type: 'filtering'\n }\n });\n }\n else if (group.type === 'texture_2d')\n {\n layout[group.group].push({\n binding: group.binding,\n visibility: ShaderStage.FRAGMENT,\n texture: {\n sampleType: 'float',\n viewDimension: '2d',\n multisampled: false,\n }\n });\n }\n }\n\n return layout;\n}\n"],"names":[],"mappings":";;;AAKgB,SAAA,uBAAA,CAAwB,EAAE,MAAA,EAC1C,EAAA;AACI,EAAA,MAAM,SAA2C,EAAC,CAAA;AAElD,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,MAAA,CAAO,QAAQ,CACnC,EAAA,EAAA;AACI,IAAM,MAAA,KAAA,GAAQ,OAAO,CAAC,CAAA,CAAA;AAEtB,IAAA,IAAI,CAAC,MAAA,CAAO,KAAM,CAAA,KAAK,CACvB,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,GAAI,EAAC,CAAA;AAAA,KAC3B;AAEA,IAAA,IAAI,MAAM,SACV,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,CAAE,IAAK,CAAA;AAAA,QACrB,SAAS,KAAM,CAAA,OAAA;AAAA,QACf,UAAA,EAAY,WAAY,CAAA,MAAA,GAAS,WAAY,CAAA,QAAA;AAAA,QAC7C,MAAQ,EAAA;AAAA,UACJ,IAAM,EAAA,SAAA;AAAA,SACV;AAAA,OACH,CAAA,CAAA;AAAA,KACL,MAAA,IACS,KAAM,CAAA,IAAA,KAAS,SACxB,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,CAAE,IAAK,CAAA;AAAA,QACrB,SAAS,KAAM,CAAA,OAAA;AAAA,QACf,YAAY,WAAY,CAAA,QAAA;AAAA,QACxB,OAAS,EAAA;AAAA,UACL,IAAM,EAAA,WAAA;AAAA,SACV;AAAA,OACH,CAAA,CAAA;AAAA,KACL,MAAA,IACS,KAAM,CAAA,IAAA,KAAS,YACxB,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,CAAE,IAAK,CAAA;AAAA,QACrB,SAAS,KAAM,CAAA,OAAA;AAAA,QACf,YAAY,WAAY,CAAA,QAAA;AAAA,QACxB,OAAS,EAAA;AAAA,UACL,UAAY,EAAA,OAAA;AAAA,UACZ,aAAe,EAAA,IAAA;AAAA,UACf,YAAc,EAAA,KAAA;AAAA,SAClB;AAAA,OACH,CAAA,CAAA;AAAA,KACL;AAAA,GACJ;AAEA,EAAO,OAAA,MAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,3 @@
import type { ProgramLayout } from '../GpuProgram';
import type { StructsAndGroups } from './extractStructAndGroups';
export declare function generateLayoutHash({ groups }: StructsAndGroups): ProgramLayout;

View File

@@ -0,0 +1,17 @@
'use strict';
"use strict";
function generateLayoutHash({ groups }) {
const layout = [];
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
if (!layout[group.group]) {
layout[group.group] = {};
}
layout[group.group][group.name] = group.binding;
}
return layout;
}
exports.generateLayoutHash = generateLayoutHash;
//# sourceMappingURL=generateLayoutHash.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateLayoutHash.js","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/generateLayoutHash.ts"],"sourcesContent":["import type { ProgramLayout } from '../GpuProgram';\nimport type { StructsAndGroups } from './extractStructAndGroups';\n\nexport function generateLayoutHash({ groups }: StructsAndGroups): ProgramLayout\n{\n const layout: ProgramLayout = [];\n\n for (let i = 0; i < groups.length; i++)\n {\n const group = groups[i];\n\n if (!layout[group.group])\n {\n layout[group.group] = {};\n }\n\n layout[group.group][group.name] = group.binding;\n }\n\n return layout;\n}\n"],"names":[],"mappings":";;;AAGgB,SAAA,kBAAA,CAAmB,EAAE,MAAA,EACrC,EAAA;AACI,EAAA,MAAM,SAAwB,EAAC,CAAA;AAE/B,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,MAAA,CAAO,QAAQ,CACnC,EAAA,EAAA;AACI,IAAM,MAAA,KAAA,GAAQ,OAAO,CAAC,CAAA,CAAA;AAEtB,IAAA,IAAI,CAAC,MAAA,CAAO,KAAM,CAAA,KAAK,CACvB,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,GAAI,EAAC,CAAA;AAAA,KAC3B;AAEA,IAAA,MAAA,CAAO,MAAM,KAAK,CAAA,CAAE,KAAM,CAAA,IAAI,IAAI,KAAM,CAAA,OAAA,CAAA;AAAA,GAC5C;AAEA,EAAO,OAAA,MAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,15 @@
"use strict";
function generateLayoutHash({ groups }) {
const layout = [];
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
if (!layout[group.group]) {
layout[group.group] = {};
}
layout[group.group][group.name] = group.binding;
}
return layout;
}
export { generateLayoutHash };
//# sourceMappingURL=generateLayoutHash.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateLayoutHash.mjs","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/generateLayoutHash.ts"],"sourcesContent":["import type { ProgramLayout } from '../GpuProgram';\nimport type { StructsAndGroups } from './extractStructAndGroups';\n\nexport function generateLayoutHash({ groups }: StructsAndGroups): ProgramLayout\n{\n const layout: ProgramLayout = [];\n\n for (let i = 0; i < groups.length; i++)\n {\n const group = groups[i];\n\n if (!layout[group.group])\n {\n layout[group.group] = {};\n }\n\n layout[group.group][group.name] = group.binding;\n }\n\n return layout;\n}\n"],"names":[],"mappings":";AAGgB,SAAA,kBAAA,CAAmB,EAAE,MAAA,EACrC,EAAA;AACI,EAAA,MAAM,SAAwB,EAAC,CAAA;AAE/B,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,MAAA,CAAO,QAAQ,CACnC,EAAA,EAAA;AACI,IAAM,MAAA,KAAA,GAAQ,OAAO,CAAC,CAAA,CAAA;AAEtB,IAAA,IAAI,CAAC,MAAA,CAAO,KAAM,CAAA,KAAK,CACvB,EAAA;AACI,MAAO,MAAA,CAAA,KAAA,CAAM,KAAK,CAAA,GAAI,EAAC,CAAA;AAAA,KAC3B;AAEA,IAAA,MAAA,CAAO,MAAM,KAAK,CAAA,CAAE,KAAM,CAAA,IAAI,IAAI,KAAM,CAAA,OAAA,CAAA;AAAA,GAC5C;AAEA,EAAO,OAAA,MAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,14 @@
import type { StructsAndGroups } from './extractStructAndGroups';
export declare function removeStructAndGroupDuplicates(vertexStructsAndGroups: StructsAndGroups, fragmentStructsAndGroups: StructsAndGroups): {
structs: {
name: string;
members: Record<string, string>;
}[];
groups: {
group: number;
binding: number;
name: string;
isUniform: boolean;
type: string;
}[];
};

View File

@@ -0,0 +1,26 @@
'use strict';
"use strict";
function removeStructAndGroupDuplicates(vertexStructsAndGroups, fragmentStructsAndGroups) {
const structNameSet = /* @__PURE__ */ new Set();
const dupeGroupKeySet = /* @__PURE__ */ new Set();
const structs = [...vertexStructsAndGroups.structs, ...fragmentStructsAndGroups.structs].filter((struct) => {
if (structNameSet.has(struct.name)) {
return false;
}
structNameSet.add(struct.name);
return true;
});
const groups = [...vertexStructsAndGroups.groups, ...fragmentStructsAndGroups.groups].filter((group) => {
const key = `${group.name}-${group.binding}`;
if (dupeGroupKeySet.has(key)) {
return false;
}
dupeGroupKeySet.add(key);
return true;
});
return { structs, groups };
}
exports.removeStructAndGroupDuplicates = removeStructAndGroupDuplicates;
//# sourceMappingURL=removeStructAndGroupDuplicates.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"removeStructAndGroupDuplicates.js","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/removeStructAndGroupDuplicates.ts"],"sourcesContent":["import type { StructsAndGroups } from './extractStructAndGroups';\n\nexport function removeStructAndGroupDuplicates(\n vertexStructsAndGroups: StructsAndGroups,\n fragmentStructsAndGroups: StructsAndGroups\n)\n{\n const structNameSet = new Set();\n const dupeGroupKeySet = new Set();\n\n const structs = [...vertexStructsAndGroups.structs, ...fragmentStructsAndGroups.structs]\n .filter((struct) =>\n {\n if (structNameSet.has(struct.name))\n {\n return false;\n }\n structNameSet.add(struct.name);\n\n return true;\n });\n\n const groups = [...vertexStructsAndGroups.groups, ...fragmentStructsAndGroups.groups]\n .filter((group) =>\n {\n const key = `${group.name}-${group.binding}`;\n\n if (dupeGroupKeySet.has(key))\n {\n return false;\n }\n dupeGroupKeySet.add(key);\n\n return true;\n });\n\n return { structs, groups };\n}\n"],"names":[],"mappings":";;;AAEgB,SAAA,8BAAA,CACZ,wBACA,wBAEJ,EAAA;AACI,EAAM,MAAA,aAAA,uBAAoB,GAAI,EAAA,CAAA;AAC9B,EAAM,MAAA,eAAA,uBAAsB,GAAI,EAAA,CAAA;AAEhC,EAAM,MAAA,OAAA,GAAU,CAAC,GAAG,sBAAuB,CAAA,OAAA,EAAS,GAAG,wBAAA,CAAyB,OAAO,CAAA,CAClF,MAAO,CAAA,CAAC,MACT,KAAA;AACI,IAAA,IAAI,aAAc,CAAA,GAAA,CAAI,MAAO,CAAA,IAAI,CACjC,EAAA;AACI,MAAO,OAAA,KAAA,CAAA;AAAA,KACX;AACA,IAAc,aAAA,CAAA,GAAA,CAAI,OAAO,IAAI,CAAA,CAAA;AAE7B,IAAO,OAAA,IAAA,CAAA;AAAA,GACV,CAAA,CAAA;AAEL,EAAM,MAAA,MAAA,GAAS,CAAC,GAAG,sBAAuB,CAAA,MAAA,EAAQ,GAAG,wBAAA,CAAyB,MAAM,CAAA,CAC/E,MAAO,CAAA,CAAC,KACT,KAAA;AACI,IAAA,MAAM,MAAM,CAAG,EAAA,KAAA,CAAM,IAAI,CAAA,CAAA,EAAI,MAAM,OAAO,CAAA,CAAA,CAAA;AAE1C,IAAI,IAAA,eAAA,CAAgB,GAAI,CAAA,GAAG,CAC3B,EAAA;AACI,MAAO,OAAA,KAAA,CAAA;AAAA,KACX;AACA,IAAA,eAAA,CAAgB,IAAI,GAAG,CAAA,CAAA;AAEvB,IAAO,OAAA,IAAA,CAAA;AAAA,GACV,CAAA,CAAA;AAEL,EAAO,OAAA,EAAE,SAAS,MAAO,EAAA,CAAA;AAC7B;;;;"}

View File

@@ -0,0 +1,24 @@
"use strict";
function removeStructAndGroupDuplicates(vertexStructsAndGroups, fragmentStructsAndGroups) {
const structNameSet = /* @__PURE__ */ new Set();
const dupeGroupKeySet = /* @__PURE__ */ new Set();
const structs = [...vertexStructsAndGroups.structs, ...fragmentStructsAndGroups.structs].filter((struct) => {
if (structNameSet.has(struct.name)) {
return false;
}
structNameSet.add(struct.name);
return true;
});
const groups = [...vertexStructsAndGroups.groups, ...fragmentStructsAndGroups.groups].filter((group) => {
const key = `${group.name}-${group.binding}`;
if (dupeGroupKeySet.has(key)) {
return false;
}
dupeGroupKeySet.add(key);
return true;
});
return { structs, groups };
}
export { removeStructAndGroupDuplicates };
//# sourceMappingURL=removeStructAndGroupDuplicates.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"removeStructAndGroupDuplicates.mjs","sources":["../../../../../../src/rendering/renderers/gpu/shader/utils/removeStructAndGroupDuplicates.ts"],"sourcesContent":["import type { StructsAndGroups } from './extractStructAndGroups';\n\nexport function removeStructAndGroupDuplicates(\n vertexStructsAndGroups: StructsAndGroups,\n fragmentStructsAndGroups: StructsAndGroups\n)\n{\n const structNameSet = new Set();\n const dupeGroupKeySet = new Set();\n\n const structs = [...vertexStructsAndGroups.structs, ...fragmentStructsAndGroups.structs]\n .filter((struct) =>\n {\n if (structNameSet.has(struct.name))\n {\n return false;\n }\n structNameSet.add(struct.name);\n\n return true;\n });\n\n const groups = [...vertexStructsAndGroups.groups, ...fragmentStructsAndGroups.groups]\n .filter((group) =>\n {\n const key = `${group.name}-${group.binding}`;\n\n if (dupeGroupKeySet.has(key))\n {\n return false;\n }\n dupeGroupKeySet.add(key);\n\n return true;\n });\n\n return { structs, groups };\n}\n"],"names":[],"mappings":";AAEgB,SAAA,8BAAA,CACZ,wBACA,wBAEJ,EAAA;AACI,EAAM,MAAA,aAAA,uBAAoB,GAAI,EAAA,CAAA;AAC9B,EAAM,MAAA,eAAA,uBAAsB,GAAI,EAAA,CAAA;AAEhC,EAAM,MAAA,OAAA,GAAU,CAAC,GAAG,sBAAuB,CAAA,OAAA,EAAS,GAAG,wBAAA,CAAyB,OAAO,CAAA,CAClF,MAAO,CAAA,CAAC,MACT,KAAA;AACI,IAAA,IAAI,aAAc,CAAA,GAAA,CAAI,MAAO,CAAA,IAAI,CACjC,EAAA;AACI,MAAO,OAAA,KAAA,CAAA;AAAA,KACX;AACA,IAAc,aAAA,CAAA,GAAA,CAAI,OAAO,IAAI,CAAA,CAAA;AAE7B,IAAO,OAAA,IAAA,CAAA;AAAA,GACV,CAAA,CAAA;AAEL,EAAM,MAAA,MAAA,GAAS,CAAC,GAAG,sBAAuB,CAAA,MAAA,EAAQ,GAAG,wBAAA,CAAyB,MAAM,CAAA,CAC/E,MAAO,CAAA,CAAC,KACT,KAAA;AACI,IAAA,MAAM,MAAM,CAAG,EAAA,KAAA,CAAM,IAAI,CAAA,CAAA,EAAI,MAAM,OAAO,CAAA,CAAA,CAAA;AAE1C,IAAI,IAAA,eAAA,CAAgB,GAAI,CAAA,GAAG,CAC3B,EAAA;AACI,MAAO,OAAA,KAAA,CAAA;AAAA,KACX;AACA,IAAA,eAAA,CAAgB,IAAI,GAAG,CAAA,CAAA;AAEvB,IAAO,OAAA,IAAA,CAAA;AAAA,GACV,CAAA,CAAA;AAEL,EAAO,OAAA,EAAE,SAAS,MAAO,EAAA,CAAA;AAC7B;;;;"}