{
  "xGPU": {
    "BuiltIns": [
      {
        "objectType": "class",
        "name": "BuiltIns",
        "filePath": "xGPU.BuiltIns",
        "statics": {
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "vertexInputs",
                "type": "{ vertexIndex: { builtin: string; type: string; }; instanceIndex: { builtin: string; type: string; }; }",
                "visibility": "public",
                "rawText": "public static vertexInputs = {\r\n        vertexIndex: { builtin: \"@builtin(vertex_index)\", type: \"u32\" },\r\n        instanceIndex: { builtin: \"@builtin(instance_index)\", type: \"u32\" },\r\n    }"
              },
              {
                "objectType": "property",
                "name": "vertexOutputs",
                "type": "{ position: { builtin: string; type: string; }; Float: { type: string; vsOut: boolean; }; Vec2: { type: string; vsOut: boolean; }; Vec3: { type: string; vsOut: boolean; }; Vec4: { type: string; vsOut: boolean; }; }",
                "visibility": "public",
                "rawText": "public static vertexOutputs = {\r\n        position: { builtin: \"@builtin(position)\", type: \"vec4<f32>\" },\r\n        Float: { type: \"f32\", vsOut: true },\r\n        Vec2: { type: \"vec2<f32>\", vsOut: true },\r\n        Vec3: { type: \"vec3<f32>\", vsOut: true },\r\n        Vec4: { type: \"vec4<f32>\", vsOut: true },\r\n\r\n    }"
              },
              {
                "objectType": "property",
                "name": "vertexDebug",
                "type": "{ Float: (instanceId?: number, vertexId?: number) => { vertexId: number; instanceId: number; type: string; __debug: boolean; }; Vec2: (instanceId?: number, vertexId?: number) => { vertexId: number; instanceId: number; type: string; __debug: boolean; }; ... 15 more ...; Matrix4x4Array: (len?: number, instanceId?: num...",
                "visibility": "public",
                "rawText": "public static vertexDebug = {\r\n\r\n        Float: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"f32\", __debug: true }\r\n        },\r\n        Vec2: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec2<f32>\", __debug: true }\r\n        },\r\n        Vec3: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec3<f32>\", __debug: true }\r\n        },\r\n        Vec4: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec4<f32>\", __debug: true }\r\n        },\r\n        Int: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"i32\", __debug: true }\r\n        },\r\n        IVec2: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec2<i32>\", __debug: true }\r\n        },\r\n        IVec3: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec3<i32>\", __debug: true }\r\n        },\r\n        IVec4: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec4<i32>\", __debug: true }\r\n        },\r\n        Uint: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"uint\", __debug: true }\r\n        },\r\n        UVec2: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec2<u32>\", __debug: true }\r\n        },\r\n        UVec3: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec3<u32>\", __debug: true }\r\n        },\r\n        UVec4: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec4<uf32>\", __debug: true }\r\n        },\r\n        Matrix3x3: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"mat3x3<f32>\", __debug: true }\r\n        },\r\n        Matrix4x4: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"mat4x4<f32>\", __debug: true }\r\n        },\r\n\r\n        Vec4Array: (len: number = 1, instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"array<vec4<f32>,\" + len + \">\", __debug: true, len, isArray: true, primitiveType: \"f32\" }\r\n        },\r\n        IVec4Array: (len: number = 1, instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"array<vec4<i32>,\" + len + \">\", __debug: true, len, isArray: true, primitiveType: \"i32\" }\r\n        },\r\n        UVec4Array: (len: number = 1, instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"array<vec4<u32>,\" + len + \">\", __debug: true, len, isArray: true, primitiveType: \"u32\" }\r\n        },\r\n        Matrix4x4Array: (len: number = 1, instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"array<mat4x4<f32>,\" + len + \">\", __debug: true, len, isArray: true, primitiveType: \"mat4\" }\r\n        }\r\n    }"
              },
              {
                "objectType": "property",
                "name": "fragmentInputs",
                "type": "{ frontFacing: { builtin: string; type: string; }; fragDepth: { builtin: string; type: string; }; sampleIndex: { builtin: string; type: string; }; sampleMask: { builtin: string; type: string; }; }",
                "visibility": "public",
                "rawText": "public static fragmentInputs = {\r\n        frontFacing: { builtin: \"@builtin(front_facing)\", type: \"bool\" },\r\n        fragDepth: { builtin: \"@builtin(frag_depth)\", type: \"f32\" },\r\n        sampleIndex: { builtin: \"@builtin(sample_index)\", type: \"u32\" },\r\n        sampleMask: { builtin: \"@builtin(sample_mask)\", type: \"u32\" },\r\n    }"
              },
              {
                "objectType": "property",
                "name": "fragmentOutputs",
                "type": "{ color: { builtin: string; type: string; }; }",
                "visibility": "public",
                "rawText": "public static fragmentOutputs = {\r\n        color: { builtin: \"@location(0)\", type: \"vec4<f32>\" }\r\n    }"
              },
              {
                "objectType": "property",
                "name": "computeInputs",
                "type": "{ localInvocationId: { builtin: string; type: string; }; localInvocationIndex: { builtin: string; type: string; }; globalInvocationId: { builtin: string; type: string; }; workgroupId: { builtin: string; type: string; }; numWorkgroup: { ...; }; }",
                "visibility": "public",
                "rawText": "public static computeInputs = {\r\n        localInvocationId: { builtin: \"@builtin(local_invocation_id)\", type: \"vec3<u32>\" },\r\n        localInvocationIndex: { builtin: \"@builtin(local_invocation_index)\", type: \"u32\" },\r\n        globalInvocationId: { builtin: \"@builtin(global_invocation_id)\", type: \"vec3<u32>\" },\r\n        workgroupId: { builtin: \"@builtin(workgroup_id)\", type: \"vec3<u32>\" },\r\n        numWorkgroup: { builtin: \"@builtin(num_workgroup)\", type: \"vec3<u32>\" },\r\n    }"
              },
              {
                "objectType": "property",
                "name": "computeOutputs",
                "type": "{ result: { builtin: string; type: string; }; }",
                "visibility": "public",
                "rawText": "public static computeOutputs = {\r\n        result: { builtin: \"@location(0)\", type: \"???\" }\r\n    }"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "__initDebug",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public static __initDebug() {\r\n        let o: any;\r\n\r\n        /*\r\n        I set the value directly to the function in order to be able to write \r\n        BuiltIns.vertexDebug.Float  //=> implicit {vertexId:0,instanceId:0}\r\n        and BuiltIns.vertexDebug.Float(vertexId,instanceId)\r\n        */\r\n\r\n        for (let z in this.vertexDebug) {\r\n            o = this.vertexDebug[z]();\r\n            this.vertexDebug[z].isArray = !!o.isArray;\r\n            this.vertexDebug[z].len = o.len;\r\n            this.vertexDebug[z].primitiveType = o.primitiveType;\r\n            this.vertexDebug[z].type = o.type;\r\n            this.vertexDebug[z].__debug = true;\r\n        }\r\n\r\n    }"
              }
            ]
          }
        },
        "rawText": "export class BuiltIns {\r\n\r\n    public static vertexInputs = {\r\n        vertexIndex: { builtin: \"@builtin(vertex_index)\", type: \"u32\" },\r\n        instanceIndex: { builtin: \"@builtin(instance_index)\", type: \"u32\" },\r\n    }\r\n\r\n    public static vertexOutputs = {\r\n        position: { builtin: \"@builtin(position)\", type: \"vec4<f32>\" },\r\n        Float: { type: \"f32\", vsOut: true },\r\n        Vec2: { type: \"vec2<f32>\", vsOut: true },\r\n        Vec3: { type: \"vec3<f32>\", vsOut: true },\r\n        Vec4: { type: \"vec4<f32>\", vsOut: true },\r\n\r\n    }\r\n\r\n\r\n\r\n    public static vertexDebug = {\r\n\r\n        Float: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"f32\", __debug: true }\r\n        },\r\n        Vec2: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec2<f32>\", __debug: true }\r\n        },\r\n        Vec3: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec3<f32>\", __debug: true }\r\n        },\r\n        Vec4: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec4<f32>\", __debug: true }\r\n        },\r\n        Int: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"i32\", __debug: true }\r\n        },\r\n        IVec2: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec2<i32>\", __debug: true }\r\n        },\r\n        IVec3: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec3<i32>\", __debug: true }\r\n        },\r\n        IVec4: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec4<i32>\", __debug: true }\r\n        },\r\n        Uint: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"uint\", __debug: true }\r\n        },\r\n        UVec2: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec2<u32>\", __debug: true }\r\n        },\r\n        UVec3: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec3<u32>\", __debug: true }\r\n        },\r\n        UVec4: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"vec4<uf32>\", __debug: true }\r\n        },\r\n        Matrix3x3: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"mat3x3<f32>\", __debug: true }\r\n        },\r\n        Matrix4x4: (instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"mat4x4<f32>\", __debug: true }\r\n        },\r\n\r\n        Vec4Array: (len: number = 1, instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"array<vec4<f32>,\" + len + \">\", __debug: true, len, isArray: true, primitiveType: \"f32\" }\r\n        },\r\n        IVec4Array: (len: number = 1, instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"array<vec4<i32>,\" + len + \">\", __debug: true, len, isArray: true, primitiveType: \"i32\" }\r\n        },\r\n        UVec4Array: (len: number = 1, instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"array<vec4<u32>,\" + len + \">\", __debug: true, len, isArray: true, primitiveType: \"u32\" }\r\n        },\r\n        Matrix4x4Array: (len: number = 1, instanceId: number = 0, vertexId: number = 0) => {\r\n            return { vertexId, instanceId, type: \"array<mat4x4<f32>,\" + len + \">\", __debug: true, len, isArray: true, primitiveType: \"mat4\" }\r\n        }\r\n    }\r\n\r\n    public static __initDebug() {\r\n        let o: any;\r\n\r\n        /*\r\n        I set the value directly to the function in order to be able to write \r\n        BuiltIns.vertexDebug.Float  //=> implicit {vertexId:0,instanceId:0}\r\n        and BuiltIns.vertexDebug.Float(vertexId,instanceId)\r\n        */\r\n\r\n        for (let z in this.vertexDebug) {\r\n            o = this.vertexDebug[z]();\r\n            this.vertexDebug[z].isArray = !!o.isArray;\r\n            this.vertexDebug[z].len = o.len;\r\n            this.vertexDebug[z].primitiveType = o.primitiveType;\r\n            this.vertexDebug[z].type = o.type;\r\n            this.vertexDebug[z].__debug = true;\r\n        }\r\n\r\n    }\r\n\r\n\r\n    //----\r\n\r\n    public static fragmentInputs = {\r\n        frontFacing: { builtin: \"@builtin(front_facing)\", type: \"bool\" },\r\n        fragDepth: { builtin: \"@builtin(frag_depth)\", type: \"f32\" },\r\n        sampleIndex: { builtin: \"@builtin(sample_index)\", type: \"u32\" },\r\n        sampleMask: { builtin: \"@builtin(sample_mask)\", type: \"u32\" },\r\n    }\r\n\r\n    public static fragmentOutputs = {\r\n        color: { builtin: \"@location(0)\", type: \"vec4<f32>\" }\r\n    }\r\n\r\n    //----\r\n\r\n    public static computeInputs = {\r\n        localInvocationId: { builtin: \"@builtin(local_invocation_id)\", type: \"vec3<u32>\" },\r\n        localInvocationIndex: { builtin: \"@builtin(local_invocation_index)\", type: \"u32\" },\r\n        globalInvocationId: { builtin: \"@builtin(global_invocation_id)\", type: \"vec3<u32>\" },\r\n        workgroupId: { builtin: \"@builtin(workgroup_id)\", type: \"vec3<u32>\" },\r\n        numWorkgroup: { builtin: \"@builtin(num_workgroup)\", type: \"vec3<u32>\" },\r\n    }\r\n\r\n    public static computeOutputs = {\r\n        result: { builtin: \"@location(0)\", type: \"???\" }\r\n    }\r\n}"
      },
      {
        "objectType": "type",
        "name": "BuiltIns_vertexInputs",
        "type": "{ vertexIndex: { builtin: string; type: string; }; instanceIndex: { builtin: string; type: string; }; }",
        "rawText": "type BuiltIns_vertexInputs = typeof BuiltIns.vertexInputs;"
      },
      {
        "objectType": "type",
        "name": "BuiltIns_vertexOutputs",
        "type": "{ position: { builtin: string; type: string; }; Float: { type: string; vsOut: boolean; }; Vec2: { type: string; vsOut: boolean; }; Vec3: { type: string; vsOut: boolean; }; Vec4: { type: string; vsOut: boolean; }; }",
        "rawText": "type BuiltIns_vertexOutputs = typeof BuiltIns.vertexOutputs;"
      },
      {
        "objectType": "type",
        "name": "BuiltIns_fragmentInputs",
        "type": "{ frontFacing: { builtin: string; type: string; }; fragDepth: { builtin: string; type: string; }; sampleIndex: { builtin: string; type: string; }; sampleMask: { builtin: string; type: string; }; }",
        "rawText": "type BuiltIns_fragmentInputs = typeof BuiltIns.fragmentInputs;"
      },
      {
        "objectType": "type",
        "name": "BuiltIns_fragmentOutputs",
        "type": "{ color: { builtin: string; type: string; }; }",
        "rawText": "type BuiltIns_fragmentOutputs = typeof BuiltIns.fragmentOutputs;"
      },
      {
        "objectType": "type",
        "name": "BuiltIns_computeInputs",
        "type": "{ localInvocationId: { builtin: string; type: string; }; localInvocationIndex: { builtin: string; type: string; }; globalInvocationId: { builtin: string; type: string; }; workgroupId: { builtin: string; type: string; }; numWorkgroup: { ...; }; }",
        "rawText": "type BuiltIns_computeInputs = typeof BuiltIns.computeInputs;"
      },
      {
        "objectType": "type",
        "name": "BuiltIns_computeOutputs",
        "type": "{ result: { builtin: string; type: string; }; }",
        "rawText": "type BuiltIns_computeOutputs = typeof BuiltIns.computeOutputs;"
      },
      {
        "objectType": "type",
        "name": "VertexShaderInput",
        "type": "VertexShaderInput",
        "rawText": "export type VertexShaderInput = (\r\n    BuiltIns_vertexInputs[\"vertexIndex\"] |\r\n    BuiltIns_vertexInputs[\"instanceIndex\"]\r\n);"
      },
      {
        "objectType": "type",
        "name": "VertexShaderOutput",
        "type": "VertexShaderOutput",
        "rawText": "export type VertexShaderOutput = (\r\n    BuiltIns_vertexOutputs[\"position\"] |\r\n    BuiltIns_vertexOutputs[\"Float\"] |\r\n    BuiltIns_vertexOutputs[\"Vec2\"] |\r\n    BuiltIns_vertexOutputs[\"Vec3\"] |\r\n    BuiltIns_vertexOutputs[\"Vec4\"] /*|\r\n    BuiltIns_vertexOutputs[\"Int\"] |\r\n    BuiltIns_vertexOutputs[\"IVec2\"] |\r\n    BuiltIns_vertexOutputs[\"IVec3\"] |\r\n    BuiltIns_vertexOutputs[\"IVec4\"] |\r\n    BuiltIns_vertexOutputs[\"Uint\"] |\r\n    BuiltIns_vertexOutputs[\"UVec2\"] |\r\n    BuiltIns_vertexOutputs[\"UVec3\"] |\r\n    BuiltIns_vertexOutputs[\"UVec4\"]*/\r\n);"
      },
      {
        "objectType": "type",
        "name": "FragmentShaderInput",
        "type": "FragmentShaderInput",
        "rawText": "export type FragmentShaderInput = (\r\n    BuiltIns_fragmentInputs[\"frontFacing\"] |\r\n    BuiltIns_fragmentInputs[\"fragDepth\"] |\r\n    BuiltIns_fragmentInputs[\"sampleIndex\"] |\r\n    BuiltIns_fragmentInputs[\"sampleMask\"]\r\n);"
      },
      {
        "objectType": "type",
        "name": "FragmentShaderOutputs",
        "type": "{ builtin: string; type: string; }",
        "rawText": "export type FragmentShaderOutputs = BuiltIns_fragmentOutputs[\"color\"];"
      },
      {
        "objectType": "type",
        "name": "ComputeShaderInput",
        "type": "ComputeShaderInput",
        "rawText": "export type ComputeShaderInput = (\r\n    BuiltIns_computeInputs[\"localInvocationId\"] |\r\n    BuiltIns_computeInputs[\"localInvocationIndex\"] |\r\n    BuiltIns_computeInputs[\"globalInvocationId\"] |\r\n    BuiltIns_computeInputs[\"workgroupId\"] |\r\n    BuiltIns_computeInputs[\"numWorkgroup\"]\r\n);"
      },
      {
        "objectType": "type",
        "name": "ComputeShaderOutputs",
        "type": "{ builtin: string; type: string; }",
        "rawText": "export type ComputeShaderOutputs = BuiltIns_computeOutputs[\"result\"];"
      }
    ],
    "EventDispatcher": [
      {
        "objectType": "class",
        "name": "EventDispatcher",
        "filePath": "xGPU.EventDispatcher",
        "properties": {
          "protected": [
            {
              "objectType": "property",
              "name": "eventListeners",
              "type": "any",
              "visibility": "protected",
              "rawText": "protected eventListeners: any = {};"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "addEventListener",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "callback",
                  "type": "(data?: any) => void"
                },
                {
                  "name": "removeListenerAfterDispatch",
                  "type": "boolean"
                }
              ],
              "visibility": "public",
              "rawText": "public addEventListener(eventName: string, callback: ( data?: any) => void, removeListenerAfterDispatch: boolean = false) {\r\n        if (!this.eventListeners[eventName]) this.eventListeners[eventName] = [];\r\n        if (removeListenerAfterDispatch) (callback as any).removeAfter = true;\r\n        this.eventListeners[eventName].push(callback);\r\n    }"
            },
            {
              "objectType": "method",
              "name": "removeEventListener",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "callback",
                  "type": "(dispatcher: EventDispatcher, data?: any) => void"
                }
              ],
              "visibility": "public",
              "rawText": "public removeEventListener(eventName: string, callback: (dispatcher: EventDispatcher, data?: any) => void) {\r\n        if (this.eventListeners[eventName]) {\r\n            const id = this.eventListeners[eventName].indexOf(callback);\r\n            if (id != -1) {\r\n                this.eventListeners[eventName].splice(id, 1);\r\n            }\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "clearEvents",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "any"
                }
              ],
              "visibility": "public",
              "rawText": "public clearEvents(eventName) {\r\n        this.addEventListener[eventName] = [];\r\n    }"
            },
            {
              "objectType": "method",
              "name": "hasEventListener",
              "returnType": "boolean",
              "params": [
                {
                  "name": "eventName",
                  "type": "any"
                }
              ],
              "visibility": "public",
              "rawText": "public hasEventListener(eventName): boolean { return !!this.eventListeners[eventName] }"
            },
            {
              "objectType": "method",
              "name": "dispatchEvent",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "eventData",
                  "type": "any"
                }
              ],
              "visibility": "public",
              "rawText": "public dispatchEvent(eventName: string, eventData?: any) {\r\n        if (this.eventListeners[eventName]) {\r\n\r\n            const t = [...this.eventListeners[eventName]];\r\n            t.forEach(callback => {\r\n                callback( eventData);\r\n                if ((callback as any).removeAfter) this.removeEventListener(eventName, callback);\r\n            });\r\n        }\r\n    }"
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "rawText": "constructor() {\r\n\r\n    }"
        },
        "rawText": "export class EventDispatcher {\r\n\r\n    protected eventListeners: any = {};\r\n\r\n    constructor() {\r\n\r\n    }\r\n\r\n    public addEventListener(eventName: string, callback: ( data?: any) => void, removeListenerAfterDispatch: boolean = false) {\r\n        if (!this.eventListeners[eventName]) this.eventListeners[eventName] = [];\r\n        if (removeListenerAfterDispatch) (callback as any).removeAfter = true;\r\n        this.eventListeners[eventName].push(callback);\r\n    }\r\n    public removeEventListener(eventName: string, callback: (dispatcher: EventDispatcher, data?: any) => void) {\r\n        if (this.eventListeners[eventName]) {\r\n            const id = this.eventListeners[eventName].indexOf(callback);\r\n            if (id != -1) {\r\n                this.eventListeners[eventName].splice(id, 1);\r\n            }\r\n        }\r\n    }\r\n    public clearEvents(eventName) {\r\n        this.addEventListener[eventName] = [];\r\n    }\r\n    public hasEventListener(eventName): boolean { return !!this.eventListeners[eventName] }\r\n\r\n    public dispatchEvent(eventName: string, eventData?: any) {\r\n        if (this.eventListeners[eventName]) {\r\n\r\n            const t = [...this.eventListeners[eventName]];\r\n            t.forEach(callback => {\r\n                callback( eventData);\r\n                if ((callback as any).removeAfter) this.removeEventListener(eventName, callback);\r\n            });\r\n        }\r\n    }\r\n}"
      }
    ],
    "GPURenderer": [
      {
        "objectType": "class",
        "name": "GPURenderer",
        "filePath": "xGPU.GPURenderer",
        "extends": [
          "EventDispatcher"
        ],
        "implements": [
          "IRenderer"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "frameId",
              "type": "number",
              "visibility": "public",
              "rawText": "public frameId: number = 0;"
            },
            {
              "objectType": "property",
              "name": "renderPipelines",
              "type": "RenderPipeline[]",
              "visibility": "public",
              "rawText": "public renderPipelines: RenderPipeline[] = [];"
            },
            {
              "objectType": "property",
              "name": "resized",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get resized(): boolean { return this.dimensionChanged; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "firstPipeline",
              "type": "RenderPipeline",
              "visibility": "public",
              "rawText": "public get firstPipeline(): RenderPipeline { return this.renderPipelines[0]; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "texture",
              "type": "GPUTexture",
              "visibility": "public",
              "rawText": "public get texture(): GPUTexture { return this.ctx.getCurrentTexture() }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "view",
              "type": "GPUTextureView",
              "visibility": "public",
              "rawText": "public get view(): GPUTextureView { return this.ctx.getCurrentTexture().createView(); }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "width",
              "type": "number",
              "visibility": "public",
              "rawText": "public get width(): number { return this.domElement.width }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "height",
              "type": "number",
              "visibility": "public",
              "rawText": "public get height(): number { return this.domElement.height }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "canvas",
              "type": "HTMLCanvasElement",
              "visibility": "public",
              "rawText": "public get canvas(): HTMLCanvasElement { return this.domElement }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "nbPipeline",
              "type": "number",
              "visibility": "public",
              "rawText": "public get nbPipeline(): number { return this.renderPipelines.length }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "useSinglePipeline",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get useSinglePipeline(): boolean { return this.nbColorAttachment === 1 }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "commandEncoder",
              "type": "GPUCommandEncoder",
              "visibility": "public",
              "rawText": "public commandEncoder: GPUCommandEncoder = null;"
            }
          ],
          "protected": [
            {
              "objectType": "property",
              "name": "domElement",
              "type": "HTMLCanvasElement",
              "visibility": "protected",
              "rawText": "protected domElement: HTMLCanvasElement;"
            },
            {
              "objectType": "property",
              "name": "canvasView",
              "type": "GPUTextureView",
              "visibility": "protected",
              "rawText": "protected canvasView: GPUTextureView;"
            },
            {
              "objectType": "property",
              "name": "ctx",
              "type": "GPUCanvasContext",
              "visibility": "protected",
              "rawText": "protected ctx: GPUCanvasContext;"
            },
            {
              "objectType": "property",
              "name": "currentWidth",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected currentWidth: number;"
            },
            {
              "objectType": "property",
              "name": "currentHeight",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected currentHeight: number;"
            },
            {
              "objectType": "property",
              "name": "dimensionChanged",
              "type": "boolean",
              "visibility": "protected",
              "rawText": "protected dimensionChanged: boolean = false;"
            },
            {
              "objectType": "property",
              "name": "deviceId",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected deviceId: number;"
            },
            {
              "objectType": "property",
              "name": "nbColorAttachment",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected nbColorAttachment: number = 0;"
            },
            {
              "objectType": "property",
              "name": "gpuCtxConfiguration",
              "type": "any",
              "visibility": "protected",
              "rawText": "protected gpuCtxConfiguration: any;"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "resize",
              "returnType": "void",
              "params": [
                {
                  "name": "w",
                  "type": "number"
                },
                {
                  "name": "h",
                  "type": "number"
                }
              ],
              "visibility": "public",
              "rawText": "public resize(w: number, h: number) {\r\n        this.domElement.width = w;\r\n        this.domElement.height = h;\r\n        this.dimensionChanged = true;\r\n\r\n    }"
            },
            {
              "objectType": "method",
              "name": "destroy",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public destroy(): void {\r\n        for (let i = 0; i < this.renderPipelines.length; i++) {\r\n            this.renderPipelines[i].destroy();\r\n        }\r\n        this.renderPipelines = [];\r\n        for (let z in this) {\r\n            this[z] = null;\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "initCanvas",
              "returnType": "Promise<HTMLCanvasElement>",
              "params": [
                {
                  "name": "canvas",
                  "type": "HTMLCanvasElement"
                },
                {
                  "name": "alphaMode",
                  "type": "\"opaque\" | \"premultiplied\""
                }
              ],
              "visibility": "public",
              "rawText": "public initCanvas(canvas: HTMLCanvasElement, alphaMode: \"opaque\" | \"premultiplied\" = \"opaque\"): Promise<HTMLCanvasElement> {\r\n\r\n        this.domElement = canvas;\r\n\r\n\r\n        return new Promise(async (resolve: (e: HTMLCanvasElement) => void, error: (e: unknown) => void) => {\r\n            await XGPU.init()\r\n            this.deviceId = XGPU.deviceId;\r\n            if (this.domElement == null) return\r\n\r\n            this.currentWidth = this.domElement.width;\r\n            this.currentHeight = this.domElement.height;\r\n\r\n            try {\r\n                this.gpuCtxConfiguration = {\r\n                    device: XGPU.device,\r\n                    format: XGPU.getPreferredCanvasFormat(),\r\n                    alphaMode: alphaMode,\r\n                    colorSpace: \"srgb\",\r\n                    usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING,\r\n                };\r\n                this.ctx = this.domElement.getContext(\"webgpu\");\r\n                this.ctx.configure(this.gpuCtxConfiguration)\r\n\r\n                resolve(canvas)\r\n            } catch (e) {\r\n                error(e)\r\n            }\r\n\r\n        })\r\n    }"
            },
            {
              "objectType": "method",
              "name": "addPipeline",
              "returnType": "RenderPipeline",
              "params": [
                {
                  "name": "pipeline",
                  "type": "RenderPipeline"
                },
                {
                  "name": "offset",
                  "type": "number"
                }
              ],
              "visibility": "public",
              "rawText": "public addPipeline(pipeline: RenderPipeline, offset: number = null): RenderPipeline {\r\n\r\n        pipeline.renderer = this;\r\n        if (pipeline.renderPassDescriptor.colorAttachments[0]) this.nbColorAttachment++;\r\n\r\n        if (offset === null) this.renderPipelines.push(pipeline);\r\n        else this.renderPipelines.splice(offset, 0, pipeline)\r\n\r\n        return pipeline;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "removePipeline",
              "returnType": "RenderPipeline",
              "params": [
                {
                  "name": "pipeline",
                  "type": "RenderPipeline"
                }
              ],
              "visibility": "public",
              "rawText": "public removePipeline(pipeline: RenderPipeline) {\r\n        if (pipeline.renderPassDescriptor.colorAttachments[0]) this.nbColorAttachment--;\r\n        const id = this.renderPipelines.indexOf(pipeline);\r\n        if (id != -1) {\r\n            this.renderPipelines.splice(id, 1);\r\n        }\r\n        pipeline.renderer = null;\r\n        return pipeline;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "configure",
              "returnType": "void",
              "params": [
                {
                  "name": "textureUsage",
                  "type": "GPUTextureUsageFlags"
                },
                {
                  "name": "alphaMode",
                  "type": "\"opaque\" | \"premultiplied\""
                }
              ],
              "visibility": "public",
              "rawText": "public configure(textureUsage: GPUTextureUsageFlags = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING, alphaMode: \"opaque\" | \"premultiplied\" = \"opaque\") {\r\n\r\n        this.gpuCtxConfiguration = {\r\n            device: XGPU.device,\r\n            format: XGPU.getPreferredCanvasFormat(),\r\n            alphaMode: alphaMode,\r\n            colorSpace: \"srgb\",\r\n            usage: textureUsage\r\n        };\r\n\r\n        this.ctx.configure(this.gpuCtxConfiguration)\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "Promise<void>",
              "visibility": "public",
              "rawText": "public async update() {\r\n        if (!this.ctx) return;\r\n        if (!XGPU.ready || this.renderPipelines.length === 0 || this.deviceId === undefined) return;\r\n\r\n\r\n        if (XGPU.deviceId != this.deviceId) {\r\n            this.ctx.configure({ ...this.gpuCtxConfiguration, device: XGPU.device })\r\n        }\r\n\r\n        if (this.canvas.width != this.currentWidth || this.canvas.height != this.currentHeight) {\r\n            this.currentWidth = this.canvas.width;\r\n            this.currentHeight = this.canvas.height;\r\n            this.dimensionChanged = true;\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n\r\n        let deviceChanged: boolean = XGPU.deviceId != this.deviceId;\r\n        if (deviceChanged) {\r\n\r\n\r\n            this.deviceId = XGPU.deviceId;\r\n            for (let i = 0; i < this.renderPipelines.length; i++) {\r\n                this.renderPipelines[i].clearAfterDeviceLostAndRebuild();\r\n            }\r\n        }\r\n\r\n        this.commandEncoder = XGPU.device.createCommandEncoder();\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n        let pipeline: RenderPipeline, renderPass:GPURenderPassEncoder;\r\n        for (let i = 0; i < this.renderPipelines.length; i++) {\r\n            pipeline = this.renderPipelines[i];\r\n\r\n            pipeline.update();\r\n\r\n\r\n            renderPass = pipeline.beginRenderPass(this.commandEncoder, this.view, 0);\r\n           \r\n            for (let j = 0; j < pipeline.pipelineCount; j++) {\r\n                pipeline.dispatchEvent(RenderPipeline.ON_DRAW, j);\r\n                pipeline.draw(renderPass);\r\n            }\r\n\r\n            pipeline.end(this.commandEncoder, renderPass);\r\n\r\n\r\n        }\r\n\r\n        const commandBuffer = this.commandEncoder.finish();\r\n        this.commandEncoder = null;\r\n        XGPU.device.queue.submit([commandBuffer]);\r\n\r\n        this.dimensionChanged = false;\r\n\r\n\r\n        this.dispatchEvent(GPURenderer.ON_DRAW_END);\r\n        this.frameId++;\r\n\r\n    }"
            }
          ]
        },
        "statics": {
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "ON_DRAW_END",
                "type": "string",
                "visibility": "public",
                "rawText": "public static ON_DRAW_END: string = \"ON_DRAW_END\";"
              }
            ],
            "private": [
              {
                "objectType": "property",
                "name": "texturedQuadPipeline",
                "type": "RenderPipeline",
                "visibility": "private",
                "rawText": "private static texturedQuadPipeline: RenderPipeline;"
              }
            ]
          }
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "rawText": "constructor() {\r\n        super();\r\n\r\n        if (!GPURenderer.texturedQuadPipeline) {\r\n            GPURenderer.texturedQuadPipeline = new RenderPipeline()\r\n            GPURenderer.texturedQuadPipeline.initFromObject({\r\n                vertexCount: 6,\r\n                vertexId: BuiltIns.vertexInputs.vertexIndex,\r\n                image: new ImageTexture({ source: null }),\r\n                imgSampler: new TextureSampler(),\r\n                uv: BuiltIns.vertexOutputs.Vec2,\r\n                vertexShader: {\r\n                    constants: `\r\n                    const pos = array<vec2<f32>([\r\n                        vec2(-0.5,-0.5),\r\n                        vec2(+0.5,-0.5),\r\n                        vec2(-0.5,+0.5),\r\n                        vec2(+0.5,-0.5),\r\n                        vec2(+0.5,+0.5),\r\n                        vec2(-0.5,+0.5),\r\n                    ]);\r\n                    `,\r\n                    main: `\r\n                    output.position = vec4(pos[vertexId],0.0,1.0);\r\n                    output.uv = 0.5 + output.position.xy;\r\n                    `\r\n                },\r\n                fragmentShader: `\r\n                    output.color = textureSample(image,imgSampler,uv);\r\n                `,\r\n            })\r\n        }\r\n\r\n        this.texturedQuadPipeline = GPURenderer.texturedQuadPipeline;\r\n\r\n\r\n\r\n\r\n    }"
        },
        "rawText": "export class GPURenderer extends EventDispatcher implements IRenderer {\r\n\r\n\r\n    public static ON_DRAW_END: string = \"ON_DRAW_END\";\r\n\r\n\r\n    protected domElement: HTMLCanvasElement;\r\n    protected canvasView: GPUTextureView;\r\n    protected ctx: GPUCanvasContext;\r\n\r\n    protected currentWidth: number;\r\n    protected currentHeight: number;\r\n    protected dimensionChanged: boolean = false;\r\n\r\n    protected deviceId: number;\r\n    public frameId: number = 0;\r\n    protected nbColorAttachment: number = 0;\r\n    public renderPipelines: RenderPipeline[] = [];\r\n\r\n\r\n    private static texturedQuadPipeline: RenderPipeline;\r\n    protected texturedQuadPipeline;\r\n    constructor() {\r\n        super();\r\n\r\n        if (!GPURenderer.texturedQuadPipeline) {\r\n            GPURenderer.texturedQuadPipeline = new RenderPipeline()\r\n            GPURenderer.texturedQuadPipeline.initFromObject({\r\n                vertexCount: 6,\r\n                vertexId: BuiltIns.vertexInputs.vertexIndex,\r\n                image: new ImageTexture({ source: null }),\r\n                imgSampler: new TextureSampler(),\r\n                uv: BuiltIns.vertexOutputs.Vec2,\r\n                vertexShader: {\r\n                    constants: `\r\n                    const pos = array<vec2<f32>([\r\n                        vec2(-0.5,-0.5),\r\n                        vec2(+0.5,-0.5),\r\n                        vec2(-0.5,+0.5),\r\n                        vec2(+0.5,-0.5),\r\n                        vec2(+0.5,+0.5),\r\n                        vec2(-0.5,+0.5),\r\n                    ]);\r\n                    `,\r\n                    main: `\r\n                    output.position = vec4(pos[vertexId],0.0,1.0);\r\n                    output.uv = 0.5 + output.position.xy;\r\n                    `\r\n                },\r\n                fragmentShader: `\r\n                    output.color = textureSample(image,imgSampler,uv);\r\n                `,\r\n            })\r\n        }\r\n\r\n        this.texturedQuadPipeline = GPURenderer.texturedQuadPipeline;\r\n\r\n\r\n\r\n\r\n    }\r\n\r\n    public resize(w: number, h: number) {\r\n        this.domElement.width = w;\r\n        this.domElement.height = h;\r\n        this.dimensionChanged = true;\r\n\r\n    }\r\n\r\n    public destroy(): void {\r\n        for (let i = 0; i < this.renderPipelines.length; i++) {\r\n            this.renderPipelines[i].destroy();\r\n        }\r\n        this.renderPipelines = [];\r\n        for (let z in this) {\r\n            this[z] = null;\r\n        }\r\n    }\r\n\r\n    protected gpuCtxConfiguration: any;\r\n    public initCanvas(canvas: HTMLCanvasElement, alphaMode: \"opaque\" | \"premultiplied\" = \"opaque\"): Promise<HTMLCanvasElement> {\r\n\r\n        this.domElement = canvas;\r\n\r\n\r\n        return new Promise(async (resolve: (e: HTMLCanvasElement) => void, error: (e: unknown) => void) => {\r\n            await XGPU.init()\r\n            this.deviceId = XGPU.deviceId;\r\n            if (this.domElement == null) return\r\n\r\n            this.currentWidth = this.domElement.width;\r\n            this.currentHeight = this.domElement.height;\r\n\r\n            try {\r\n                this.gpuCtxConfiguration = {\r\n                    device: XGPU.device,\r\n                    format: XGPU.getPreferredCanvasFormat(),\r\n                    alphaMode: alphaMode,\r\n                    colorSpace: \"srgb\",\r\n                    usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING,\r\n                };\r\n                this.ctx = this.domElement.getContext(\"webgpu\");\r\n                this.ctx.configure(this.gpuCtxConfiguration)\r\n\r\n                resolve(canvas)\r\n            } catch (e) {\r\n                error(e)\r\n            }\r\n\r\n        })\r\n    }\r\n\r\n\r\n\r\n    public get resized(): boolean { return this.dimensionChanged; }\r\n    public get firstPipeline(): RenderPipeline { return this.renderPipelines[0]; }\r\n    public get texture(): GPUTexture { return this.ctx.getCurrentTexture() }\r\n    public get view(): GPUTextureView { return this.ctx.getCurrentTexture().createView(); }\r\n\r\n    public get width(): number { return this.domElement.width }\r\n    public get height(): number { return this.domElement.height }\r\n    public get canvas(): HTMLCanvasElement { return this.domElement }\r\n    public addPipeline(pipeline: RenderPipeline, offset: number = null): RenderPipeline {\r\n\r\n        pipeline.renderer = this;\r\n        if (pipeline.renderPassDescriptor.colorAttachments[0]) this.nbColorAttachment++;\r\n\r\n        if (offset === null) this.renderPipelines.push(pipeline);\r\n        else this.renderPipelines.splice(offset, 0, pipeline)\r\n\r\n        return pipeline;\r\n    }\r\n\r\n    public removePipeline(pipeline: RenderPipeline) {\r\n        if (pipeline.renderPassDescriptor.colorAttachments[0]) this.nbColorAttachment--;\r\n        const id = this.renderPipelines.indexOf(pipeline);\r\n        if (id != -1) {\r\n            this.renderPipelines.splice(id, 1);\r\n        }\r\n        pipeline.renderer = null;\r\n        return pipeline;\r\n    }\r\n    public get nbPipeline(): number { return this.renderPipelines.length }\r\n    public get useSinglePipeline(): boolean { return this.nbColorAttachment === 1 }\r\n\r\n    public configure(textureUsage: GPUTextureUsageFlags = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING, alphaMode: \"opaque\" | \"premultiplied\" = \"opaque\") {\r\n\r\n        this.gpuCtxConfiguration = {\r\n            device: XGPU.device,\r\n            format: XGPU.getPreferredCanvasFormat(),\r\n            alphaMode: alphaMode,\r\n            colorSpace: \"srgb\",\r\n            usage: textureUsage\r\n        };\r\n\r\n        this.ctx.configure(this.gpuCtxConfiguration)\r\n    }\r\n\r\n\r\n\r\n    public commandEncoder: GPUCommandEncoder = null;\r\n\r\n    public async update() {\r\n        if (!this.ctx) return;\r\n        if (!XGPU.ready || this.renderPipelines.length === 0 || this.deviceId === undefined) return;\r\n\r\n\r\n        if (XGPU.deviceId != this.deviceId) {\r\n            this.ctx.configure({ ...this.gpuCtxConfiguration, device: XGPU.device })\r\n        }\r\n\r\n        if (this.canvas.width != this.currentWidth || this.canvas.height != this.currentHeight) {\r\n            this.currentWidth = this.canvas.width;\r\n            this.currentHeight = this.canvas.height;\r\n            this.dimensionChanged = true;\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n\r\n        let deviceChanged: boolean = XGPU.deviceId != this.deviceId;\r\n        if (deviceChanged) {\r\n\r\n\r\n            this.deviceId = XGPU.deviceId;\r\n            for (let i = 0; i < this.renderPipelines.length; i++) {\r\n                this.renderPipelines[i].clearAfterDeviceLostAndRebuild();\r\n            }\r\n        }\r\n\r\n        this.commandEncoder = XGPU.device.createCommandEncoder();\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n        let pipeline: RenderPipeline, renderPass:GPURenderPassEncoder;\r\n        for (let i = 0; i < this.renderPipelines.length; i++) {\r\n            pipeline = this.renderPipelines[i];\r\n\r\n            pipeline.update();\r\n\r\n\r\n            renderPass = pipeline.beginRenderPass(this.commandEncoder, this.view, 0);\r\n           \r\n            for (let j = 0; j < pipeline.pipelineCount; j++) {\r\n                pipeline.dispatchEvent(RenderPipeline.ON_DRAW, j);\r\n                pipeline.draw(renderPass);\r\n            }\r\n\r\n            pipeline.end(this.commandEncoder, renderPass);\r\n\r\n\r\n        }\r\n\r\n        const commandBuffer = this.commandEncoder.finish();\r\n        this.commandEncoder = null;\r\n        XGPU.device.queue.submit([commandBuffer]);\r\n\r\n        this.dimensionChanged = false;\r\n\r\n\r\n        this.dispatchEvent(GPURenderer.ON_DRAW_END);\r\n        this.frameId++;\r\n\r\n    }\r\n\r\n}"
      }
    ],
    "GPUType": [
      {
        "objectType": "class",
        "name": "GPUType",
        "filePath": "xGPU.GPUType",
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "isPrimitive",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get isPrimitive(): boolean { return !this._isVector && !this._isArray && !this._isMatrix }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "isVector",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get isVector(): boolean { return this._isVector && !this._isArray && !this._isMatrix }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "isMatrix",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get isMatrix(): boolean { return this._isMatrix && !this._isArray }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "isArray",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get isArray(): boolean { return this._isArray }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "isMatrixOfVectors",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get isMatrixOfVectors(): boolean { return this._isMatrix && this._isVector }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "isArrayOfVectors",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get isArrayOfVectors(): boolean { return this._isArray && this._isVector }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "isArrayOfMatrixs",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get isArrayOfMatrixs(): boolean { return this._isArray && this._isMatrix }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "vectorType",
              "type": "number",
              "visibility": "public",
              "rawText": "public get vectorType(): number { return this._vecType; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "arrayLength",
              "type": "number",
              "visibility": "public",
              "rawText": "public get arrayLength(): number { return this._arrayLen; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "matrixColumns",
              "type": "number",
              "visibility": "public",
              "rawText": "public get matrixColumns(): number { return this._matrixColumns; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "matrixRows",
              "type": "number",
              "visibility": "public",
              "rawText": "public get matrixRows(): number { return this._matrixRows; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "primitive",
              "type": "\"u32\" | \"f32\" | \"i32\" | \"f16\"",
              "visibility": "public",
              "rawText": "public get primitive(): \"u32\" | \"i32\" | \"f32\" | \"f16\" { return this._primitive; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "nbValues",
              "type": "number",
              "visibility": "public",
              "rawText": "public get nbValues(): number { return this._matrixColumns * this._matrixRows * this._vecType * (this._arrayLen ? this._arrayLen : 1) }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "byteSize",
              "type": "number",
              "visibility": "public",
              "rawText": "public get byteSize(): number { return this._sizeOf; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "byteAlign",
              "type": "number",
              "visibility": "public",
              "rawText": "public get byteAlign(): number { return this._alignOf; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "dataType",
              "type": "string",
              "visibility": "public",
              "rawText": "public get dataType(): string { return this._dataType; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "rawType",
              "type": "string",
              "visibility": "public",
              "rawText": "public get rawType(): string { return this._rawType; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "byteValue",
              "type": "number",
              "visibility": "public",
              "rawText": "public get byteValue(): number {\r\n        if (this._primitive === \"f16\") return 2;\r\n        return 4;\r\n    }",
              "get": true
            }
          ],
          "private": [
            {
              "objectType": "property",
              "name": "_isVector",
              "type": "boolean",
              "visibility": "private",
              "rawText": "private _isVector: boolean = false;"
            },
            {
              "objectType": "property",
              "name": "_isMatrix",
              "type": "boolean",
              "visibility": "private",
              "rawText": "private _isMatrix: boolean = false;"
            },
            {
              "objectType": "property",
              "name": "_isArray",
              "type": "boolean",
              "visibility": "private",
              "rawText": "private _isArray: boolean = false;"
            },
            {
              "objectType": "property",
              "name": "_vecType",
              "type": "number",
              "visibility": "private",
              "rawText": "private _vecType: number = 1;"
            },
            {
              "objectType": "property",
              "name": "_arrayLen",
              "type": "number",
              "visibility": "private",
              "rawText": "private _arrayLen: number | undefined;"
            },
            {
              "objectType": "property",
              "name": "_primitive",
              "type": "\"u32\" | \"f32\" | \"i32\" | \"f16\"",
              "visibility": "private",
              "rawText": "private _primitive: \"u32\" | \"i32\" | \"f32\" | \"f16\";"
            },
            {
              "objectType": "property",
              "name": "_matrixColumns",
              "type": "number",
              "visibility": "private",
              "rawText": "private _matrixColumns: number = 1;"
            },
            {
              "objectType": "property",
              "name": "_matrixRows",
              "type": "number",
              "visibility": "private",
              "rawText": "private _matrixRows: number = 1;"
            },
            {
              "objectType": "property",
              "name": "_alignOf",
              "type": "number",
              "visibility": "private",
              "rawText": "private _alignOf: number;"
            },
            {
              "objectType": "property",
              "name": "_sizeOf",
              "type": "number",
              "visibility": "private",
              "rawText": "private _sizeOf: number;"
            },
            {
              "objectType": "property",
              "name": "_dataType",
              "type": "string",
              "visibility": "private",
              "rawText": "private _dataType: string;"
            },
            {
              "objectType": "property",
              "name": "_rawType",
              "type": "string",
              "visibility": "private",
              "rawText": "private _rawType: string;"
            },
            {
              "objectType": "property",
              "name": "getPrimitiveDataType",
              "type": "(dataType: string, start: number) => void",
              "visibility": "private",
              "rawText": "private getPrimitiveDataType = (dataType: string, start: number) => {\r\n        //console.log(\"getPrimitiveDataType \", dataType)\r\n        const first = dataType.substring(start, start + 1);\r\n\r\n        switch (first) {\r\n            case \"u\":\r\n                this._primitive = \"u32\";\r\n                this._alignOf = 4;\r\n                this._sizeOf = 4;\r\n                break\r\n            case \"i\":\r\n                this._primitive = \"i32\";\r\n                this._alignOf = 4;\r\n                this._sizeOf = 4;\r\n                break\r\n            case \"f\":\r\n                const val: string = dataType.substring(start, start + 3);\r\n\r\n                if (val === \"f32\" || val == \"flo\") { //float\r\n                    this._primitive = \"f32\";\r\n                    this._alignOf = 4;\r\n                    this._sizeOf = 4;\r\n                } else if (val === \"f16\") {\r\n                    this._primitive = val;\r\n                    this._alignOf = 2;\r\n                    this._sizeOf = 2;\r\n                } else throw new Error(\"invalid primitive type\");\r\n                break\r\n            case \"v\":\r\n\r\n                if (dataType.substring(start, start + 3) === \"vec\") {\r\n                    this._isVector = true;\r\n                    const type: number = Number(dataType.substring(start + 3, start + 4));\r\n                    if (type >= 2 && type <= 4) {\r\n                        this._vecType = type;\r\n                        this.getPrimitiveDataType(dataType, start + 5);\r\n\r\n                        if (this._primitive === \"f16\") {\r\n                            this._sizeOf = 2 * type;\r\n                            if (type === 2) this._alignOf = 4;\r\n                            else if (type === 3) this._alignOf = 8\r\n                            else if (type === 4) this._alignOf = 8;\r\n\r\n                        } else {\r\n                            this._sizeOf = 4 * type;\r\n                            if (type === 2) this._alignOf = 8;\r\n                            else if (type === 3) this._alignOf = 16\r\n                            else if (type === 4) this._alignOf = 16;\r\n                        }\r\n\r\n                    } else {\r\n                        throw new Error(\"invalid vec type\");\r\n                    }\r\n                } else {\r\n                    throw new Error(\"invalid primitive type\");\r\n                }\r\n                break\r\n            case \"a\":\r\n                if (dataType.substring(start, start + 5) === \"array\") {\r\n                    this._isArray = true;\r\n\r\n                    let temp = 15;\r\n                    if (dataType.substring(6, 7) === \"m\") {//array of matrix\r\n                        temp = 17;\r\n                    } else if (dataType.substring(6, 7) === \"f\" || dataType.substring(6, 7) === \"i\" || dataType.substring(6, 7) === \"u\") {//array of f32/i32/u32\r\n                        temp = 9;\r\n                    }\r\n                    //console.log(start, temp, dataType.substring(start, temp))\r\n                    //console.log(\"dataType.substring(start + temp, start + temp + 1) = \", dataType.substring(start + temp, start + temp + 1))\r\n                    if (dataType.substring(start + temp, start + temp + 1) === \",\") {\r\n                        let num;\r\n                        temp++;\r\n                        //console.log(\"=> \", dataType.substring(temp, temp + 1))\r\n                        for (let i = 1; i < 16; i++) {\r\n                            let n = dataType.substring(temp, temp + i);\r\n                            if (isNaN(Number(n))) break;\r\n                            num = n;\r\n                        }\r\n                        //console.log(\"num = \", num)\r\n                        this._arrayLen = Number(num);\r\n                    }\r\n\r\n\r\n                    this.getPrimitiveDataType(dataType, start + 6);\r\n\r\n                    if (this.arrayLength) this._sizeOf *= this._arrayLen;\r\n\r\n\r\n                } else {\r\n                    throw new Error(\"invalid primitive type\");\r\n                }\r\n                break\r\n            case \"m\":\r\n\r\n                if (dataType.substring(start, start + 3) === \"mat\") {\r\n\r\n                    this._isMatrix = true;\r\n                    const col: number = Number(dataType.substring(start + 3, start + 4));\r\n                    const row: number = Number(dataType.substring(start + 5, start + 6));\r\n                    //console.log(\"matrix \", col, row)\r\n                    if (!isNaN(col) && !isNaN(row)) {\r\n                        this._matrixColumns = col;\r\n                        this._matrixRows = row;\r\n                        this.getPrimitiveDataType(dataType, start + 7);\r\n                        if (this._primitive === \"f16\" || this._primitive === \"f32\") {\r\n                            this.getMatrixBytesStructure(col, row, this._primitive);\r\n                        } else {\r\n                            throw new Error(\"Matrix values must be f32 or f16\")\r\n                        }\r\n\r\n\r\n                    } else {\r\n                        throw new Error(\"invalid matrix type\");\r\n                    }\r\n                } else {\r\n                    throw new Error(\"invalid primitive type\");\r\n                }\r\n                break\r\n        }\r\n\r\n    }"
            }
          ]
        },
        "methods": {
          "private": [
            {
              "objectType": "method",
              "name": "renameDataType",
              "returnType": "string",
              "params": [
                {
                  "name": "type",
                  "type": "string"
                }
              ],
              "visibility": "private",
              "rawText": "private renameDataType(type: string): string {\r\n\r\n\r\n\r\n        switch (type) {\r\n            case \"float\":\r\n                return \"f32\";\r\n            case \"vec2\":\r\n                return \"vec2<f32>\";\r\n            case \"vec3\":\r\n                return \"vec3<f32>\";\r\n            case \"vec4\":\r\n                return \"vec4<f32>\";\r\n\r\n            case \"int\":\r\n                return \"i32\";\r\n            case \"ivec2\":\r\n                return \"vec2<i32>\";\r\n            case \"ivec3\":\r\n                return \"vec3<i32>\";\r\n            case \"ivec4\":\r\n                return \"vec4<i32>\";\r\n\r\n            case \"uint\":\r\n                return \"u32\";\r\n            case \"uvec2\":\r\n                return \"vec2<u32>\";\r\n            case \"uvec3\":\r\n                return \"vec3<u32>\";\r\n            case \"uvec4\":\r\n                return \"vec4<u32>\";\r\n\r\n            case \"mat4\":\r\n                return \"mat4x4<f32>\";\r\n            case \"mat3\":\r\n                return \"mat3x3<f32>\";\r\n            case \"mat2\":\r\n                return \"mat2x2<f32>\";\r\n            case \"mat2d\":\r\n                return \"mat2w3<f32>\";\r\n\r\n        }\r\n        return type;\r\n\r\n\r\n    }"
            },
            {
              "objectType": "method",
              "name": "getMatrixBytesStructure",
              "returnType": "void",
              "params": [
                {
                  "name": "col",
                  "type": "number"
                },
                {
                  "name": "row",
                  "type": "number"
                },
                {
                  "name": "primitive",
                  "type": "string"
                }
              ],
              "visibility": "private",
              "rawText": "private getMatrixBytesStructure(col: number, row: number, primitive: string): void {\r\n\r\n        const type = \"mat\" + col + \"x\" + row + \"<\" + primitive + \">\";\r\n        //console.log(\"getMatrixBytesStructure \", type)\r\n        const dataInfos = {\r\n            \"mat2x2<f32>\": [8, 16],\r\n            \"mat2x2<f16>\": [4, 8],\r\n            \"mat3x2<f32>\": [8, 24],\r\n            \"mat3x2<f16>\": [4, 12],\r\n            \"mat4x2<f32>\": [8, 32],\r\n            \"mat4x2<f16>\": [4, 16],\r\n            \"mat2x3<f32>\": [16, 32],\r\n            \"mat2x3<f16>\": [8, 16],\r\n            \"mat3x3<f32>\": [16, 48],\r\n            \"mat3x3<f16>\": [8, 24],\r\n            \"mat4x3<f32>\": [16, 64],\r\n            \"mat4x3<f16>\": [8, 32],\r\n            \"mat2x4<f32>\": [16, 32],\r\n            \"mat2x4<f16>\": [8, 16],\r\n            \"mat3x4<f32>\": [16, 48],\r\n            \"mat3x4<f16>\": [8, 24],\r\n            \"mat4x4<f32>\": [16, 64],\r\n            \"mat4x4<f16>\": [8, 32]\r\n        }\r\n\r\n        const o = dataInfos[type];\r\n        //console.log(o)\r\n        this._alignOf = o[0];\r\n        this._sizeOf = o[1];\r\n    }"
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "dataType",
              "type": "string"
            }
          ],
          "rawText": "constructor(dataType: string) {\r\n        this._rawType = dataType;\r\n        dataType = this.renameDataType(dataType);\r\n        this._dataType = dataType;\r\n        //console.log(\"GPUType dataType = \", dataType)\r\n        this.getPrimitiveDataType(dataType, 0);\r\n\r\n\r\n    }"
        },
        "rawText": "export class GPUType {\r\n\r\n    private _isVector: boolean = false;\r\n    private _isMatrix: boolean = false;\r\n    private _isArray: boolean = false;\r\n    private _vecType: number = 1;\r\n    private _arrayLen: number | undefined;\r\n    private _primitive: \"u32\" | \"i32\" | \"f32\" | \"f16\";\r\n    private _matrixColumns: number = 1;\r\n    private _matrixRows: number = 1;\r\n\r\n    private _alignOf: number;\r\n    private _sizeOf: number;\r\n    private _dataType: string;\r\n    private _rawType: string;\r\n\r\n\r\n    //https://www.w3.org/TR/WGSL/#alignment-and-size\r\n\r\n    constructor(dataType: string) {\r\n        this._rawType = dataType;\r\n        dataType = this.renameDataType(dataType);\r\n        this._dataType = dataType;\r\n        //console.log(\"GPUType dataType = \", dataType)\r\n        this.getPrimitiveDataType(dataType, 0);\r\n\r\n\r\n    }\r\n\r\n    private renameDataType(type: string): string {\r\n\r\n\r\n\r\n        switch (type) {\r\n            case \"float\":\r\n                return \"f32\";\r\n            case \"vec2\":\r\n                return \"vec2<f32>\";\r\n            case \"vec3\":\r\n                return \"vec3<f32>\";\r\n            case \"vec4\":\r\n                return \"vec4<f32>\";\r\n\r\n            case \"int\":\r\n                return \"i32\";\r\n            case \"ivec2\":\r\n                return \"vec2<i32>\";\r\n            case \"ivec3\":\r\n                return \"vec3<i32>\";\r\n            case \"ivec4\":\r\n                return \"vec4<i32>\";\r\n\r\n            case \"uint\":\r\n                return \"u32\";\r\n            case \"uvec2\":\r\n                return \"vec2<u32>\";\r\n            case \"uvec3\":\r\n                return \"vec3<u32>\";\r\n            case \"uvec4\":\r\n                return \"vec4<u32>\";\r\n\r\n            case \"mat4\":\r\n                return \"mat4x4<f32>\";\r\n            case \"mat3\":\r\n                return \"mat3x3<f32>\";\r\n            case \"mat2\":\r\n                return \"mat2x2<f32>\";\r\n            case \"mat2d\":\r\n                return \"mat2w3<f32>\";\r\n\r\n        }\r\n        return type;\r\n\r\n\r\n    }\r\n\r\n\r\n    public get isPrimitive(): boolean { return !this._isVector && !this._isArray && !this._isMatrix };\r\n    public get isVector(): boolean { return this._isVector && !this._isArray && !this._isMatrix };\r\n    public get isMatrix(): boolean { return this._isMatrix && !this._isArray }\r\n    public get isArray(): boolean { return this._isArray }\r\n\r\n    public get isMatrixOfVectors(): boolean { return this._isMatrix && this._isVector }\r\n    public get isArrayOfVectors(): boolean { return this._isArray && this._isVector }\r\n    public get isArrayOfMatrixs(): boolean { return this._isArray && this._isMatrix }\r\n\r\n    public get vectorType(): number { return this._vecType; }\r\n    public get arrayLength(): number { return this._arrayLen; }\r\n    public get matrixColumns(): number { return this._matrixColumns; }\r\n    public get matrixRows(): number { return this._matrixRows; }\r\n\r\n    public get primitive(): \"u32\" | \"i32\" | \"f32\" | \"f16\" { return this._primitive; }\r\n\r\n    public get nbValues(): number { return this._matrixColumns * this._matrixRows * this._vecType * (this._arrayLen ? this._arrayLen : 1) }\r\n    public get byteSize(): number { return this._sizeOf; }\r\n    public get byteAlign(): number { return this._alignOf; }\r\n    public set byteAlign(n: number) { this._alignOf = n; }\r\n\r\n    public get dataType(): string { return this._dataType; }\r\n    public get rawType(): string { return this._rawType; }\r\n\r\n    public get byteValue(): number {\r\n        if (this._primitive === \"f16\") return 2;\r\n        return 4;\r\n    }\r\n\r\n    private getMatrixBytesStructure(col: number, row: number, primitive: string): void {\r\n\r\n        const type = \"mat\" + col + \"x\" + row + \"<\" + primitive + \">\";\r\n        //console.log(\"getMatrixBytesStructure \", type)\r\n        const dataInfos = {\r\n            \"mat2x2<f32>\": [8, 16],\r\n            \"mat2x2<f16>\": [4, 8],\r\n            \"mat3x2<f32>\": [8, 24],\r\n            \"mat3x2<f16>\": [4, 12],\r\n            \"mat4x2<f32>\": [8, 32],\r\n            \"mat4x2<f16>\": [4, 16],\r\n            \"mat2x3<f32>\": [16, 32],\r\n            \"mat2x3<f16>\": [8, 16],\r\n            \"mat3x3<f32>\": [16, 48],\r\n            \"mat3x3<f16>\": [8, 24],\r\n            \"mat4x3<f32>\": [16, 64],\r\n            \"mat4x3<f16>\": [8, 32],\r\n            \"mat2x4<f32>\": [16, 32],\r\n            \"mat2x4<f16>\": [8, 16],\r\n            \"mat3x4<f32>\": [16, 48],\r\n            \"mat3x4<f16>\": [8, 24],\r\n            \"mat4x4<f32>\": [16, 64],\r\n            \"mat4x4<f16>\": [8, 32]\r\n        }\r\n\r\n        const o = dataInfos[type];\r\n        //console.log(o)\r\n        this._alignOf = o[0];\r\n        this._sizeOf = o[1];\r\n    }\r\n\r\n    private getPrimitiveDataType = (dataType: string, start: number) => {\r\n        //console.log(\"getPrimitiveDataType \", dataType)\r\n        const first = dataType.substring(start, start + 1);\r\n\r\n        switch (first) {\r\n            case \"u\":\r\n                this._primitive = \"u32\";\r\n                this._alignOf = 4;\r\n                this._sizeOf = 4;\r\n                break\r\n            case \"i\":\r\n                this._primitive = \"i32\";\r\n                this._alignOf = 4;\r\n                this._sizeOf = 4;\r\n                break\r\n            case \"f\":\r\n                const val: string = dataType.substring(start, start + 3);\r\n\r\n                if (val === \"f32\" || val == \"flo\") { //float\r\n                    this._primitive = \"f32\";\r\n                    this._alignOf = 4;\r\n                    this._sizeOf = 4;\r\n                } else if (val === \"f16\") {\r\n                    this._primitive = val;\r\n                    this._alignOf = 2;\r\n                    this._sizeOf = 2;\r\n                } else throw new Error(\"invalid primitive type\");\r\n                break\r\n            case \"v\":\r\n\r\n                if (dataType.substring(start, start + 3) === \"vec\") {\r\n                    this._isVector = true;\r\n                    const type: number = Number(dataType.substring(start + 3, start + 4));\r\n                    if (type >= 2 && type <= 4) {\r\n                        this._vecType = type;\r\n                        this.getPrimitiveDataType(dataType, start + 5);\r\n\r\n                        if (this._primitive === \"f16\") {\r\n                            this._sizeOf = 2 * type;\r\n                            if (type === 2) this._alignOf = 4;\r\n                            else if (type === 3) this._alignOf = 8\r\n                            else if (type === 4) this._alignOf = 8;\r\n\r\n                        } else {\r\n                            this._sizeOf = 4 * type;\r\n                            if (type === 2) this._alignOf = 8;\r\n                            else if (type === 3) this._alignOf = 16\r\n                            else if (type === 4) this._alignOf = 16;\r\n                        }\r\n\r\n                    } else {\r\n                        throw new Error(\"invalid vec type\");\r\n                    }\r\n                } else {\r\n                    throw new Error(\"invalid primitive type\");\r\n                }\r\n                break\r\n            case \"a\":\r\n                if (dataType.substring(start, start + 5) === \"array\") {\r\n                    this._isArray = true;\r\n\r\n                    let temp = 15;\r\n                    if (dataType.substring(6, 7) === \"m\") {//array of matrix\r\n                        temp = 17;\r\n                    } else if (dataType.substring(6, 7) === \"f\" || dataType.substring(6, 7) === \"i\" || dataType.substring(6, 7) === \"u\") {//array of f32/i32/u32\r\n                        temp = 9;\r\n                    }\r\n                    //console.log(start, temp, dataType.substring(start, temp))\r\n                    //console.log(\"dataType.substring(start + temp, start + temp + 1) = \", dataType.substring(start + temp, start + temp + 1))\r\n                    if (dataType.substring(start + temp, start + temp + 1) === \",\") {\r\n                        let num;\r\n                        temp++;\r\n                        //console.log(\"=> \", dataType.substring(temp, temp + 1))\r\n                        for (let i = 1; i < 16; i++) {\r\n                            let n = dataType.substring(temp, temp + i);\r\n                            if (isNaN(Number(n))) break;\r\n                            num = n;\r\n                        }\r\n                        //console.log(\"num = \", num)\r\n                        this._arrayLen = Number(num);\r\n                    }\r\n\r\n\r\n                    this.getPrimitiveDataType(dataType, start + 6);\r\n\r\n                    if (this.arrayLength) this._sizeOf *= this._arrayLen;\r\n\r\n\r\n                } else {\r\n                    throw new Error(\"invalid primitive type\");\r\n                }\r\n                break\r\n            case \"m\":\r\n\r\n                if (dataType.substring(start, start + 3) === \"mat\") {\r\n\r\n                    this._isMatrix = true;\r\n                    const col: number = Number(dataType.substring(start + 3, start + 4));\r\n                    const row: number = Number(dataType.substring(start + 5, start + 6));\r\n                    //console.log(\"matrix \", col, row)\r\n                    if (!isNaN(col) && !isNaN(row)) {\r\n                        this._matrixColumns = col;\r\n                        this._matrixRows = row;\r\n                        this.getPrimitiveDataType(dataType, start + 7);\r\n                        if (this._primitive === \"f16\" || this._primitive === \"f32\") {\r\n                            this.getMatrixBytesStructure(col, row, this._primitive);\r\n                        } else {\r\n                            throw new Error(\"Matrix values must be f32 or f16\")\r\n                        }\r\n\r\n\r\n                    } else {\r\n                        throw new Error(\"invalid matrix type\");\r\n                    }\r\n                } else {\r\n                    throw new Error(\"invalid primitive type\");\r\n                }\r\n                break\r\n        }\r\n\r\n    }\r\n\r\n}"
      }
    ],
    "HighLevelParser": [
      {
        "objectType": "class",
        "name": "HighLevelParser",
        "filePath": "xGPU.HighLevelParser",
        "properties": {
          "private": [
            {
              "objectType": "property",
              "name": "parseDebugValues",
              "type": "(descriptor: any) => any",
              "visibility": "private",
              "rawText": "private parseDebugValues = (descriptor: any): any => {\r\n\r\n\r\n        let o: any;\r\n\r\n        let indexs: Vec4[] = [];\r\n        let objectById: any[] = [];\r\n        let objectByName: any = {};\r\n        let nb = 0;\r\n        for (let name in descriptor) {\r\n            o = descriptor[name];\r\n            if (o && o.__debug == true) {\r\n\r\n                if (typeof (o) === \"function\") {\r\n                    o = { name, id: nb, ...(o()) };\r\n                } else {\r\n                    o.id = nb;\r\n                    o.name = name;\r\n                }\r\n\r\n\r\n                /*\r\n                if (name.includes(\"_\")) {\r\n                    throw new Error(`BUILTINS ERROR :: ${name}  A variable using a BuiltIns.vertexDebug cannot use an underscore in its name.`)\r\n                }*/\r\n\r\n                descriptor[name] = undefined;\r\n                indexs[nb] = new Vec4(o.vertexId, o.instanceId, 0, 0);\r\n                objectByName[name] = o;\r\n                objectById[nb] = o;\r\n                nb++;\r\n            }\r\n        }\r\n\r\n        return {\r\n            nb,\r\n            indexs,\r\n            objectByName,\r\n            objectById\r\n        }\r\n\r\n    }"
            },
            {
              "objectType": "property",
              "name": "parseVertexShaderDebug",
              "type": "(descriptor: any) => any",
              "visibility": "private",
              "rawText": "private parseVertexShaderDebug = (descriptor: any) => {\r\n\r\n        if (typeof (descriptor.vertexShader) === \"string\") {\r\n            descriptor.vertexShader = { main: descriptor.vertexShader };\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n        const clearDebug = (shader: string) => {\r\n            let lines = shader.split(\"\\n\");\r\n            let line: string;\r\n            let result = \"\";\r\n            for (let i = 0; i < lines.length; i++) {\r\n                line = lines[i];\r\n                if (line.includes(\"debug.\")) continue;\r\n                result += line + \"\\n\";\r\n            }\r\n            return result;\r\n        }\r\n\r\n        const shader = descriptor.vertexShader.main;\r\n        descriptor.vertexShader.main = clearDebug(shader);\r\n\r\n\r\n        const debugByName = descriptor.__DEBUG__.objectByName;\r\n\r\n\r\n        const removeEmptySpaceAtStart = (line: string): string => {\r\n            let abc = \"abcdefghijklmnopqrstuvwxyz/\";\r\n            abc += abc.toUpperCase();\r\n\r\n            let char: string;\r\n            for (let i = 0; i < line.length; i++) {\r\n                char = line[i];\r\n                if (abc.includes(char)) {\r\n                    return line.slice(i);\r\n                }\r\n            }\r\n\r\n            return line;\r\n        }\r\n\r\n        const extractDebugName = (line: string): string => {\r\n            let abc = \"abcdefghijklmnopqrstuvwxyz0123456789_\";\r\n            abc += abc.toUpperCase();\r\n\r\n            let char: string;\r\n            let name: string = \"\";\r\n            for (let i = 0; i < line.length; i++) {\r\n                char = line[i];\r\n                if (abc.includes(char)) {\r\n                    name += char;\r\n                    continue;\r\n                }\r\n                if (char === \" \") continue;\r\n                if (char != \"=\") {\r\n                    //console.log(\"char = \", char)\r\n                    throw new Error(`VERTEX SHADER ERROR on this line :\"debug.${line} \". The keyword \"debug\" must only be used to store data. It can't be used in computations.`)\r\n                }\r\n                return name;\r\n            }\r\n            return name;\r\n        }\r\n\r\n        const analyseAndRewriteDebug = (shader: string) => {\r\n            let lines = shader.split(\"\\n\");\r\n            let line: string;\r\n            let result: string = \";\"\r\n            let names: string[] = [];\r\n            let nbUsedByName: any = {};\r\n            let newName: string;\r\n            let objById: any[] = [];\r\n            let count = 0;\r\n            for (let i = 0; i < lines.length; i++) {\r\n                line = removeEmptySpaceAtStart(lines[i]);\r\n                if (line.slice(0, 2) == \"//\") continue;\r\n\r\n\r\n                if (line.includes(\"debug.\")) {\r\n                    if (line.slice(0, \"debug.\".length) === \"debug.\") {\r\n\r\n                        if (line.split(\"=\").length == 2) {\r\n\r\n\r\n                            const dName = extractDebugName(line.slice(\"debug.\".length));\r\n\r\n\r\n                            const o = debugByName[dName];\r\n                            if (!debugByName[dName]) {\r\n                                throw new Error(`VERTEX SHADER ERROR on this line :\" ${line} \". The value \"debug.${dName}\" is used in the vertexShader but not defined in RenderPipeline.initFromObject `);\r\n                            }\r\n\r\n                            if (names.includes(dName) === false) names.push(dName);\r\n\r\n\r\n                            if (isNaN(nbUsedByName[dName])) {\r\n                                //debugByName[dName] = undefined;\r\n                                //delete debugByName[dName];\r\n                                nbUsedByName[dName] = 0;\r\n                            } else nbUsedByName[dName]++;\r\n\r\n                            newName = dName + \"__\" + nbUsedByName[dName];\r\n                            o.newName = newName;\r\n                            //console.log(\"o = \", o)\r\n                            debugByName[newName] = objById[count++] = { ...o };\r\n\r\n                            line = line.replace(\"debug.\" + dName, \"debug.\" + newName)\r\n\r\n                        } else {\r\n                            throw new Error(`VERTEX SHADER ERROR on this line :\" ${line} \".`);\r\n                        }\r\n\r\n                    } else {\r\n                        //console.log(line.slice(0, \"debug.\".length) + \" VS \" + \"debug.\")\r\n                        throw new Error(`VERTEX SHADER ERROR on this line :\" ${line} \". The keyword \"debug\" must only be used to store data. It can't be used in computations.`)\r\n                    }\r\n                }\r\n\r\n                result += line + \"\\n\";\r\n            }\r\n\r\n            descriptor.__DEBUG__.objectById = objById;\r\n\r\n            for (let i = 0; i < names.length; i++) {\r\n                debugByName[names[i]] = undefined;\r\n                delete debugByName[names[i]];\r\n            }\r\n\r\n            return result;\r\n        }\r\n\r\n        const clearComments = (shader: string) => {\r\n            let lines = shader.split(\"\\n\");\r\n            for (let i = 0; i < lines.length; i++) lines[i] = lines[i].split(\"//\")[0];\r\n            return lines.join(\"\\n\");\r\n        }\r\n\r\n        descriptor.vertexShader.debugVersion = analyseAndRewriteDebug(clearComments(shader));\r\n\r\n\r\n\r\n\r\n        const simplifyComplexData = () => {\r\n\r\n            const objById = descriptor.__DEBUG__.objectById;\r\n            const objByName = descriptor.__DEBUG__.objectByName;\r\n\r\n            let o, name, newName, n;\r\n            let result = [];\r\n\r\n\r\n            for (let i = 0; i < objById.length; i++) {\r\n                o = { ...objById[i] };\r\n\r\n                if (o.type == \"mat4x4<f32>\") {\r\n                    name = o.newName;\r\n                    newName = name + \"_m4\"\r\n                    o.isMatrix = true;\r\n                    o.realType = o.type;\r\n                    o.type = \"vec4<f32>\";\r\n\r\n                    objByName[name] = undefined;\r\n                    delete objByName[name];\r\n\r\n                    n = newName + \"0\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"1\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"2\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"3\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                } else if (o.type == \"mat3x3<f32>\") {\r\n                    name = o.newName;\r\n                    newName = name + \"_m3\"\r\n                    o.isMatrix = true;\r\n                    o.realType = o.type;\r\n                    o.type = \"vec3<f32>\";\r\n\r\n                    objByName[name] = undefined;\r\n                    delete objByName[name];\r\n\r\n                    n = newName + \"0\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"1\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"2\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"3\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n                } else if (o.isArray) {\r\n\r\n                    const arrayOfMatrix = o.type.includes(\"mat\");\r\n                    const len = o.len;\r\n\r\n                    name = o.newName;\r\n                    newName = name + \"_ar\"\r\n                    o.isMatrix = false;\r\n                    o.realType = o.type;\r\n                    o.type = \"vec4<f32>\";\r\n                    if (o.realType.includes(\"i32\")) o.type = \"vec4<i32>\";\r\n                    else if (o.realType.includes(\"u32\")) o.type = \"vec4<u32>\";\r\n\r\n                    objByName[name] = undefined;\r\n                    delete objByName[name];\r\n\r\n                    if (arrayOfMatrix) {\r\n\r\n\r\n                        objByName[name] = undefined;\r\n                        delete objByName[name];\r\n\r\n                        for (let j = 0; j < len; j++) {\r\n\r\n                            n = newName + j + \"_m0\";\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n\r\n                            n = newName + j + \"_m1\";\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n\r\n                            n = newName + j + \"_m2\";\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n\r\n                            n = newName + j + \"_m3\";\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n\r\n\r\n                        }\r\n\r\n\r\n\r\n                    } else {\r\n\r\n\r\n\r\n                        for (let i = 0; i < len; i++) {\r\n                            n = newName + i;\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n                        }\r\n\r\n\r\n                    }\r\n\r\n\r\n\r\n                } else {\r\n                    result.push(o);\r\n                }\r\n            }\r\n\r\n            descriptor.__DEBUG__.objectById = result;\r\n        }\r\n\r\n        simplifyComplexData()\r\n\r\n\r\n        return descriptor;\r\n\r\n\r\n    }"
            }
          ],
          "protected": [
            {
              "objectType": "property",
              "name": "targetIsBindgroup",
              "type": "boolean",
              "visibility": "protected",
              "rawText": "protected targetIsBindgroup: boolean;"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "parse",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                },
                {
                  "name": "target",
                  "type": "\"render\" | \"compute\" | \"bindgroup\""
                },
                {
                  "name": "drawConfig",
                  "type": "DrawConfig"
                }
              ],
              "visibility": "public",
              "rawText": "public parse(descriptor: any, target: \"render\" | \"compute\" | \"bindgroup\", drawConfig?: DrawConfig) {\r\n\r\n        this.targetIsBindgroup = target === \"bindgroup\";\r\n\r\n        if (target === \"bindgroup\") {\r\n            descriptor = this.parseBindgroupEntries(descriptor);\r\n        } else {\r\n\r\n            const debug = this.parseDebugValues(descriptor);\r\n\r\n            descriptor = this.firstPass(descriptor, target, drawConfig);\r\n            descriptor = this.parseHighLevelObj(descriptor);\r\n            descriptor = this.findAndFixRepetitionInDataStructure(descriptor);\r\n\r\n            if (debug.nb != 0) {\r\n                descriptor.__DEBUG__ = debug;\r\n                descriptor = this.parseVertexShaderDebug(descriptor);\r\n            }\r\n\r\n            //console.log(descriptor);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            }
          ],
          "protected": [
            {
              "objectType": "method",
              "name": "parseShaderBuiltins",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseShaderBuiltins(descriptor: any) {\r\n\r\n        //------------- COMPUTE INPUTS -----------------\r\n\r\n        const addComputeInput = (name: string, val: any) => {\r\n            if (typeof descriptor.computeShader === \"string\") {\r\n                const main: string = descriptor.computeShader;\r\n                descriptor.computeShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.computeShader.inputs) descriptor.computeShader.inputs = {};\r\n            descriptor.computeShader.inputs[name] = val;\r\n        }\r\n        const checkComputeInputBuiltIns = (name: string, o: any) => {\r\n\r\n            for (let z in BuiltIns.computeInputs) {\r\n                if (o === BuiltIns.computeInputs[z]) {\r\n                    addComputeInput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        //-------------- COMPUTE OUTPUTS ------------\r\n        const addComputeOutput = (name: string, val: any) => {\r\n            if (typeof descriptor.computeShader === \"string\") {\r\n                const main: string = descriptor.computeShader;\r\n                descriptor.computeShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.computeShader.outputs) descriptor.computeShader.outputs = {};\r\n            descriptor.computeShader.outputs[name] = val;\r\n        }\r\n        const checkComputeOutputBuiltIns = (name: string, o: any) => {\r\n            for (let z in BuiltIns.computeOutputs) {\r\n                if (o === BuiltIns.computeOutputs[z]) {\r\n                    addComputeOutput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n\r\n        //------------- VERTEX INPUTS -----------------\r\n\r\n        const addVertexInput = (name: string, val: any) => {\r\n            if (typeof descriptor.vertexShader === \"string\") {\r\n                const main: string = descriptor.vertexShader;\r\n                descriptor.vertexShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.vertexShader.inputs) descriptor.vertexShader.inputs = {};\r\n            descriptor.vertexShader.inputs[name] = val;\r\n        }\r\n        const checkVertexInputBuiltIns = (name: string, o: any) => {\r\n\r\n            for (let z in BuiltIns.vertexInputs) {\r\n                if (o === BuiltIns.vertexInputs[z]) {\r\n                    addVertexInput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        //-------------- VERTEX OUTPUTS ------------\r\n        const addVertexOutput = (name: string, val: any) => {\r\n            if (typeof descriptor.vertexShader === \"string\") {\r\n                const main: string = descriptor.vertexShader;\r\n                descriptor.vertexShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.vertexShader.outputs) descriptor.vertexShader.outputs = {};\r\n            descriptor.vertexShader.outputs[name] = val;\r\n        }\r\n        const checkVertexOutputBuiltIns = (name: string, o: any) => {\r\n            for (let z in BuiltIns.vertexOutputs) {\r\n                if (o === BuiltIns.vertexOutputs[z]) {\r\n                    addVertexOutput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        //------------- FRAGMENT INPUTS -----------------\r\n\r\n        const addFragmentInput = (name: string, val: any) => {\r\n            if (typeof descriptor.fragmentShader === \"string\") {\r\n                const main: string = descriptor.fragmentShader;\r\n                descriptor.fragmentShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.fragmentShader.inputs) descriptor.fragmentShader.inputs = {};\r\n            descriptor.fragmentShader.inputs[name] = val;\r\n        }\r\n        const checkFragmentInputBuiltIns = (name: string, o: any) => {\r\n\r\n            for (let z in BuiltIns.fragmentInputs) {\r\n                if (o === BuiltIns.vertexInputs[z]) {\r\n                    addFragmentInput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        //-------------- FRAGMENT OUTPUTS ------------\r\n        const addFragmentOutput = (name: string, val: any) => {\r\n            if (typeof descriptor.fragmentShader === \"string\") {\r\n                const main: string = descriptor.fragmentShader;\r\n                descriptor.fragmentShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.fragmentShader.outputs) descriptor.fragmentShader.outputs = {};\r\n            descriptor.fragmentShader.outputs[name] = val;\r\n        }\r\n        const checkFragmentOutputBuiltIns = (name: string, o: any) => {\r\n            for (let z in BuiltIns.fragmentOutputs) {\r\n                if (o === BuiltIns.fragmentOutputs[z]) {\r\n                    addFragmentOutput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) {\r\n                checkVertexInputBuiltIns(z, o);\r\n                checkVertexOutputBuiltIns(z, o);\r\n                checkFragmentInputBuiltIns(z, o);\r\n                checkFragmentOutputBuiltIns(z, o);\r\n                checkComputeInputBuiltIns(z, o);\r\n                checkComputeOutputBuiltIns(z, o);\r\n            }\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseVertexBufferIOs",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseVertexBufferIOs(descriptor: any) {\r\n\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addVertexBufferIO = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.io) descriptor.bindgroups.io = {};\r\n            descriptor.bindgroups.io[name] = o;\r\n            return o;\r\n        }\r\n\r\n        const checkVertexBufferIO = (name: string, o: any) => {\r\n            if (o instanceof VertexBufferIO) {\r\n                addVertexBufferIO(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkVertexBufferIO(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseImageTextureIOs",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseImageTextureIOs(descriptor: any) {\r\n\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addTextureIO = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.io) descriptor.bindgroups.io = {};\r\n            descriptor.bindgroups.io[name] = o;\r\n            return o;\r\n        }\r\n\r\n        const checkTextureIO = (name: string, o: any) => {\r\n            if (o instanceof ImageTextureIO) {\r\n                addTextureIO(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkTextureIO(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseVertexBuffers",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseVertexBuffers(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addVertexBuffer = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n            return o;\r\n        }\r\n\r\n        const checkVertexBuffer = (name: string, o: any) => {\r\n            if (o instanceof VertexBuffer) {\r\n                addVertexBuffer(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkVertexBuffer(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseVertexAttributes",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseVertexAttributes(descriptor: any) {\r\n\r\n        const addVertexAttribute = (name: string, o: any) => {\r\n\r\n            let bindgroup: any = descriptor;\r\n\r\n            if (!this.targetIsBindgroup) {\r\n                if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n                if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n                bindgroup = descriptor.bindgroups.default;\r\n            }\r\n\r\n\r\n\r\n\r\n\r\n            if (!bindgroup.buffer) {\r\n\r\n\r\n                const attributes: any = {};\r\n                attributes[name] = o;\r\n\r\n                //console.log(attributes)\r\n\r\n                bindgroup.buffer = new VertexBuffer(attributes);\r\n\r\n\r\n\r\n\r\n\r\n            } else {\r\n\r\n\r\n                //console.log(\"O = \", o)\r\n\r\n                let offset = o.offset;\r\n                if (o instanceof VertexAttribute) {\r\n                    offset = o.dataOffset;\r\n                    (bindgroup.buffer as VertexBuffer).attributes[o.name] = o;\r\n                }\r\n\r\n                const attribute = (bindgroup.buffer as VertexBuffer).createArray(name, o.type, offset);\r\n                if (o.datas) attribute.datas = o.datas;\r\n\r\n\r\n\r\n            }\r\n\r\n            //console.log(\"addVertexAttribute \", name, \"buffer = \", bindgroup)\r\n        }\r\n\r\n        const checkVertexAttribute = (name: string, o: any) => {\r\n            if (o.type && VertexAttribute.types[o.type]) {\r\n                addVertexAttribute(name, o);\r\n            } else if (o instanceof VertexAttribute) {\r\n\r\n                addVertexAttribute(name, {\r\n                    type: o.format,\r\n                    offset: o.dataOffset,\r\n                    datas: o.datas\r\n                })\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkVertexAttribute(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseUniformBuffers",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseUniformBuffers(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addUniformBuffer = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n            return o;\r\n        }\r\n\r\n        const checkUniformBuffer = (name: string, o: any) => {\r\n            if (o instanceof UniformBuffer) {\r\n                addUniformBuffer(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkUniformBuffer(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseUniform",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseUniform(descriptor: any) {\r\n        \r\n        const addUniform = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n\r\n            let bindgroup: any = descriptor.bindgroups.default;\r\n            let uniformBufferName: string = \"uniforms\";\r\n\r\n            if (this.targetIsBindgroup) {\r\n                bindgroup = descriptor;\r\n                uniformBufferName = descriptor.uniformBufferName ? descriptor.uniformBufferName : \"bindgroupUniforms\";\r\n            }\r\n\r\n\r\n            /* \r\n            if(o.name){\r\n                console.warn(\"parseUniform \",name)\r\n\r\n                let old = o;\r\n                let newObj = o.clone();\r\n                o.addEventListener(\"ON_CHANGE\",()=>{\r\n                    newObj.set(old);\r\n                })\r\n                \r\n\r\n                o = o.clone();\r\n            }*/\r\n\r\n            if (!bindgroup[uniformBufferName]) {\r\n                const uniforms: any = {};\r\n                uniforms[name] = o;\r\n              \r\n                bindgroup[uniformBufferName] = new UniformBuffer(uniforms, { useLocalVariable: true });\r\n\r\n            } else {\r\n                //console.warn(name);\r\n                (bindgroup[uniformBufferName] as UniformBuffer).add(name, o);\r\n            }\r\n\r\n\r\n\r\n            //console.log(\"addUniform \", name, \" vertexBuffer = \", descriptor.bindgroups.default.buffer)\r\n        }\r\n\r\n        const checkUniform = (name: string, o: any) => {\r\n            if (o instanceof PrimitiveFloatUniform || o instanceof PrimitiveIntUniform || o instanceof PrimitiveUintUniform || o instanceof UniformGroup || o instanceof UniformGroupArray) {\r\n                addUniform(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkUniform(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseImageTextureArray",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseImageTextureArray(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addImageTextureArray = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkImageTextureArray = (name: string, o: any) => {\r\n            if (o instanceof ImageTextureArray) {\r\n                addImageTextureArray(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkImageTextureArray(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseImageTexture",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseImageTexture(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addImageTexture = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkImageTexture = (name: string, o: any) => {\r\n            if (o instanceof ImageTexture) {\r\n                addImageTexture(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkImageTexture(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseTextureSampler",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseTextureSampler(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addTextureSampler = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkTextureSampler = (name: string, o: any) => {\r\n            if (o instanceof TextureSampler) {\r\n                addTextureSampler(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkTextureSampler(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseVideoTexture",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseVideoTexture(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addVideoTexture = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkVideoTexture = (name: string, o: any) => {\r\n            if (o instanceof VideoTexture) {\r\n                addVideoTexture(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkVideoTexture(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseCubeMapTexture",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseCubeMapTexture(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addCubeMapTexture = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkCubeMapTexture = (name: string, o: any) => {\r\n            if (o instanceof CubeMapTexture) {\r\n                addCubeMapTexture(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkCubeMapTexture(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseDrawConfig",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                },
                {
                  "name": "drawConfig",
                  "type": "DrawConfig"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseDrawConfig(descriptor: any, drawConfig: DrawConfig) {\r\n        // vertexCount: number, instanceCount: number, firstVertexId: number, firstInstanceId: number\r\n        if (descriptor.vertexCount) {\r\n            if (isNaN(descriptor.vertexCount)) throw new Error(\"descriptor.vertexCount is a reserved keyword and must be a number\");\r\n            drawConfig.vertexCount = descriptor.vertexCount;\r\n        }\r\n        if (descriptor.instanceCount) {\r\n            if (isNaN(descriptor.instanceCount)) throw new Error(\"descriptor.instanceCount is a reserved keyword and must be a number\");\r\n            drawConfig.instanceCount = descriptor.instanceCount;\r\n        }\r\n        if (descriptor.firstVertexId) {\r\n            if (isNaN(descriptor.firstVertexId)) throw new Error(\"descriptor.firstVertexId is a reserved keyword and must be a number\");\r\n            drawConfig.firstVertexId = descriptor.firstVertexId;\r\n        }\r\n        if (descriptor.firstInstanceId) {\r\n            if (isNaN(descriptor.firstInstanceId)) throw new Error(\"descriptor.firstInstanceId is a reserved keyword and must be a number\");\r\n            drawConfig.firstInstanceId = descriptor.firstInstanceId;\r\n        }\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseBindgroup",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseBindgroup(descriptor: any): any {\r\n        for (let z in descriptor) {\r\n            if (descriptor[z] instanceof Bindgroup) {\r\n                if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n                descriptor.bindgroups[z] = descriptor[z];\r\n                delete descriptor[z];\r\n            }\r\n        }\r\n\r\n        return descriptor;\r\n\r\n    }"
            },
            {
              "objectType": "method",
              "name": "firstPass",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                },
                {
                  "name": "target",
                  "type": "\"render\" | \"compute\" | \"bindgroup\""
                },
                {
                  "name": "drawConfig",
                  "type": "DrawConfig"
                }
              ],
              "visibility": "protected",
              "rawText": "protected firstPass(descriptor: any, target: \"render\" | \"compute\" | \"bindgroup\", drawConfig?: DrawConfig): any {\r\n\r\n\r\n        descriptor = this.parseBindgroup(descriptor);\r\n        descriptor = this.parseVertexBuffers(descriptor);\r\n        descriptor = this.parseVertexAttributes(descriptor);\r\n        descriptor = this.parseUniformBuffers(descriptor);\r\n        descriptor = this.parseUniform(descriptor);\r\n        descriptor = this.parseImageTexture(descriptor);\r\n        descriptor = this.parseImageTextureArray(descriptor);\r\n        descriptor = this.parseTextureSampler(descriptor);\r\n        descriptor = this.parseVideoTexture(descriptor);\r\n        descriptor = this.parseCubeMapTexture(descriptor);\r\n        descriptor = this.parseVertexBufferIOs(descriptor);\r\n        descriptor = this.parseImageTextureIOs(descriptor);\r\n\r\n        if (target === \"render\" || target === \"compute\") {\r\n\r\n            //console.log(\"target.type = \", target)\r\n\r\n            descriptor = this.parseShaderBuiltins(descriptor);\r\n\r\n\r\n            if (target === \"render\") {\r\n                descriptor = this.parseDrawConfig(descriptor, drawConfig);\r\n            }\r\n        }\r\n\r\n\r\n        return descriptor;\r\n\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseHighLevelObj",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseHighLevelObj(descriptor: any) {\r\n\r\n        const isBuiltIn = (obj) => {\r\n            for (let z in BuiltIns.vertexInputs) if (BuiltIns.vertexInputs[z] === obj) return true;\r\n            for (let z in BuiltIns.vertexOutputs) if (BuiltIns.vertexOutputs[z] === obj) return true;\r\n            for (let z in BuiltIns.fragmentInputs) if (BuiltIns.fragmentInputs[z] === obj) return true;\r\n            for (let z in BuiltIns.fragmentOutputs) if (BuiltIns.fragmentOutputs[z] === obj) return true;\r\n            for (let z in BuiltIns.computeInputs) if (BuiltIns.computeInputs[z] === obj) return true;\r\n            return false;\r\n        }\r\n\r\n        const searchComplexObject = (o: any): any[] => {\r\n            let name: string;\r\n            let obj;\r\n            let objs: any[] = [];\r\n\r\n            for (let z in o) {\r\n                //console.log(\"=> \", z, o[z])\r\n                obj = o[z];\r\n                if (!obj) continue;\r\n                //console.log(\"OBJ = \", z, obj)\r\n                name = obj.constructor.name;\r\n                if (name === \"Object\") {\r\n                    if (z !== \"bindgroups\" && z !== \"vertexShader\" && z !== \"fragmentShader\" && z !== \"computeShader\") {\r\n                        if (!isBuiltIn(obj)) {\r\n                            objs.push({ name, resource: obj });\r\n                            //console.log(\"######## \", z)\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            return objs;\r\n        }\r\n\r\n        const analyseObjects = (objs: any[]): { primitives: { name: string, containerName: string, resource: PrimitiveType }[], vertexAttributes: { name: string, containerName: string, resource: VertexAttribute }[], shaderResources: { name: string, containerName: string, resource: IShaderResource }[] } => {\r\n\r\n            const primitives: { name: string, resource: PrimitiveType, containerName: string }[] = [];\r\n            const vertexAttributes: { name: string, resource: VertexAttribute, containerName: string }[] = [];\r\n            const shaderResources: { name: string, resource: IShaderResource, containerName: string }[] = [];\r\n\r\n            let o: any;\r\n            let resource: PrimitiveType | IShaderResource;\r\n            let containerName: string;\r\n            for (let i = 0; i < objs.length; i++) {\r\n                containerName = objs[i].name;\r\n                o = objs[i].resource;\r\n\r\n                for (let name in o) {\r\n                    resource = o[name];\r\n\r\n                    if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n                        primitives.push({ containerName, name, resource });\r\n                    } else if (resource instanceof VertexAttribute) {\r\n                        vertexAttributes.push({ containerName, name, resource });\r\n                    } else {\r\n                        shaderResources.push({ containerName, name, resource });\r\n                    }\r\n\r\n                }\r\n            }\r\n\r\n            return { primitives, vertexAttributes, shaderResources };\r\n        }\r\n\r\n        //console.log(\"descriptor = \", descriptor)\r\n\r\n        let objects: any = searchComplexObject(descriptor);\r\n        if (objects.length) {\r\n\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n\r\n            analyseObjects(objects);\r\n\r\n        }\r\n\r\n\r\n        //descriptor.bindgroups.default.buffer = new VertexBuffer(attributes);\r\n\r\n\r\n\r\n        return descriptor;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "findAndFixRepetitionInDataStructure",
              "returnType": "any",
              "params": [
                {
                  "name": "o",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected findAndFixRepetitionInDataStructure(o: any): any {\r\n\r\n\r\n        let name: string;\r\n        let obj;\r\n        let exist = {};\r\n        let bindgroup;\r\n        let resource;\r\n        let uniformBuffers: UniformBuffer[] = [];\r\n        let bool;\r\n\r\n\r\n        for (let z in o.bindgroups) {\r\n            bindgroup = o.bindgroups[z];\r\n\r\n            for (let a in bindgroup) {\r\n\r\n                resource = bindgroup[a];\r\n\r\n                if (resource instanceof UniformBuffer) {\r\n                    bool = true;\r\n\r\n\r\n                    for (let i = resource.itemNames.length - 1; i >= 0; i--) {\r\n                        name = resource.itemNames[i];\r\n                        obj = resource.items[name];\r\n\r\n                        if (!exist[name]) {\r\n                            exist[name] = obj;\r\n                        } else {\r\n\r\n                            resource.remove(name);\r\n\r\n                            if (resource.itemNames.length === 0) {\r\n                                bool = false;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n                    if (bool) uniformBuffers.push(resource);\r\n                    else {\r\n                        bindgroup[a] = undefined;\r\n                    }\r\n                }\r\n                resource = bindgroup[a];\r\n            }\r\n        }\r\n\r\n        return o;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "parseBindgroupEntries",
              "returnType": "any",
              "params": [
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "visibility": "protected",
              "rawText": "protected parseBindgroupEntries(descriptor: any): any {\r\n\r\n\r\n\r\n\r\n        const uniformBufferName: string = descriptor.uniformBufferName ? descriptor.uniformBufferName : \"bindgroupUniforms\";\r\n        const addUniform = (name: string, resource: PrimitiveType) => {\r\n\r\n            if (!descriptor[uniformBufferName]) {\r\n\r\n                const uniforms = {};\r\n                uniforms[name] = resource;\r\n                descriptor[uniformBufferName] = new UniformBuffer(uniforms, { useLocalVariable: true });\r\n            } else {\r\n                (descriptor[uniformBufferName] as UniformBuffer).add(name, resource);\r\n            }\r\n\r\n        }\r\n\r\n        const vertexBufferName: string = descriptor.vertexBufferName ? descriptor.vertexBufferName : \"bindgroupVertexBuffer\";\r\n        const addVertexAttribute = (name: string, resource: any) => {\r\n\r\n\r\n\r\n            if (!descriptor[vertexBufferName]) {\r\n                const attributes = {};\r\n                attributes[name] = resource;\r\n                descriptor[vertexBufferName] = new VertexBuffer(attributes)\r\n            } else {\r\n                const attribute: VertexAttribute = (descriptor[vertexBufferName] as VertexBuffer).createArray(name, resource.type, resource.dataOffset)\r\n                if (resource.datas) attribute.datas = resource.datas;\r\n            }\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n        let resource;\r\n        for (let z in descriptor) {\r\n            resource = descriptor[z];\r\n            if (!resource) continue\r\n            if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n                addUniform(z, resource);\r\n            } else if (VertexAttribute.types[resource.type]) {\r\n                addVertexAttribute(z, resource)\r\n            }\r\n        }\r\n\r\n\r\n\r\n        return descriptor;\r\n    }"
            }
          ]
        },
        "statics": {
          "properties": {
            "private": [
              {
                "objectType": "property",
                "name": "instance",
                "type": "HighLevelParser",
                "visibility": "private",
                "rawText": "private static instance: HighLevelParser = null;"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "parse",
                "returnType": "any",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "any"
                  },
                  {
                    "name": "target",
                    "type": "\"render\" | \"compute\" | \"bindgroup\""
                  },
                  {
                    "name": "drawConfig",
                    "type": "DrawConfig"
                  }
                ],
                "visibility": "public",
                "rawText": "public static parse(descriptor: any, target: \"render\" | \"compute\" | \"bindgroup\", drawConfig?: DrawConfig) {\r\n        if (!this.instance) this.instance = new HighLevelParser();\r\n        //console.log(\"highLevelParser = \", this.instance)\r\n        return this.instance.parse(descriptor, target, drawConfig);\r\n    }"
              }
            ]
          }
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "rawText": "constructor() {\r\n\r\n    }"
        },
        "rawText": "export class HighLevelParser {\r\n\r\n\r\n\r\n    constructor() {\r\n\r\n    }\r\n\r\n\r\n\r\n    protected parseShaderBuiltins(descriptor: any) {\r\n\r\n        //------------- COMPUTE INPUTS -----------------\r\n\r\n        const addComputeInput = (name: string, val: any) => {\r\n            if (typeof descriptor.computeShader === \"string\") {\r\n                const main: string = descriptor.computeShader;\r\n                descriptor.computeShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.computeShader.inputs) descriptor.computeShader.inputs = {};\r\n            descriptor.computeShader.inputs[name] = val;\r\n        }\r\n        const checkComputeInputBuiltIns = (name: string, o: any) => {\r\n\r\n            for (let z in BuiltIns.computeInputs) {\r\n                if (o === BuiltIns.computeInputs[z]) {\r\n                    addComputeInput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        //-------------- COMPUTE OUTPUTS ------------\r\n        const addComputeOutput = (name: string, val: any) => {\r\n            if (typeof descriptor.computeShader === \"string\") {\r\n                const main: string = descriptor.computeShader;\r\n                descriptor.computeShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.computeShader.outputs) descriptor.computeShader.outputs = {};\r\n            descriptor.computeShader.outputs[name] = val;\r\n        }\r\n        const checkComputeOutputBuiltIns = (name: string, o: any) => {\r\n            for (let z in BuiltIns.computeOutputs) {\r\n                if (o === BuiltIns.computeOutputs[z]) {\r\n                    addComputeOutput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n\r\n        //------------- VERTEX INPUTS -----------------\r\n\r\n        const addVertexInput = (name: string, val: any) => {\r\n            if (typeof descriptor.vertexShader === \"string\") {\r\n                const main: string = descriptor.vertexShader;\r\n                descriptor.vertexShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.vertexShader.inputs) descriptor.vertexShader.inputs = {};\r\n            descriptor.vertexShader.inputs[name] = val;\r\n        }\r\n        const checkVertexInputBuiltIns = (name: string, o: any) => {\r\n\r\n            for (let z in BuiltIns.vertexInputs) {\r\n                if (o === BuiltIns.vertexInputs[z]) {\r\n                    addVertexInput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        //-------------- VERTEX OUTPUTS ------------\r\n        const addVertexOutput = (name: string, val: any) => {\r\n            if (typeof descriptor.vertexShader === \"string\") {\r\n                const main: string = descriptor.vertexShader;\r\n                descriptor.vertexShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.vertexShader.outputs) descriptor.vertexShader.outputs = {};\r\n            descriptor.vertexShader.outputs[name] = val;\r\n        }\r\n        const checkVertexOutputBuiltIns = (name: string, o: any) => {\r\n            for (let z in BuiltIns.vertexOutputs) {\r\n                if (o === BuiltIns.vertexOutputs[z]) {\r\n                    addVertexOutput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        //------------- FRAGMENT INPUTS -----------------\r\n\r\n        const addFragmentInput = (name: string, val: any) => {\r\n            if (typeof descriptor.fragmentShader === \"string\") {\r\n                const main: string = descriptor.fragmentShader;\r\n                descriptor.fragmentShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.fragmentShader.inputs) descriptor.fragmentShader.inputs = {};\r\n            descriptor.fragmentShader.inputs[name] = val;\r\n        }\r\n        const checkFragmentInputBuiltIns = (name: string, o: any) => {\r\n\r\n            for (let z in BuiltIns.fragmentInputs) {\r\n                if (o === BuiltIns.vertexInputs[z]) {\r\n                    addFragmentInput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        //-------------- FRAGMENT OUTPUTS ------------\r\n        const addFragmentOutput = (name: string, val: any) => {\r\n            if (typeof descriptor.fragmentShader === \"string\") {\r\n                const main: string = descriptor.fragmentShader;\r\n                descriptor.fragmentShader = {\r\n                    main\r\n                }\r\n            }\r\n            if (!descriptor.fragmentShader.outputs) descriptor.fragmentShader.outputs = {};\r\n            descriptor.fragmentShader.outputs[name] = val;\r\n        }\r\n        const checkFragmentOutputBuiltIns = (name: string, o: any) => {\r\n            for (let z in BuiltIns.fragmentOutputs) {\r\n                if (o === BuiltIns.fragmentOutputs[z]) {\r\n                    addFragmentOutput(name, o);\r\n                }\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) {\r\n                checkVertexInputBuiltIns(z, o);\r\n                checkVertexOutputBuiltIns(z, o);\r\n                checkFragmentInputBuiltIns(z, o);\r\n                checkFragmentOutputBuiltIns(z, o);\r\n                checkComputeInputBuiltIns(z, o);\r\n                checkComputeOutputBuiltIns(z, o);\r\n            }\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n    protected parseVertexBufferIOs(descriptor: any) {\r\n\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addVertexBufferIO = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.io) descriptor.bindgroups.io = {};\r\n            descriptor.bindgroups.io[name] = o;\r\n            return o;\r\n        }\r\n\r\n        const checkVertexBufferIO = (name: string, o: any) => {\r\n            if (o instanceof VertexBufferIO) {\r\n                addVertexBufferIO(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkVertexBufferIO(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n    protected parseImageTextureIOs(descriptor: any) {\r\n\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addTextureIO = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.io) descriptor.bindgroups.io = {};\r\n            descriptor.bindgroups.io[name] = o;\r\n            return o;\r\n        }\r\n\r\n        const checkTextureIO = (name: string, o: any) => {\r\n            if (o instanceof ImageTextureIO) {\r\n                addTextureIO(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkTextureIO(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n\r\n\r\n    protected parseVertexBuffers(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addVertexBuffer = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n            return o;\r\n        }\r\n\r\n        const checkVertexBuffer = (name: string, o: any) => {\r\n            if (o instanceof VertexBuffer) {\r\n                addVertexBuffer(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkVertexBuffer(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n\r\n    protected parseVertexAttributes(descriptor: any) {\r\n\r\n        const addVertexAttribute = (name: string, o: any) => {\r\n\r\n            let bindgroup: any = descriptor;\r\n\r\n            if (!this.targetIsBindgroup) {\r\n                if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n                if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n                bindgroup = descriptor.bindgroups.default;\r\n            }\r\n\r\n\r\n\r\n\r\n\r\n            if (!bindgroup.buffer) {\r\n\r\n\r\n                const attributes: any = {};\r\n                attributes[name] = o;\r\n\r\n                //console.log(attributes)\r\n\r\n                bindgroup.buffer = new VertexBuffer(attributes);\r\n\r\n\r\n\r\n\r\n\r\n            } else {\r\n\r\n\r\n                //console.log(\"O = \", o)\r\n\r\n                let offset = o.offset;\r\n                if (o instanceof VertexAttribute) {\r\n                    offset = o.dataOffset;\r\n                    (bindgroup.buffer as VertexBuffer).attributes[o.name] = o;\r\n                }\r\n\r\n                const attribute = (bindgroup.buffer as VertexBuffer).createArray(name, o.type, offset);\r\n                if (o.datas) attribute.datas = o.datas;\r\n\r\n\r\n\r\n            }\r\n\r\n            //console.log(\"addVertexAttribute \", name, \"buffer = \", bindgroup)\r\n        }\r\n\r\n        const checkVertexAttribute = (name: string, o: any) => {\r\n            if (o.type && VertexAttribute.types[o.type]) {\r\n                addVertexAttribute(name, o);\r\n            } else if (o instanceof VertexAttribute) {\r\n\r\n                addVertexAttribute(name, {\r\n                    type: o.format,\r\n                    offset: o.dataOffset,\r\n                    datas: o.datas\r\n                })\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkVertexAttribute(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\n    protected parseUniformBuffers(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addUniformBuffer = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n            return o;\r\n        }\r\n\r\n        const checkUniformBuffer = (name: string, o: any) => {\r\n            if (o instanceof UniformBuffer) {\r\n                addUniformBuffer(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkUniformBuffer(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n\r\n\r\n    protected parseUniform(descriptor: any) {\r\n        \r\n        const addUniform = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n\r\n            let bindgroup: any = descriptor.bindgroups.default;\r\n            let uniformBufferName: string = \"uniforms\";\r\n\r\n            if (this.targetIsBindgroup) {\r\n                bindgroup = descriptor;\r\n                uniformBufferName = descriptor.uniformBufferName ? descriptor.uniformBufferName : \"bindgroupUniforms\";\r\n            }\r\n\r\n\r\n            /* \r\n            if(o.name){\r\n                console.warn(\"parseUniform \",name)\r\n\r\n                let old = o;\r\n                let newObj = o.clone();\r\n                o.addEventListener(\"ON_CHANGE\",()=>{\r\n                    newObj.set(old);\r\n                })\r\n                \r\n\r\n                o = o.clone();\r\n            }*/\r\n\r\n            if (!bindgroup[uniformBufferName]) {\r\n                const uniforms: any = {};\r\n                uniforms[name] = o;\r\n              \r\n                bindgroup[uniformBufferName] = new UniformBuffer(uniforms, { useLocalVariable: true });\r\n\r\n            } else {\r\n                //console.warn(name);\r\n                (bindgroup[uniformBufferName] as UniformBuffer).add(name, o);\r\n            }\r\n\r\n\r\n\r\n            //console.log(\"addUniform \", name, \" vertexBuffer = \", descriptor.bindgroups.default.buffer)\r\n        }\r\n\r\n        const checkUniform = (name: string, o: any) => {\r\n            if (o instanceof PrimitiveFloatUniform || o instanceof PrimitiveIntUniform || o instanceof PrimitiveUintUniform || o instanceof UniformGroup || o instanceof UniformGroupArray) {\r\n                addUniform(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkUniform(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n    protected parseImageTextureArray(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addImageTextureArray = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkImageTextureArray = (name: string, o: any) => {\r\n            if (o instanceof ImageTextureArray) {\r\n                addImageTextureArray(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkImageTextureArray(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n    protected parseImageTexture(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addImageTexture = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkImageTexture = (name: string, o: any) => {\r\n            if (o instanceof ImageTexture) {\r\n                addImageTexture(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkImageTexture(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n\r\n    protected parseTextureSampler(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addTextureSampler = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkTextureSampler = (name: string, o: any) => {\r\n            if (o instanceof TextureSampler) {\r\n                addTextureSampler(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkTextureSampler(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n    protected parseVideoTexture(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addVideoTexture = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkVideoTexture = (name: string, o: any) => {\r\n            if (o instanceof VideoTexture) {\r\n                addVideoTexture(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkVideoTexture(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n    protected parseCubeMapTexture(descriptor: any) {\r\n        if (this.targetIsBindgroup) return descriptor;\r\n\r\n        const addCubeMapTexture = (name: string, o: any) => {\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n            descriptor.bindgroups.default[name] = o;\r\n        }\r\n\r\n        const checkCubeMapTexture = (name: string, o: any) => {\r\n            if (o instanceof CubeMapTexture) {\r\n                addCubeMapTexture(name, o);\r\n            }\r\n        }\r\n\r\n        let o: any;\r\n        for (let z in descriptor) {\r\n            o = descriptor[z];\r\n            if (o) checkCubeMapTexture(z, o);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n\r\n\r\n    protected parseDrawConfig(descriptor: any, drawConfig: DrawConfig) {\r\n        // vertexCount: number, instanceCount: number, firstVertexId: number, firstInstanceId: number\r\n        if (descriptor.vertexCount) {\r\n            if (isNaN(descriptor.vertexCount)) throw new Error(\"descriptor.vertexCount is a reserved keyword and must be a number\");\r\n            drawConfig.vertexCount = descriptor.vertexCount;\r\n        }\r\n        if (descriptor.instanceCount) {\r\n            if (isNaN(descriptor.instanceCount)) throw new Error(\"descriptor.instanceCount is a reserved keyword and must be a number\");\r\n            drawConfig.instanceCount = descriptor.instanceCount;\r\n        }\r\n        if (descriptor.firstVertexId) {\r\n            if (isNaN(descriptor.firstVertexId)) throw new Error(\"descriptor.firstVertexId is a reserved keyword and must be a number\");\r\n            drawConfig.firstVertexId = descriptor.firstVertexId;\r\n        }\r\n        if (descriptor.firstInstanceId) {\r\n            if (isNaN(descriptor.firstInstanceId)) throw new Error(\"descriptor.firstInstanceId is a reserved keyword and must be a number\");\r\n            drawConfig.firstInstanceId = descriptor.firstInstanceId;\r\n        }\r\n        return descriptor;\r\n    }\r\n\r\n    protected parseBindgroup(descriptor: any): any {\r\n        for (let z in descriptor) {\r\n            if (descriptor[z] instanceof Bindgroup) {\r\n                if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n                descriptor.bindgroups[z] = descriptor[z];\r\n                delete descriptor[z];\r\n            }\r\n        }\r\n\r\n        return descriptor;\r\n\r\n    }\r\n\r\n\r\n    protected firstPass(descriptor: any, target: \"render\" | \"compute\" | \"bindgroup\", drawConfig?: DrawConfig): any {\r\n\r\n\r\n        descriptor = this.parseBindgroup(descriptor);\r\n        descriptor = this.parseVertexBuffers(descriptor);\r\n        descriptor = this.parseVertexAttributes(descriptor);\r\n        descriptor = this.parseUniformBuffers(descriptor);\r\n        descriptor = this.parseUniform(descriptor);\r\n        descriptor = this.parseImageTexture(descriptor);\r\n        descriptor = this.parseImageTextureArray(descriptor);\r\n        descriptor = this.parseTextureSampler(descriptor);\r\n        descriptor = this.parseVideoTexture(descriptor);\r\n        descriptor = this.parseCubeMapTexture(descriptor);\r\n        descriptor = this.parseVertexBufferIOs(descriptor);\r\n        descriptor = this.parseImageTextureIOs(descriptor);\r\n\r\n        if (target === \"render\" || target === \"compute\") {\r\n\r\n            //console.log(\"target.type = \", target)\r\n\r\n            descriptor = this.parseShaderBuiltins(descriptor);\r\n\r\n\r\n            if (target === \"render\") {\r\n                descriptor = this.parseDrawConfig(descriptor, drawConfig);\r\n            }\r\n        }\r\n\r\n\r\n        return descriptor;\r\n\r\n    }\r\n\r\n\r\n    //--------\r\n    protected parseHighLevelObj(descriptor: any) {\r\n\r\n        const isBuiltIn = (obj) => {\r\n            for (let z in BuiltIns.vertexInputs) if (BuiltIns.vertexInputs[z] === obj) return true;\r\n            for (let z in BuiltIns.vertexOutputs) if (BuiltIns.vertexOutputs[z] === obj) return true;\r\n            for (let z in BuiltIns.fragmentInputs) if (BuiltIns.fragmentInputs[z] === obj) return true;\r\n            for (let z in BuiltIns.fragmentOutputs) if (BuiltIns.fragmentOutputs[z] === obj) return true;\r\n            for (let z in BuiltIns.computeInputs) if (BuiltIns.computeInputs[z] === obj) return true;\r\n            return false;\r\n        }\r\n\r\n        const searchComplexObject = (o: any): any[] => {\r\n            let name: string;\r\n            let obj;\r\n            let objs: any[] = [];\r\n\r\n            for (let z in o) {\r\n                //console.log(\"=> \", z, o[z])\r\n                obj = o[z];\r\n                if (!obj) continue;\r\n                //console.log(\"OBJ = \", z, obj)\r\n                name = obj.constructor.name;\r\n                if (name === \"Object\") {\r\n                    if (z !== \"bindgroups\" && z !== \"vertexShader\" && z !== \"fragmentShader\" && z !== \"computeShader\") {\r\n                        if (!isBuiltIn(obj)) {\r\n                            objs.push({ name, resource: obj });\r\n                            //console.log(\"######## \", z)\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            return objs;\r\n        }\r\n\r\n        const analyseObjects = (objs: any[]): { primitives: { name: string, containerName: string, resource: PrimitiveType }[], vertexAttributes: { name: string, containerName: string, resource: VertexAttribute }[], shaderResources: { name: string, containerName: string, resource: IShaderResource }[] } => {\r\n\r\n            const primitives: { name: string, resource: PrimitiveType, containerName: string }[] = [];\r\n            const vertexAttributes: { name: string, resource: VertexAttribute, containerName: string }[] = [];\r\n            const shaderResources: { name: string, resource: IShaderResource, containerName: string }[] = [];\r\n\r\n            let o: any;\r\n            let resource: PrimitiveType | IShaderResource;\r\n            let containerName: string;\r\n            for (let i = 0; i < objs.length; i++) {\r\n                containerName = objs[i].name;\r\n                o = objs[i].resource;\r\n\r\n                for (let name in o) {\r\n                    resource = o[name];\r\n\r\n                    if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n                        primitives.push({ containerName, name, resource });\r\n                    } else if (resource instanceof VertexAttribute) {\r\n                        vertexAttributes.push({ containerName, name, resource });\r\n                    } else {\r\n                        shaderResources.push({ containerName, name, resource });\r\n                    }\r\n\r\n                }\r\n            }\r\n\r\n            return { primitives, vertexAttributes, shaderResources };\r\n        }\r\n\r\n        //console.log(\"descriptor = \", descriptor)\r\n\r\n        let objects: any = searchComplexObject(descriptor);\r\n        if (objects.length) {\r\n\r\n            if (!descriptor.bindgroups) descriptor.bindgroups = {};\r\n            if (!descriptor.bindgroups.default) descriptor.bindgroups.default = {};\r\n\r\n            analyseObjects(objects);\r\n\r\n        }\r\n\r\n\r\n        //descriptor.bindgroups.default.buffer = new VertexBuffer(attributes);\r\n\r\n\r\n\r\n        return descriptor;\r\n    }\r\n\r\n    //---\r\n\r\n    protected findAndFixRepetitionInDataStructure(o: any): any {\r\n\r\n\r\n        let name: string;\r\n        let obj;\r\n        let exist = {};\r\n        let bindgroup;\r\n        let resource;\r\n        let uniformBuffers: UniformBuffer[] = [];\r\n        let bool;\r\n\r\n\r\n        for (let z in o.bindgroups) {\r\n            bindgroup = o.bindgroups[z];\r\n\r\n            for (let a in bindgroup) {\r\n\r\n                resource = bindgroup[a];\r\n\r\n                if (resource instanceof UniformBuffer) {\r\n                    bool = true;\r\n\r\n\r\n                    for (let i = resource.itemNames.length - 1; i >= 0; i--) {\r\n                        name = resource.itemNames[i];\r\n                        obj = resource.items[name];\r\n\r\n                        if (!exist[name]) {\r\n                            exist[name] = obj;\r\n                        } else {\r\n\r\n                            resource.remove(name);\r\n\r\n                            if (resource.itemNames.length === 0) {\r\n                                bool = false;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n                    if (bool) uniformBuffers.push(resource);\r\n                    else {\r\n                        bindgroup[a] = undefined;\r\n                    }\r\n                }\r\n                resource = bindgroup[a];\r\n            }\r\n        }\r\n\r\n        return o;\r\n    }\r\n\r\n\r\n    protected targetIsBindgroup: boolean;\r\n\r\n    protected parseBindgroupEntries(descriptor: any): any {\r\n\r\n\r\n\r\n\r\n        const uniformBufferName: string = descriptor.uniformBufferName ? descriptor.uniformBufferName : \"bindgroupUniforms\";\r\n        const addUniform = (name: string, resource: PrimitiveType) => {\r\n\r\n            if (!descriptor[uniformBufferName]) {\r\n\r\n                const uniforms = {};\r\n                uniforms[name] = resource;\r\n                descriptor[uniformBufferName] = new UniformBuffer(uniforms, { useLocalVariable: true });\r\n            } else {\r\n                (descriptor[uniformBufferName] as UniformBuffer).add(name, resource);\r\n            }\r\n\r\n        }\r\n\r\n        const vertexBufferName: string = descriptor.vertexBufferName ? descriptor.vertexBufferName : \"bindgroupVertexBuffer\";\r\n        const addVertexAttribute = (name: string, resource: any) => {\r\n\r\n\r\n\r\n            if (!descriptor[vertexBufferName]) {\r\n                const attributes = {};\r\n                attributes[name] = resource;\r\n                descriptor[vertexBufferName] = new VertexBuffer(attributes)\r\n            } else {\r\n                const attribute: VertexAttribute = (descriptor[vertexBufferName] as VertexBuffer).createArray(name, resource.type, resource.dataOffset)\r\n                if (resource.datas) attribute.datas = resource.datas;\r\n            }\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n        let resource;\r\n        for (let z in descriptor) {\r\n            resource = descriptor[z];\r\n            if (!resource) continue\r\n            if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n                addUniform(z, resource);\r\n            } else if (VertexAttribute.types[resource.type]) {\r\n                addVertexAttribute(z, resource)\r\n            }\r\n        }\r\n\r\n\r\n\r\n        return descriptor;\r\n    }\r\n\r\n\r\n    private parseDebugValues = (descriptor: any): any => {\r\n\r\n\r\n        let o: any;\r\n\r\n        let indexs: Vec4[] = [];\r\n        let objectById: any[] = [];\r\n        let objectByName: any = {};\r\n        let nb = 0;\r\n        for (let name in descriptor) {\r\n            o = descriptor[name];\r\n            if (o && o.__debug == true) {\r\n\r\n                if (typeof (o) === \"function\") {\r\n                    o = { name, id: nb, ...(o()) };\r\n                } else {\r\n                    o.id = nb;\r\n                    o.name = name;\r\n                }\r\n\r\n\r\n                /*\r\n                if (name.includes(\"_\")) {\r\n                    throw new Error(`BUILTINS ERROR :: ${name}  A variable using a BuiltIns.vertexDebug cannot use an underscore in its name.`)\r\n                }*/\r\n\r\n                descriptor[name] = undefined;\r\n                indexs[nb] = new Vec4(o.vertexId, o.instanceId, 0, 0);\r\n                objectByName[name] = o;\r\n                objectById[nb] = o;\r\n                nb++;\r\n            }\r\n        }\r\n\r\n        return {\r\n            nb,\r\n            indexs,\r\n            objectByName,\r\n            objectById\r\n        }\r\n\r\n    }\r\n\r\n    private parseVertexShaderDebug = (descriptor: any) => {\r\n\r\n        if (typeof (descriptor.vertexShader) === \"string\") {\r\n            descriptor.vertexShader = { main: descriptor.vertexShader };\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n        const clearDebug = (shader: string) => {\r\n            let lines = shader.split(\"\\n\");\r\n            let line: string;\r\n            let result = \"\";\r\n            for (let i = 0; i < lines.length; i++) {\r\n                line = lines[i];\r\n                if (line.includes(\"debug.\")) continue;\r\n                result += line + \"\\n\";\r\n            }\r\n            return result;\r\n        }\r\n\r\n        const shader = descriptor.vertexShader.main;\r\n        descriptor.vertexShader.main = clearDebug(shader);\r\n\r\n\r\n        const debugByName = descriptor.__DEBUG__.objectByName;\r\n\r\n\r\n        const removeEmptySpaceAtStart = (line: string): string => {\r\n            let abc = \"abcdefghijklmnopqrstuvwxyz/\";\r\n            abc += abc.toUpperCase();\r\n\r\n            let char: string;\r\n            for (let i = 0; i < line.length; i++) {\r\n                char = line[i];\r\n                if (abc.includes(char)) {\r\n                    return line.slice(i);\r\n                }\r\n            }\r\n\r\n            return line;\r\n        }\r\n\r\n        const extractDebugName = (line: string): string => {\r\n            let abc = \"abcdefghijklmnopqrstuvwxyz0123456789_\";\r\n            abc += abc.toUpperCase();\r\n\r\n            let char: string;\r\n            let name: string = \"\";\r\n            for (let i = 0; i < line.length; i++) {\r\n                char = line[i];\r\n                if (abc.includes(char)) {\r\n                    name += char;\r\n                    continue;\r\n                }\r\n                if (char === \" \") continue;\r\n                if (char != \"=\") {\r\n                    //console.log(\"char = \", char)\r\n                    throw new Error(`VERTEX SHADER ERROR on this line :\"debug.${line} \". The keyword \"debug\" must only be used to store data. It can't be used in computations.`)\r\n                }\r\n                return name;\r\n            }\r\n            return name;\r\n        }\r\n\r\n        const analyseAndRewriteDebug = (shader: string) => {\r\n            let lines = shader.split(\"\\n\");\r\n            let line: string;\r\n            let result: string = \";\"\r\n            let names: string[] = [];\r\n            let nbUsedByName: any = {};\r\n            let newName: string;\r\n            let objById: any[] = [];\r\n            let count = 0;\r\n            for (let i = 0; i < lines.length; i++) {\r\n                line = removeEmptySpaceAtStart(lines[i]);\r\n                if (line.slice(0, 2) == \"//\") continue;\r\n\r\n\r\n                if (line.includes(\"debug.\")) {\r\n                    if (line.slice(0, \"debug.\".length) === \"debug.\") {\r\n\r\n                        if (line.split(\"=\").length == 2) {\r\n\r\n\r\n                            const dName = extractDebugName(line.slice(\"debug.\".length));\r\n\r\n\r\n                            const o = debugByName[dName];\r\n                            if (!debugByName[dName]) {\r\n                                throw new Error(`VERTEX SHADER ERROR on this line :\" ${line} \". The value \"debug.${dName}\" is used in the vertexShader but not defined in RenderPipeline.initFromObject `);\r\n                            }\r\n\r\n                            if (names.includes(dName) === false) names.push(dName);\r\n\r\n\r\n                            if (isNaN(nbUsedByName[dName])) {\r\n                                //debugByName[dName] = undefined;\r\n                                //delete debugByName[dName];\r\n                                nbUsedByName[dName] = 0;\r\n                            } else nbUsedByName[dName]++;\r\n\r\n                            newName = dName + \"__\" + nbUsedByName[dName];\r\n                            o.newName = newName;\r\n                            //console.log(\"o = \", o)\r\n                            debugByName[newName] = objById[count++] = { ...o };\r\n\r\n                            line = line.replace(\"debug.\" + dName, \"debug.\" + newName)\r\n\r\n                        } else {\r\n                            throw new Error(`VERTEX SHADER ERROR on this line :\" ${line} \".`);\r\n                        }\r\n\r\n                    } else {\r\n                        //console.log(line.slice(0, \"debug.\".length) + \" VS \" + \"debug.\")\r\n                        throw new Error(`VERTEX SHADER ERROR on this line :\" ${line} \". The keyword \"debug\" must only be used to store data. It can't be used in computations.`)\r\n                    }\r\n                }\r\n\r\n                result += line + \"\\n\";\r\n            }\r\n\r\n            descriptor.__DEBUG__.objectById = objById;\r\n\r\n            for (let i = 0; i < names.length; i++) {\r\n                debugByName[names[i]] = undefined;\r\n                delete debugByName[names[i]];\r\n            }\r\n\r\n            return result;\r\n        }\r\n\r\n        const clearComments = (shader: string) => {\r\n            let lines = shader.split(\"\\n\");\r\n            for (let i = 0; i < lines.length; i++) lines[i] = lines[i].split(\"//\")[0];\r\n            return lines.join(\"\\n\");\r\n        }\r\n\r\n        descriptor.vertexShader.debugVersion = analyseAndRewriteDebug(clearComments(shader));\r\n\r\n\r\n\r\n\r\n        const simplifyComplexData = () => {\r\n\r\n            const objById = descriptor.__DEBUG__.objectById;\r\n            const objByName = descriptor.__DEBUG__.objectByName;\r\n\r\n            let o, name, newName, n;\r\n            let result = [];\r\n\r\n\r\n            for (let i = 0; i < objById.length; i++) {\r\n                o = { ...objById[i] };\r\n\r\n                if (o.type == \"mat4x4<f32>\") {\r\n                    name = o.newName;\r\n                    newName = name + \"_m4\"\r\n                    o.isMatrix = true;\r\n                    o.realType = o.type;\r\n                    o.type = \"vec4<f32>\";\r\n\r\n                    objByName[name] = undefined;\r\n                    delete objByName[name];\r\n\r\n                    n = newName + \"0\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"1\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"2\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"3\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                } else if (o.type == \"mat3x3<f32>\") {\r\n                    name = o.newName;\r\n                    newName = name + \"_m3\"\r\n                    o.isMatrix = true;\r\n                    o.realType = o.type;\r\n                    o.type = \"vec3<f32>\";\r\n\r\n                    objByName[name] = undefined;\r\n                    delete objByName[name];\r\n\r\n                    n = newName + \"0\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"1\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"2\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n\r\n                    n = newName + \"3\";\r\n                    objByName[n] = { ...o, newName: n };\r\n                    result.push(objByName[n])\r\n                } else if (o.isArray) {\r\n\r\n                    const arrayOfMatrix = o.type.includes(\"mat\");\r\n                    const len = o.len;\r\n\r\n                    name = o.newName;\r\n                    newName = name + \"_ar\"\r\n                    o.isMatrix = false;\r\n                    o.realType = o.type;\r\n                    o.type = \"vec4<f32>\";\r\n                    if (o.realType.includes(\"i32\")) o.type = \"vec4<i32>\";\r\n                    else if (o.realType.includes(\"u32\")) o.type = \"vec4<u32>\";\r\n\r\n                    objByName[name] = undefined;\r\n                    delete objByName[name];\r\n\r\n                    if (arrayOfMatrix) {\r\n\r\n\r\n                        objByName[name] = undefined;\r\n                        delete objByName[name];\r\n\r\n                        for (let j = 0; j < len; j++) {\r\n\r\n                            n = newName + j + \"_m0\";\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n\r\n                            n = newName + j + \"_m1\";\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n\r\n                            n = newName + j + \"_m2\";\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n\r\n                            n = newName + j + \"_m3\";\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n\r\n\r\n                        }\r\n\r\n\r\n\r\n                    } else {\r\n\r\n\r\n\r\n                        for (let i = 0; i < len; i++) {\r\n                            n = newName + i;\r\n                            objByName[n] = { ...o, newName: n };\r\n                            result.push(objByName[n])\r\n                        }\r\n\r\n\r\n                    }\r\n\r\n\r\n\r\n                } else {\r\n                    result.push(o);\r\n                }\r\n            }\r\n\r\n            descriptor.__DEBUG__.objectById = result;\r\n        }\r\n\r\n        simplifyComplexData()\r\n\r\n\r\n        return descriptor;\r\n\r\n\r\n    }\r\n\r\n\r\n    public parse(descriptor: any, target: \"render\" | \"compute\" | \"bindgroup\", drawConfig?: DrawConfig) {\r\n\r\n        this.targetIsBindgroup = target === \"bindgroup\";\r\n\r\n        if (target === \"bindgroup\") {\r\n            descriptor = this.parseBindgroupEntries(descriptor);\r\n        } else {\r\n\r\n            const debug = this.parseDebugValues(descriptor);\r\n\r\n            descriptor = this.firstPass(descriptor, target, drawConfig);\r\n            descriptor = this.parseHighLevelObj(descriptor);\r\n            descriptor = this.findAndFixRepetitionInDataStructure(descriptor);\r\n\r\n            if (debug.nb != 0) {\r\n                descriptor.__DEBUG__ = debug;\r\n                descriptor = this.parseVertexShaderDebug(descriptor);\r\n            }\r\n\r\n            //console.log(descriptor);\r\n        }\r\n\r\n        return descriptor;\r\n    }\r\n\r\n    private static instance: HighLevelParser = null;\r\n    public static parse(descriptor: any, target: \"render\" | \"compute\" | \"bindgroup\", drawConfig?: DrawConfig) {\r\n        if (!this.instance) this.instance = new HighLevelParser();\r\n        //console.log(\"highLevelParser = \", this.instance)\r\n        return this.instance.parse(descriptor, target, drawConfig);\r\n    }\r\n\r\n}"
      }
    ],
    "IRenderer": [
      {
        "objectType": "interface",
        "name": "IRenderer",
        "methods": [
          {
            "objectType": "method",
            "name": "addPipeline",
            "returnType": "void",
            "params": [
              {
                "name": "pipeline",
                "type": "RenderPipeline"
              },
              {
                "name": "offset",
                "type": "number"
              }
            ],
            "visibility": "public",
            "rawText": "addPipeline(pipeline: RenderPipeline, offset?: number): void;"
          },
          {
            "objectType": "method",
            "name": "resize",
            "returnType": "any",
            "params": [
              {
                "name": "w",
                "type": "number"
              },
              {
                "name": "h",
                "type": "number"
              }
            ],
            "visibility": "public",
            "rawText": "resize(w: number, h: number);"
          },
          {
            "objectType": "method",
            "name": "destroy",
            "returnType": "void",
            "visibility": "public",
            "rawText": "destroy(): void;"
          },
          {
            "objectType": "method",
            "name": "update",
            "returnType": "void",
            "visibility": "public",
            "rawText": "update(): void;"
          }
        ],
        "properties": [
          {
            "objectType": "property",
            "name": "renderPipelines",
            "type": "RenderPipeline[]",
            "get": true,
            "set": false,
            "visibility": "public",
            "rawText": "get renderPipelines(): RenderPipeline[];"
          },
          {
            "objectType": "property",
            "name": "canvas",
            "type": "HTMLCanvasElement",
            "get": true,
            "set": false,
            "visibility": "public",
            "rawText": "get canvas(): HTMLCanvasElement;"
          },
          {
            "objectType": "property",
            "name": "resized",
            "type": "boolean",
            "get": true,
            "set": false,
            "visibility": "public",
            "rawText": "get resized(): boolean;"
          },
          {
            "objectType": "property",
            "name": "width",
            "type": "number",
            "get": true,
            "set": false,
            "visibility": "public",
            "rawText": "get width(): number;"
          },
          {
            "objectType": "property",
            "name": "height",
            "type": "number",
            "get": true,
            "set": false,
            "visibility": "public",
            "rawText": "get height(): number;"
          },
          {
            "objectType": "property",
            "name": "texture",
            "type": "GPUTexture",
            "get": true,
            "set": false,
            "visibility": "public",
            "rawText": "get texture(): GPUTexture;"
          },
          {
            "objectType": "property",
            "name": "view",
            "type": "GPUTextureView",
            "get": true,
            "set": false,
            "visibility": "public",
            "rawText": "get view(): GPUTextureView;"
          },
          {
            "objectType": "property",
            "name": "frameId",
            "type": "number",
            "get": true,
            "set": false,
            "visibility": "public",
            "rawText": "get frameId(): number;"
          },
          {
            "objectType": "property",
            "name": "commandEncoder",
            "type": "GPUCommandEncoder",
            "get": true,
            "set": false,
            "visibility": "public",
            "rawText": "get commandEncoder(): GPUCommandEncoder;"
          }
        ],
        "filePath": "xGPU.IRenderer",
        "rawText": "export interface IRenderer {\r\n\r\n    addPipeline(pipeline: RenderPipeline, offset?: number): void;\r\n    resize(w: number, h: number);\r\n    destroy(): void;\r\n    update(): void;\r\n\r\n    get renderPipelines(): RenderPipeline[];\r\n    get canvas(): HTMLCanvasElement;\r\n    get resized(): boolean;\r\n    get width(): number;\r\n    get height(): number;\r\n    get texture(): GPUTexture;\r\n    get view(): GPUTextureView;\r\n    get frameId(): number;\r\n    get commandEncoder(): GPUCommandEncoder;\r\n\r\n}"
      }
    ],
    "PrimitiveType": [
      {
        "objectType": "type",
        "name": "PrimitiveType",
        "type": "PrimitiveType",
        "rawText": "export type PrimitiveType = PrimitiveFloatUniform | PrimitiveIntUniform | PrimitiveUintUniform;"
      },
      {
        "objectType": "class",
        "name": "PrimitiveFloatUniform",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "Float32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "name",
              "type": "string",
              "visibility": "public",
              "rawText": "public name: string;"
            },
            {
              "objectType": "property",
              "name": "type",
              "type": "GPUType",
              "visibility": "public",
              "rawText": "public type: GPUType;"
            },
            {
              "objectType": "property",
              "name": "startId",
              "type": "number",
              "visibility": "public",
              "rawText": "public startId: number = 0;"
            },
            {
              "objectType": "property",
              "name": "globalStartId",
              "type": "number",
              "visibility": "public",
              "rawText": "public globalStartId:number = 0;"
            },
            {
              "objectType": "property",
              "name": "onChange",
              "type": "() => void",
              "visibility": "public",
              "rawText": "public onChange: () => void;"
            },
            {
              "objectType": "property",
              "name": "mustBeTransfered",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get mustBeTransfered(): boolean { return this._mustBeTransfered; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "uniformBuffer",
              "type": "UniformBuffer",
              "visibility": "public",
              "rawText": "public uniformBuffer: UniformBuffer;"
            },
            {
              "objectType": "property",
              "name": "propertyNames",
              "type": "string[]",
              "visibility": "public",
              "rawText": "public propertyNames: string[];"
            },
            {
              "objectType": "property",
              "name": "createVariableInsideMain",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public createVariableInsideMain: boolean = false;"
            },
            {
              "objectType": "property",
              "name": "className",
              "type": "string",
              "visibility": "public",
              "rawText": "public className: string;"
            },
            {
              "objectType": "property",
              "name": "definition",
              "type": "{ type: string; values: Float32Array; name?: string; }",
              "visibility": "public",
              "rawText": "public get definition():{\r\n        type:string,\r\n        values:Float32Array,\r\n        name?:string\r\n    }{\r\n        return {type:this.constructor.name,values:this,name:this.name}\r\n    }",
              "get": true
            }
          ],
          "protected": [
            {
              "objectType": "property",
              "name": "_mustBeTransfered",
              "type": "boolean",
              "visibility": "protected",
              "rawText": "protected _mustBeTransfered: boolean = true;"
            },
            {
              "objectType": "property",
              "name": "eventListeners",
              "type": "any",
              "visibility": "protected",
              "rawText": "protected eventListeners: any = {};"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "clone",
              "returnType": "PrimitiveFloatUniform",
              "visibility": "public",
              "rawText": "public clone(): PrimitiveFloatUniform {\r\n        const o = new PrimitiveFloatUniform(this.type.rawType, this as Float32Array, this.createVariableInsideMain);\r\n        o.propertyNames = this.propertyNames;\r\n        o.className = this.className;\r\n        o.name = this.name;\r\n        o.startId = this.startId;\r\n\r\n        //for (let z in this) o[z] = this[z];\r\n        return o;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "initStruct",
              "returnType": "void",
              "params": [
                {
                  "name": "propertyNames",
                  "type": "string[]"
                },
                {
                  "name": "createVariableInsideMain",
                  "type": "boolean"
                }
              ],
              "visibility": "public",
              "rawText": "public initStruct(propertyNames: string[], createVariableInsideMain: boolean = false) {\r\n        if (this.type.isArray || this.type.isMatrix) throw new Error(\"initStruct doesn't accept array or matrix\");\r\n        this.propertyNames = propertyNames;\r\n        this.createVariableInsideMain = createVariableInsideMain;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "createStruct",
              "returnType": "string",
              "visibility": "public",
              "rawText": "public createStruct(): string {\r\n\r\n        //let result = \"struct \" + this.constructor.name + \" {\\n\";\r\n        let result = \"struct \" + this.className + \" {\\n\";\r\n        for (let i = 0; i < this.propertyNames.length; i++) {\r\n            result += \"   \" + this.propertyNames[i] + \":f32,\\n\";\r\n        }\r\n        result += \"}\\n\"\r\n        return result;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "set",
              "returnType": "void",
              "params": [
                {
                  "name": "m",
                  "type": "Float32Array"
                },
                {
                  "name": "offset",
                  "type": "number"
                }
              ],
              "visibility": "public",
              "rawText": "public override set(m: Float32Array, offset?: number) {\r\n        super.set(m, offset);\r\n        this.mustBeTransfered = true;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "createVariable",
              "returnType": "string",
              "params": [
                {
                  "name": "uniformBufferName",
                  "type": "string"
                },
                {
                  "name": "name",
                  "type": "string"
                }
              ],
              "visibility": "public",
              "rawText": "public createVariable(uniformBufferName: string, name?: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n\r\n        if (!name) name = this.name;\r\n\r\n        let type = this.className;\r\n        if (type === \"Float\") type = \"f32\";\r\n        if (type === \"Vec2\") type = \"vec2<f32>\";\r\n        if (type === \"Vec3\") type = \"vec3<f32>\";\r\n        if (type === \"Vec4\") type = \"vec4<f32>\";\r\n\r\n        const res: string = \"   var \" + name + \":\" + type + \" = \" + uniformBufferName + \".\" + name + \";\\n\";\r\n        //console.log(\"createVariable = \", res);\r\n\r\n        return res;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public update() {\r\n      \r\n     }"
            },
            {
              "objectType": "method",
              "name": "updateStartIdFromParentToChildren",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n    }"
            },
            {
              "objectType": "method",
              "name": "addEventListener",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "callback",
                  "type": "(dispatcher: PrimitiveFloatUniform, data?: any) => void"
                }
              ],
              "visibility": "public",
              "rawText": "public addEventListener(eventName: string, callback: (dispatcher: PrimitiveFloatUniform, data?: any) => void) {\r\n        if (!this.eventListeners[eventName]) this.eventListeners[eventName] = [];\r\n        this.eventListeners[eventName].push(callback);\r\n    }"
            },
            {
              "objectType": "method",
              "name": "removeEventListener",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "callback",
                  "type": "(dispatcher: PrimitiveFloatUniform, data?: any) => void"
                }
              ],
              "visibility": "public",
              "rawText": "public removeEventListener(eventName: string, callback: (dispatcher: PrimitiveFloatUniform, data?: any) => void) {\r\n        if (this.eventListeners[eventName]) {\r\n            const id = this.eventListeners[eventName].indexOf(callback);\r\n            if (id != -1) {\r\n                this.eventListeners[eventName].splice(id, 1);\r\n            }\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "dispatchEvent",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "eventData",
                  "type": "any"
                }
              ],
              "visibility": "public",
              "rawText": "public dispatchEvent(eventName: string, eventData?: any) {\r\n        if (this.eventListeners[eventName]) {\r\n            this.eventListeners[eventName].forEach(callback => {\r\n                callback(this, eventData);\r\n            });\r\n        }\r\n    }"
            }
          ]
        },
        "statics": {
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "ON_CHANGE",
                "type": "string",
                "visibility": "public",
                "rawText": "public static ON_CHANGE:string = \"ON_CHANGE\";"
              },
              {
                "objectType": "property",
                "name": "ON_CHANGED",
                "type": "string",
                "visibility": "public",
                "rawText": "public static ON_CHANGED: string = \"ON_CHANGED\";"
              }
            ]
          }
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "type",
              "type": "string"
            },
            {
              "name": "val",
              "type": "Float32Array | number[]"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(type: string, val: number[] | Float32Array, createLocalVariable: boolean = false) {\r\n        super(val);\r\n        this.type = new GPUType(type);\r\n        this.createVariableInsideMain = createLocalVariable;\r\n        this.className = this.constructor.name;\r\n    }"
        },
        "rawText": "export class PrimitiveFloatUniform extends Float32Array {\r\n\r\n\r\n\r\n\r\n\r\n\r\n    public static ON_CHANGE:string = \"ON_CHANGE\";\r\n    public static ON_CHANGED: string = \"ON_CHANGED\";\r\n\r\n\r\n    //public uniform: Uniform;\r\n    public name: string;\r\n    public type: GPUType;\r\n    public startId: number = 0;\r\n    public globalStartId:number = 0;\r\n\r\n    public onChange: () => void;\r\n\r\n    \r\n    \r\n    protected _mustBeTransfered: boolean = true;\r\n    \r\n    public get mustBeTransfered(): boolean { return this._mustBeTransfered; }\r\n    public set mustBeTransfered(b: boolean) {\r\n\r\n        //if(this.name == \"timeBytes\"){\r\n        //    console.warn(this.name,this._mustBeTransfered,b);\r\n        //}\r\n        if (b != this._mustBeTransfered) {\r\n\r\n            //if(b) this.mustTriggerChangeEvent = true;\r\n            //else this.mustTriggerChangedEvent = true; \r\n\r\n            if(b) this.dispatchEvent(PrimitiveFloatUniform.ON_CHANGE);\r\n            else this.dispatchEvent(PrimitiveFloatUniform.ON_CHANGED);\r\n           \r\n            //if (!b && this.onChange) this.onChange();\r\n            this._mustBeTransfered = b;\r\n        }\r\n    }\r\n    \r\n   //public mustBeTransfered:boolean = true;\r\n\r\n\r\n    public uniformBuffer: UniformBuffer;\r\n\r\n    public propertyNames: string[];\r\n    public createVariableInsideMain: boolean = false;\r\n\r\n    public className: string;\r\n\r\n    constructor(type: string, val: number[] | Float32Array, createLocalVariable: boolean = false) {\r\n        super(val);\r\n        this.type = new GPUType(type);\r\n        this.createVariableInsideMain = createLocalVariable;\r\n        this.className = this.constructor.name;\r\n    }\r\n\r\n    public clone(): PrimitiveFloatUniform {\r\n        const o = new PrimitiveFloatUniform(this.type.rawType, this as Float32Array, this.createVariableInsideMain);\r\n        o.propertyNames = this.propertyNames;\r\n        o.className = this.className;\r\n        o.name = this.name;\r\n        o.startId = this.startId;\r\n\r\n        //for (let z in this) o[z] = this[z];\r\n        return o;\r\n    }\r\n\r\n    public initStruct(propertyNames: string[], createVariableInsideMain: boolean = false) {\r\n        if (this.type.isArray || this.type.isMatrix) throw new Error(\"initStruct doesn't accept array or matrix\");\r\n        this.propertyNames = propertyNames;\r\n        this.createVariableInsideMain = createVariableInsideMain;\r\n    }\r\n\r\n    public createStruct(): string {\r\n\r\n        //let result = \"struct \" + this.constructor.name + \" {\\n\";\r\n        let result = \"struct \" + this.className + \" {\\n\";\r\n        for (let i = 0; i < this.propertyNames.length; i++) {\r\n            result += \"   \" + this.propertyNames[i] + \":f32,\\n\";\r\n        }\r\n        result += \"}\\n\"\r\n        return result;\r\n    }\r\n\r\n    public override set(m: Float32Array, offset?: number) {\r\n        super.set(m, offset);\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n\r\n    public createVariable(uniformBufferName: string, name?: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n\r\n        if (!name) name = this.name;\r\n\r\n        let type = this.className;\r\n        if (type === \"Float\") type = \"f32\";\r\n        if (type === \"Vec2\") type = \"vec2<f32>\";\r\n        if (type === \"Vec3\") type = \"vec3<f32>\";\r\n        if (type === \"Vec4\") type = \"vec4<f32>\";\r\n\r\n        const res: string = \"   var \" + name + \":\" + type + \" = \" + uniformBufferName + \".\" + name + \";\\n\";\r\n        //console.log(\"createVariable = \", res);\r\n\r\n        return res;\r\n    }\r\n\r\n   \r\n\r\n\r\n    public update() {\r\n      \r\n     }\r\n\r\n     public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n    }\r\n\r\n\r\n    //--------- EVENT DISPATCHER CLASS (that I can't extends because we already extends Float32Array)----\r\n    protected eventListeners: any = {};\r\n    public addEventListener(eventName: string, callback: (dispatcher: PrimitiveFloatUniform, data?: any) => void) {\r\n        if (!this.eventListeners[eventName]) this.eventListeners[eventName] = [];\r\n        this.eventListeners[eventName].push(callback);\r\n    }\r\n    public removeEventListener(eventName: string, callback: (dispatcher: PrimitiveFloatUniform, data?: any) => void) {\r\n        if (this.eventListeners[eventName]) {\r\n            const id = this.eventListeners[eventName].indexOf(callback);\r\n            if (id != -1) {\r\n                this.eventListeners[eventName].splice(id, 1);\r\n            }\r\n        }\r\n    }\r\n    public dispatchEvent(eventName: string, eventData?: any) {\r\n        if (this.eventListeners[eventName]) {\r\n            this.eventListeners[eventName].forEach(callback => {\r\n                callback(this, eventData);\r\n            });\r\n        }\r\n    }\r\n\r\n    //---------------------------------------------------------------------------------------------\r\n\r\n    \r\n    public get definition():{\r\n        type:string,\r\n        values:Float32Array,\r\n        name?:string\r\n    }{\r\n        return {type:this.constructor.name,values:this,name:this.name}\r\n    }\r\n}"
      },
      {
        "objectType": "class",
        "name": "PrimitiveIntUniform",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "Int32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "name",
              "type": "string",
              "visibility": "public",
              "rawText": "public name: string;"
            },
            {
              "objectType": "property",
              "name": "type",
              "type": "GPUType",
              "visibility": "public",
              "rawText": "public type: GPUType;"
            },
            {
              "objectType": "property",
              "name": "startId",
              "type": "number",
              "visibility": "public",
              "rawText": "public startId: number = 0;"
            },
            {
              "objectType": "property",
              "name": "globalStartId",
              "type": "number",
              "visibility": "public",
              "rawText": "public globalStartId:number = 0;"
            },
            {
              "objectType": "property",
              "name": "onChange",
              "type": "() => void",
              "visibility": "public",
              "rawText": "public onChange: () => void;"
            },
            {
              "objectType": "property",
              "name": "mustBeTransfered",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get mustBeTransfered(): boolean { return this._mustBeTransfered; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "uniformBuffer",
              "type": "UniformBuffer",
              "visibility": "public",
              "rawText": "public uniformBuffer: UniformBuffer;"
            },
            {
              "objectType": "property",
              "name": "propertyNames",
              "type": "string[]",
              "visibility": "public",
              "rawText": "public propertyNames: string[];"
            },
            {
              "objectType": "property",
              "name": "createVariableInsideMain",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public createVariableInsideMain: boolean = false;"
            },
            {
              "objectType": "property",
              "name": "className",
              "type": "string",
              "visibility": "public",
              "rawText": "public className: string;"
            },
            {
              "objectType": "property",
              "name": "definition",
              "type": "{ type: string; values: Int32Array; name?: string; }",
              "visibility": "public",
              "rawText": "public get definition():{\r\n        type:string,\r\n        values:Int32Array,\r\n        name?:string\r\n    }{\r\n        return {type:this.constructor.name,values:this,name:this.name}\r\n    }",
              "get": true
            }
          ],
          "protected": [
            {
              "objectType": "property",
              "name": "_mustBeTransfered",
              "type": "boolean",
              "visibility": "protected",
              "rawText": "protected _mustBeTransfered: boolean = true;"
            },
            {
              "objectType": "property",
              "name": "eventListeners",
              "type": "any",
              "visibility": "protected",
              "rawText": "protected eventListeners: any = {};"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "clone",
              "returnType": "PrimitiveIntUniform",
              "visibility": "public",
              "rawText": "public clone(): PrimitiveIntUniform {\r\n        return new PrimitiveIntUniform(this.type.rawType, this as Int32Array, this.createVariableInsideMain)\r\n    }"
            },
            {
              "objectType": "method",
              "name": "initStruct",
              "returnType": "void",
              "params": [
                {
                  "name": "propertyNames",
                  "type": "string[]"
                },
                {
                  "name": "createVariableInsideMain",
                  "type": "boolean"
                }
              ],
              "visibility": "public",
              "rawText": "public initStruct(propertyNames: string[], createVariableInsideMain: boolean = false) {\r\n        if (this.type.isArray || this.type.isMatrix) throw new Error(\"initStruct doesn't accept array or matrix\");\r\n        this.propertyNames = propertyNames;\r\n        this.createVariableInsideMain = createVariableInsideMain;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "createStruct",
              "returnType": "string",
              "visibility": "public",
              "rawText": "public createStruct(): string {\r\n\r\n        let result = \"struct \" + this.constructor.name + \" {\\n\";\r\n        for (let i = 0; i < this.propertyNames.length; i++) {\r\n            result += \"   \" + this.propertyNames[i] + \":i32,\\n\";\r\n        }\r\n        result += \"}\\n\"\r\n        return result;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "updateStartIdFromParentToChildren",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n    }"
            },
            {
              "objectType": "method",
              "name": "createVariable",
              "returnType": "string",
              "params": [
                {
                  "name": "uniformBufferName",
                  "type": "string"
                }
              ],
              "visibility": "public",
              "rawText": "public createVariable(uniformBufferName: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n\r\n        let type = this.className;\r\n        if (type === \"Int\") type = \"i32\";\r\n        if (type === \"IVec2\") type = \"vec2<i32>\";\r\n        if (type === \"IVec3\") type = \"vec3<i32>\";\r\n        if (type === \"IVec4\") type = \"vec4<i32>\";\r\n\r\n        return \"   var \" + this.name + \":\" + type + \" = \" + uniformBufferName + \".\" + this.name + \";\\n\"\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public update() { }"
            },
            {
              "objectType": "method",
              "name": "addEventListener",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "callback",
                  "type": "(dispatcher: PrimitiveIntUniform, data?: any) => void"
                }
              ],
              "visibility": "public",
              "rawText": "public addEventListener(eventName: string, callback: (dispatcher: PrimitiveIntUniform, data?: any) => void) {\r\n        if (!this.eventListeners[eventName]) this.eventListeners[eventName] = [];\r\n        this.eventListeners[eventName].push(callback);\r\n    }"
            },
            {
              "objectType": "method",
              "name": "removeEventListener",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "callback",
                  "type": "(dispatcher: PrimitiveIntUniform, data?: any) => void"
                }
              ],
              "visibility": "public",
              "rawText": "public removeEventListener(eventName: string, callback: (dispatcher: PrimitiveIntUniform, data?: any) => void) {\r\n        if (this.eventListeners[eventName]) {\r\n            const id = this.eventListeners[eventName].indexOf(callback);\r\n            if (id != -1) {\r\n                this.eventListeners[eventName].splice(id, 1);\r\n            }\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "dispatchEvent",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "eventData",
                  "type": "any"
                }
              ],
              "visibility": "public",
              "rawText": "public dispatchEvent(eventName: string, eventData?: any) {\r\n        if (this.eventListeners[eventName]) {\r\n            this.eventListeners[eventName].forEach(callback => {\r\n                callback(this, eventData);\r\n            });\r\n        }\r\n    }"
            }
          ]
        },
        "statics": {
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "ON_CHANGE",
                "type": "string",
                "visibility": "public",
                "rawText": "public static ON_CHANGE:string = \"ON_CHANGE\";"
              },
              {
                "objectType": "property",
                "name": "ON_CHANGED",
                "type": "string",
                "visibility": "public",
                "rawText": "public static ON_CHANGED: string = \"ON_CHANGED\";"
              }
            ]
          }
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "type",
              "type": "string"
            },
            {
              "name": "val",
              "type": "number[] | Int32Array"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(type: string, val: number[] | Int32Array, createLocalVariable: boolean = false) {\r\n        super(val);\r\n        this.type = new GPUType(type);\r\n        this.createVariableInsideMain = createLocalVariable;\r\n        this.className = this.constructor.name;\r\n    }"
        },
        "rawText": "export class PrimitiveIntUniform extends Int32Array {\r\n\r\n\r\n\r\n    public static ON_CHANGE:string = \"ON_CHANGE\";\r\n    public static ON_CHANGED: string = \"ON_CHANGED\";\r\n\r\n    public name: string;\r\n    public type: GPUType;\r\n    public startId: number = 0;\r\n    public globalStartId:number = 0;\r\n\r\n    public onChange: () => void;\r\n    protected _mustBeTransfered: boolean = true;\r\n    public get mustBeTransfered(): boolean { return this._mustBeTransfered; }\r\n    public set mustBeTransfered(b: boolean) {\r\n        if (b != this._mustBeTransfered) {\r\n            if (!b) this.dispatchEvent(PrimitiveIntUniform.ON_CHANGED)\r\n            else this.dispatchEvent(PrimitiveIntUniform.ON_CHANGE);\r\n            //if (!b && this.onChange) this.onChange();\r\n            this._mustBeTransfered = b;\r\n        }\r\n    }\r\n\r\n    public uniformBuffer: UniformBuffer;\r\n\r\n    public propertyNames: string[];\r\n    public createVariableInsideMain: boolean = false;;\r\n    public className: string;\r\n\r\n    constructor(type: string, val: number[] | Int32Array, createLocalVariable: boolean = false) {\r\n        super(val);\r\n        this.type = new GPUType(type);\r\n        this.createVariableInsideMain = createLocalVariable;\r\n        this.className = this.constructor.name;\r\n    }\r\n\r\n    public clone(): PrimitiveIntUniform {\r\n        return new PrimitiveIntUniform(this.type.rawType, this as Int32Array, this.createVariableInsideMain)\r\n    }\r\n\r\n    public initStruct(propertyNames: string[], createVariableInsideMain: boolean = false) {\r\n        if (this.type.isArray || this.type.isMatrix) throw new Error(\"initStruct doesn't accept array or matrix\");\r\n        this.propertyNames = propertyNames;\r\n        this.createVariableInsideMain = createVariableInsideMain;\r\n    }\r\n\r\n    public createStruct(): string {\r\n\r\n        let result = \"struct \" + this.constructor.name + \" {\\n\";\r\n        for (let i = 0; i < this.propertyNames.length; i++) {\r\n            result += \"   \" + this.propertyNames[i] + \":i32,\\n\";\r\n        }\r\n        result += \"}\\n\"\r\n        return result;\r\n    }\r\n\r\n    public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n    }\r\n\r\n    public createVariable(uniformBufferName: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n\r\n        let type = this.className;\r\n        if (type === \"Int\") type = \"i32\";\r\n        if (type === \"IVec2\") type = \"vec2<i32>\";\r\n        if (type === \"IVec3\") type = \"vec3<i32>\";\r\n        if (type === \"IVec4\") type = \"vec4<i32>\";\r\n\r\n        return \"   var \" + this.name + \":\" + type + \" = \" + uniformBufferName + \".\" + this.name + \";\\n\"\r\n    }\r\n\r\n    /*\r\n    public feedbackVertexId: number = 0;\r\n    public feedbackInstanceId: number = 0;\r\n    public setFeedback(vertexId: number, instanceId: number): PrimitiveIntUniform {\r\n        this.feedbackVertexId = vertexId;\r\n        this.feedbackInstanceId = instanceId;\r\n        return this;\r\n    }*/\r\n\r\n    public update() { }\r\n\r\n    //--------- EVENT DISPATCHER CLASS (that I can't extends because we already extends Int32Array)----\r\n    protected eventListeners: any = {};\r\n    public addEventListener(eventName: string, callback: (dispatcher: PrimitiveIntUniform, data?: any) => void) {\r\n        if (!this.eventListeners[eventName]) this.eventListeners[eventName] = [];\r\n        this.eventListeners[eventName].push(callback);\r\n    }\r\n    public removeEventListener(eventName: string, callback: (dispatcher: PrimitiveIntUniform, data?: any) => void) {\r\n        if (this.eventListeners[eventName]) {\r\n            const id = this.eventListeners[eventName].indexOf(callback);\r\n            if (id != -1) {\r\n                this.eventListeners[eventName].splice(id, 1);\r\n            }\r\n        }\r\n    }\r\n    public dispatchEvent(eventName: string, eventData?: any) {\r\n        if (this.eventListeners[eventName]) {\r\n            this.eventListeners[eventName].forEach(callback => {\r\n                callback(this, eventData);\r\n            });\r\n        }\r\n    }\r\n\r\n    \r\n    //---------------------------------------------------------------------------------------------\r\n\r\n    \r\n    public get definition():{\r\n        type:string,\r\n        values:Int32Array,\r\n        name?:string\r\n    }{\r\n        return {type:this.constructor.name,values:this,name:this.name}\r\n    }\r\n}"
      },
      {
        "objectType": "class",
        "name": "PrimitiveUintUniform",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "Uint32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "name",
              "type": "string",
              "visibility": "public",
              "rawText": "public name: string;"
            },
            {
              "objectType": "property",
              "name": "type",
              "type": "GPUType",
              "visibility": "public",
              "rawText": "public type: GPUType;"
            },
            {
              "objectType": "property",
              "name": "startId",
              "type": "number",
              "visibility": "public",
              "rawText": "public startId: number = 0;"
            },
            {
              "objectType": "property",
              "name": "globalStartId",
              "type": "number",
              "visibility": "public",
              "rawText": "public globalStartId:number = 0;"
            },
            {
              "objectType": "property",
              "name": "uniformBuffer",
              "type": "UniformBuffer",
              "visibility": "public",
              "rawText": "public uniformBuffer: UniformBuffer;"
            },
            {
              "objectType": "property",
              "name": "onChange",
              "type": "() => void",
              "visibility": "public",
              "rawText": "public onChange: () => void;"
            },
            {
              "objectType": "property",
              "name": "mustBeTransfered",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get mustBeTransfered(): boolean { return this._mustBeTransfered; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "propertyNames",
              "type": "string[]",
              "visibility": "public",
              "rawText": "public propertyNames: string[];"
            },
            {
              "objectType": "property",
              "name": "createVariableInsideMain",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public createVariableInsideMain: boolean = false;"
            },
            {
              "objectType": "property",
              "name": "className",
              "type": "string",
              "visibility": "public",
              "rawText": "public className: string;"
            },
            {
              "objectType": "property",
              "name": "definition",
              "type": "{ type: string; values: Uint32Array; name?: string; }",
              "visibility": "public",
              "rawText": "public get definition():{\r\n        type:string,\r\n        values:Uint32Array,\r\n        name?:string\r\n    }{\r\n        return {type:this.constructor.name,values:this,name:this.name}\r\n    }",
              "get": true
            }
          ],
          "protected": [
            {
              "objectType": "property",
              "name": "_mustBeTransfered",
              "type": "boolean",
              "visibility": "protected",
              "rawText": "protected _mustBeTransfered: boolean = true;"
            },
            {
              "objectType": "property",
              "name": "eventListeners",
              "type": "any",
              "visibility": "protected",
              "rawText": "protected eventListeners: any = {};"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "clone",
              "returnType": "PrimitiveUintUniform",
              "visibility": "public",
              "rawText": "public clone(): PrimitiveUintUniform {\r\n        return new PrimitiveUintUniform(this.type.rawType, this as Uint32Array, this.createVariableInsideMain)\r\n    }"
            },
            {
              "objectType": "method",
              "name": "initStruct",
              "returnType": "void",
              "params": [
                {
                  "name": "propertyNames",
                  "type": "string[]"
                },
                {
                  "name": "createVariableInsideMain",
                  "type": "boolean"
                }
              ],
              "visibility": "public",
              "rawText": "public initStruct(propertyNames: string[], createVariableInsideMain: boolean = false) {\r\n        if (this.type.isArray || this.type.isMatrix) throw new Error(\"initStruct doesn't accept array or matrix\");\r\n        this.propertyNames = propertyNames;\r\n        this.createVariableInsideMain = createVariableInsideMain;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "createStruct",
              "returnType": "string",
              "visibility": "public",
              "rawText": "public createStruct(): string {\r\n\r\n        let result = \"struct \" + this.constructor.name + \" {\\n\";\r\n        for (let i = 0; i < this.propertyNames.length; i++) {\r\n            result += \"   \" + this.propertyNames[i] + \":u32,\\n\";\r\n        }\r\n        result += \"}\\n\"\r\n        return result;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "updateStartIdFromParentToChildren",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n    }"
            },
            {
              "objectType": "method",
              "name": "createVariable",
              "returnType": "string",
              "params": [
                {
                  "name": "uniformBufferName",
                  "type": "string"
                }
              ],
              "visibility": "public",
              "rawText": "public createVariable(uniformBufferName: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n\r\n        let type = this.className;\r\n        if (type === \"Uint\") type = \"u32\";\r\n        if (type === \"UVec2\") type = \"vec2<u32>\";\r\n        if (type === \"UVec3\") type = \"vec3<u32>\";\r\n        if (type === \"UVec4\") type = \"vec4<u32>\";\r\n\r\n\r\n        return \"   var \" + this.name + \":\" + type + \" = \" + uniformBufferName + \".\" + this.name + \";\\n\";\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public update() { }"
            },
            {
              "objectType": "method",
              "name": "addEventListener",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "callback",
                  "type": "(dispatcher: PrimitiveUintUniform, data?: any) => void"
                }
              ],
              "visibility": "public",
              "rawText": "public addEventListener(eventName: string, callback: (dispatcher: PrimitiveUintUniform, data?: any) => void) {\r\n        if (!this.eventListeners[eventName]) this.eventListeners[eventName] = [];\r\n        this.eventListeners[eventName].push(callback);\r\n    }"
            },
            {
              "objectType": "method",
              "name": "removeEventListener",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "callback",
                  "type": "(dispatcher: PrimitiveUintUniform, data?: any) => void"
                }
              ],
              "visibility": "public",
              "rawText": "public removeEventListener(eventName: string, callback: (dispatcher: PrimitiveUintUniform, data?: any) => void) {\r\n        if (this.eventListeners[eventName]) {\r\n            const id = this.eventListeners[eventName].indexOf(callback);\r\n            if (id != -1) {\r\n                this.eventListeners[eventName].splice(id, 1);\r\n            }\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "dispatchEvent",
              "returnType": "void",
              "params": [
                {
                  "name": "eventName",
                  "type": "string"
                },
                {
                  "name": "eventData",
                  "type": "any"
                }
              ],
              "visibility": "public",
              "rawText": "public dispatchEvent(eventName: string, eventData?: any) {\r\n        if (this.eventListeners[eventName]) {\r\n            this.eventListeners[eventName].forEach(callback => {\r\n                callback(this, eventData);\r\n            });\r\n        }\r\n    }"
            }
          ]
        },
        "statics": {
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "ON_CHANGE",
                "type": "string",
                "visibility": "public",
                "rawText": "public static ON_CHANGE:string = \"ON_CHANGE\";"
              },
              {
                "objectType": "property",
                "name": "ON_CHANGED",
                "type": "string",
                "visibility": "public",
                "rawText": "public static ON_CHANGED: string = \"ON_CHANGED\";"
              }
            ]
          }
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "type",
              "type": "string"
            },
            {
              "name": "val",
              "type": "number[] | Uint32Array"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(type: string, val: number[] | Uint32Array, createLocalVariable: boolean = false) {\r\n        super(val);\r\n        this.type = new GPUType(type);\r\n        this.createVariableInsideMain = createLocalVariable;\r\n        this.className = this.constructor.name;\r\n    }"
        },
        "rawText": "export class PrimitiveUintUniform extends Uint32Array {\r\n\r\n\r\n    public static ON_CHANGE:string = \"ON_CHANGE\";\r\n    public static ON_CHANGED: string = \"ON_CHANGED\";\r\n\r\n\r\n\r\n    public name: string;\r\n    public type: GPUType;\r\n    public startId: number = 0;\r\n    public globalStartId:number = 0;\r\n    public uniformBuffer: UniformBuffer;\r\n\r\n    public onChange: () => void;\r\n    protected _mustBeTransfered: boolean = true;\r\n    public get mustBeTransfered(): boolean { return this._mustBeTransfered; }\r\n    public set mustBeTransfered(b: boolean) {\r\n        if (b != this._mustBeTransfered) {\r\n            //if (!b && this.onChange) this.onChange();\r\n            if (!b) this.dispatchEvent(PrimitiveUintUniform.ON_CHANGED)\r\n            else this.dispatchEvent(PrimitiveUintUniform.ON_CHANGE);\r\n            this._mustBeTransfered = b;\r\n        }\r\n    }\r\n\r\n    public propertyNames: string[];\r\n    public createVariableInsideMain: boolean = false;;\r\n    public className: string;\r\n\r\n    constructor(type: string, val: number[] | Uint32Array, createLocalVariable: boolean = false) {\r\n        super(val);\r\n        this.type = new GPUType(type);\r\n        this.createVariableInsideMain = createLocalVariable;\r\n        this.className = this.constructor.name;\r\n    }\r\n\r\n    public clone(): PrimitiveUintUniform {\r\n        return new PrimitiveUintUniform(this.type.rawType, this as Uint32Array, this.createVariableInsideMain)\r\n    }\r\n\r\n    public initStruct(propertyNames: string[], createVariableInsideMain: boolean = false) {\r\n        if (this.type.isArray || this.type.isMatrix) throw new Error(\"initStruct doesn't accept array or matrix\");\r\n        this.propertyNames = propertyNames;\r\n        this.createVariableInsideMain = createVariableInsideMain;\r\n    }\r\n\r\n    public createStruct(): string {\r\n\r\n        let result = \"struct \" + this.constructor.name + \" {\\n\";\r\n        for (let i = 0; i < this.propertyNames.length; i++) {\r\n            result += \"   \" + this.propertyNames[i] + \":u32,\\n\";\r\n        }\r\n        result += \"}\\n\"\r\n        return result;\r\n    }\r\n\r\n    public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n    }\r\n\r\n    public createVariable(uniformBufferName: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n\r\n        let type = this.className;\r\n        if (type === \"Uint\") type = \"u32\";\r\n        if (type === \"UVec2\") type = \"vec2<u32>\";\r\n        if (type === \"UVec3\") type = \"vec3<u32>\";\r\n        if (type === \"UVec4\") type = \"vec4<u32>\";\r\n\r\n\r\n        return \"   var \" + this.name + \":\" + type + \" = \" + uniformBufferName + \".\" + this.name + \";\\n\";\r\n    }\r\n    /*\r\n    public feedbackVertexId: number = 0;\r\n    public feedbackInstanceId: number = 0;\r\n    public setFeedback(vertexId: number, instanceId: number): PrimitiveUintUniform {\r\n        this.feedbackVertexId = vertexId;\r\n        this.feedbackInstanceId = instanceId;\r\n        return this;\r\n    }\r\n    */\r\n\r\n    public update() { }\r\n\r\n    //--------- EVENT DISPATCHER CLASS (that I can't extends because we already extends Uint32Array)----\r\n    protected eventListeners: any = {};\r\n    public addEventListener(eventName: string, callback: (dispatcher: PrimitiveUintUniform, data?: any) => void) {\r\n        if (!this.eventListeners[eventName]) this.eventListeners[eventName] = [];\r\n        this.eventListeners[eventName].push(callback);\r\n    }\r\n    public removeEventListener(eventName: string, callback: (dispatcher: PrimitiveUintUniform, data?: any) => void) {\r\n        if (this.eventListeners[eventName]) {\r\n            const id = this.eventListeners[eventName].indexOf(callback);\r\n            if (id != -1) {\r\n                this.eventListeners[eventName].splice(id, 1);\r\n            }\r\n        }\r\n    }\r\n    public dispatchEvent(eventName: string, eventData?: any) {\r\n        if (this.eventListeners[eventName]) {\r\n            this.eventListeners[eventName].forEach(callback => {\r\n                callback(this, eventData);\r\n            });\r\n        }\r\n    }\r\n\r\n   \r\n    //---------------------------------------------------------------------------------------------\r\n\r\n    \r\n    public get definition():{\r\n        type:string,\r\n        values:Uint32Array,\r\n        name?:string\r\n    }{\r\n        return {type:this.constructor.name,values:this,name:this.name}\r\n    }\r\n}"
      },
      {
        "objectType": "class",
        "name": "Float",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveFloatUniform",
          "Float32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"f32\", [x], createLocalVariable);\r\n    }"
        },
        "rawText": "export class Float extends PrimitiveFloatUniform {\r\n\r\n    constructor(x: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"f32\", [x], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n    public get x(): number {\r\n        return this[0];\r\n    }\r\n    \r\n    \r\n}"
      },
      {
        "objectType": "class",
        "name": "Vec2",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveFloatUniform",
          "Float32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "y",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, y: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec2<f32>\", [x, y], createLocalVariable);\r\n    }"
        },
        "rawText": "export class Vec2 extends PrimitiveFloatUniform {\r\n\r\n    constructor(x: number = 0, y: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec2<f32>\", [x, y], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public get x(): number { return this[0]; }\r\n    public get y(): number { return this[1]; }\r\n\r\n    \r\n}"
      },
      {
        "objectType": "class",
        "name": "Vec3",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveFloatUniform",
          "Float32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "z",
              "type": "number",
              "visibility": "public",
              "rawText": "public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "y",
              "type": "number"
            },
            {
              "name": "z",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, y: number = 0, z: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec3<f32>\", [x, y, z], createLocalVariable);\r\n    }"
        },
        "rawText": "export class Vec3 extends PrimitiveFloatUniform {\r\n\r\n    constructor(x: number = 0, y: number = 0, z: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec3<f32>\", [x, y, z], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public get x(): number { return this[0]; }\r\n    public get y(): number { return this[1]; }\r\n    public get z(): number { return this[2]; }\r\n}"
      },
      {
        "objectType": "class",
        "name": "Vec4",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveFloatUniform",
          "Float32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "z",
              "type": "number",
              "visibility": "public",
              "rawText": "public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "w",
              "type": "number",
              "visibility": "public",
              "rawText": "public set w(n: number) {\r\n        this[3] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "y",
              "type": "number"
            },
            {
              "name": "z",
              "type": "number"
            },
            {
              "name": "w",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, y: number = 0, z: number = 0, w: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec4<f32>\", [x, y, z, w], createLocalVariable);\r\n    }"
        },
        "rawText": "export class Vec4 extends PrimitiveFloatUniform {\r\n\r\n    constructor(x: number = 0, y: number = 0, z: number = 0, w: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec4<f32>\", [x, y, z, w], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public set w(n: number) {\r\n        this[3] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public get x(): number { return this[0]; }\r\n    public get y(): number { return this[1]; }\r\n    public get z(): number { return this[2]; }\r\n    public get w(): number { return this[3]; }\r\n}"
      },
      {
        "objectType": "class",
        "name": "Int",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveIntUniform",
          "Int32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"i32\", [x], createLocalVariable);\r\n    }"
        },
        "rawText": "export class Int extends PrimitiveIntUniform {\r\n\r\n    constructor(x: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"i32\", [x], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public get x(): number { return this[0]; }\r\n\r\n}"
      },
      {
        "objectType": "class",
        "name": "IVec2",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveIntUniform",
          "Int32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "y",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, y: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec2<i32>\", [x, y], createLocalVariable);\r\n    }"
        },
        "rawText": "export class IVec2 extends PrimitiveIntUniform {\r\n\r\n    constructor(x: number = 0, y: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec2<i32>\", [x, y], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public get x(): number { return this[0]; }\r\n    public get y(): number { return this[1]; }\r\n}"
      },
      {
        "objectType": "class",
        "name": "IVec3",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveIntUniform",
          "Int32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "z",
              "type": "number",
              "visibility": "public",
              "rawText": "public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "y",
              "type": "number"
            },
            {
              "name": "z",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, y: number = 0, z: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec3<i32>\", [x, y, z], createLocalVariable);\r\n    }"
        },
        "rawText": "export class IVec3 extends PrimitiveIntUniform {\r\n\r\n    constructor(x: number = 0, y: number = 0, z: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec3<i32>\", [x, y, z], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public get x(): number { return this[0]; }\r\n    public get y(): number { return this[1]; }\r\n    public get z(): number { return this[2]; }\r\n\r\n}"
      },
      {
        "objectType": "class",
        "name": "IVec4",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveIntUniform",
          "Int32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "z",
              "type": "number",
              "visibility": "public",
              "rawText": "public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "w",
              "type": "number",
              "visibility": "public",
              "rawText": "public set w(n: number) {\r\n        this[3] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "y",
              "type": "number"
            },
            {
              "name": "z",
              "type": "number"
            },
            {
              "name": "w",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, y: number = 0, z: number = 0, w: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec4<i32>\", [x, y, z, w], createLocalVariable);\r\n    }"
        },
        "rawText": "export class IVec4 extends PrimitiveIntUniform {\r\n\r\n    constructor(x: number = 0, y: number = 0, z: number = 0, w: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec4<i32>\", [x, y, z, w], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public set w(n: number) {\r\n        this[3] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public get x(): number { return this[0]; }\r\n    public get y(): number { return this[1]; }\r\n    public get z(): number { return this[2]; }\r\n    public get w(): number { return this[3]; }\r\n}"
      },
      {
        "objectType": "class",
        "name": "Uint",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveUintUniform",
          "Uint32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"u32\", [x], createLocalVariable);\r\n    }"
        },
        "rawText": "export class Uint extends PrimitiveUintUniform {\r\n\r\n    constructor(x: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"u32\", [x], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public get x(): number { return this[0]; }\r\n\r\n}"
      },
      {
        "objectType": "class",
        "name": "UVec2",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveUintUniform",
          "Uint32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "y",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, y: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec2<u32>\", [x, y], createLocalVariable);\r\n    }"
        },
        "rawText": "export class UVec2 extends PrimitiveUintUniform {\r\n\r\n    constructor(x: number = 0, y: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec2<u32>\", [x, y], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public get x(): number { return this[0]; }\r\n    public get y(): number { return this[1]; }\r\n}"
      },
      {
        "objectType": "class",
        "name": "UVec3",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveUintUniform",
          "Uint32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "z",
              "type": "number",
              "visibility": "public",
              "rawText": "public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "y",
              "type": "number"
            },
            {
              "name": "z",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, y: number = 0, z: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec3<u32>\", [x, y, z], createLocalVariable);\r\n    }"
        },
        "rawText": "export class UVec3 extends PrimitiveUintUniform {\r\n\r\n    constructor(x: number = 0, y: number = 0, z: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec3<u32>\", [x, y, z], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public get x(): number { return this[0]; }\r\n    public get y(): number { return this[1]; }\r\n    public get z(): number { return this[2]; }\r\n}"
      },
      {
        "objectType": "class",
        "name": "UVec4",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveUintUniform",
          "Uint32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "z",
              "type": "number",
              "visibility": "public",
              "rawText": "public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            },
            {
              "objectType": "property",
              "name": "w",
              "type": "number",
              "visibility": "public",
              "rawText": "public set w(n: number) {\r\n        this[3] = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true,
              "get": true
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "x",
              "type": "number"
            },
            {
              "name": "y",
              "type": "number"
            },
            {
              "name": "z",
              "type": "number"
            },
            {
              "name": "w",
              "type": "number"
            },
            {
              "name": "createLocalVariable",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(x: number = 0, y: number = 0, z: number = 0, w: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec4<u32>\", [x, y, z, w], createLocalVariable);\r\n    }"
        },
        "rawText": "export class UVec4 extends PrimitiveUintUniform {\r\n\r\n    constructor(x: number = 0, y: number = 0, z: number = 0, w: number = 0, createLocalVariable: boolean = false) {\r\n        super(\"vec4<u32>\", [x, y, z, w], createLocalVariable);\r\n    }\r\n\r\n    public set x(n: number) {\r\n        this[0] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        this[1] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public set z(n: number) {\r\n        this[2] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public set w(n: number) {\r\n        this[3] = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public get x(): number { return this[0]; }\r\n    public get y(): number { return this[1]; }\r\n    public get z(): number { return this[2]; }\r\n    public get w(): number { return this[3]; }\r\n}"
      },
      {
        "objectType": "class",
        "name": "Vec4Array",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveFloatUniform",
          "Float32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "vec4Array",
              "type": "Vec4[]",
              "visibility": "public",
              "rawText": "public vec4Array: Vec4[];"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "updateStartIdFromParentToChildren",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n\r\n       \r\n        for(let i=0;i<this.vec4Array.length;i++){\r\n            this.vec4Array[i].globalStartId = this.globalStartId + this.vec4Array[i].startId;\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public update(): void {\r\n        \r\n        let mustBeTransfered = false;\r\n        let m: Vec4;\r\n        for (let i = 0; i < this.vec4Array.length; i++) {\r\n            m = this.vec4Array[i];\r\n            if(!m.name) m.name = this.name+\"#\"+i;\r\n            m.update();\r\n            if (m.mustBeTransfered) {\r\n               \r\n                mustBeTransfered = true;\r\n                this.set(m, i * 4);\r\n                m.mustBeTransfered = false;\r\n               \r\n            }\r\n        }\r\n\r\n        if(this.mustBeTransfered != mustBeTransfered){\r\n            this.mustBeTransfered = mustBeTransfered;\r\n        }\r\n        \r\n    }"
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "vec4Array_or_arrayLength",
              "type": "number | Vec4[]"
            }
          ],
          "rawText": "constructor(vec4Array_or_arrayLength: Vec4[]|number) {\r\n\r\n       let array:Vec4[];\r\n       if(typeof vec4Array_or_arrayLength != \"number\") array = vec4Array_or_arrayLength;\r\n       else {\r\n          array = [];\r\n          for(let i =0;i<vec4Array_or_arrayLength;i++) array[i] = new Vec4();\r\n       }\r\n\r\n\r\n        const len = array.length;\r\n\r\n        let buf: Float32Array = new Float32Array(len * 4);\r\n        for (let i = 0; i < len; i++) buf.set(array[i], i * 4);\r\n        let type: string = \"array<vec4<f32>,\" + array.length + \">\";\r\n        super(\"array<vec4<f32>,\" + array.length + \">\", buf)\r\n        this.className = type;\r\n        this.vec4Array = array;\r\n       \r\n        for(let i=0;i<this.vec4Array.length;i++){\r\n            this.vec4Array[i].addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.set(this.vec4Array[i], i * 4);\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n        \r\n    }"
        },
        "rawText": "export class Vec4Array extends PrimitiveFloatUniform {\r\n\r\n    public vec4Array: Vec4[];\r\n\r\n    constructor(vec4Array_or_arrayLength: Vec4[]|number) {\r\n\r\n       let array:Vec4[];\r\n       if(typeof vec4Array_or_arrayLength != \"number\") array = vec4Array_or_arrayLength;\r\n       else {\r\n          array = [];\r\n          for(let i =0;i<vec4Array_or_arrayLength;i++) array[i] = new Vec4();\r\n       }\r\n\r\n\r\n        const len = array.length;\r\n\r\n        let buf: Float32Array = new Float32Array(len * 4);\r\n        for (let i = 0; i < len; i++) buf.set(array[i], i * 4);\r\n        let type: string = \"array<vec4<f32>,\" + array.length + \">\";\r\n        super(\"array<vec4<f32>,\" + array.length + \">\", buf)\r\n        this.className = type;\r\n        this.vec4Array = array;\r\n       \r\n        for(let i=0;i<this.vec4Array.length;i++){\r\n            this.vec4Array[i].addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.set(this.vec4Array[i], i * 4);\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n        \r\n    }\r\n\r\n    public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n\r\n       \r\n        for(let i=0;i<this.vec4Array.length;i++){\r\n            this.vec4Array[i].globalStartId = this.globalStartId + this.vec4Array[i].startId;\r\n        }\r\n    }\r\n\r\n    public update(): void {\r\n        \r\n        let mustBeTransfered = false;\r\n        let m: Vec4;\r\n        for (let i = 0; i < this.vec4Array.length; i++) {\r\n            m = this.vec4Array[i];\r\n            if(!m.name) m.name = this.name+\"#\"+i;\r\n            m.update();\r\n            if (m.mustBeTransfered) {\r\n               \r\n                mustBeTransfered = true;\r\n                this.set(m, i * 4);\r\n                m.mustBeTransfered = false;\r\n               \r\n            }\r\n        }\r\n\r\n        if(this.mustBeTransfered != mustBeTransfered){\r\n            this.mustBeTransfered = mustBeTransfered;\r\n        }\r\n        \r\n    }\r\n\r\n   \r\n}"
      },
      {
        "objectType": "class",
        "name": "IVec4Array",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveIntUniform",
          "Int32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "ivec4Array",
              "type": "IVec4[]",
              "visibility": "public",
              "rawText": "public ivec4Array: IVec4[];"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "updateStartIdFromParentToChildren",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n\r\n        for(let i=0;i<this.ivec4Array.length;i++){\r\n            this.ivec4Array[i].globalStartId = this.globalStartId + this.ivec4Array[i].startId;\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public update(): void {\r\n\r\n        let mustBeTransfered = false;\r\n        let m: IVec4;\r\n        for (let i = 0; i < this.ivec4Array.length; i++) {\r\n            m = this.ivec4Array[i];\r\n            m.update();\r\n            if (m.mustBeTransfered) {\r\n                mustBeTransfered = true;\r\n                this.set(m, i * 4);\r\n                m.mustBeTransfered = false;\r\n            }\r\n        }\r\n        this.mustBeTransfered = mustBeTransfered;\r\n    }"
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "vec4Array_or_arrayLength",
              "type": "number | IVec4[]"
            }
          ],
          "rawText": "constructor(vec4Array_or_arrayLength: IVec4[]|number) {\r\n\r\n        let array:IVec4[];\r\n        if(typeof vec4Array_or_arrayLength != \"number\") array = vec4Array_or_arrayLength;\r\n        else {\r\n           array = [];\r\n           for(let i =0;i<vec4Array_or_arrayLength;i++) array[i] = new IVec4();\r\n        }\r\n \r\n \r\n        const len = array.length;\r\n        let buf: Int32Array = new Int32Array(len * 4);\r\n        for (let i = 0; i < len; i++) buf.set(array[i], i * 4);\r\n        let type: string = \"array<vec4<i32>,\" + array.length + \">\";\r\n        super(type, buf);\r\n        this.className = type;\r\n        this.ivec4Array = array;\r\n\r\n        for(let i=0;i<this.ivec4Array.length;i++){\r\n            this.ivec4Array[i].addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.set(this.ivec4Array[i], i * 4);\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n    }"
        },
        "rawText": "export class IVec4Array extends PrimitiveIntUniform {\r\n\r\n    public ivec4Array: IVec4[];\r\n\r\n    constructor(vec4Array_or_arrayLength: IVec4[]|number) {\r\n\r\n        let array:IVec4[];\r\n        if(typeof vec4Array_or_arrayLength != \"number\") array = vec4Array_or_arrayLength;\r\n        else {\r\n           array = [];\r\n           for(let i =0;i<vec4Array_or_arrayLength;i++) array[i] = new IVec4();\r\n        }\r\n \r\n \r\n        const len = array.length;\r\n        let buf: Int32Array = new Int32Array(len * 4);\r\n        for (let i = 0; i < len; i++) buf.set(array[i], i * 4);\r\n        let type: string = \"array<vec4<i32>,\" + array.length + \">\";\r\n        super(type, buf);\r\n        this.className = type;\r\n        this.ivec4Array = array;\r\n\r\n        for(let i=0;i<this.ivec4Array.length;i++){\r\n            this.ivec4Array[i].addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.set(this.ivec4Array[i], i * 4);\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n    }\r\n\r\n    public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n\r\n        for(let i=0;i<this.ivec4Array.length;i++){\r\n            this.ivec4Array[i].globalStartId = this.globalStartId + this.ivec4Array[i].startId;\r\n        }\r\n    }\r\n\r\n    public update(): void {\r\n\r\n        let mustBeTransfered = false;\r\n        let m: IVec4;\r\n        for (let i = 0; i < this.ivec4Array.length; i++) {\r\n            m = this.ivec4Array[i];\r\n            m.update();\r\n            if (m.mustBeTransfered) {\r\n                mustBeTransfered = true;\r\n                this.set(m, i * 4);\r\n                m.mustBeTransfered = false;\r\n            }\r\n        }\r\n        this.mustBeTransfered = mustBeTransfered;\r\n    }\r\n}"
      },
      {
        "objectType": "class",
        "name": "UVec4Array",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveUintUniform",
          "Uint32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "uvec4Array",
              "type": "UVec4[]",
              "visibility": "public",
              "rawText": "public uvec4Array: UVec4[];"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "updateStartIdFromParentToChildren",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n\r\n        for(let i=0;i<this.uvec4Array.length;i++){\r\n            this.uvec4Array[i].globalStartId = this.globalStartId + this.uvec4Array[i].startId;\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public update(): void {\r\n\r\n        let mustBeTransfered = false;\r\n        let m: UVec4;\r\n        for (let i = 0; i < this.uvec4Array.length; i++) {\r\n            m = this.uvec4Array[i];\r\n            m.update();\r\n            if (m.mustBeTransfered) {\r\n                mustBeTransfered = true;\r\n                this.set(m, i * 4);\r\n                m.mustBeTransfered = false;\r\n            }\r\n        }\r\n        this.mustBeTransfered = mustBeTransfered;\r\n    }"
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "vec4Array_or_arrayLength",
              "type": "number | UVec4[]"
            }
          ],
          "rawText": "constructor(vec4Array_or_arrayLength: UVec4[]|number) {\r\n\r\n        let array:UVec4[];\r\n        if(typeof vec4Array_or_arrayLength != \"number\") array = vec4Array_or_arrayLength;\r\n        else {\r\n           array = [];\r\n           for(let i =0;i<vec4Array_or_arrayLength;i++) array[i] = new UVec4();\r\n        }\r\n \r\n \r\n        const len = array.length;\r\n        let buf: Uint32Array = new Uint32Array(len * 4);\r\n        for (let i = 0; i < len; i++) buf.set(array[i], i * 4);\r\n        let type: string = \"array<vec4<u32>,\" + array.length + \">\";\r\n        super(type, buf);\r\n        this.className = type;\r\n        this.uvec4Array = array;\r\n\r\n        for(let i=0;i<this.uvec4Array.length;i++){\r\n            this.uvec4Array[i].addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.set(this.uvec4Array[i], i * 4);\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n    }"
        },
        "rawText": "export class UVec4Array extends PrimitiveUintUniform {\r\n\r\n    public uvec4Array: UVec4[];\r\n\r\n    constructor(vec4Array_or_arrayLength: UVec4[]|number) {\r\n\r\n        let array:UVec4[];\r\n        if(typeof vec4Array_or_arrayLength != \"number\") array = vec4Array_or_arrayLength;\r\n        else {\r\n           array = [];\r\n           for(let i =0;i<vec4Array_or_arrayLength;i++) array[i] = new UVec4();\r\n        }\r\n \r\n \r\n        const len = array.length;\r\n        let buf: Uint32Array = new Uint32Array(len * 4);\r\n        for (let i = 0; i < len; i++) buf.set(array[i], i * 4);\r\n        let type: string = \"array<vec4<u32>,\" + array.length + \">\";\r\n        super(type, buf);\r\n        this.className = type;\r\n        this.uvec4Array = array;\r\n\r\n        for(let i=0;i<this.uvec4Array.length;i++){\r\n            this.uvec4Array[i].addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.set(this.uvec4Array[i], i * 4);\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n    }\r\n\r\n    public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n\r\n        for(let i=0;i<this.uvec4Array.length;i++){\r\n            this.uvec4Array[i].globalStartId = this.globalStartId + this.uvec4Array[i].startId;\r\n        }\r\n    }\r\n\r\n    public update(): void {\r\n\r\n        let mustBeTransfered = false;\r\n        let m: UVec4;\r\n        for (let i = 0; i < this.uvec4Array.length; i++) {\r\n            m = this.uvec4Array[i];\r\n            m.update();\r\n            if (m.mustBeTransfered) {\r\n                mustBeTransfered = true;\r\n                this.set(m, i * 4);\r\n                m.mustBeTransfered = false;\r\n            }\r\n        }\r\n        this.mustBeTransfered = mustBeTransfered;\r\n    }\r\n}"
      },
      {
        "objectType": "class",
        "name": "Matrix3x3",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveFloatUniform",
          "Float32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "protected": [
            {
              "objectType": "property",
              "name": "disableUpdate",
              "type": "boolean",
              "visibility": "protected",
              "rawText": "protected disableUpdate: boolean;"
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "floatArray",
              "type": "Float32Array"
            }
          ],
          "rawText": "constructor(floatArray: Float32Array = null) {\r\n        const disableUpdate = !!floatArray;\r\n        if(!floatArray) floatArray = new Float32Array([\r\n            1,0,0,\r\n            0,1,0,\r\n            0,0,1\r\n        ])\r\n\r\n        super(\"mat3x3<f32>\", floatArray);\r\n        this.className = \"mat3x3<f32>\"\r\n        this.disableUpdate = disableUpdate;\r\n    }"
        },
        "rawText": "export class Matrix3x3 extends PrimitiveFloatUniform {\r\n    protected disableUpdate: boolean;\r\n    constructor(floatArray: Float32Array = null) {\r\n        const disableUpdate = !!floatArray;\r\n        if(!floatArray) floatArray = new Float32Array([\r\n            1,0,0,\r\n            0,1,0,\r\n            0,0,1\r\n        ])\r\n\r\n        super(\"mat3x3<f32>\", floatArray);\r\n        this.className = \"mat3x3<f32>\"\r\n        this.disableUpdate = disableUpdate;\r\n    }\r\n}"
      },
      {
        "objectType": "class",
        "name": "Matrix4x4",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveFloatUniform",
          "Float32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "x",
              "type": "number",
              "visibility": "public",
              "rawText": "public get x(): number { return this._x; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "y",
              "type": "number",
              "visibility": "public",
              "rawText": "public get y(): number { return this._y; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "z",
              "type": "number",
              "visibility": "public",
              "rawText": "public get z(): number { return this._z; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "rotationX",
              "type": "number",
              "visibility": "public",
              "rawText": "public get rotationX(): number { return this._rx; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "rotationY",
              "type": "number",
              "visibility": "public",
              "rawText": "public get rotationY(): number { return this._ry; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "rotationZ",
              "type": "number",
              "visibility": "public",
              "rawText": "public get rotationZ(): number { return this._rz; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "scaleX",
              "type": "number",
              "visibility": "public",
              "rawText": "public get scaleX(): number { return this._sx; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "scaleY",
              "type": "number",
              "visibility": "public",
              "rawText": "public get scaleY(): number { return this._sy; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "scaleZ",
              "type": "number",
              "visibility": "public",
              "rawText": "public get scaleZ(): number { return this._sz; }",
              "get": true,
              "set": true
            },
            {
              "objectType": "property",
              "name": "scaleXYZ",
              "type": "number",
              "visibility": "public",
              "rawText": "public set scaleXYZ(n: number) {\r\n        this.scaleX = this.scaleY = this.scaleZ = n;\r\n        this.mustBeTransfered = true;\r\n    }",
              "set": true
            }
          ],
          "protected": [
            {
              "objectType": "property",
              "name": "_x",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected _x: number = 0;"
            },
            {
              "objectType": "property",
              "name": "_y",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected _y: number = 0;"
            },
            {
              "objectType": "property",
              "name": "_z",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected _z: number = 0;"
            },
            {
              "objectType": "property",
              "name": "_sx",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected _sx: number = 1;"
            },
            {
              "objectType": "property",
              "name": "_sy",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected _sy: number = 1;"
            },
            {
              "objectType": "property",
              "name": "_sz",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected _sz: number = 1;"
            },
            {
              "objectType": "property",
              "name": "_rx",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected _rx: number = 0;"
            },
            {
              "objectType": "property",
              "name": "_ry",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected _ry: number = 0;"
            },
            {
              "objectType": "property",
              "name": "_rz",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected _rz: number = 0;"
            },
            {
              "objectType": "property",
              "name": "disableUpdate",
              "type": "boolean",
              "visibility": "protected",
              "rawText": "protected disableUpdate: boolean;"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "clone",
              "returnType": "PrimitiveFloatUniform",
              "visibility": "public",
              "rawText": "public clone(): PrimitiveFloatUniform {\r\n        const m = new Matrix4x4(this as Float32Array);\r\n        m.x = this.x;\r\n        m.y = this.y;\r\n        m.z = this.z;\r\n        m.rotationX = this.rotationX;\r\n        m.rotationY = this.rotationY;\r\n        m.rotationZ = this.rotationZ;\r\n        m.scaleX = this.scaleX;\r\n        m.scaleY = this.scaleY;\r\n        m.scaleZ = this.scaleZ;\r\n        m.disableUpdate = this.disableUpdate;\r\n        return m;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "setMatrix",
              "returnType": "void",
              "params": [
                {
                  "name": "mat",
                  "type": "Float32Array"
                }
              ],
              "visibility": "public",
              "rawText": "public setMatrix(mat: Float32Array) {\r\n        this.set(mat);\r\n        this.mustBeTransfered = true;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public update() {\r\n\r\n        //console.log(\"matrix.update \", this.disableUpdate)\r\n        if (this.disableUpdate) return;\r\n\r\n        if (this.mustBeTransfered) {\r\n\r\n            mat4.identity(this);\r\n            mat4.rotate(this, this, this._rx, vec3.fromValues(1, 0, 0));\r\n            mat4.rotate(this, this, this._ry, vec3.fromValues(0, 1, 0));\r\n            mat4.rotate(this, this, this._rz, vec3.fromValues(0, 0, 1));\r\n            mat4.translate(this, this, vec3.fromValues(this._x, this._y, this._z));\r\n            mat4.scale(this, this, vec3.fromValues(this._sx, this._sy, this._sz));\r\n\r\n\r\n\r\n            /*\r\n            \r\n            //with wgpu-matrix\r\n             mat4.identity(this);\r\n            mat4.rotateX(this, this._rx, this);\r\n            mat4.rotateY(this, this._ry, this);\r\n            mat4.rotateZ(this, this._rz, this);\r\n            mat4.translate(this, vec3.fromValues(this._x, this._y, this._z), this)\r\n            mat4.scale(this, vec3.fromValues(this._sx, this._sy, this._sz), this);\r\n\r\n            */\r\n        }\r\n\r\n\r\n    }"
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "floatArray",
              "type": "Float32Array"
            }
          ],
          "rawText": "constructor(floatArray: Float32Array = null) {\r\n        const disableUpdate = !!floatArray;\r\n        if (!floatArray) floatArray = new Float32Array([1, 0, 0, 0,\r\n            0, 1, 0, 0,\r\n            0, 0, 1, 0,\r\n            0, 0, 0, 1]);\r\n        super(\"mat4x4<f32>\", floatArray);\r\n        this.className = \"mat4x4<f32>\"\r\n        this.disableUpdate = disableUpdate;\r\n\r\n    }"
        },
        "rawText": "export class Matrix4x4 extends PrimitiveFloatUniform {\r\n\r\n\r\n\r\n    protected _x: number = 0;\r\n    protected _y: number = 0;\r\n    protected _z: number = 0;\r\n\r\n    protected _sx: number = 1;\r\n    protected _sy: number = 1;\r\n    protected _sz: number = 1;\r\n\r\n    protected _rx: number = 0;\r\n    protected _ry: number = 0;\r\n    protected _rz: number = 0;\r\n\r\n    protected disableUpdate: boolean;\r\n\r\n\r\n    constructor(floatArray: Float32Array = null) {\r\n        const disableUpdate = !!floatArray;\r\n        if (!floatArray) floatArray = new Float32Array([1, 0, 0, 0,\r\n            0, 1, 0, 0,\r\n            0, 0, 1, 0,\r\n            0, 0, 0, 1]);\r\n        super(\"mat4x4<f32>\", floatArray);\r\n        this.className = \"mat4x4<f32>\"\r\n        this.disableUpdate = disableUpdate;\r\n\r\n    }\r\n\r\n    public clone(): PrimitiveFloatUniform {\r\n        const m = new Matrix4x4(this as Float32Array);\r\n        m.x = this.x;\r\n        m.y = this.y;\r\n        m.z = this.z;\r\n        m.rotationX = this.rotationX;\r\n        m.rotationY = this.rotationY;\r\n        m.rotationZ = this.rotationZ;\r\n        m.scaleX = this.scaleX;\r\n        m.scaleY = this.scaleY;\r\n        m.scaleZ = this.scaleZ;\r\n        m.disableUpdate = this.disableUpdate;\r\n        return m;\r\n    }\r\n\r\n\r\n    public get x(): number { return this._x; }\r\n    public get y(): number { return this._y; }\r\n    public get z(): number { return this._z; }\r\n\r\n    public get rotationX(): number { return this._rx; }\r\n    public get rotationY(): number { return this._ry; }\r\n    public get rotationZ(): number { return this._rz; }\r\n\r\n    public get scaleX(): number { return this._sx; }\r\n    public get scaleY(): number { return this._sy; }\r\n    public get scaleZ(): number { return this._sz; }\r\n\r\n\r\n    public set x(n: number) {\r\n\r\n        if (n === this._x) return;\r\n        this.mustBeTransfered = true;\r\n        this._x = n;\r\n    }\r\n\r\n    public set y(n: number) {\r\n        if (n === this._y) return;\r\n        this.mustBeTransfered = true;\r\n        this._y = n;\r\n    }\r\n\r\n    public set z(n: number) {\r\n        if (n === this._z) return;\r\n        this.mustBeTransfered = true;\r\n        this._z = n;\r\n\r\n    }\r\n\r\n    public set rotationX(n: number) {\r\n        if (n === this._rx) return;\r\n        this.mustBeTransfered = true;\r\n        this._rx = n;\r\n    }\r\n\r\n    public set rotationY(n: number) {\r\n        if (n === this._ry) return;\r\n        this.mustBeTransfered = true;\r\n        this._ry = n;\r\n    }\r\n\r\n    public set rotationZ(n: number) {\r\n        if (n === this._rz) return;\r\n        this.mustBeTransfered = true;\r\n        this._rz = n;\r\n    }\r\n\r\n    public set scaleX(n: number) {\r\n        if (n === this._sx) return;\r\n        this.mustBeTransfered = true;\r\n        this._sx = n;\r\n    }\r\n\r\n    public set scaleY(n: number) {\r\n        if (n === this._sy) return;\r\n        this.mustBeTransfered = true;\r\n        this._sy = n;\r\n    }\r\n\r\n    public set scaleZ(n: number) {\r\n        if (n === this._sz) return;\r\n        this.mustBeTransfered = true;\r\n        this._sz = n;\r\n    }\r\n\r\n    public set scaleXYZ(n: number) {\r\n        this.scaleX = this.scaleY = this.scaleZ = n;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public setMatrix(mat: Float32Array) {\r\n        this.set(mat);\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public update() {\r\n\r\n        //console.log(\"matrix.update \", this.disableUpdate)\r\n        if (this.disableUpdate) return;\r\n\r\n        if (this.mustBeTransfered) {\r\n\r\n            mat4.identity(this);\r\n            mat4.rotate(this, this, this._rx, vec3.fromValues(1, 0, 0));\r\n            mat4.rotate(this, this, this._ry, vec3.fromValues(0, 1, 0));\r\n            mat4.rotate(this, this, this._rz, vec3.fromValues(0, 0, 1));\r\n            mat4.translate(this, this, vec3.fromValues(this._x, this._y, this._z));\r\n            mat4.scale(this, this, vec3.fromValues(this._sx, this._sy, this._sz));\r\n\r\n\r\n\r\n            /*\r\n            \r\n            //with wgpu-matrix\r\n             mat4.identity(this);\r\n            mat4.rotateX(this, this._rx, this);\r\n            mat4.rotateY(this, this._ry, this);\r\n            mat4.rotateZ(this, this._rz, this);\r\n            mat4.translate(this, vec3.fromValues(this._x, this._y, this._z), this)\r\n            mat4.scale(this, vec3.fromValues(this._sx, this._sy, this._sz), this);\r\n\r\n            */\r\n        }\r\n\r\n\r\n    }\r\n\r\n}"
      },
      {
        "objectType": "class",
        "name": "Matrix4x4Array",
        "filePath": "xGPU.PrimitiveType",
        "extends": [
          "PrimitiveFloatUniform",
          "Float32Array",
          "RelativeIndexable"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "matrixs",
              "type": "Matrix4x4[]",
              "visibility": "public",
              "rawText": "public matrixs: Matrix4x4[];"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "updateStartIdFromParentToChildren",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n\r\n        for(let i=0;i<this.matrixs.length;i++){\r\n            this.matrixs[i].globalStartId = this.globalStartId + this.matrixs[i].startId;\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public update(): void {\r\n\r\n\r\n\r\n        let mustBeTransfered = false;\r\n        let m: Matrix4x4;\r\n        for (let i = 0; i < this.matrixs.length; i++) {\r\n            m = this.matrixs[i];\r\n            m.update();\r\n            if (m.mustBeTransfered) {\r\n                mustBeTransfered = true;\r\n                this.set(m, i * 16);\r\n                m.mustBeTransfered = false;\r\n            }\r\n        }\r\n        this.mustBeTransfered = mustBeTransfered;\r\n    }"
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "mat4x4Array_or_arrayLength",
              "type": "number | Matrix4x4[]"
            }
          ],
          "rawText": "constructor(mat4x4Array_or_arrayLength: Matrix4x4[]|number) {\r\n\r\n        let array:Matrix4x4[];\r\n        if(typeof mat4x4Array_or_arrayLength != \"number\") array = mat4x4Array_or_arrayLength;\r\n        else {\r\n           array = [];\r\n           for(let i =0;i<mat4x4Array_or_arrayLength;i++) array[i] = new Matrix4x4();\r\n        }\r\n \r\n \r\n        const len = array.length;\r\n\r\n\r\n        let buf: Float32Array = new Float32Array(len * 16);\r\n        for (let i = 0; i < len; i++) buf.set(array[i], i * 16);\r\n        super(\"array<mat4x4<f32>,\" + len + \">\", buf)\r\n\r\n        this.matrixs = array;\r\n        this.mustBeTransfered = true;\r\n\r\n        this.className = \"array<mat4x4<f32>,\" + len + \">\";\r\n\r\n        for(let i=0;i<this.matrixs.length;i++){\r\n            this.matrixs[i].addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.set(this.matrixs[i], i * 16);\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n    }"
        },
        "rawText": "export class Matrix4x4Array extends PrimitiveFloatUniform {\r\n\r\n    public matrixs: Matrix4x4[];\r\n\r\n    constructor(mat4x4Array_or_arrayLength: Matrix4x4[]|number) {\r\n\r\n        let array:Matrix4x4[];\r\n        if(typeof mat4x4Array_or_arrayLength != \"number\") array = mat4x4Array_or_arrayLength;\r\n        else {\r\n           array = [];\r\n           for(let i =0;i<mat4x4Array_or_arrayLength;i++) array[i] = new Matrix4x4();\r\n        }\r\n \r\n \r\n        const len = array.length;\r\n\r\n\r\n        let buf: Float32Array = new Float32Array(len * 16);\r\n        for (let i = 0; i < len; i++) buf.set(array[i], i * 16);\r\n        super(\"array<mat4x4<f32>,\" + len + \">\", buf)\r\n\r\n        this.matrixs = array;\r\n        this.mustBeTransfered = true;\r\n\r\n        this.className = \"array<mat4x4<f32>,\" + len + \">\";\r\n\r\n        for(let i=0;i<this.matrixs.length;i++){\r\n            this.matrixs[i].addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.set(this.matrixs[i], i * 16);\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n    }\r\n    public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n\r\n        for(let i=0;i<this.matrixs.length;i++){\r\n            this.matrixs[i].globalStartId = this.globalStartId + this.matrixs[i].startId;\r\n        }\r\n    }\r\n    public update(): void {\r\n\r\n\r\n\r\n        let mustBeTransfered = false;\r\n        let m: Matrix4x4;\r\n        for (let i = 0; i < this.matrixs.length; i++) {\r\n            m = this.matrixs[i];\r\n            m.update();\r\n            if (m.mustBeTransfered) {\r\n                mustBeTransfered = true;\r\n                this.set(m, i * 16);\r\n                m.mustBeTransfered = false;\r\n            }\r\n        }\r\n        this.mustBeTransfered = mustBeTransfered;\r\n    }\r\n\r\n\r\n\r\n\r\n}"
      }
    ],
    "TextureRenderer": [
      {
        "objectType": "class",
        "name": "TextureRenderer",
        "filePath": "xGPU.TextureRenderer",
        "implements": [
          "IRenderer"
        ],
        "properties": {
          "public": [
            {
              "objectType": "property",
              "name": "renderPipelines",
              "type": "RenderPipeline[]",
              "visibility": "public",
              "rawText": "public renderPipelines: RenderPipeline[] = [];"
            },
            {
              "objectType": "property",
              "name": "frameId",
              "type": "number",
              "visibility": "public",
              "rawText": "public frameId: number = -1;"
            },
            {
              "objectType": "property",
              "name": "commandEncoder",
              "type": "GPUCommandEncoder",
              "visibility": "public",
              "rawText": "public commandEncoder: GPUCommandEncoder = null;"
            },
            {
              "objectType": "property",
              "name": "resized",
              "type": "boolean",
              "visibility": "public",
              "rawText": "public get resized(): boolean { return this.dimensionChanged; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "canvas",
              "type": "HTMLCanvasElement",
              "visibility": "public",
              "rawText": "public get canvas(): HTMLCanvasElement { return null; }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "width",
              "type": "number",
              "visibility": "public",
              "rawText": "public get width(): number { return this.currentWidth }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "height",
              "type": "number",
              "visibility": "public",
              "rawText": "public get height(): number { return this.currentHeight }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "texture",
              "type": "GPUTexture",
              "visibility": "public",
              "rawText": "public get texture(): GPUTexture {\r\n        if (!this.textureObj) throw new Error(\"TextureRenderer is not initialized yet. You must Use TextureRenderer.init in order to initialize it\")\r\n        return this.textureObj.gpuResource;\r\n    }",
              "get": true
            },
            {
              "objectType": "property",
              "name": "view",
              "type": "GPUTextureView",
              "visibility": "public",
              "rawText": "public get view(): GPUTextureView {\r\n        if (!this.textureObj) throw new Error(\"TextureRenderer is not initialized yet. You must Use TextureRenderer.init in order to initialize it\")\r\n        return this.textureObj.view;\r\n    }",
              "get": true
            }
          ],
          "protected": [
            {
              "objectType": "property",
              "name": "textureObj",
              "type": "Texture",
              "visibility": "protected",
              "rawText": "protected textureObj: Texture"
            },
            {
              "objectType": "property",
              "name": "dimensionChanged",
              "type": "boolean",
              "visibility": "protected",
              "rawText": "protected dimensionChanged: boolean = false;"
            },
            {
              "objectType": "property",
              "name": "currentWidth",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected currentWidth: number;"
            },
            {
              "objectType": "property",
              "name": "currentHeight",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected currentHeight: number;"
            },
            {
              "objectType": "property",
              "name": "useTextureInComputeShader",
              "type": "any",
              "visibility": "protected",
              "rawText": "protected useTextureInComputeShader;"
            },
            {
              "objectType": "property",
              "name": "deviceId",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected deviceId: number;"
            },
            {
              "objectType": "property",
              "name": "nbColorAttachment",
              "type": "number",
              "visibility": "protected",
              "rawText": "protected nbColorAttachment: number = 0;"
            }
          ]
        },
        "methods": {
          "public": [
            {
              "objectType": "method",
              "name": "init",
              "returnType": "Promise<any>",
              "params": [
                {
                  "name": "w",
                  "type": "number"
                },
                {
                  "name": "h",
                  "type": "number"
                },
                {
                  "name": "usage",
                  "type": "number"
                },
                {
                  "name": "sampleCount",
                  "type": "number"
                }
              ],
              "visibility": "public",
              "rawText": "public init(w: number, h: number, usage?: number, sampleCount?: number) {\r\n\r\n        this.currentWidth = w;\r\n        this.currentHeight = h;\r\n\r\n        return new Promise((onResolve: (val: any) => void) => {\r\n\r\n            XGPU.init().then(() => {\r\n\r\n                this.deviceId = XGPU.deviceId;\r\n\r\n                if (!usage) usage = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC;\r\n\r\n                let format: GPUTextureFormat = \"bgra8unorm\";\r\n                if (this.useTextureInComputeShader) {\r\n                    format = \"rgba8unorm\";\r\n                    usage += GPUTextureUsage.STORAGE_BINDING;\r\n                }\r\n\r\n\r\n\r\n                this.textureObj = new Texture({\r\n                    size: [w, h],\r\n                    format,\r\n                    usage,\r\n                    sampleCount\r\n                })\r\n                this.textureObj.create();\r\n\r\n                onResolve(this);\r\n            });\r\n\r\n        });\r\n\r\n\r\n    }"
            },
            {
              "objectType": "method",
              "name": "addPipeline",
              "returnType": "RenderPipeline",
              "params": [
                {
                  "name": "pipeline",
                  "type": "RenderPipeline"
                },
                {
                  "name": "offset",
                  "type": "number"
                }
              ],
              "visibility": "public",
              "rawText": "public addPipeline(pipeline: RenderPipeline, offset: number = null): RenderPipeline {\r\n\r\n        pipeline.renderer = this;\r\n        if (pipeline.renderPassDescriptor.colorAttachments[0]) this.nbColorAttachment++;\r\n\r\n        if (offset === null) this.renderPipelines.push(pipeline);\r\n        else this.renderPipelines.splice(offset, 0, pipeline)\r\n\r\n        return pipeline;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "removePipeline",
              "returnType": "RenderPipeline",
              "params": [
                {
                  "name": "pipeline",
                  "type": "RenderPipeline"
                }
              ],
              "visibility": "public",
              "rawText": "public removePipeline(pipeline: RenderPipeline) {\r\n        if (pipeline.renderPassDescriptor.colorAttachments[0]) this.nbColorAttachment--;\r\n        const id = this.renderPipelines.indexOf(pipeline);\r\n        if (id != -1) {\r\n            this.renderPipelines.splice(id, 1);\r\n        }\r\n        pipeline.renderer = null;\r\n        return pipeline;\r\n    }"
            },
            {
              "objectType": "method",
              "name": "resize",
              "returnType": "void",
              "params": [
                {
                  "name": "w",
                  "type": "number"
                },
                {
                  "name": "h",
                  "type": "number"
                }
              ],
              "visibility": "public",
              "rawText": "public resize(w: number, h: number) {\r\n        this.currentWidth = w;\r\n        this.currentHeight = h;\r\n        this.dimensionChanged = true;\r\n        if (this.textureObj) this.textureObj.resize(w, h);\r\n    }"
            },
            {
              "objectType": "method",
              "name": "destroy",
              "returnType": "void",
              "visibility": "public",
              "rawText": "public destroy(): void {\r\n        for (let i = 0; i < this.renderPipelines.length; i++) {\r\n            this.renderPipelines[i].destroy();\r\n        }\r\n        this.renderPipelines = [];\r\n        for (let z in this) {\r\n            this[z] = null;\r\n        }\r\n    }"
            },
            {
              "objectType": "method",
              "name": "update",
              "returnType": "Promise<void>",
              "visibility": "public",
              "rawText": "public async update() {\r\n\r\n\r\n\r\n\r\n        if (!XGPU.ready || this.renderPipelines.length === 0 || this.deviceId === undefined) return;\r\n\r\n        let deviceChanged: boolean = XGPU.deviceId != this.deviceId;\r\n        if (deviceChanged) {\r\n\r\n            if (this.textureObj) this.textureObj.create();\r\n            this.deviceId = XGPU.deviceId;\r\n            for (let i = 0; i < this.renderPipelines.length; i++) {\r\n                this.renderPipelines[i].clearAfterDeviceLostAndRebuild();\r\n            }\r\n        }\r\n\r\n        this.commandEncoder = XGPU.device.createCommandEncoder();\r\n\r\n\r\n        let pipeline: RenderPipeline, renderPass;\r\n        for (let i = 0; i < this.renderPipelines.length; i++) {\r\n            pipeline = this.renderPipelines[i];\r\n            pipeline.update();\r\n\r\n            for (let j = 0; j < pipeline.pipelineCount; j++) {\r\n\r\n                renderPass = pipeline.beginRenderPass(this.commandEncoder, this.view, j);\r\n                pipeline.dispatchEvent(RenderPipeline.ON_DRAW, j);\r\n                //if (pipeline.onDraw) pipeline.onDraw(j);\r\n                pipeline.draw(renderPass);\r\n                pipeline.end(this.commandEncoder, renderPass);\r\n            }\r\n        }\r\n\r\n        const commandBuffer = this.commandEncoder.finish();\r\n        this.commandEncoder = null;\r\n\r\n        XGPU.device.queue.submit([commandBuffer]);\r\n\r\n        this.dimensionChanged = false;\r\n\r\n\r\n\r\n    }"
            }
          ]
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "params": [
            {
              "name": "useTextureInComputeShader",
              "type": "boolean"
            }
          ],
          "rawText": "constructor(useTextureInComputeShader: boolean = false) {\r\n        this.useTextureInComputeShader = useTextureInComputeShader;\r\n    }"
        },
        "rawText": "export class TextureRenderer implements IRenderer {\r\n\r\n    protected textureObj: Texture\r\n    protected dimensionChanged: boolean = false;\r\n    protected currentWidth: number;\r\n    protected currentHeight: number;\r\n\r\n    public renderPipelines: RenderPipeline[] = [];\r\n\r\n    protected useTextureInComputeShader;\r\n    public frameId: number = -1;\r\n\r\n\r\n    constructor(useTextureInComputeShader: boolean = false) {\r\n        this.useTextureInComputeShader = useTextureInComputeShader;\r\n    }\r\n\r\n    protected deviceId: number;\r\n\r\n    public init(w: number, h: number, usage?: number, sampleCount?: number) {\r\n\r\n        this.currentWidth = w;\r\n        this.currentHeight = h;\r\n\r\n        return new Promise((onResolve: (val: any) => void) => {\r\n\r\n            XGPU.init().then(() => {\r\n\r\n                this.deviceId = XGPU.deviceId;\r\n\r\n                if (!usage) usage = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC;\r\n\r\n                let format: GPUTextureFormat = \"bgra8unorm\";\r\n                if (this.useTextureInComputeShader) {\r\n                    format = \"rgba8unorm\";\r\n                    usage += GPUTextureUsage.STORAGE_BINDING;\r\n                }\r\n\r\n\r\n\r\n                this.textureObj = new Texture({\r\n                    size: [w, h],\r\n                    format,\r\n                    usage,\r\n                    sampleCount\r\n                })\r\n                this.textureObj.create();\r\n\r\n                onResolve(this);\r\n            });\r\n\r\n        });\r\n\r\n\r\n    }\r\n\r\n    //public get firstPipeline(): RenderPipeline { return this.renderPipelines[0]; }\r\n\r\n    protected nbColorAttachment: number = 0;\r\n\r\n    public addPipeline(pipeline: RenderPipeline, offset: number = null): RenderPipeline {\r\n\r\n        pipeline.renderer = this;\r\n        if (pipeline.renderPassDescriptor.colorAttachments[0]) this.nbColorAttachment++;\r\n\r\n        if (offset === null) this.renderPipelines.push(pipeline);\r\n        else this.renderPipelines.splice(offset, 0, pipeline)\r\n\r\n        return pipeline;\r\n    }\r\n\r\n    public removePipeline(pipeline: RenderPipeline) {\r\n        if (pipeline.renderPassDescriptor.colorAttachments[0]) this.nbColorAttachment--;\r\n        const id = this.renderPipelines.indexOf(pipeline);\r\n        if (id != -1) {\r\n            this.renderPipelines.splice(id, 1);\r\n        }\r\n        pipeline.renderer = null;\r\n        return pipeline;\r\n    }\r\n\r\n\r\n    //public get nbPipeline(): number { return this.renderPipelines.length }\r\n    //public get useSinglePipeline(): boolean { return this.nbColorAttachment === 1 }\r\n\r\n    public resize(w: number, h: number) {\r\n        this.currentWidth = w;\r\n        this.currentHeight = h;\r\n        this.dimensionChanged = true;\r\n        if (this.textureObj) this.textureObj.resize(w, h);\r\n    }\r\n\r\n    public destroy(): void {\r\n        for (let i = 0; i < this.renderPipelines.length; i++) {\r\n            this.renderPipelines[i].destroy();\r\n        }\r\n        this.renderPipelines = [];\r\n        for (let z in this) {\r\n            this[z] = null;\r\n        }\r\n    }\r\n\r\n    public commandEncoder: GPUCommandEncoder = null;\r\n\r\n\r\n    public async update() {\r\n\r\n\r\n\r\n\r\n        if (!XGPU.ready || this.renderPipelines.length === 0 || this.deviceId === undefined) return;\r\n\r\n        let deviceChanged: boolean = XGPU.deviceId != this.deviceId;\r\n        if (deviceChanged) {\r\n\r\n            if (this.textureObj) this.textureObj.create();\r\n            this.deviceId = XGPU.deviceId;\r\n            for (let i = 0; i < this.renderPipelines.length; i++) {\r\n                this.renderPipelines[i].clearAfterDeviceLostAndRebuild();\r\n            }\r\n        }\r\n\r\n        this.commandEncoder = XGPU.device.createCommandEncoder();\r\n\r\n\r\n        let pipeline: RenderPipeline, renderPass;\r\n        for (let i = 0; i < this.renderPipelines.length; i++) {\r\n            pipeline = this.renderPipelines[i];\r\n            pipeline.update();\r\n\r\n            for (let j = 0; j < pipeline.pipelineCount; j++) {\r\n\r\n                renderPass = pipeline.beginRenderPass(this.commandEncoder, this.view, j);\r\n                pipeline.dispatchEvent(RenderPipeline.ON_DRAW, j);\r\n                //if (pipeline.onDraw) pipeline.onDraw(j);\r\n                pipeline.draw(renderPass);\r\n                pipeline.end(this.commandEncoder, renderPass);\r\n            }\r\n        }\r\n\r\n        const commandBuffer = this.commandEncoder.finish();\r\n        this.commandEncoder = null;\r\n\r\n        XGPU.device.queue.submit([commandBuffer]);\r\n\r\n        this.dimensionChanged = false;\r\n\r\n\r\n\r\n    }\r\n\r\n    public get resized(): boolean { return this.dimensionChanged; }\r\n    public get canvas(): HTMLCanvasElement { return null; }\r\n    public get width(): number { return this.currentWidth }\r\n    public get height(): number { return this.currentHeight }\r\n\r\n    public get texture(): GPUTexture {\r\n        if (!this.textureObj) throw new Error(\"TextureRenderer is not initialized yet. You must Use TextureRenderer.init in order to initialize it\")\r\n        return this.textureObj.gpuResource;\r\n    }\r\n    public get view(): GPUTextureView {\r\n        if (!this.textureObj) throw new Error(\"TextureRenderer is not initialized yet. You must Use TextureRenderer.init in order to initialize it\")\r\n        return this.textureObj.view;\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n}"
      }
    ],
    "WebGPUProperties": [
      {
        "objectType": "class",
        "name": "WebGPUProperties",
        "filePath": "xGPU.WebGPUProperties",
        "statics": {
          "properties": {
            "private": [
              {
                "objectType": "property",
                "name": "ready",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private static ready: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "textureUsage",
                "type": "any",
                "visibility": "private",
                "rawText": "private static textureUsage: any;"
              },
              {
                "objectType": "property",
                "name": "bufferUsage",
                "type": "any",
                "visibility": "private",
                "rawText": "private static bufferUsage: any;"
              },
              {
                "objectType": "property",
                "name": "shaderStage",
                "type": "any",
                "visibility": "private",
                "rawText": "private static shaderStage: any;"
              },
              {
                "objectType": "property",
                "name": "_instance",
                "type": "WebGPUProperties",
                "visibility": "private",
                "rawText": "private static _instance: WebGPUProperties;"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "init",
                "returnType": "Promise<void>",
                "visibility": "public",
                "rawText": "public static async init(): Promise<void> {\r\n        if (!this._instance) new WebGPUProperties();\r\n        return new Promise(async (resolve) => {\r\n            if (this.ready) resolve();\r\n            else {\r\n                this.bufferUsage = await this.getResult(GPUBufferUsage);\r\n                this.shaderStage = await this.getResult(GPUShaderStage);\r\n                this.textureUsage = await this.getResult(GPUTextureUsage);\r\n                this.ready = true;\r\n                resolve();\r\n            }\r\n        });\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getTextureUsageById",
                "returnType": "string",
                "params": [
                  {
                    "name": "id",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public static getTextureUsageById(id: number): string {\r\n        return this.resolve(this.textureUsage, id);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getBufferUsageById",
                "returnType": "string",
                "params": [
                  {
                    "name": "id",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public static getBufferUsageById(id: number): string {\r\n        return this.resolve(this.bufferUsage, id);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getShaderStageById",
                "returnType": "string",
                "params": [
                  {
                    "name": "id",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public static getShaderStageById(id: number): string {\r\n        return this.resolve(this.shaderStage, id);\r\n    }"
              }
            ],
            "private": [
              {
                "objectType": "method",
                "name": "build",
                "returnType": "{}",
                "params": [
                  {
                    "name": "obj",
                    "type": "any"
                  },
                  {
                    "name": "currentId",
                    "type": "number"
                  },
                  {
                    "name": "currentNames",
                    "type": "string[]"
                  }
                ],
                "visibility": "private",
                "rawText": "private static build(obj: any, currentId: number, currentNames: string[]) {\r\n\r\n        let infoById = {};\r\n        let processedIds = new Set();\r\n        let stack = [{ id: currentId, names: currentNames }];\r\n        while (stack.length > 0) {\r\n            let current = stack.pop();\r\n            let currentId = current.id;\r\n            let currentNames = current.names;\r\n            if (processedIds.has(currentId)) continue;\r\n\r\n            for (let name in obj) {\r\n                let id = obj[name];\r\n                let combinedId = currentId | id;\r\n                let combinedNames = [...new Set(currentNames.concat(name))];\r\n\r\n                if (!(combinedId in infoById)) {\r\n                    infoById[combinedId] = combinedNames;\r\n                    stack.push({ id: combinedId, names: combinedNames });\r\n                } else {\r\n                    infoById[combinedId] = [...new Set(infoById[combinedId].concat(combinedNames))];\r\n                }\r\n            }\r\n            processedIds.add(currentId);\r\n        }\r\n        return infoById;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "resolve",
                "returnType": "any",
                "params": [
                  {
                    "name": "obj",
                    "type": "any"
                  },
                  {
                    "name": "id",
                    "type": "number"
                  }
                ],
                "visibility": "private",
                "rawText": "private static resolve(obj: any, id: number) {\r\n        if (id in obj) return obj[id].join(\"|\");\r\n        return \"undefined\"\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getResult",
                "returnType": "Promise<any>",
                "params": [
                  {
                    "name": "WebGpuObject",
                    "type": "any"
                  }
                ],
                "visibility": "private",
                "rawText": "private static async getResult(WebGpuObject: any): Promise<any> {\r\n        return new Promise((resolve) => {\r\n            const result = this.build(WebGpuObject, 0, [])\r\n            setTimeout(() => {\r\n                //i make a pause to unblock the thread\r\n                resolve(result);\r\n            }, 1)\r\n        });\r\n    }"
              }
            ]
          }
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "rawText": "constructor() {\r\n        if (WebGPUProperties._instance) {\r\n            throw new Error(\"WebGPUProperties is not instanciable\");\r\n        }\r\n        WebGPUProperties._instance = this;\r\n    }"
        },
        "rawText": "export class WebGPUProperties {\r\n\r\n    private static build(obj: any, currentId: number, currentNames: string[]) {\r\n\r\n        let infoById = {};\r\n        let processedIds = new Set();\r\n        let stack = [{ id: currentId, names: currentNames }];\r\n        while (stack.length > 0) {\r\n            let current = stack.pop();\r\n            let currentId = current.id;\r\n            let currentNames = current.names;\r\n            if (processedIds.has(currentId)) continue;\r\n\r\n            for (let name in obj) {\r\n                let id = obj[name];\r\n                let combinedId = currentId | id;\r\n                let combinedNames = [...new Set(currentNames.concat(name))];\r\n\r\n                if (!(combinedId in infoById)) {\r\n                    infoById[combinedId] = combinedNames;\r\n                    stack.push({ id: combinedId, names: combinedNames });\r\n                } else {\r\n                    infoById[combinedId] = [...new Set(infoById[combinedId].concat(combinedNames))];\r\n                }\r\n            }\r\n            processedIds.add(currentId);\r\n        }\r\n        return infoById;\r\n    }\r\n\r\n    private static resolve(obj: any, id: number) {\r\n        if (id in obj) return obj[id].join(\"|\");\r\n        return \"undefined\"\r\n    }\r\n\r\n    private static async getResult(WebGpuObject: any): Promise<any> {\r\n        return new Promise((resolve) => {\r\n            const result = this.build(WebGpuObject, 0, [])\r\n            setTimeout(() => {\r\n                //i make a pause to unblock the thread\r\n                resolve(result);\r\n            }, 1)\r\n        });\r\n    }\r\n    private static ready: boolean = false;\r\n    private static textureUsage: any;\r\n    private static bufferUsage: any;\r\n    private static shaderStage: any;\r\n\r\n    public static async init(): Promise<void> {\r\n        if (!this._instance) new WebGPUProperties();\r\n        return new Promise(async (resolve) => {\r\n            if (this.ready) resolve();\r\n            else {\r\n                this.bufferUsage = await this.getResult(GPUBufferUsage);\r\n                this.shaderStage = await this.getResult(GPUShaderStage);\r\n                this.textureUsage = await this.getResult(GPUTextureUsage);\r\n                this.ready = true;\r\n                resolve();\r\n            }\r\n        });\r\n    }\r\n\r\n    private static _instance: WebGPUProperties;\r\n    constructor() {\r\n        if (WebGPUProperties._instance) {\r\n            throw new Error(\"WebGPUProperties is not instanciable\");\r\n        }\r\n        WebGPUProperties._instance = this;\r\n    }\r\n\r\n\r\n\r\n    public static getTextureUsageById(id: number): string {\r\n        return this.resolve(this.textureUsage, id);\r\n    }\r\n\r\n    public static getBufferUsageById(id: number): string {\r\n        return this.resolve(this.bufferUsage, id);\r\n    }\r\n\r\n    public static getShaderStageById(id: number): string {\r\n        return this.resolve(this.shaderStage, id);\r\n    }\r\n}"
      }
    ],
    "XGPU": [
      {
        "objectType": "type",
        "name": "TransferableUniforms",
        "type": "TransferableUniforms",
        "rawText": "export type TransferableUniforms = {\r\n    items:{name:string,type:string,values:any,groups?:any,items?:any};\r\n    transferables:ArrayBuffer[]\r\n}"
      },
      {
        "objectType": "class",
        "name": "XGPU",
        "filePath": "xGPU.XGPU",
        "statics": {
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "showVertexShader",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public static showVertexShader: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "showFragmentShader",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public static showFragmentShader: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "showComputeShader",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public static showComputeShader: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "showVertexDebuggerShader",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public static showVertexDebuggerShader: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "ready",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public static get ready(): boolean { return this._ready; }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "deviceLost",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public static deviceLost: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "deviceId",
                "type": "number",
                "visibility": "public",
                "rawText": "public static deviceId: number = -1;"
              },
              {
                "objectType": "property",
                "name": "loseDeviceRecently",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public static get loseDeviceRecently(): boolean {\r\n        //console.log(\"delay = \", new Date().getTime() - this.deviceLostTime)\r\n        return new Date().getTime() - this.deviceLostTime <= 3000;\r\n    }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "device",
                "type": "GPUDevice",
                "visibility": "public",
                "rawText": "public static get device(): GPUDevice {\r\n        if (this.deviceLost) return null;\r\n        if (!this.gpuDevice && !this.ready) throw new Error(\"you must use XGPU.init() to get the reference of the gpuDevice\")\r\n        return this.gpuDevice;\r\n    }",
                "get": true
              }
            ],
            "private": [
              {
                "objectType": "property",
                "name": "_ready",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private static _ready: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "requestAdapterOptions",
                "type": "GPURequestAdapterOptions",
                "visibility": "private",
                "rawText": "private static requestAdapterOptions: GPURequestAdapterOptions;"
              },
              {
                "objectType": "property",
                "name": "losingDevice",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private static losingDevice: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "deviceLostTime",
                "type": "number",
                "visibility": "private",
                "rawText": "private static deviceLostTime: number;"
              },
              {
                "objectType": "property",
                "name": "_preferedCanvasFormat",
                "type": "GPUTextureFormat",
                "visibility": "private",
                "rawText": "private static _preferedCanvasFormat: GPUTextureFormat;"
              }
            ],
            "protected": [
              {
                "objectType": "property",
                "name": "gpuDevice",
                "type": "GPUDevice",
                "visibility": "protected",
                "rawText": "protected static gpuDevice: GPUDevice;"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "debugUsage",
                "returnType": "string",
                "params": [
                  {
                    "name": "usage",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public static debugUsage(usage: number) {\r\n        return WebGPUProperties.getBufferUsageById(usage);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "debugTextureUsage",
                "returnType": "string",
                "params": [
                  {
                    "name": "usage",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public static debugTextureUsage(usage: number): string {\r\n        return WebGPUProperties.getTextureUsageById(usage);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "debugShaderStage",
                "returnType": "string",
                "params": [
                  {
                    "name": "n",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public static debugShaderStage(n: number) {\r\n        return WebGPUProperties.getShaderStageById(n)\r\n    }"
              },
              {
                "objectType": "method",
                "name": "loseDevice",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public static loseDevice() {\r\n        this.losingDevice = true;\r\n        this.gpuDevice.destroy();\r\n    }"
              },
              {
                "objectType": "method",
                "name": "clear",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public static clear() {\r\n        this.gpuDevice.destroy();\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getTransferableUniforms",
                "returnType": "TransferableUniforms",
                "params": [
                  {
                    "name": "uniforms",
                    "type": "{ [key: string]: Uniformable; }"
                  }
                ],
                "visibility": "public",
                "rawText": "public static getTransferableUniforms(uniforms:{[key:string]:Uniformable}):TransferableUniforms{\r\n        \r\n        let def:any;\r\n        let o:Uniformable;\r\n        const transferables:ArrayBuffer[] = [];\r\n        const items:any = {};\r\n        for(let z in uniforms){\r\n            o = uniforms[z];\r\n            o.name = z;\r\n\r\n            def = o.definition;\r\n\r\n            items[z] = def;\r\n            //console.log(\"type ======> \",o.type)\r\n            if(def.type == \"UniformGroup\"){\r\n                if(transferables.includes(def.values) == false){\r\n                    transferables.push(def.values);\r\n                }\r\n            }else if(def.type == \"UniformGroupArray\"){\r\n                let groups = def.groups;\r\n                for(let i=0;i<groups.length;i++){\r\n                    if(transferables.includes(groups[i].values) == false){\r\n                        transferables.push(groups[i].values)\r\n                    }\r\n                }\r\n            }else if(def.values.buffer){\r\n                if(transferables.includes(def.values.buffer) == false){\r\n                    transferables.push(def.values.buffer);\r\n                }\r\n            } \r\n        }\r\n\r\n        return {\r\n            items,\r\n            transferables\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "parseTransferableUniform",
                "returnType": "{ [key: string]: Uniformable; }",
                "params": [
                  {
                    "name": "uniforms",
                    "type": "TransferableUniforms"
                  }
                ],
                "visibility": "public",
                "rawText": "public static parseTransferableUniform(uniforms:TransferableUniforms):{[key:string]:Uniformable}{\r\n\r\n        const parsePrimitive = (o:any):PrimitiveType=>{\r\n            if(o.type == \"Float\") return new Float(o.values[0]);\r\n            if(o.type == \"Vec2\") return new Vec2(o.values[0],o.values[1]);\r\n            if(o.type == \"Vec3\") return new Vec3(o.values[0],o.values[1],o.values[2]);\r\n            if(o.type == \"Vec4\") return new Vec4(o.values[0],o.values[1],o.values[2],o.values[3]);\r\n\r\n            if(o.type == \"Int\") return new Int(o.values[0]);\r\n            if(o.type == \"IVec2\") return new IVec2(o.values[0],o.values[1]);\r\n            if(o.type == \"IVec3\") return new IVec3(o.values[0],o.values[1],o.values[2]);\r\n            if(o.type == \"IVec4\") return new IVec4(o.values[0],o.values[1],o.values[2],o.values[3]);\r\n\r\n            if(o.type == \"Uint\") return new Uint(o.values[0]);\r\n            if(o.type == \"UVec2\") return new UVec2(o.values[0],o.values[1]);\r\n            if(o.type == \"UVec3\") return new UVec3(o.values[0],o.values[1],o.values[2]);\r\n            if(o.type == \"UVec4\") return new UVec4(o.values[0],o.values[1],o.values[2],o.values[3]);\r\n\r\n            if(o.type == \"Matrix4x4\"){\r\n                return new Matrix4x4(o.values);\r\n            }\r\n            if(o.type == \"Matrix3x3\"){\r\n                return new Matrix3x3(o.values);\r\n            }\r\n\r\n            if(o.type == \"Vec4Array\"){\r\n                const array = new Vec4Array(o.values.length/4);\r\n                array.set(o.values);\r\n                return array\r\n            }\r\n\r\n            if(o.type == \"IVec4Array\"){\r\n                const array = new IVec4Array(o.values.length/4);\r\n                array.set(o.values);\r\n                return array\r\n            }\r\n\r\n            if(o.type == \"UVec4Array\"){\r\n                const array = new UVec4Array(o.values.length/4);\r\n                array.set(o.values);\r\n                return array\r\n            }\r\n\r\n            if(o.type == \"Matrix4x4Array\"){\r\n                const array = new Matrix4x4Array(o.values.length/16);\r\n                array.set(o.values);\r\n                return array\r\n            }\r\n\r\n            throw new Error(\"incorrect type\")\r\n        }\r\n\r\n        const parseObject = (o:any):{[key:string]:Uniformable}=>{\r\n            let result:{[key:string]:Uniformable} = {};\r\n            let item;\r\n            for(let z in o.items){\r\n                item = o.items[z];\r\n                if(item.type == \"UniformGroup\"){\r\n                    result[z] = parseUniformGroup(item);\r\n                }else if(item.type == \"UniformGroupArray\"){\r\n                    result[z] = parseUniformGroupArray(item);\r\n                }else{  \r\n                    result[z] = parsePrimitive(item);\r\n                }\r\n            }\r\n            return result;\r\n        }\r\n\r\n        const parseUniformGroup = (o:any):UniformGroup=>{\r\n            let result = {};\r\n            let item;\r\n            for(let z in o.items){\r\n                item = o.items[z];\r\n                if(item.type == \"UniformGroup\"){\r\n                    result[z] = parseUniformGroup(item);\r\n                }else if(item.type == \"UniformGroupArray\"){\r\n                    result[z] = parseUniformGroupArray(item);\r\n                }else{  \r\n                    result[z] = parsePrimitive(item);\r\n                }\r\n            }\r\n           \r\n            return new UniformGroup(result);\r\n        }\r\n\r\n        const parseUniformGroupArray = (o:any):UniformGroupArray=>{\r\n            let result = [];\r\n            for(let i=0;i<o.groups.length;i++){\r\n                result[i] = parseUniformGroup(o.groups[i]);\r\n            }\r\n            return new UniformGroupArray(result)\r\n        }\r\n\r\n\r\n\r\n        return parseObject(uniforms);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "init",
                "returnType": "Promise<void>",
                "params": [
                  {
                    "name": "options",
                    "type": "{ powerPreference?: \"low-power\" | \"high-performance\"; forceFallbackAdaoter?: boolean; }"
                  }
                ],
                "visibility": "public",
                "rawText": "public static init(options?: { powerPreference?: \"low-power\" | \"high-performance\", forceFallbackAdaoter?: boolean }): Promise<void> {\r\n        this.requestAdapterOptions = options;\r\n        BuiltIns.__initDebug();\r\n        return new Promise(async (resolve: (val: any) => void, error: () => void) => {\r\n\r\n            if (this.gpuDevice) {\r\n                resolve(this);\r\n                return;\r\n            }\r\n\r\n            const adapter = await navigator.gpu.requestAdapter(options)\r\n            if (adapter) {\r\n                this.gpuDevice = await adapter.requestDevice();\r\n\r\n                this.deviceId++;\r\n                //console.log(\"get GPU device : \", this.deviceId)\r\n\r\n\r\n                this.deviceLost = false;\r\n\r\n                this.gpuDevice.lost.then((info) => {\r\n                    console.clear();\r\n                    console.error(`WebGPU device was lost: ${info.message}`);\r\n                    this.gpuDevice = null;\r\n                    this._ready = false;\r\n                    this.deviceLost = true;\r\n                    this.deviceLostTime = new Date().getTime();\r\n                    if (this.losingDevice || info.reason != 'destroyed') {\r\n\r\n                        this.losingDevice = false;\r\n                        XGPU.init(this.requestAdapterOptions);\r\n                    }\r\n                })\r\n\r\n                await WebGPUProperties.init();\r\n                this.debugUsage(172)\r\n                this._ready = true;\r\n                resolve(this);\r\n            } else {\r\n                error()\r\n            }\r\n        })\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getPreferredCanvasFormat",
                "returnType": "GPUTextureFormat",
                "visibility": "public",
                "rawText": "public static getPreferredCanvasFormat(): GPUTextureFormat {\r\n        if (!this._preferedCanvasFormat) this._preferedCanvasFormat = navigator.gpu.getPreferredCanvasFormat();\r\n        //console.warn(\"getPreferedCanvasFormat = \", this._preferedCanvasFormat)\r\n        return this._preferedCanvasFormat;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setPreferredCanvasFormat",
                "returnType": "void",
                "params": [
                  {
                    "name": "format",
                    "type": "GPUTextureFormat"
                  }
                ],
                "visibility": "public",
                "rawText": "public static setPreferredCanvasFormat(format: GPUTextureFormat) {\r\n        this._preferedCanvasFormat = format;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "destroy",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public static destroy() {\r\n        if (this.gpuDevice) {\r\n            this.gpuDevice.destroy();\r\n            this.gpuDevice = null;\r\n            this._ready = false;\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createBindgroup",
                "returnType": "GPUBindGroup",
                "params": [
                  {
                    "name": "o",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public static createBindgroup(o: any): GPUBindGroup {\r\n        return this.device.createBindGroup(o);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createBindgroupLayout",
                "returnType": "GPUBindGroupLayout",
                "params": [
                  {
                    "name": "o",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public static createBindgroupLayout(o: any): GPUBindGroupLayout {\r\n        return this.device.createBindGroupLayout(o);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createPipelineLayout",
                "returnType": "GPUPipelineLayout",
                "params": [
                  {
                    "name": "o",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public static createPipelineLayout(o: any): GPUPipelineLayout {\r\n        return this.device.createPipelineLayout(o);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createRenderPipeline",
                "returnType": "GPURenderPipeline",
                "params": [
                  {
                    "name": "o",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public static createRenderPipeline(o: any): GPURenderPipeline {\r\n        return this.device.createRenderPipeline(o);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createComputePipeline",
                "returnType": "GPUComputePipeline",
                "params": [
                  {
                    "name": "o",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public static createComputePipeline(o: any): GPUComputePipeline {\r\n        return this.device.createComputePipeline(o);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createStagingBuffer",
                "returnType": "GPUBuffer",
                "params": [
                  {
                    "name": "size",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public static createStagingBuffer(size: number): GPUBuffer {\r\n        return this.device.createBuffer({\r\n            size,\r\n            usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,\r\n            mappedAtCreation: false\r\n        })\r\n    }"
              }
            ]
          }
        },
        "constructor": {
          "objectType": "constructor",
          "name": "constructor",
          "rawText": "constructor() {\r\n        throw new Error(\"GPU is static and can't be instanciated\")\r\n    }"
        },
        "rawText": "export class XGPU {\r\n\r\n\r\n    public static showVertexShader: boolean = false;\r\n    public static showFragmentShader: boolean = false;\r\n    public static showComputeShader: boolean = false;\r\n    public static showVertexDebuggerShader: boolean = false;\r\n\r\n    private static _ready: boolean = false;\r\n    public static get ready(): boolean { return this._ready; }\r\n\r\n    protected static gpuDevice: GPUDevice;\r\n\r\n\r\n\r\n    public static debugUsage(usage: number) {\r\n        return WebGPUProperties.getBufferUsageById(usage);\r\n    }\r\n\r\n    public static debugTextureUsage(usage: number): string {\r\n        return WebGPUProperties.getTextureUsageById(usage);\r\n    }\r\n\r\n    public static debugShaderStage(n: number) {\r\n        return WebGPUProperties.getShaderStageById(n)\r\n    }\r\n\r\n\r\n    constructor() {\r\n        throw new Error(\"GPU is static and can't be instanciated\")\r\n    }\r\n\r\n    private static requestAdapterOptions: GPURequestAdapterOptions;\r\n    private static losingDevice: boolean = false;\r\n\r\n    public static deviceLost: boolean = false;\r\n    private static deviceLostTime: number;\r\n\r\n    public static deviceId: number = -1;\r\n\r\n    public static loseDevice() {\r\n        this.losingDevice = true;\r\n        this.gpuDevice.destroy();\r\n    }\r\n    public static clear() {\r\n        this.gpuDevice.destroy();\r\n    }\r\n\r\n    public static get loseDeviceRecently(): boolean {\r\n        //console.log(\"delay = \", new Date().getTime() - this.deviceLostTime)\r\n        return new Date().getTime() - this.deviceLostTime <= 3000;\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\n    public static getTransferableUniforms(uniforms:{[key:string]:Uniformable}):TransferableUniforms{\r\n        \r\n        let def:any;\r\n        let o:Uniformable;\r\n        const transferables:ArrayBuffer[] = [];\r\n        const items:any = {};\r\n        for(let z in uniforms){\r\n            o = uniforms[z];\r\n            o.name = z;\r\n\r\n            def = o.definition;\r\n\r\n            items[z] = def;\r\n            //console.log(\"type ======> \",o.type)\r\n            if(def.type == \"UniformGroup\"){\r\n                if(transferables.includes(def.values) == false){\r\n                    transferables.push(def.values);\r\n                }\r\n            }else if(def.type == \"UniformGroupArray\"){\r\n                let groups = def.groups;\r\n                for(let i=0;i<groups.length;i++){\r\n                    if(transferables.includes(groups[i].values) == false){\r\n                        transferables.push(groups[i].values)\r\n                    }\r\n                }\r\n            }else if(def.values.buffer){\r\n                if(transferables.includes(def.values.buffer) == false){\r\n                    transferables.push(def.values.buffer);\r\n                }\r\n            } \r\n        }\r\n\r\n        return {\r\n            items,\r\n            transferables\r\n        }\r\n    }\r\n    /*\r\n    export type TransferableUniforms = {\r\n    items:{name:string,type:string,values:any,groups?:any,items?:any};\r\n    transferables:ArrayBuffer[]\r\n} \r\n    */\r\n    public static parseTransferableUniform(uniforms:TransferableUniforms):{[key:string]:Uniformable}{\r\n\r\n        const parsePrimitive = (o:any):PrimitiveType=>{\r\n            if(o.type == \"Float\") return new Float(o.values[0]);\r\n            if(o.type == \"Vec2\") return new Vec2(o.values[0],o.values[1]);\r\n            if(o.type == \"Vec3\") return new Vec3(o.values[0],o.values[1],o.values[2]);\r\n            if(o.type == \"Vec4\") return new Vec4(o.values[0],o.values[1],o.values[2],o.values[3]);\r\n\r\n            if(o.type == \"Int\") return new Int(o.values[0]);\r\n            if(o.type == \"IVec2\") return new IVec2(o.values[0],o.values[1]);\r\n            if(o.type == \"IVec3\") return new IVec3(o.values[0],o.values[1],o.values[2]);\r\n            if(o.type == \"IVec4\") return new IVec4(o.values[0],o.values[1],o.values[2],o.values[3]);\r\n\r\n            if(o.type == \"Uint\") return new Uint(o.values[0]);\r\n            if(o.type == \"UVec2\") return new UVec2(o.values[0],o.values[1]);\r\n            if(o.type == \"UVec3\") return new UVec3(o.values[0],o.values[1],o.values[2]);\r\n            if(o.type == \"UVec4\") return new UVec4(o.values[0],o.values[1],o.values[2],o.values[3]);\r\n\r\n            if(o.type == \"Matrix4x4\"){\r\n                return new Matrix4x4(o.values);\r\n            }\r\n            if(o.type == \"Matrix3x3\"){\r\n                return new Matrix3x3(o.values);\r\n            }\r\n\r\n            if(o.type == \"Vec4Array\"){\r\n                const array = new Vec4Array(o.values.length/4);\r\n                array.set(o.values);\r\n                return array\r\n            }\r\n\r\n            if(o.type == \"IVec4Array\"){\r\n                const array = new IVec4Array(o.values.length/4);\r\n                array.set(o.values);\r\n                return array\r\n            }\r\n\r\n            if(o.type == \"UVec4Array\"){\r\n                const array = new UVec4Array(o.values.length/4);\r\n                array.set(o.values);\r\n                return array\r\n            }\r\n\r\n            if(o.type == \"Matrix4x4Array\"){\r\n                const array = new Matrix4x4Array(o.values.length/16);\r\n                array.set(o.values);\r\n                return array\r\n            }\r\n\r\n            throw new Error(\"incorrect type\")\r\n        }\r\n\r\n        const parseObject = (o:any):{[key:string]:Uniformable}=>{\r\n            let result:{[key:string]:Uniformable} = {};\r\n            let item;\r\n            for(let z in o.items){\r\n                item = o.items[z];\r\n                if(item.type == \"UniformGroup\"){\r\n                    result[z] = parseUniformGroup(item);\r\n                }else if(item.type == \"UniformGroupArray\"){\r\n                    result[z] = parseUniformGroupArray(item);\r\n                }else{  \r\n                    result[z] = parsePrimitive(item);\r\n                }\r\n            }\r\n            return result;\r\n        }\r\n\r\n        const parseUniformGroup = (o:any):UniformGroup=>{\r\n            let result = {};\r\n            let item;\r\n            for(let z in o.items){\r\n                item = o.items[z];\r\n                if(item.type == \"UniformGroup\"){\r\n                    result[z] = parseUniformGroup(item);\r\n                }else if(item.type == \"UniformGroupArray\"){\r\n                    result[z] = parseUniformGroupArray(item);\r\n                }else{  \r\n                    result[z] = parsePrimitive(item);\r\n                }\r\n            }\r\n           \r\n            return new UniformGroup(result);\r\n        }\r\n\r\n        const parseUniformGroupArray = (o:any):UniformGroupArray=>{\r\n            let result = [];\r\n            for(let i=0;i<o.groups.length;i++){\r\n                result[i] = parseUniformGroup(o.groups[i]);\r\n            }\r\n            return new UniformGroupArray(result)\r\n        }\r\n\r\n\r\n\r\n        return parseObject(uniforms);\r\n    }\r\n\r\n\r\n\r\n    public static init(options?: { powerPreference?: \"low-power\" | \"high-performance\", forceFallbackAdaoter?: boolean }): Promise<void> {\r\n        this.requestAdapterOptions = options;\r\n        BuiltIns.__initDebug();\r\n        return new Promise(async (resolve: (val: any) => void, error: () => void) => {\r\n\r\n            if (this.gpuDevice) {\r\n                resolve(this);\r\n                return;\r\n            }\r\n\r\n            const adapter = await navigator.gpu.requestAdapter(options)\r\n            if (adapter) {\r\n                this.gpuDevice = await adapter.requestDevice();\r\n\r\n                this.deviceId++;\r\n                //console.log(\"get GPU device : \", this.deviceId)\r\n\r\n\r\n                this.deviceLost = false;\r\n\r\n                this.gpuDevice.lost.then((info) => {\r\n                    console.clear();\r\n                    console.error(`WebGPU device was lost: ${info.message}`);\r\n                    this.gpuDevice = null;\r\n                    this._ready = false;\r\n                    this.deviceLost = true;\r\n                    this.deviceLostTime = new Date().getTime();\r\n                    if (this.losingDevice || info.reason != 'destroyed') {\r\n\r\n                        this.losingDevice = false;\r\n                        XGPU.init(this.requestAdapterOptions);\r\n                    }\r\n                })\r\n\r\n                await WebGPUProperties.init();\r\n                this.debugUsage(172)\r\n                this._ready = true;\r\n                resolve(this);\r\n            } else {\r\n                error()\r\n            }\r\n        })\r\n    }\r\n\r\n    public static get device(): GPUDevice {\r\n        if (this.deviceLost) return null;\r\n        if (!this.gpuDevice && !this.ready) throw new Error(\"you must use XGPU.init() to get the reference of the gpuDevice\")\r\n        return this.gpuDevice;\r\n    }\r\n\r\n    private static _preferedCanvasFormat: GPUTextureFormat;\r\n\r\n    public static getPreferredCanvasFormat(): GPUTextureFormat {\r\n        if (!this._preferedCanvasFormat) this._preferedCanvasFormat = navigator.gpu.getPreferredCanvasFormat();\r\n        //console.warn(\"getPreferedCanvasFormat = \", this._preferedCanvasFormat)\r\n        return this._preferedCanvasFormat;\r\n    }\r\n\r\n    public static setPreferredCanvasFormat(format: GPUTextureFormat) {\r\n        this._preferedCanvasFormat = format;\r\n    }\r\n\r\n    public static destroy() {\r\n        if (this.gpuDevice) {\r\n            this.gpuDevice.destroy();\r\n            this.gpuDevice = null;\r\n            this._ready = false;\r\n        }\r\n    }\r\n\r\n    public static createBindgroup(o: any): GPUBindGroup {\r\n        return this.device.createBindGroup(o);\r\n    }\r\n    public static createBindgroupLayout(o: any): GPUBindGroupLayout {\r\n        return this.device.createBindGroupLayout(o);\r\n    }\r\n\r\n    public static createPipelineLayout(o: any): GPUPipelineLayout {\r\n        return this.device.createPipelineLayout(o);\r\n    }\r\n\r\n    public static createRenderPipeline(o: any): GPURenderPipeline {\r\n        return this.device.createRenderPipeline(o);\r\n    }\r\n    public static createComputePipeline(o: any): GPUComputePipeline {\r\n        return this.device.createComputePipeline(o);\r\n    }\r\n\r\n    public static createStagingBuffer(size: number): GPUBuffer {\r\n        return this.device.createBuffer({\r\n            size,\r\n            usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,\r\n            mappedAtCreation: false\r\n        })\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n}"
      }
    ],
    "blendmodes": {
      "AlphaBlendMode": [
        {
          "objectType": "class",
          "name": "AlphaBlendMode",
          "filePath": "xGPU.blendmodes.AlphaBlendMode",
          "extends": [
            "BlendMode"
          ],
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "rawText": "constructor() {\r\n        super();\r\n\r\n        this.color.operation = \"add\";\r\n        this.color.srcFactor = \"src-alpha\";\r\n        this.color.dstFactor = \"one-minus-src-alpha\";\r\n\r\n        this.alpha.operation = \"add\";\r\n        this.alpha.srcFactor = \"src-alpha\";\r\n        this.alpha.dstFactor = \"one-minus-src-alpha\";\r\n    }"
          },
          "rawText": "export class AlphaBlendMode extends BlendMode {\r\n\r\n    constructor() {\r\n        super();\r\n\r\n        this.color.operation = \"add\";\r\n        this.color.srcFactor = \"src-alpha\";\r\n        this.color.dstFactor = \"one-minus-src-alpha\";\r\n\r\n        this.alpha.operation = \"add\";\r\n        this.alpha.srcFactor = \"src-alpha\";\r\n        this.alpha.dstFactor = \"one-minus-src-alpha\";\r\n    }\r\n\r\n}"
        }
      ],
      "BlendMode": [
        {
          "objectType": "class",
          "name": "BlendMode",
          "filePath": "xGPU.blendmodes.BlendMode",
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "color",
                "type": "{ operation: \"add\" | \"subtract\" | \"reverse-subtract\" | \"min\" | \"max\"; srcFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\"; dstFactor: \"zero\" | ... 10 more ... | \"one-min...",
                "visibility": "public",
                "rawText": "public color: {\r\n        operation: \"add\" | \"subtract\" | \"reverse-subtract\" | \"min\" | \"max\",\r\n        srcFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\",\r\n        dstFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\",\r\n    } = { operation: \"add\", srcFactor: \"one\", dstFactor: \"zero\" }"
              },
              {
                "objectType": "property",
                "name": "alpha",
                "type": "{ operation: \"add\" | \"subtract\" | \"reverse-subtract\" | \"min\" | \"max\"; srcFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\"; dstFactor: \"zero\" | ... 10 more ... | \"one-min...",
                "visibility": "public",
                "rawText": "public alpha: {\r\n        operation: \"add\" | \"subtract\" | \"reverse-subtract\" | \"min\" | \"max\",\r\n        srcFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\",\r\n        dstFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\",\r\n    } = { operation: \"add\", srcFactor: \"one\", dstFactor: \"zero\" }"
              }
            ]
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "rawText": "constructor() {\r\n\r\n    }"
          },
          "rawText": "export abstract class BlendMode {\r\n\r\n    public color: {\r\n        operation: \"add\" | \"subtract\" | \"reverse-subtract\" | \"min\" | \"max\",\r\n        srcFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\",\r\n        dstFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\",\r\n    } = { operation: \"add\", srcFactor: \"one\", dstFactor: \"zero\" }\r\n\r\n    public alpha: {\r\n        operation: \"add\" | \"subtract\" | \"reverse-subtract\" | \"min\" | \"max\",\r\n        srcFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\",\r\n        dstFactor: \"zero\" | \"one\" | \"src\" | \"one-minus-src\" | \"src-alpha\" | \"one-minus-src-alpha\" | \"dst\" | \"one-minus-dst\" | \"one-minus-dst-alpha\" | \"src-alpha-saturated\" | \"constant\" | \"one-minus-constant\",\r\n    } = { operation: \"add\", srcFactor: \"one\", dstFactor: \"zero\" }\r\n\r\n    constructor() {\r\n\r\n    }\r\n}"
        }
      ]
    },
    "pipelines": {
      "ComputePipeline": [
        {
          "objectType": "class",
          "name": "ComputePipeline",
          "filePath": "xGPU.pipelines.ComputePipeline",
          "extends": [
            "Pipeline",
            "EventDispatcher"
          ],
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "computeShader",
                "type": "ComputeShader",
                "visibility": "public",
                "rawText": "public computeShader: ComputeShader;"
              },
              {
                "objectType": "property",
                "name": "workgroups",
                "type": "number[]",
                "visibility": "public",
                "rawText": "public workgroups: number[];"
              },
              {
                "objectType": "property",
                "name": "onComputeBegin",
                "type": "() => void",
                "visibility": "public",
                "rawText": "public onComputeBegin: () => void;"
              },
              {
                "objectType": "property",
                "name": "onComputeEnd",
                "type": "() => void",
                "visibility": "public",
                "rawText": "public onComputeEnd: () => void;"
              },
              {
                "objectType": "property",
                "name": "onShaderBuild",
                "type": "(shaderInfos: { code: string; }) => void",
                "visibility": "public",
                "rawText": "public onShaderBuild:(shaderInfos:{code:string})=>void;"
              },
              {
                "objectType": "property",
                "name": "useRenderPipeline",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public set useRenderPipeline(b: boolean) {\r\n        if (b) this.type = \"compute_mixed\";\r\n        else this.type = \"compute\";\r\n    }",
                "set": true
              }
            ],
            "private": [
              {
                "objectType": "property",
                "name": "firstFrame",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private firstFrame: boolean = true;"
              },
              {
                "objectType": "property",
                "name": "processingFirstFrame",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private processingFirstFrame: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "waitingFrame",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private waitingFrame: boolean = false;"
              }
            ],
            "protected": [
              {
                "objectType": "property",
                "name": "gpuComputePipeline",
                "type": "GPUComputePipeline",
                "visibility": "protected",
                "rawText": "protected gpuComputePipeline: GPUComputePipeline;"
              },
              {
                "objectType": "property",
                "name": "dispatchWorkgroup",
                "type": "number[]",
                "visibility": "protected",
                "rawText": "protected dispatchWorkgroup: number[];"
              },
              {
                "objectType": "property",
                "name": "bufferSize",
                "type": "number",
                "visibility": "protected",
                "rawText": "protected bufferSize: number;"
              },
              {
                "objectType": "property",
                "name": "textureSize",
                "type": "number[]",
                "visibility": "protected",
                "rawText": "protected textureSize: number[];"
              },
              {
                "objectType": "property",
                "name": "stagingBuffer",
                "type": "GPUBuffer",
                "visibility": "protected",
                "rawText": "protected stagingBuffer: GPUBuffer;"
              },
              {
                "objectType": "property",
                "name": "bufferIOs",
                "type": "VertexBuffer[]",
                "visibility": "protected",
                "rawText": "protected bufferIOs: VertexBuffer[];"
              },
              {
                "objectType": "property",
                "name": "textureIOs",
                "type": "ImageTexture[]",
                "visibility": "protected",
                "rawText": "protected textureIOs: ImageTexture[];"
              },
              {
                "objectType": "property",
                "name": "vertexBufferIOs",
                "type": "VertexBufferIO[]",
                "visibility": "protected",
                "rawText": "protected vertexBufferIOs: VertexBufferIO[] = [];"
              },
              {
                "objectType": "property",
                "name": "imageTextureIOs",
                "type": "ImageTextureIO[]",
                "visibility": "protected",
                "rawText": "protected imageTextureIOs: ImageTextureIO[] = [];"
              },
              {
                "objectType": "property",
                "name": "resourceIOs",
                "type": "(VertexBufferIO | ImageTextureIO)[]",
                "visibility": "protected",
                "rawText": "protected resourceIOs: (VertexBufferIO | ImageTextureIO)[] = [];"
              },
              {
                "objectType": "property",
                "name": "nbVertexMax",
                "type": "number",
                "visibility": "protected",
                "rawText": "protected nbVertexMax: number = 0;"
              },
              {
                "objectType": "property",
                "name": "widthMax",
                "type": "number",
                "visibility": "protected",
                "rawText": "protected widthMax: number = 0;"
              },
              {
                "objectType": "property",
                "name": "heightMax",
                "type": "number",
                "visibility": "protected",
                "rawText": "protected heightMax: number = 0;"
              },
              {
                "objectType": "property",
                "name": "deviceId",
                "type": "number",
                "visibility": "protected",
                "rawText": "protected deviceId: number;"
              },
              {
                "objectType": "property",
                "name": "lastFrameTime",
                "type": "number",
                "visibility": "protected",
                "rawText": "protected lastFrameTime: number = -1;"
              },
              {
                "objectType": "property",
                "name": "rebuildingAfterDeviceLost",
                "type": "boolean",
                "visibility": "protected",
                "rawText": "protected rebuildingAfterDeviceLost: boolean = false;"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "initFromObject",
                "returnType": "{ [key: string]: unknown; bindgroups?: any; computeShader: string | ComputeShader | { outputs?: any; main: string; inputs?: any; constants?: string; }; }",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "{ [key: string]: unknown; bindgroups?: any; computeShader: string | ComputeShader | { outputs?: any; main: string; inputs?: any; constants?: string; }; }"
                  }
                ],
                "visibility": "public",
                "rawText": "public initFromObject(descriptor: {\r\n        bindgroups?: any,\r\n        computeShader: {\r\n            outputs?: any,\r\n            main: string\r\n            inputs?: any,\r\n            constants?: string,\r\n        } | string | ComputeShader,\r\n        [key: string]: unknown\r\n    }) {\r\n\r\n\r\n        this._resources = {};\r\n        this.vertexShader = null;\r\n        this.fragmentShader = null;\r\n\r\n        this.bindGroups.destroy();\r\n        this.bindGroups = new Bindgroups(this, \"pipeline\");\r\n\r\n        descriptor = HighLevelParser.parse(descriptor, \"compute\");\r\n\r\n        super.initFromObject(descriptor);\r\n\r\n\r\n        if (descriptor.bindgroups) {\r\n            let group: Bindgroup;\r\n            for (let z in descriptor.bindgroups) {\r\n                group = new Bindgroup();\r\n                group.name = z;\r\n                group.initFromObject(descriptor.bindgroups[z]);\r\n                this.bindGroups.add(group);\r\n            }\r\n\r\n            if (descriptor.bindgroups.default) {\r\n                if (descriptor.bindgroups.default.buffer) {\r\n                    const attributes = (descriptor.bindgroups.default.buffer as VertexBuffer).attributes;\r\n                    for (let z in attributes) {\r\n                        if (descriptor[z]) descriptor[z] = attributes[z];\r\n                    }\r\n                }\r\n            }\r\n\r\n        }\r\n\r\n        const createArrayOfObjects = (obj: any) => {\r\n            const result = [];\r\n            let o: any;\r\n            for (let z in obj) {\r\n                o = obj[z];\r\n                result.push({ name: z, ...o })\r\n            }\r\n            return result;\r\n        }\r\n\r\n\r\n        this.computeShader = new ComputeShader();\r\n       \r\n        if (typeof descriptor.computeShader === \"string\") {\r\n            this.computeShader.main.text = descriptor.computeShader;\r\n        } else {\r\n\r\n            if(descriptor.computeShader instanceof ComputeShader){\r\n                this.computeShader = descriptor.computeShader;\r\n            }else{\r\n                if (descriptor.computeShader.constants) this.computeShader.constants.text = descriptor.computeShader.constants;\r\n                this.computeShader.main.text = descriptor.computeShader.main;\r\n            }\r\n            \r\n            this.computeShader.inputs = createArrayOfObjects(descriptor.computeShader.inputs);\r\n            this.computeShader.outputs = createArrayOfObjects(descriptor.computeShader.outputs);\r\n           \r\n        }\r\n\r\n\r\n        let vertexBufferReadyToUse: boolean = true;\r\n        for (let bufferName in this.resources.bindgroups.io) {\r\n            if (!this.resources.bindgroups.io[bufferName].data) {\r\n                vertexBufferReadyToUse = false;\r\n            }\r\n        }\r\n\r\n\r\n        if (vertexBufferReadyToUse) this.nextFrame()\r\n        \r\n        this.dispatchEvent(ComputePipeline.ON_INIT_FROM_OBJECT,descriptor);\r\n        return descriptor;\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "destroy",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public destroy() {\r\n        this.bindGroups.destroy();\r\n        for (let z in this.description) this.description[z] = null;\r\n        for (let z in this) {\r\n            try {\r\n                (this[z] as any).destroy();\r\n            } catch (e) {\r\n                try {\r\n                    (this[z] as any).destroyGpuResource();\r\n                } catch (e) {\r\n\r\n                }\r\n            }\r\n            this[z] = null;\r\n        }\r\n        this.dispatchEvent(ComputePipeline.ON_DESTROY);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setWorkgroups",
                "returnType": "void",
                "params": [
                  {
                    "name": "x",
                    "type": "number"
                  },
                  {
                    "name": "y",
                    "type": "number"
                  },
                  {
                    "name": "z",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public setWorkgroups(x: number, y: number = 1, z: number = 1) {\r\n        this.workgroups = [x, y, z];\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setDispatchWorkgroup",
                "returnType": "void",
                "params": [
                  {
                    "name": "x",
                    "type": "number"
                  },
                  {
                    "name": "y",
                    "type": "number"
                  },
                  {
                    "name": "z",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public setDispatchWorkgroup(x: number = 1, y: number = 1, z: number = 1) {\r\n        this.dispatchWorkgroup = [x, y, z];\r\n    }"
              },
              {
                "objectType": "method",
                "name": "update",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public update(): void {\r\n        if (!this.gpuComputePipeline) return;\r\n\r\n        if (this.deviceId !== XGPU.deviceId) {\r\n            this.deviceId = XGPU.deviceId;\r\n            this.dispatchEvent(ComputePipeline.ON_DEVICE_LOST);\r\n\r\n            this.clearAfterDeviceLostAndRebuild();\r\n            if (new Date().getTime() - this.lastFrameTime < 100) {\r\n\r\n                this.nextFrame();\r\n            }\r\n        }\r\n        //console.log(\"update \", this.bindGroups)\r\n        this.bindGroups.update();\r\n        this.lastFrameTime = new Date().getTime();\r\n    }"
              },
              {
                "objectType": "method",
                "name": "clearAfterDeviceLostAndRebuild",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public clearAfterDeviceLostAndRebuild() {\r\n        console.warn(\"ComputePipeline.clearAfterDeviceLostAndRebuild()\")\r\n        this.gpuComputePipeline = null;\r\n\r\n        this.rebuildingAfterDeviceLost = true;\r\n        super.clearAfterDeviceLostAndRebuild();\r\n\r\n\r\n        //this.buildGpuPipeline();\r\n    }"
              },
              {
                "objectType": "method",
                "name": "buildGpuPipeline",
                "returnType": "GPUComputePipeline",
                "visibility": "public",
                "rawText": "public buildGpuPipeline() {\r\n        //console.log(\"buildGpuPipeline \", this.gpuComputePipeline)\r\n        if (this.gpuComputePipeline) return this.gpuComputePipeline;\r\n\r\n\r\n        this.initPipelineResources(this);\r\n\r\n\r\n        this.createLayouts();\r\n        this.bindGroups.handleComputePipelineResourceIOs();\r\n\r\n        this.initResourceIOs();\r\n\r\n        if (!this.workgroups) this.setupDefaultWorkgroups();\r\n\r\n        this.bindGroups.build();\r\n\r\n\r\n        const outputs = this.computeShader.outputs;\r\n        const inputs = this.computeShader.inputs;\r\n\r\n\r\n        for (let i = 0; i < outputs.length; i++) {\r\n            if (outputs[i].type.createGpuResource) { //it's a pipeline resource\r\n                (outputs[i] as any).isOutput = true;\r\n                inputs.push(outputs[i]);\r\n            }\r\n        }\r\n\r\n        \r\n        let resources:{name:string,resource:any}[][] = this.bindGroups.resources.types;\r\n        for(let type in resources){\r\n            (resources[type] as any[]).forEach((o)=>{\r\n                o.resource.gpuResource.label = o.name;\r\n            });\r\n        }\r\n\r\n        \r\n        \r\n\r\n\r\n        const inputStruct: ShaderStruct = new ShaderStruct(\"Input\", [...inputs]);;\r\n        const shaderInfos = this.computeShader.build(this, inputStruct)\r\n\r\n        this.dispatchEvent(ComputePipeline.ON_COMPUTE_SHADER_CODE_BUILT,shaderInfos)\r\n        if(this.onShaderBuild) this.onShaderBuild(shaderInfos);\r\n\r\n        this.description.compute = {\r\n            module: XGPU.device.createShaderModule({ code: shaderInfos.code }),\r\n            entryPoint: \"main\"\r\n        }\r\n        this.description.layout = this.gpuPipelineLayout;\r\n\r\n        //console.log(\"description = \", this.description)\r\n        this.deviceId = XGPU.deviceId;\r\n        this.gpuComputePipeline = XGPU.createComputePipeline(this.description);\r\n\r\n        this.dispatchEvent(ComputePipeline.ON_GPU_PIPELINE_BUILT);\r\n\r\n        return this.gpuComputePipeline;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "nextFrame",
                "returnType": "Promise<void>",
                "visibility": "public",
                "rawText": "public async nextFrame() {\r\n\r\n        if (this.processingFirstFrame) {\r\n            this.waitingFrame = true;\r\n            return;\r\n        }\r\n\r\n        this.dispatchEvent(ComputePipeline.ON_COMPUTE_BEGIN);\r\n        if (this.onComputeBegin) this.onComputeBegin();\r\n\r\n        this.processingFirstFrame = this.firstFrame;\r\n\r\n\r\n\r\n        this.update();\r\n        \r\n\r\n        const commandEncoder = XGPU.device.createCommandEncoder();\r\n        const computePass = commandEncoder.beginComputePass();\r\n        computePass.setPipeline(this.buildGpuPipeline());\r\n\r\n        //console.log(this.dispatchWorkgroup[0]*64)\r\n        this.bindGroups.update();\r\n        this.bindGroups.apply(computePass)\r\n        computePass.dispatchWorkgroups(this.dispatchWorkgroup[0], this.dispatchWorkgroup[1], this.dispatchWorkgroup[2]);\r\n        computePass.end();\r\n\r\n        this.dispatchEvent(ComputePipeline.ON_SUBMIT_QUEUE);\r\n        XGPU.device.queue.submit([commandEncoder.finish()]);\r\n\r\n        \r\n\r\n\r\n\r\n        if (this.firstFrame) {\r\n            await XGPU.device.queue.onSubmittedWorkDone()\r\n        }\r\n\r\n        \r\n        for (let i = 0; i < this.resourceIOs.length; i++) {\r\n            this.resourceIOs[i].getOutputData();\r\n        }\r\n\r\n       \r\n        (this.bindGroups.resources.all as any[]).forEach((o)=>{\r\n            if(o instanceof VertexBuffer){\r\n                if(o.resourceIO == null){\r\n                    o.getOutputData(o.gpuResource);\r\n                }\r\n            }else if(o.getOutputData) o.getOutputData(o.gpuResource);\r\n        })\r\n\r\n        /*\r\n        for(let i=0;i<this.vertexBuffers.length;i++){\r\n            this.vertexBuffers[i].getOutputData();\r\n        }\r\n        */\r\n\r\n\r\n\r\n        this.firstFrame = false;\r\n        this.processingFirstFrame = false;\r\n        this.dispatchEvent(ComputePipeline.ON_COMPUTE_END);\r\n        if (this.onComputeEnd) this.onComputeEnd();\r\n\r\n\r\n        if (this.waitingFrame) {\r\n            this.waitingFrame = false;\r\n            this.nextFrame()\r\n        }\r\n\r\n\r\n    }"
              }
            ],
            "protected": [
              {
                "objectType": "method",
                "name": "initResourceIOs",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected initResourceIOs() {\r\n        const resources = this.bindGroups.resources.io;\r\n        if (!resources) return;\r\n\r\n        let res: VertexBuffer | ImageTexture;\r\n        let io: VertexBufferIO | ImageTextureIO;\r\n\r\n        //console.log(\"IOOOO = \", resources)\r\n\r\n        for (let z in resources) {\r\n            res = resources[z];\r\n            io = res.resourceIO;\r\n\r\n\r\n\r\n            if (io instanceof VertexBufferIO) {\r\n                if (this.vertexBufferIOs.indexOf(io) === -1) {\r\n                    this.resourceIOs.push(io);\r\n                    if (io.nbVertex > this.nbVertexMax) this.nbVertexMax = io.nbVertex;\r\n                    this.vertexBufferIOs.push(io);\r\n                }\r\n            } else if (io instanceof ImageTextureIO) {\r\n\r\n                if (this.imageTextureIOs.indexOf(io) === -1) {\r\n                    this.resourceIOs.push(io);\r\n                    if (io.width > this.widthMax) this.widthMax = io.width;\r\n                    if (io.height > this.heightMax) this.heightMax = io.height;\r\n                    this.imageTextureIOs.push(io);\r\n                }\r\n            } else {\r\n\r\n            }\r\n        }\r\n\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupDefaultWorkgroups",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected setupDefaultWorkgroups() {\r\n\r\n        if (this.vertexBufferIOs.length) {\r\n\r\n            let n = 64;\r\n            while (this.nbVertexMax / n >= 65536) n *= 2;\r\n\r\n            this.setWorkgroups(n);\r\n            this.setDispatchWorkgroup(Math.ceil(this.nbVertexMax / n));\r\n\r\n        } else {\r\n\r\n            this.setWorkgroups(1);\r\n            this.setDispatchWorkgroup(this.widthMax, this.heightMax);\r\n        }\r\n\r\n    }"
              }
            ]
          },
          "statics": {
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "ON_COMPUTE_SHADER_CODE_BUILT",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_COMPUTE_SHADER_CODE_BUILT:string = \"ON_COMPUTE_SHADER_CODE_BUILT\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_COMPUTE_BEGIN",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_COMPUTE_BEGIN: string = \"ON_COMPUTE_BEGIN\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_COMPUTE_END",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_COMPUTE_END: string = \"ON_COMPUTE_END\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_GPU_PIPELINE_BUILT",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_GPU_PIPELINE_BUILT: string = \"ON_GPU_PIPELINE_BUILT\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_INIT_FROM_OBJECT",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_INIT_FROM_OBJECT:string = \"ON_INIT_FROM_OBJECT\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_DESTROY",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_DESTROY:string = \"ON_DESTROY\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_DEVICE_LOST",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_DEVICE_LOST:string = \"ON_DEVICE_LOST\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_UPDATE_RESOURCES",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_UPDATE_RESOURCES:string = \"ON_UPDATE_RESOURCES\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_SUBMIT_QUEUE",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_SUBMIT_QUEUE:string = \"ON_SUBMIT_QUEUE\";"
                }
              ]
            }
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "rawText": "constructor() {\r\n        super()\r\n        //this.computeShader = new ComputeShader();\r\n        this.type = \"compute\";\r\n    }"
          },
          "rawText": "export class ComputePipeline extends Pipeline {\r\n\r\n    public static ON_COMPUTE_SHADER_CODE_BUILT:string = \"ON_COMPUTE_SHADER_CODE_BUILT\";\r\n    public static ON_COMPUTE_BEGIN: string = \"ON_COMPUTE_BEGIN\";\r\n    public static ON_COMPUTE_END: string = \"ON_COMPUTE_END\";\r\n    public static ON_GPU_PIPELINE_BUILT: string = \"ON_GPU_PIPELINE_BUILT\";\r\n    public static ON_INIT_FROM_OBJECT:string = \"ON_INIT_FROM_OBJECT\";\r\n    public static ON_DESTROY:string = \"ON_DESTROY\";\r\n    public static ON_DEVICE_LOST:string = \"ON_DEVICE_LOST\";\r\n    public static ON_UPDATE_RESOURCES:string = \"ON_UPDATE_RESOURCES\";\r\n    public static ON_SUBMIT_QUEUE:string = \"ON_SUBMIT_QUEUE\";\r\n\r\n    public computeShader: ComputeShader;\r\n    //public onReceiveData: (datas: Float32Array) => void;\r\n\r\n    protected gpuComputePipeline: GPUComputePipeline;\r\n    public workgroups: number[];\r\n    protected dispatchWorkgroup: number[];\r\n    protected bufferSize: number;\r\n    protected textureSize: number[];// [width,height]\r\n    protected stagingBuffer: GPUBuffer;\r\n\r\n    protected bufferIOs: VertexBuffer[];\r\n    protected textureIOs: ImageTexture[];\r\n\r\n    public onComputeBegin: () => void;\r\n    public onComputeEnd: () => void;\r\n\r\n    public onShaderBuild:(shaderInfos:{code:string})=>void;\r\n\r\n    constructor() {\r\n        super()\r\n        //this.computeShader = new ComputeShader();\r\n        this.type = \"compute\";\r\n    }\r\n\r\n    public set useRenderPipeline(b: boolean) {\r\n        if (b) this.type = \"compute_mixed\";\r\n        else this.type = \"compute\";\r\n    }\r\n\r\n    public initFromObject(descriptor: {\r\n        bindgroups?: any,\r\n        computeShader: {\r\n            outputs?: any,\r\n            main: string\r\n            inputs?: any,\r\n            constants?: string,\r\n        } | string | ComputeShader,\r\n        [key: string]: unknown\r\n    }) {\r\n\r\n\r\n        this._resources = {};\r\n        this.vertexShader = null;\r\n        this.fragmentShader = null;\r\n\r\n        this.bindGroups.destroy();\r\n        this.bindGroups = new Bindgroups(this, \"pipeline\");\r\n\r\n        descriptor = HighLevelParser.parse(descriptor, \"compute\");\r\n\r\n        super.initFromObject(descriptor);\r\n\r\n\r\n        if (descriptor.bindgroups) {\r\n            let group: Bindgroup;\r\n            for (let z in descriptor.bindgroups) {\r\n                group = new Bindgroup();\r\n                group.name = z;\r\n                group.initFromObject(descriptor.bindgroups[z]);\r\n                this.bindGroups.add(group);\r\n            }\r\n\r\n            if (descriptor.bindgroups.default) {\r\n                if (descriptor.bindgroups.default.buffer) {\r\n                    const attributes = (descriptor.bindgroups.default.buffer as VertexBuffer).attributes;\r\n                    for (let z in attributes) {\r\n                        if (descriptor[z]) descriptor[z] = attributes[z];\r\n                    }\r\n                }\r\n            }\r\n\r\n        }\r\n\r\n        const createArrayOfObjects = (obj: any) => {\r\n            const result = [];\r\n            let o: any;\r\n            for (let z in obj) {\r\n                o = obj[z];\r\n                result.push({ name: z, ...o })\r\n            }\r\n            return result;\r\n        }\r\n\r\n\r\n        this.computeShader = new ComputeShader();\r\n       \r\n        if (typeof descriptor.computeShader === \"string\") {\r\n            this.computeShader.main.text = descriptor.computeShader;\r\n        } else {\r\n\r\n            if(descriptor.computeShader instanceof ComputeShader){\r\n                this.computeShader = descriptor.computeShader;\r\n            }else{\r\n                if (descriptor.computeShader.constants) this.computeShader.constants.text = descriptor.computeShader.constants;\r\n                this.computeShader.main.text = descriptor.computeShader.main;\r\n            }\r\n            \r\n            this.computeShader.inputs = createArrayOfObjects(descriptor.computeShader.inputs);\r\n            this.computeShader.outputs = createArrayOfObjects(descriptor.computeShader.outputs);\r\n           \r\n        }\r\n\r\n\r\n        let vertexBufferReadyToUse: boolean = true;\r\n        for (let bufferName in this.resources.bindgroups.io) {\r\n            if (!this.resources.bindgroups.io[bufferName].data) {\r\n                vertexBufferReadyToUse = false;\r\n            }\r\n        }\r\n\r\n\r\n        if (vertexBufferReadyToUse) this.nextFrame()\r\n        \r\n        this.dispatchEvent(ComputePipeline.ON_INIT_FROM_OBJECT,descriptor);\r\n        return descriptor;\r\n\r\n    }\r\n\r\n    public destroy() {\r\n        this.bindGroups.destroy();\r\n        for (let z in this.description) this.description[z] = null;\r\n        for (let z in this) {\r\n            try {\r\n                (this[z] as any).destroy();\r\n            } catch (e) {\r\n                try {\r\n                    (this[z] as any).destroyGpuResource();\r\n                } catch (e) {\r\n\r\n                }\r\n            }\r\n            this[z] = null;\r\n        }\r\n        this.dispatchEvent(ComputePipeline.ON_DESTROY);\r\n    }\r\n\r\n\r\n    public setWorkgroups(x: number, y: number = 1, z: number = 1) {\r\n        this.workgroups = [x, y, z];\r\n    }\r\n\r\n\r\n    public setDispatchWorkgroup(x: number = 1, y: number = 1, z: number = 1) {\r\n        this.dispatchWorkgroup = [x, y, z];\r\n    }\r\n\r\n\r\n    protected vertexBufferIOs: VertexBufferIO[] = [];\r\n    protected imageTextureIOs: ImageTextureIO[] = [];\r\n    protected resourceIOs: (VertexBufferIO | ImageTextureIO)[] = [];\r\n    protected nbVertexMax: number = 0;\r\n    protected widthMax: number = 0;\r\n    protected heightMax: number = 0;\r\n\r\n    protected initResourceIOs() {\r\n        const resources = this.bindGroups.resources.io;\r\n        if (!resources) return;\r\n\r\n        let res: VertexBuffer | ImageTexture;\r\n        let io: VertexBufferIO | ImageTextureIO;\r\n\r\n        //console.log(\"IOOOO = \", resources)\r\n\r\n        for (let z in resources) {\r\n            res = resources[z];\r\n            io = res.resourceIO;\r\n\r\n\r\n\r\n            if (io instanceof VertexBufferIO) {\r\n                if (this.vertexBufferIOs.indexOf(io) === -1) {\r\n                    this.resourceIOs.push(io);\r\n                    if (io.nbVertex > this.nbVertexMax) this.nbVertexMax = io.nbVertex;\r\n                    this.vertexBufferIOs.push(io);\r\n                }\r\n            } else if (io instanceof ImageTextureIO) {\r\n\r\n                if (this.imageTextureIOs.indexOf(io) === -1) {\r\n                    this.resourceIOs.push(io);\r\n                    if (io.width > this.widthMax) this.widthMax = io.width;\r\n                    if (io.height > this.heightMax) this.heightMax = io.height;\r\n                    this.imageTextureIOs.push(io);\r\n                }\r\n            } else {\r\n\r\n            }\r\n        }\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n    protected deviceId: number;\r\n    protected lastFrameTime: number = -1;\r\n\r\n    public update(): void {\r\n        if (!this.gpuComputePipeline) return;\r\n\r\n        if (this.deviceId !== XGPU.deviceId) {\r\n            this.deviceId = XGPU.deviceId;\r\n            this.dispatchEvent(ComputePipeline.ON_DEVICE_LOST);\r\n\r\n            this.clearAfterDeviceLostAndRebuild();\r\n            if (new Date().getTime() - this.lastFrameTime < 100) {\r\n\r\n                this.nextFrame();\r\n            }\r\n        }\r\n        //console.log(\"update \", this.bindGroups)\r\n        this.bindGroups.update();\r\n        this.lastFrameTime = new Date().getTime();\r\n    }\r\n\r\n\r\n    protected setupDefaultWorkgroups() {\r\n\r\n        if (this.vertexBufferIOs.length) {\r\n\r\n            let n = 64;\r\n            while (this.nbVertexMax / n >= 65536) n *= 2;\r\n\r\n            this.setWorkgroups(n);\r\n            this.setDispatchWorkgroup(Math.ceil(this.nbVertexMax / n));\r\n\r\n        } else {\r\n\r\n            this.setWorkgroups(1);\r\n            this.setDispatchWorkgroup(this.widthMax, this.heightMax);\r\n        }\r\n\r\n    }\r\n\r\n\r\n\r\n    protected rebuildingAfterDeviceLost: boolean = false;\r\n    public clearAfterDeviceLostAndRebuild() {\r\n        console.warn(\"ComputePipeline.clearAfterDeviceLostAndRebuild()\")\r\n        this.gpuComputePipeline = null;\r\n\r\n        this.rebuildingAfterDeviceLost = true;\r\n        super.clearAfterDeviceLostAndRebuild();\r\n\r\n\r\n        //this.buildGpuPipeline();\r\n    }\r\n\r\n\r\n    \r\n    public buildGpuPipeline() {\r\n        //console.log(\"buildGpuPipeline \", this.gpuComputePipeline)\r\n        if (this.gpuComputePipeline) return this.gpuComputePipeline;\r\n\r\n\r\n        this.initPipelineResources(this);\r\n\r\n\r\n        this.createLayouts();\r\n        this.bindGroups.handleComputePipelineResourceIOs();\r\n\r\n        this.initResourceIOs();\r\n\r\n        if (!this.workgroups) this.setupDefaultWorkgroups();\r\n\r\n        this.bindGroups.build();\r\n\r\n\r\n        const outputs = this.computeShader.outputs;\r\n        const inputs = this.computeShader.inputs;\r\n\r\n\r\n        for (let i = 0; i < outputs.length; i++) {\r\n            if (outputs[i].type.createGpuResource) { //it's a pipeline resource\r\n                (outputs[i] as any).isOutput = true;\r\n                inputs.push(outputs[i]);\r\n            }\r\n        }\r\n\r\n        \r\n        let resources:{name:string,resource:any}[][] = this.bindGroups.resources.types;\r\n        for(let type in resources){\r\n            (resources[type] as any[]).forEach((o)=>{\r\n                o.resource.gpuResource.label = o.name;\r\n            });\r\n        }\r\n\r\n        \r\n        \r\n\r\n\r\n        const inputStruct: ShaderStruct = new ShaderStruct(\"Input\", [...inputs]);;\r\n        const shaderInfos = this.computeShader.build(this, inputStruct)\r\n\r\n        this.dispatchEvent(ComputePipeline.ON_COMPUTE_SHADER_CODE_BUILT,shaderInfos)\r\n        if(this.onShaderBuild) this.onShaderBuild(shaderInfos);\r\n\r\n        this.description.compute = {\r\n            module: XGPU.device.createShaderModule({ code: shaderInfos.code }),\r\n            entryPoint: \"main\"\r\n        }\r\n        this.description.layout = this.gpuPipelineLayout;\r\n\r\n        //console.log(\"description = \", this.description)\r\n        this.deviceId = XGPU.deviceId;\r\n        this.gpuComputePipeline = XGPU.createComputePipeline(this.description);\r\n\r\n        this.dispatchEvent(ComputePipeline.ON_GPU_PIPELINE_BUILT);\r\n\r\n        return this.gpuComputePipeline;\r\n    }\r\n\r\n\r\n\r\n\r\n    \r\n\r\n\r\n\r\n    private firstFrame: boolean = true;\r\n    private processingFirstFrame: boolean = false;\r\n    private waitingFrame: boolean = false;\r\n    public async nextFrame() {\r\n\r\n        if (this.processingFirstFrame) {\r\n            this.waitingFrame = true;\r\n            return;\r\n        }\r\n\r\n        this.dispatchEvent(ComputePipeline.ON_COMPUTE_BEGIN);\r\n        if (this.onComputeBegin) this.onComputeBegin();\r\n\r\n        this.processingFirstFrame = this.firstFrame;\r\n\r\n\r\n\r\n        this.update();\r\n        \r\n\r\n        const commandEncoder = XGPU.device.createCommandEncoder();\r\n        const computePass = commandEncoder.beginComputePass();\r\n        computePass.setPipeline(this.buildGpuPipeline());\r\n\r\n        //console.log(this.dispatchWorkgroup[0]*64)\r\n        this.bindGroups.update();\r\n        this.bindGroups.apply(computePass)\r\n        computePass.dispatchWorkgroups(this.dispatchWorkgroup[0], this.dispatchWorkgroup[1], this.dispatchWorkgroup[2]);\r\n        computePass.end();\r\n\r\n        this.dispatchEvent(ComputePipeline.ON_SUBMIT_QUEUE);\r\n        XGPU.device.queue.submit([commandEncoder.finish()]);\r\n\r\n        \r\n\r\n\r\n\r\n        if (this.firstFrame) {\r\n            await XGPU.device.queue.onSubmittedWorkDone()\r\n        }\r\n\r\n        \r\n        for (let i = 0; i < this.resourceIOs.length; i++) {\r\n            this.resourceIOs[i].getOutputData();\r\n        }\r\n\r\n       \r\n        (this.bindGroups.resources.all as any[]).forEach((o)=>{\r\n            if(o instanceof VertexBuffer){\r\n                if(o.resourceIO == null){\r\n                    o.getOutputData(o.gpuResource);\r\n                }\r\n            }else if(o.getOutputData) o.getOutputData(o.gpuResource);\r\n        })\r\n\r\n        /*\r\n        for(let i=0;i<this.vertexBuffers.length;i++){\r\n            this.vertexBuffers[i].getOutputData();\r\n        }\r\n        */\r\n\r\n\r\n\r\n        this.firstFrame = false;\r\n        this.processingFirstFrame = false;\r\n        this.dispatchEvent(ComputePipeline.ON_COMPUTE_END);\r\n        if (this.onComputeEnd) this.onComputeEnd();\r\n\r\n\r\n        if (this.waitingFrame) {\r\n            this.waitingFrame = false;\r\n            this.nextFrame()\r\n        }\r\n\r\n\r\n    }\r\n\r\n}"
        }
      ],
      "Pipeline": [
        {
          "objectType": "class",
          "name": "Pipeline",
          "filePath": "xGPU.pipelines.Pipeline",
          "extends": [
            "EventDispatcher"
          ],
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "description",
                "type": "any",
                "visibility": "public",
                "rawText": "public description: any = {};"
              },
              {
                "objectType": "property",
                "name": "nbVertex",
                "type": "number",
                "visibility": "public",
                "rawText": "public nbVertex: number;"
              },
              {
                "objectType": "property",
                "name": "bindGroups",
                "type": "Bindgroups",
                "visibility": "public",
                "rawText": "public bindGroups: Bindgroups;"
              },
              {
                "objectType": "property",
                "name": "vertexBuffers",
                "type": "VertexBuffer[]",
                "visibility": "public",
                "rawText": "public vertexBuffers: VertexBuffer[];"
              },
              {
                "objectType": "property",
                "name": "vertexShader",
                "type": "VertexShader",
                "visibility": "public",
                "rawText": "public vertexShader: VertexShader;"
              },
              {
                "objectType": "property",
                "name": "fragmentShader",
                "type": "FragmentShader",
                "visibility": "public",
                "rawText": "public fragmentShader: FragmentShader;"
              },
              {
                "objectType": "property",
                "name": "type",
                "type": "\"render\" | \"compute\" | \"compute_mixed\"",
                "visibility": "public",
                "rawText": "public type: \"compute\" | \"compute_mixed\" | \"render\" = null;"
              },
              {
                "objectType": "property",
                "name": "isComputePipeline",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public get isComputePipeline(): boolean { return this.type === \"compute\" || this.type === \"compute_mixed\"; }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "isRenderPipeline",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public get isRenderPipeline(): boolean { return this.type === \"render\"; }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "isMixedPipeline",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public get isMixedPipeline(): boolean { return this.type === \"compute_mixed\"; }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "resources",
                "type": "any",
                "visibility": "public",
                "rawText": "public get resources(): any { return this._resources; }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "debug",
                "type": "string",
                "visibility": "public",
                "rawText": "public debug: string;"
              },
              {
                "objectType": "property",
                "name": "pipelineCount",
                "type": "number",
                "visibility": "public",
                "rawText": "public pipelineCount: number = 1;"
              }
            ],
            "protected": [
              {
                "objectType": "property",
                "name": "vertexBufferLayouts",
                "type": "Iterable<GPUVertexBufferLayout>",
                "visibility": "protected",
                "rawText": "protected vertexBufferLayouts: Iterable<GPUVertexBufferLayout>;"
              },
              {
                "objectType": "property",
                "name": "gpuBindgroups",
                "type": "GPUBindGroup[]",
                "visibility": "protected",
                "rawText": "protected gpuBindgroups: GPUBindGroup[] = [];"
              },
              {
                "objectType": "property",
                "name": "gpuBindGroupLayouts",
                "type": "GPUBindGroupLayout[]",
                "visibility": "protected",
                "rawText": "protected gpuBindGroupLayouts: GPUBindGroupLayout[] = [];"
              },
              {
                "objectType": "property",
                "name": "gpuPipelineLayout",
                "type": "GPUPipelineLayout",
                "visibility": "protected",
                "rawText": "protected gpuPipelineLayout: GPUPipelineLayout;"
              },
              {
                "objectType": "property",
                "name": "_resources",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected _resources: any;"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "clearAfterDeviceLostAndRebuild",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public clearAfterDeviceLostAndRebuild() {\r\n\r\n        this.bindGroups.clearAfterDeviceLost()\r\n        this.vertexBufferLayouts = undefined;\r\n        this.gpuPipelineLayout = undefined;\r\n        this.gpuBindGroupLayouts = [];\r\n        this.gpuBindgroups = [];\r\n\r\n        //this.build();\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "initFromObject",
                "returnType": "void",
                "params": [
                  {
                    "name": "obj",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public initFromObject(obj: any) {\r\n\r\n        this._resources = obj;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "addBindgroup",
                "returnType": "void",
                "params": [
                  {
                    "name": "group",
                    "type": "Bindgroup"
                  }
                ],
                "visibility": "public",
                "rawText": "public addBindgroup(group: Bindgroup) {\r\n        this.bindGroups.add(group);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "update",
                "returnType": "void",
                "params": [
                  {
                    "name": "o",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public update(o?: any) {\r\n        if (o) {\r\n\r\n        }\r\n        //must be overided\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getResourceName",
                "returnType": "string",
                "params": [
                  {
                    "name": "resource",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public getResourceName(resource: any) {\r\n\r\n        if (resource instanceof VertexAttribute) {\r\n            if (this.type !== \"render\") {\r\n                const buffer: VertexBuffer = resource.vertexBuffer;\r\n                const bufferName: string = this.bindGroups.getNameByResource(buffer);\r\n                return bufferName + \".\" + resource.name;\r\n            } else {\r\n                return resource.name;\r\n            }\r\n        } else {\r\n\r\n            if (resource.uniformBuffer) {\r\n                const bufferName: string = this.bindGroups.getNameByResource(resource.uniformBuffer);\r\n                return bufferName + \".\" + resource.name;\r\n            } else {\r\n                return this.bindGroups.getNameByResource(resource);\r\n            }\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createPipelineInstanceArray",
                "returnType": "any[]",
                "params": [
                  {
                    "name": "resources",
                    "type": "(PrimitiveFloatUniform | PrimitiveIntUniform | PrimitiveUintUniform | IShaderResource)[]"
                  },
                  {
                    "name": "nbInstance",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public createPipelineInstanceArray(resources: (PrimitiveFloatUniform | PrimitiveIntUniform | PrimitiveUintUniform | IShaderResource)[], nbInstance: number): any[] {\r\n        this.pipelineCount = nbInstance;\r\n\r\n        const result: any[] = [];\r\n\r\n        let instance: any;\r\n        let resource: any\r\n        let clonedUniformBuffers: any;\r\n\r\n\r\n        const resourceNames: string[] = [];\r\n        const resourceBindgroup: Bindgroup[] = [];\r\n        const resourceUniformBufferName: string[] = [];\r\n        for (let i = 0; i < resources.length; i++) {\r\n            resource = resources[i];\r\n            const name = this.bindGroups.getNameByResource(resource);\r\n\r\n            const bindgroup = this.bindGroups.getGroupByPropertyName(name);\r\n            bindgroup.mustRefreshBindgroup = true;\r\n\r\n            resourceNames[i] = name;\r\n            resourceBindgroup[i] = bindgroup;\r\n\r\n            if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n                resourceUniformBufferName[i] = bindgroup.getResourceName(resource.uniformBuffer);\r\n            }\r\n        }\r\n\r\n\r\n\r\n        for (let k = 0; k < nbInstance; k++) {\r\n            result[k] = instance = {};\r\n            clonedUniformBuffers = {};\r\n\r\n            for (let i = 0; i < resources.length; i++) {\r\n\r\n\r\n                resource = resources[i];\r\n                resource.update();\r\n                const name = resourceNames[i];\r\n                const bindgroup = resourceBindgroup[i];\r\n\r\n                //console.log(\"resource = \", resource)\r\n\r\n\r\n                if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n                    const uniformBufferName = resourceUniformBufferName[i];//bindgroup.getResourceName(resource.uniformBuffer);\r\n                    //console.log(\"uniformBufferName = \", uniformBufferName, name)\r\n                    if (!clonedUniformBuffers[uniformBufferName]) {\r\n                        clonedUniformBuffers[uniformBufferName] = resource.uniformBuffer.clone();\r\n                        clonedUniformBuffers[uniformBufferName].name = uniformBufferName;\r\n\r\n                        //console.log(\"cloned uniformBuffer = \", clonedUniformBuffers[uniformBufferName])\r\n                    }\r\n                    //console.log(\"===>>> uniformBufferName = \", bindgroup.getResourceName(resource.uniformBuffer))\r\n                    instance[uniformBufferName] = clonedUniformBuffers[uniformBufferName];\r\n                    (instance[uniformBufferName] as any).name = clonedUniformBuffers[uniformBufferName].name;\r\n                    (instance[uniformBufferName] as any).bindgroup = bindgroup;\r\n                    instance[name] = clonedUniformBuffers[uniformBufferName].getUniformByName(name);\r\n\r\n\r\n                } else {\r\n                    instance[name] = resource.clone();\r\n                    (instance[name] as any).bindgroup = bindgroup;\r\n                    (instance[name] as any).name = name;\r\n                }\r\n            }\r\n\r\n            const shaderResources: IShaderResource[] = [];\r\n\r\n            for (let z in instance) {\r\n                resource = instance[z];\r\n                if (!(resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform)) {\r\n                    resource.setPipelineType(this.type);\r\n                    resource.createGpuResource();\r\n                    shaderResources.push(resource);\r\n                }\r\n            }\r\n\r\n            instance.deviceId = XGPU.deviceId;\r\n\r\n\r\n            instance.apply = () => {\r\n\r\n                let rebuild: boolean = false;\r\n                if (XGPU.deviceId != instance.deviceId) {\r\n                    rebuild = true;\r\n                    instance.deviceId = XGPU.deviceId;\r\n                }\r\n\r\n\r\n                let o: any;\r\n                for (let i = 0; i < shaderResources.length; i++) {\r\n                    o = shaderResources[i];\r\n                    if (rebuild) {\r\n                        o.destroyGpuResource();\r\n                        o.createGpuResource();\r\n                    }\r\n                    o.update();\r\n                    o.bindgroup.set(o.name, o);\r\n                }\r\n                this.update();\r\n            }\r\n        }\r\n\r\n        return result;\r\n    }"
              }
            ],
            "protected": [
              {
                "objectType": "method",
                "name": "createVertexBufferLayout",
                "returnType": "any",
                "visibility": "protected",
                "rawText": "protected createVertexBufferLayout(): any {\r\n\r\n\r\n\r\n        this.vertexBufferLayouts = [];\r\n        this.vertexBuffers = [];\r\n\r\n        const groups: Bindgroup[] = this.bindGroups.groups;\r\n        let elements: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let builtin: number = 0;\r\n        let k = 0;\r\n        for (let i = 0; i < groups.length; i++) {\r\n            elements = groups[i].elements;\r\n            for (let j = 0; j < elements.length; j++) {\r\n                resource = elements[j].resource;\r\n\r\n                if (resource instanceof VertexBuffer) {\r\n                    this.vertexBuffers[k] = resource;\r\n                    this.vertexBufferLayouts[k++] = resource.createVertexBufferLayout(builtin);\r\n                    builtin += resource.vertexArrays.length;\r\n                }\r\n            }\r\n        }\r\n\r\n        return this.vertexBufferLayouts;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createShaderInput",
                "returnType": "ShaderStruct",
                "params": [
                  {
                    "name": "shader",
                    "type": "VertexShader"
                  },
                  {
                    "name": "buffers",
                    "type": "VertexBuffer[]"
                  }
                ],
                "visibility": "protected",
                "rawText": "protected createShaderInput(shader: VertexShader, buffers: VertexBuffer[]): ShaderStruct {\r\n        const vertexInput: ShaderStruct = new ShaderStruct(\"Input\", shader.inputs);;\r\n\r\n        if (buffers) {\r\n            let arrays: VertexAttribute[];\r\n            let builtin: number = 0;\r\n            for (let i = 0; i < buffers.length; i++) {\r\n                arrays = buffers[i].vertexArrays;\r\n                for (let j = 0; j < arrays.length; j++) {\r\n                    vertexInput.addProperty({ name: arrays[j].name, type: arrays[j].varType, builtin: \"@location(\" + builtin + \")\" })\r\n                    builtin++;\r\n                }\r\n            }\r\n        }\r\n\r\n        return vertexInput;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createLayouts",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected createLayouts(): void {\r\n\r\n\r\n\r\n\r\n        this.gpuBindGroupLayouts = [];\r\n        this.gpuBindgroups = [];\r\n        this.gpuPipelineLayout = null;\r\n\r\n\r\n        const groups: Bindgroup[] = this.bindGroups.groups;\r\n        let elements: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let layout, group;\r\n        let layouts = [];\r\n        let k, n = 0;\r\n        for (let i = 0; i < groups.length; i++) {\r\n            elements = groups[i].elements;\r\n            layout = layouts[i] = { entries: [] };\r\n            group = { entries: [], layout: null };\r\n            k = 0;\r\n\r\n            for (let j = 0; j < elements.length; j++) {\r\n                resource = elements[j].resource;\r\n                if (!(resource instanceof VertexBuffer) || this.isComputePipeline) {\r\n                    layout.entries[k] = resource.createBindGroupLayoutEntry(k);\r\n                    group.entries[k] = resource.createBindGroupEntry(k)\r\n                    k++;\r\n                }\r\n            }\r\n\r\n            if (k > 0) {\r\n                group.layout = this.gpuBindGroupLayouts[n] = XGPU.createBindgroupLayout(layout)\r\n                this.gpuBindgroups[n] = XGPU.createBindgroup(group)\r\n                n++;\r\n            }\r\n\r\n\r\n        }\r\n        \r\n\r\n        this.gpuPipelineLayout = XGPU.createPipelineLayout({ bindGroupLayouts: this.gpuBindGroupLayouts })\r\n    }"
              },
              {
                "objectType": "method",
                "name": "initPipelineResources",
                "returnType": "void",
                "params": [
                  {
                    "name": "pipeline",
                    "type": "Pipeline"
                  }
                ],
                "visibility": "protected",
                "rawText": "protected initPipelineResources(pipeline: Pipeline) {\r\n        const resources: IShaderResource[] = this.bindGroups.resources.all;\r\n        //console.log(\"all = \", resources)\r\n        if (!resources) return;\r\n        for (let i = 0; i < resources.length; i++) resources[i].setPipelineType(pipeline.type);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "build",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected build() {\r\n\r\n        this.createVertexBufferLayout();\r\n        this.createLayouts();\r\n\r\n    }"
              }
            ]
          },
          "statics": {
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "getResourceDefinition",
                  "returnType": "any",
                  "params": [
                    {
                      "name": "resources",
                      "type": "any"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public static getResourceDefinition(resources: any): any {\r\n        const result: any = {};\r\n        let o: any;\r\n        for (let z in resources) {\r\n            o = resources[z];\r\n            result[o.name] = o;\r\n        }\r\n        return result;\r\n    }"
                }
              ]
            }
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "rawText": "constructor() {\r\n        super();\r\n        this.bindGroups = new Bindgroups(this, \"pipeline\");\r\n\r\n    }"
          },
          "rawText": "export class Pipeline extends EventDispatcher {\r\n\r\n    public description: any = {};\r\n    public nbVertex: number;\r\n    public bindGroups: Bindgroups;\r\n    public vertexBuffers: VertexBuffer[];\r\n\r\n    public vertexShader: VertexShader;\r\n    public fragmentShader: FragmentShader;\r\n\r\n    protected vertexBufferLayouts: Iterable<GPUVertexBufferLayout>;\r\n    protected gpuBindgroups: GPUBindGroup[] = [];\r\n    protected gpuBindGroupLayouts: GPUBindGroupLayout[] = [];\r\n    protected gpuPipelineLayout: GPUPipelineLayout;\r\n    public type: \"compute\" | \"compute_mixed\" | \"render\" = null;\r\n\r\n    constructor() {\r\n        super();\r\n        this.bindGroups = new Bindgroups(this, \"pipeline\");\r\n\r\n    }\r\n    public get isComputePipeline(): boolean { return this.type === \"compute\" || this.type === \"compute_mixed\"; }\r\n    public get isRenderPipeline(): boolean { return this.type === \"render\"; }\r\n    public get isMixedPipeline(): boolean { return this.type === \"compute_mixed\"; }\r\n\r\n\r\n    protected _resources: any;\r\n    public get resources(): any { return this._resources; }\r\n\r\n\r\n    public debug: string;\r\n\r\n    public clearAfterDeviceLostAndRebuild() {\r\n\r\n        this.bindGroups.clearAfterDeviceLost()\r\n        this.vertexBufferLayouts = undefined;\r\n        this.gpuPipelineLayout = undefined;\r\n        this.gpuBindGroupLayouts = [];\r\n        this.gpuBindgroups = [];\r\n\r\n        //this.build();\r\n\r\n    }\r\n\r\n\r\n\r\n\r\n    public initFromObject(obj: any) {\r\n\r\n        this._resources = obj;\r\n    }\r\n\r\n    public pipelineCount: number = 1;\r\n\r\n\r\n\r\n\r\n\r\n    public static getResourceDefinition(resources: any): any {\r\n        const result: any = {};\r\n        let o: any;\r\n        for (let z in resources) {\r\n            o = resources[z];\r\n            result[o.name] = o;\r\n        }\r\n        return result;\r\n    }\r\n\r\n    public addBindgroup(group: Bindgroup) {\r\n        this.bindGroups.add(group);\r\n    }\r\n\r\n\r\n\r\n    protected createVertexBufferLayout(): any {\r\n\r\n\r\n\r\n        this.vertexBufferLayouts = [];\r\n        this.vertexBuffers = [];\r\n\r\n        const groups: Bindgroup[] = this.bindGroups.groups;\r\n        let elements: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let builtin: number = 0;\r\n        let k = 0;\r\n        for (let i = 0; i < groups.length; i++) {\r\n            elements = groups[i].elements;\r\n            for (let j = 0; j < elements.length; j++) {\r\n                resource = elements[j].resource;\r\n\r\n                if (resource instanceof VertexBuffer) {\r\n                    this.vertexBuffers[k] = resource;\r\n                    this.vertexBufferLayouts[k++] = resource.createVertexBufferLayout(builtin);\r\n                    builtin += resource.vertexArrays.length;\r\n                }\r\n            }\r\n        }\r\n\r\n        return this.vertexBufferLayouts;\r\n    }\r\n\r\n    protected createShaderInput(shader: VertexShader, buffers: VertexBuffer[]): ShaderStruct {\r\n        const vertexInput: ShaderStruct = new ShaderStruct(\"Input\", shader.inputs);;\r\n\r\n        if (buffers) {\r\n            let arrays: VertexAttribute[];\r\n            let builtin: number = 0;\r\n            for (let i = 0; i < buffers.length; i++) {\r\n                arrays = buffers[i].vertexArrays;\r\n                for (let j = 0; j < arrays.length; j++) {\r\n                    vertexInput.addProperty({ name: arrays[j].name, type: arrays[j].varType, builtin: \"@location(\" + builtin + \")\" })\r\n                    builtin++;\r\n                }\r\n            }\r\n        }\r\n\r\n        return vertexInput;\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n    protected createLayouts(): void {\r\n\r\n\r\n\r\n\r\n        this.gpuBindGroupLayouts = [];\r\n        this.gpuBindgroups = [];\r\n        this.gpuPipelineLayout = null;\r\n\r\n\r\n        const groups: Bindgroup[] = this.bindGroups.groups;\r\n        let elements: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let layout, group;\r\n        let layouts = [];\r\n        let k, n = 0;\r\n        for (let i = 0; i < groups.length; i++) {\r\n            elements = groups[i].elements;\r\n            layout = layouts[i] = { entries: [] };\r\n            group = { entries: [], layout: null };\r\n            k = 0;\r\n\r\n            for (let j = 0; j < elements.length; j++) {\r\n                resource = elements[j].resource;\r\n                if (!(resource instanceof VertexBuffer) || this.isComputePipeline) {\r\n                    layout.entries[k] = resource.createBindGroupLayoutEntry(k);\r\n                    group.entries[k] = resource.createBindGroupEntry(k)\r\n                    k++;\r\n                }\r\n            }\r\n\r\n            if (k > 0) {\r\n                group.layout = this.gpuBindGroupLayouts[n] = XGPU.createBindgroupLayout(layout)\r\n                this.gpuBindgroups[n] = XGPU.createBindgroup(group)\r\n                n++;\r\n            }\r\n\r\n\r\n        }\r\n        \r\n\r\n        this.gpuPipelineLayout = XGPU.createPipelineLayout({ bindGroupLayouts: this.gpuBindGroupLayouts })\r\n    }\r\n\r\n\r\n    protected initPipelineResources(pipeline: Pipeline) {\r\n        const resources: IShaderResource[] = this.bindGroups.resources.all;\r\n        //console.log(\"all = \", resources)\r\n        if (!resources) return;\r\n        for (let i = 0; i < resources.length; i++) resources[i].setPipelineType(pipeline.type);\r\n    }\r\n\r\n\r\n    protected build() {\r\n\r\n        this.createVertexBufferLayout();\r\n        this.createLayouts();\r\n\r\n    }\r\n\r\n\r\n    public update(o?: any) {\r\n        if (o) {\r\n\r\n        }\r\n        //must be overided\r\n    }\r\n\r\n\r\n    public getResourceName(resource: any) {\r\n\r\n        if (resource instanceof VertexAttribute) {\r\n            if (this.type !== \"render\") {\r\n                const buffer: VertexBuffer = resource.vertexBuffer;\r\n                const bufferName: string = this.bindGroups.getNameByResource(buffer);\r\n                return bufferName + \".\" + resource.name;\r\n            } else {\r\n                return resource.name;\r\n            }\r\n        } else {\r\n\r\n            if (resource.uniformBuffer) {\r\n                const bufferName: string = this.bindGroups.getNameByResource(resource.uniformBuffer);\r\n                return bufferName + \".\" + resource.name;\r\n            } else {\r\n                return this.bindGroups.getNameByResource(resource);\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n\r\n    public createPipelineInstanceArray(resources: (PrimitiveFloatUniform | PrimitiveIntUniform | PrimitiveUintUniform | IShaderResource)[], nbInstance: number): any[] {\r\n        this.pipelineCount = nbInstance;\r\n\r\n        const result: any[] = [];\r\n\r\n        let instance: any;\r\n        let resource: any\r\n        let clonedUniformBuffers: any;\r\n\r\n\r\n        const resourceNames: string[] = [];\r\n        const resourceBindgroup: Bindgroup[] = [];\r\n        const resourceUniformBufferName: string[] = [];\r\n        for (let i = 0; i < resources.length; i++) {\r\n            resource = resources[i];\r\n            const name = this.bindGroups.getNameByResource(resource);\r\n\r\n            const bindgroup = this.bindGroups.getGroupByPropertyName(name);\r\n            bindgroup.mustRefreshBindgroup = true;\r\n\r\n            resourceNames[i] = name;\r\n            resourceBindgroup[i] = bindgroup;\r\n\r\n            if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n                resourceUniformBufferName[i] = bindgroup.getResourceName(resource.uniformBuffer);\r\n            }\r\n        }\r\n\r\n\r\n\r\n        for (let k = 0; k < nbInstance; k++) {\r\n            result[k] = instance = {};\r\n            clonedUniformBuffers = {};\r\n\r\n            for (let i = 0; i < resources.length; i++) {\r\n\r\n\r\n                resource = resources[i];\r\n                resource.update();\r\n                const name = resourceNames[i];\r\n                const bindgroup = resourceBindgroup[i];\r\n\r\n                //console.log(\"resource = \", resource)\r\n\r\n\r\n                if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n                    const uniformBufferName = resourceUniformBufferName[i];//bindgroup.getResourceName(resource.uniformBuffer);\r\n                    //console.log(\"uniformBufferName = \", uniformBufferName, name)\r\n                    if (!clonedUniformBuffers[uniformBufferName]) {\r\n                        clonedUniformBuffers[uniformBufferName] = resource.uniformBuffer.clone();\r\n                        clonedUniformBuffers[uniformBufferName].name = uniformBufferName;\r\n\r\n                        //console.log(\"cloned uniformBuffer = \", clonedUniformBuffers[uniformBufferName])\r\n                    }\r\n                    //console.log(\"===>>> uniformBufferName = \", bindgroup.getResourceName(resource.uniformBuffer))\r\n                    instance[uniformBufferName] = clonedUniformBuffers[uniformBufferName];\r\n                    (instance[uniformBufferName] as any).name = clonedUniformBuffers[uniformBufferName].name;\r\n                    (instance[uniformBufferName] as any).bindgroup = bindgroup;\r\n                    instance[name] = clonedUniformBuffers[uniformBufferName].getUniformByName(name);\r\n\r\n\r\n                } else {\r\n                    instance[name] = resource.clone();\r\n                    (instance[name] as any).bindgroup = bindgroup;\r\n                    (instance[name] as any).name = name;\r\n                }\r\n            }\r\n\r\n            const shaderResources: IShaderResource[] = [];\r\n\r\n            for (let z in instance) {\r\n                resource = instance[z];\r\n                if (!(resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform)) {\r\n                    resource.setPipelineType(this.type);\r\n                    resource.createGpuResource();\r\n                    shaderResources.push(resource);\r\n                }\r\n            }\r\n\r\n            instance.deviceId = XGPU.deviceId;\r\n\r\n\r\n            instance.apply = () => {\r\n\r\n                let rebuild: boolean = false;\r\n                if (XGPU.deviceId != instance.deviceId) {\r\n                    rebuild = true;\r\n                    instance.deviceId = XGPU.deviceId;\r\n                }\r\n\r\n\r\n                let o: any;\r\n                for (let i = 0; i < shaderResources.length; i++) {\r\n                    o = shaderResources[i];\r\n                    if (rebuild) {\r\n                        o.destroyGpuResource();\r\n                        o.createGpuResource();\r\n                    }\r\n                    o.update();\r\n                    o.bindgroup.set(o.name, o);\r\n                }\r\n                this.update();\r\n            }\r\n        }\r\n\r\n        return result;\r\n    }\r\n}"
        }
      ],
      "PipelinePlugin": [
        {
          "objectType": "class",
          "name": "PipelinePlugin",
          "filePath": "xGPU.pipelines.PipelinePlugin",
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "bindgroupResources",
                "type": "any",
                "visibility": "public",
                "rawText": "public bindgroupResources: any = {};"
              },
              {
                "objectType": "property",
                "name": "vertexShader",
                "type": "{ outputs?: any; inputs?: any; constants?: string; main?: string | string[]; }",
                "visibility": "public",
                "rawText": "public vertexShader: {\r\n        outputs?: any,\r\n        inputs?: any,\r\n        constants?: string,\r\n        main?: string | string[],\r\n    } = {};"
              },
              {
                "objectType": "property",
                "name": "fragmentShader",
                "type": "{ outputs?: any; inputs?: any; constants?: string; main?: string | string[]; }",
                "visibility": "public",
                "rawText": "public fragmentShader: {\r\n        outputs?: any,\r\n        inputs?: any,\r\n        constants?: string,\r\n        main?: string | string[],\r\n    } = {};"
              }
            ],
            "protected": [
              {
                "objectType": "property",
                "name": "target",
                "type": "Pipeline",
                "visibility": "protected",
                "rawText": "protected target: Pipeline;"
              },
              {
                "objectType": "property",
                "name": "requiredNames",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected requiredNames: any;"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "apply",
                "returnType": "PipelinePlugin",
                "params": [
                  {
                    "name": "vertexShaderNode",
                    "type": "ShaderNode"
                  },
                  {
                    "name": "fragmentShaderNode",
                    "type": "ShaderNode"
                  }
                ],
                "visibility": "public",
                "rawText": "public apply(vertexShaderNode: ShaderNode = null, fragmentShaderNode: ShaderNode = null): PipelinePlugin {\r\n\r\n\r\n\r\n        //if (!this.target.resources.bindgroups.plugins) this.target.resources.bindgroups.plugins = {};\r\n        //const plugins = this.target.resources.bindgroups.plugins;\r\n        let plugins;\r\n        for (let z in this.target.resources.bindgroups) {\r\n            plugins = this.target.resources.bindgroups[z];\r\n            break;\r\n        }\r\n\r\n\r\n        for (let z in this.bindgroupResources) plugins[z] = this.bindgroupResources[z];\r\n\r\n\r\n\r\n        //------ VERTEX SHADER --------\r\n\r\n\r\n\r\n        let vs = this.target.resources.vertexShader;\r\n        if (typeof vs === \"string\") vs = { main: vs }\r\n\r\n        if (this.vertexShader.outputs) {\r\n            if (!vs.outputs) vs.outputs = {};\r\n            for (let z in this.vertexShader.outputs) {\r\n                vs.outputs[z] = this.vertexShader.outputs[z];\r\n            }\r\n        }\r\n\r\n        if (this.vertexShader.inputs) {\r\n            if (!vs.inputs) vs.inputs = {};\r\n            for (let z in this.vertexShader.inputs) {\r\n                vs.inputs[z] = this.vertexShader.inputs[z];\r\n            }\r\n        }\r\n\r\n        if (this.vertexShader.constants) {\r\n            if (!vs.constants) vs.constants = \"\";\r\n            vs.constants += this.vertexShader.constants;\r\n        }\r\n\r\n        if (this.vertexShader.main) {\r\n            let main: string;\r\n            if (typeof this.vertexShader.main === \"string\") main = this.vertexShader.main as string;\r\n            else main = (this.vertexShader.main as string[]).join(\"\\n\");\r\n\r\n            if (vertexShaderNode) vertexShaderNode.text = main;\r\n            else {\r\n                if (!vs.main) vs.main = \"\";\r\n                vs.main += main;\r\n            }\r\n        }\r\n        this.target.resources.vertexShader = vs;\r\n\r\n        //-------- FRAGMENT SHADER --------\r\n        let fs = this.target.resources.fragmentShader;\r\n        if (typeof fs === \"string\") fs = { main: fs };\r\n\r\n        if (this.fragmentShader.outputs) {\r\n            if (!fs.outputs) fs.outputs = {};\r\n            for (let z in this.fragmentShader.outputs) {\r\n                fs.outputs[z] = this.fragmentShader.outputs[z];\r\n            }\r\n        }\r\n\r\n        if (this.fragmentShader.inputs) {\r\n            if (!fs.inputs) fs.inputs = {};\r\n            for (let z in this.fragmentShader.inputs) {\r\n                fs.inputs[z] = this.fragmentShader.inputs[z];\r\n            }\r\n        }\r\n\r\n        if (this.fragmentShader.constants) {\r\n            if (!fs.constants) fs.constants = \"\";\r\n            fs.constants += this.fragmentShader.constants;\r\n        }\r\n\r\n        if (this.fragmentShader.main) {\r\n            let main: string;\r\n            if (typeof this.fragmentShader.main === \"string\") main = this.fragmentShader.main as string;\r\n            else main = (this.fragmentShader.main as string[]).join(\"\\n\");\r\n\r\n            if (fragmentShaderNode) fragmentShaderNode.text = main;\r\n            else {\r\n                if (!fs.main) fs.main = \"\";\r\n                fs.main += main;\r\n            }\r\n        }\r\n        this.target.resources.fragmentShader = fs;\r\n\r\n        this.target.initFromObject(this.target.resources);\r\n\r\n        return this;\r\n    }"
              }
            ]
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "params": [
              {
                "name": "target",
                "type": "Pipeline"
              },
              {
                "name": "required",
                "type": "any"
              }
            ],
            "rawText": "constructor(target: Pipeline, required?: any) {\r\n        this.target = target;\r\n\r\n        if (required) {\r\n            this.requiredNames = {};\r\n            for (let z in required) {\r\n                this.requiredNames[z] = target.getResourceName(required[z]);\r\n            }\r\n        }\r\n\r\n    }"
          },
          "rawText": "export class PipelinePlugin {\r\n\r\n    protected target: Pipeline;\r\n    protected requiredNames: any;\r\n\r\n    public bindgroupResources: any = {};\r\n\r\n\r\n\r\n    public vertexShader: {\r\n        outputs?: any,\r\n        inputs?: any,\r\n        constants?: string,\r\n        main?: string | string[],\r\n    } = {};\r\n\r\n    public fragmentShader: {\r\n        outputs?: any,\r\n        inputs?: any,\r\n        constants?: string,\r\n        main?: string | string[],\r\n    } = {};\r\n\r\n    constructor(target: Pipeline, required?: any) {\r\n        this.target = target;\r\n\r\n        if (required) {\r\n            this.requiredNames = {};\r\n            for (let z in required) {\r\n                this.requiredNames[z] = target.getResourceName(required[z]);\r\n            }\r\n        }\r\n\r\n    }\r\n\r\n    public apply(vertexShaderNode: ShaderNode = null, fragmentShaderNode: ShaderNode = null): PipelinePlugin {\r\n\r\n\r\n\r\n        //if (!this.target.resources.bindgroups.plugins) this.target.resources.bindgroups.plugins = {};\r\n        //const plugins = this.target.resources.bindgroups.plugins;\r\n        let plugins;\r\n        for (let z in this.target.resources.bindgroups) {\r\n            plugins = this.target.resources.bindgroups[z];\r\n            break;\r\n        }\r\n\r\n\r\n        for (let z in this.bindgroupResources) plugins[z] = this.bindgroupResources[z];\r\n\r\n\r\n\r\n        //------ VERTEX SHADER --------\r\n\r\n\r\n\r\n        let vs = this.target.resources.vertexShader;\r\n        if (typeof vs === \"string\") vs = { main: vs }\r\n\r\n        if (this.vertexShader.outputs) {\r\n            if (!vs.outputs) vs.outputs = {};\r\n            for (let z in this.vertexShader.outputs) {\r\n                vs.outputs[z] = this.vertexShader.outputs[z];\r\n            }\r\n        }\r\n\r\n        if (this.vertexShader.inputs) {\r\n            if (!vs.inputs) vs.inputs = {};\r\n            for (let z in this.vertexShader.inputs) {\r\n                vs.inputs[z] = this.vertexShader.inputs[z];\r\n            }\r\n        }\r\n\r\n        if (this.vertexShader.constants) {\r\n            if (!vs.constants) vs.constants = \"\";\r\n            vs.constants += this.vertexShader.constants;\r\n        }\r\n\r\n        if (this.vertexShader.main) {\r\n            let main: string;\r\n            if (typeof this.vertexShader.main === \"string\") main = this.vertexShader.main as string;\r\n            else main = (this.vertexShader.main as string[]).join(\"\\n\");\r\n\r\n            if (vertexShaderNode) vertexShaderNode.text = main;\r\n            else {\r\n                if (!vs.main) vs.main = \"\";\r\n                vs.main += main;\r\n            }\r\n        }\r\n        this.target.resources.vertexShader = vs;\r\n\r\n        //-------- FRAGMENT SHADER --------\r\n        let fs = this.target.resources.fragmentShader;\r\n        if (typeof fs === \"string\") fs = { main: fs };\r\n\r\n        if (this.fragmentShader.outputs) {\r\n            if (!fs.outputs) fs.outputs = {};\r\n            for (let z in this.fragmentShader.outputs) {\r\n                fs.outputs[z] = this.fragmentShader.outputs[z];\r\n            }\r\n        }\r\n\r\n        if (this.fragmentShader.inputs) {\r\n            if (!fs.inputs) fs.inputs = {};\r\n            for (let z in this.fragmentShader.inputs) {\r\n                fs.inputs[z] = this.fragmentShader.inputs[z];\r\n            }\r\n        }\r\n\r\n        if (this.fragmentShader.constants) {\r\n            if (!fs.constants) fs.constants = \"\";\r\n            fs.constants += this.fragmentShader.constants;\r\n        }\r\n\r\n        if (this.fragmentShader.main) {\r\n            let main: string;\r\n            if (typeof this.fragmentShader.main === \"string\") main = this.fragmentShader.main as string;\r\n            else main = (this.fragmentShader.main as string[]).join(\"\\n\");\r\n\r\n            if (fragmentShaderNode) fragmentShaderNode.text = main;\r\n            else {\r\n                if (!fs.main) fs.main = \"\";\r\n                fs.main += main;\r\n            }\r\n        }\r\n        this.target.resources.fragmentShader = fs;\r\n\r\n        this.target.initFromObject(this.target.resources);\r\n\r\n        return this;\r\n    }\r\n\r\n\r\n\r\n}"
        }
      ],
      "RenderPipeline": [
        {
          "objectType": "type",
          "name": "HighLevelShaderResource",
          "type": "HighLevelShaderResource",
          "rawText": "export type HighLevelShaderResource = (IShaderResource | VertexBufferIO | ImageTextureIO | PrimitiveType | VertexAttribute)"
        },
        {
          "objectType": "type",
          "name": "BindgroupDescriptor",
          "type": "BindgroupDescriptor",
          "rawText": "export type BindgroupDescriptor = {\r\n    [key: string]: HighLevelShaderResource\r\n}"
        },
        {
          "objectType": "type",
          "name": "DefaultBindgroup",
          "type": "DefaultBindgroup",
          "rawText": "export type DefaultBindgroup = BindgroupDescriptor & {\r\n    uniforms?: UniformBuffer\r\n    buffer?: VertexBuffer\r\n}"
        },
        {
          "objectType": "type",
          "name": "BindgroupsDescriptor",
          "type": "BindgroupsDescriptor",
          "rawText": "export type BindgroupsDescriptor = {\r\n    default?: DefaultBindgroup,\r\n    [key: string]: (Bindgroup | BindgroupDescriptor)\r\n}"
        },
        {
          "objectType": "type",
          "name": "VertexShaderDescriptor",
          "type": "VertexShaderDescriptor",
          "rawText": "export type VertexShaderDescriptor = {\r\n    main: string,\r\n    constants?: string,\r\n    inputs: {\r\n        [key: string]: VertexShaderInput\r\n    },\r\n    outputs: {\r\n        [key: string]: VertexShaderOutput\r\n    }\r\n} | string;"
        },
        {
          "objectType": "type",
          "name": "FragmentShaderDescriptor",
          "type": "FragmentShaderDescriptor",
          "rawText": "export type FragmentShaderDescriptor = {\r\n    main: string,\r\n    constants?: string,\r\n    inputs: {\r\n        [key: string]: FragmentShaderInput\r\n    },\r\n    outputs: {\r\n        [key: string]: FragmentShaderOutputs\r\n    }\r\n} | string;"
        },
        {
          "objectType": "type",
          "name": "RenderPipelineProperties",
          "type": "RenderPipelineProperties",
          "rawText": "export type RenderPipelineProperties = {\r\n\r\n    vertexShader: VertexShaderDescriptor,\r\n\r\n    vertexCount?: number,\r\n    instanceCount?: number,\r\n    debugVertexCount?: number,\r\n    firstVertexId?: number,\r\n    firstInstanceId?: number,\r\n    cullMode?: \"front\" | \"back\" | \"none\",\r\n    topology?: \"point-list\" | \"line-list\" | \"line-strip\" | \"triangle-list\" | \"triangle-strip\",\r\n    frontFace?: \"ccw\" | \"cw\",\r\n    stripIndexFormat?: \"uint16\" | \"uint32\",\r\n    antiAliasing?: boolean,\r\n    useDepthTexture?: boolean,\r\n    depthTextureSize?: number,\r\n    depthTest?: boolean,\r\n    clearColor?: { r: number, g: number, b: number, a: number },\r\n    blendMode?: BlendMode,\r\n    bindgroups?: BindgroupsDescriptor,\r\n    indexBuffer?: IndexBuffer,\r\n    fragmentShader?: FragmentShaderDescriptor,\r\n\r\n}"
        },
        {
          "objectType": "type",
          "name": "RenderPipelineDescriptor",
          "type": "RenderPipelineDescriptor",
          "rawText": "export type RenderPipelineDescriptor = RenderPipelineProperties & BindgroupDescriptor"
        },
        {
          "objectType": "class",
          "name": "RenderPipeline",
          "filePath": "xGPU.pipelines.RenderPipeline",
          "extends": [
            "Pipeline",
            "EventDispatcher"
          ],
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "renderer",
                "type": "IRenderer",
                "visibility": "public",
                "rawText": "public get renderer(): IRenderer { return this._renderer }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "drawConfig",
                "type": "DrawConfig",
                "visibility": "public",
                "rawText": "public drawConfig: DrawConfig;"
              },
              {
                "objectType": "property",
                "name": "outputColor",
                "type": "any",
                "visibility": "public",
                "rawText": "public outputColor: any;"
              },
              {
                "objectType": "property",
                "name": "renderPassDescriptor",
                "type": "any",
                "visibility": "public",
                "rawText": "public renderPassDescriptor: any = { colorAttachments: [] }"
              },
              {
                "objectType": "property",
                "name": "debug",
                "type": "string",
                "visibility": "public",
                "rawText": "public debug: string = \"renderPipeline\";"
              },
              {
                "objectType": "property",
                "name": "depthStencilTexture",
                "type": "DepthStencilTexture",
                "visibility": "public",
                "rawText": "public get depthStencilTexture(): DepthStencilTexture { return this._depthStencilTexture; }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "clearValue",
                "type": "{ r: number; g: number; b: number; a: number; }",
                "visibility": "public",
                "rawText": "public get clearValue(): { r: number, g: number, b: number, a: number } {\r\n        return this._clearValue;\r\n        //if (!this.renderPassDescriptor.colorAttachment) return null;\r\n        //return this.renderPassDescriptor.colorAttachment.clearValue;\r\n    }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "debugVertexCount",
                "type": "number",
                "visibility": "public",
                "rawText": "public get debugVertexCount(): number { return this.resources.debugVertexCount }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "vertexCount",
                "type": "number",
                "visibility": "public",
                "rawText": "public get vertexCount(): number { return this.drawConfig.vertexCount }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "instanceCount",
                "type": "number",
                "visibility": "public",
                "rawText": "public get instanceCount(): number { return this.drawConfig.instanceCount }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "firstVertexId",
                "type": "number",
                "visibility": "public",
                "rawText": "public get firstVertexId(): number { return this.drawConfig.firstVertexId }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "firstInstanceId",
                "type": "number",
                "visibility": "public",
                "rawText": "public get firstInstanceId(): number { return this.drawConfig.firstInstanceId }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "baseVertex",
                "type": "number",
                "visibility": "public",
                "rawText": "public get baseVertex(): number { return this.drawConfig.baseVertex }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "renderPassView",
                "type": "GPUTextureView",
                "visibility": "public",
                "rawText": "public get renderPassView(): GPUTextureView { return this.renderPass.view }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "renderPass",
                "type": "RenderPassTexture",
                "visibility": "public",
                "rawText": "public get renderPass(): RenderPassTexture {\r\n        if (!this.renderPassTexture) {\r\n            this.renderPassTexture = new RenderPassTexture(this)\r\n        }\r\n        return this.renderPassTexture;\r\n    }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "useRenderPassTexture",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public get useRenderPassTexture(): boolean {\r\n        return !!this.renderPassTexture;\r\n    }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "blendMode",
                "type": "BlendMode",
                "visibility": "public",
                "rawText": "public blendMode: BlendMode;"
              },
              {
                "objectType": "property",
                "name": "onRebuildStartAfterDeviceLost",
                "type": "() => void",
                "visibility": "public",
                "rawText": "public onRebuildStartAfterDeviceLost: () => void;"
              },
              {
                "objectType": "property",
                "name": "resourceDefined",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public get resourceDefined(): boolean {\r\n        const bool = !!this.bindGroups.resources.all\r\n        if (!bool) {\r\n            //some very basic shader can run without any resource\r\n            if (this.drawConfig.vertexCount > 0) {\r\n                if (this.vertexShader.main.text != \"\" && this.fragmentShader.main.text != \"\") {\r\n                    return true;\r\n                }\r\n            }\r\n\r\n            return false;\r\n        }\r\n        return true\r\n    }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "pipeline",
                "type": "GPURenderPipeline",
                "visibility": "public",
                "rawText": "public get pipeline(): GPURenderPipeline { return this.gpuPipeline }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "cullMode",
                "type": "\"front\" | \"back\" | \"none\"",
                "visibility": "public",
                "rawText": "public get cullMode(): \"front\" | \"back\" | \"none\" { return this.description.primitive.cullMode }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "topology",
                "type": "\"point-list\" | \"line-list\" | \"line-strip\" | \"triangle-list\" | \"triangle-strip\"",
                "visibility": "public",
                "rawText": "public get topology(): \"point-list\" | \"line-list\" | \"line-strip\" | \"triangle-list\" | \"triangle-strip\" { return this.description.primitive.topology }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "frontFace",
                "type": "\"ccw\" | \"cw\"",
                "visibility": "public",
                "rawText": "public get frontFace(): \"ccw\" | \"cw\" { return this.description.primitive.frontFace }",
                "get": true,
                "set": true
              },
              {
                "objectType": "property",
                "name": "stripIndexFormat",
                "type": "\"uint16\" | \"uint32\"",
                "visibility": "public",
                "rawText": "public get stripIndexFormat(): \"uint16\" | \"uint32\" { return this.description.primitive.stripIndexFormat }",
                "get": true,
                "set": true
              }
            ],
            "private": [
              {
                "objectType": "property",
                "name": "buildingPipeline",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private buildingPipeline: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "clearOpReady",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private clearOpReady: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "rendererUseSinglePipeline",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private rendererUseSinglePipeline: boolean = true;"
              }
            ],
            "protected": [
              {
                "objectType": "property",
                "name": "_renderer",
                "type": "IRenderer",
                "visibility": "protected",
                "rawText": "protected _renderer: IRenderer;"
              },
              {
                "objectType": "property",
                "name": "multiSampleTextureDescriptor",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected multiSampleTextureDescriptor: any;"
              },
              {
                "objectType": "property",
                "name": "waitingMultisampleTexture",
                "type": "boolean",
                "visibility": "protected",
                "rawText": "protected waitingMultisampleTexture: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "multisampleTexture",
                "type": "MultiSampleTexture",
                "visibility": "protected",
                "rawText": "protected multisampleTexture: MultiSampleTexture;"
              },
              {
                "objectType": "property",
                "name": "waitingDepthStencilTexture",
                "type": "boolean",
                "visibility": "protected",
                "rawText": "protected waitingDepthStencilTexture: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "depthStencilTextureDescriptor",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected depthStencilTextureDescriptor: any;"
              },
              {
                "objectType": "property",
                "name": "_depthStencilTexture",
                "type": "DepthStencilTexture",
                "visibility": "protected",
                "rawText": "protected _depthStencilTexture: DepthStencilTexture;"
              },
              {
                "objectType": "property",
                "name": "renderPassTexture",
                "type": "RenderPassTexture",
                "visibility": "protected",
                "rawText": "protected renderPassTexture: RenderPassTexture;"
              },
              {
                "objectType": "property",
                "name": "vertexShaderDebuggerPipeline",
                "type": "VertexShaderDebuggerPipeline",
                "visibility": "protected",
                "rawText": "protected vertexShaderDebuggerPipeline: VertexShaderDebuggerPipeline = null;"
              },
              {
                "objectType": "property",
                "name": "gpuPipeline",
                "type": "GPURenderPipeline",
                "visibility": "protected",
                "rawText": "protected gpuPipeline: GPURenderPipeline;"
              },
              {
                "objectType": "property",
                "name": "_clearValue",
                "type": "{ r: number; g: number; b: number; a: number; }",
                "visibility": "protected",
                "rawText": "protected _clearValue: { r: number, g: number, b: number, a: number } = null;"
              },
              {
                "objectType": "property",
                "name": "rebuildingAfterDeviceLost",
                "type": "boolean",
                "visibility": "protected",
                "rawText": "protected rebuildingAfterDeviceLost: boolean = false;"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "destroy",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public destroy() {\r\n        this.bindGroups.destroy();\r\n        if (this.multisampleTexture) this.multisampleTexture.destroy();\r\n        if (this.renderPassTexture) this.renderPassTexture.destroyGpuResource();\r\n        if (this.depthStencilTexture) this.depthStencilTexture.destroy();\r\n        for (let z in this.description) this.description[z] = null;\r\n        for (let z in this) {\r\n            try {\r\n                (this[z] as any).destroy();\r\n            } catch (e) {\r\n                try {\r\n                    (this[z] as any).destroyGpuResource();\r\n                } catch (e) {\r\n\r\n                }\r\n            }\r\n\r\n            this[z] = null;\r\n        }\r\n      \r\n    }"
              },
              {
                "objectType": "method",
                "name": "initFromObject",
                "returnType": "any",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "{ [key: string]: unknown; cullMode?: \"front\" | \"back\" | \"none\"; topology?: \"point-list\" | \"line-list\" | \"line-strip\" | \"triangle-list\" | \"triangle-strip\"; frontFace?: \"ccw\" | \"cw\"; stripIndexFormat?: \"uint16\" | \"uint32\"; ... 13 more ...; fragmentShader?: string | ... 1 more ... | { ...; }; }"
                  }
                ],
                "visibility": "public",
                "rawText": "public initFromObject(descriptor: {\r\n        //description primitive : \r\n        cullMode?: \"front\" | \"back\" | \"none\",\r\n        topology?: \"point-list\" | \"line-list\" | \"line-strip\" | \"triangle-list\" | \"triangle-strip\",\r\n        frontFace?: \"ccw\" | \"cw\",\r\n        stripIndexFormat?: \"uint16\" | \"uint32\",\r\n        keepRendererAspectRatio?: boolean,\r\n        vertexCount?: number,\r\n        instanceCount?: number,\r\n        debugVertexCount?: number,\r\n        antiAliasing?: boolean,\r\n        useDepthTexture?: boolean,\r\n        depthTextureSize?: number,\r\n        depthTest?: boolean,\r\n        clearColor?: { r: number, g: number, b: number, a: number },\r\n        blendMode?: BlendMode,\r\n        bindgroups?: any,\r\n        indexBuffer?: IndexBuffer,\r\n\r\n\r\n        vertexShader: {\r\n            main: string\r\n            outputs?: any,\r\n            inputs?: any,\r\n            constants?: string,\r\n        } | string|VertexShader,\r\n        fragmentShader?: {\r\n            main: string,\r\n            outputs?: any,\r\n            inputs?: any,\r\n            constants?: string\r\n        } | string|FragmentShader\r\n        , [key: string]: unknown\r\n    }): any {\r\n\r\n\r\n\r\n        this._resources = {};\r\n        this.vertexShader = null;\r\n        this.fragmentShader = null;\r\n        this.gpuPipeline = null;\r\n        this.bindGroups.destroy();\r\n        this.bindGroups = new Bindgroups(this, \"pipeline\");\r\n\r\n\r\n\r\n        descriptor = HighLevelParser.parse(descriptor, \"render\", this.drawConfig);\r\n\r\n\r\n        super.initFromObject(descriptor);\r\n\r\n        if (!descriptor.cullMode) this.description.primitive.cullMode = \"none\";\r\n        else this.description.primitive.cullMode = descriptor.cullMode;\r\n\r\n        if (!descriptor.topology) this.description.primitive.topology = \"triangle-list\";\r\n        else {\r\n            this.description.primitive.topology = descriptor.topology;\r\n            if (descriptor.topology === \"line-strip\" || descriptor.topology === \"triangle-strip\") {\r\n                if (!descriptor.stripIndexFormat) {\r\n                    throw new Error(\"You must define a 'stripIndexFormat' in order to use a topology 'triangle-strip' or 'line-strip'. See https://www.w3.org/TR/webgpu/#enumdef-gpuindexformat for more details\")\r\n                } else {\r\n                    this.description.primitive.stripIndexFormat = descriptor.stripIndexFormat;\r\n                }\r\n            }\r\n        }\r\n\r\n        if (!descriptor.frontFace) this.description.primitive.frontFace = \"ccw\";\r\n        else this.description.primitive.frontFace = descriptor.frontFace;\r\n\r\n\r\n        if (descriptor.indexBuffer) {\r\n            this.drawConfig.indexBuffer = descriptor.indexBuffer;\r\n        }\r\n\r\n        if (this.outputColor) {\r\n            if (descriptor.clearColor) this.outputColor.clearValue = descriptor.clearColor;\r\n            else descriptor.clearColor = this.outputColor.clearValue;\r\n        }\r\n\r\n\r\n\r\n        if (descriptor.blendMode) this.blendMode = descriptor.blendMode;\r\n\r\n        if (descriptor.antiAliasing) this.setupMultiSampleView();\r\n\r\n        if (descriptor.useDepthTexture) {\r\n            let depthTextureSize: number = 1024;\r\n            if (descriptor.depthTextureSize) depthTextureSize = descriptor.depthTextureSize;\r\n            this.setupDepthStencilView({\r\n                size: [depthTextureSize, depthTextureSize, 1],\r\n                format: \"depth32float\",\r\n                usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING\r\n            })\r\n        } else if (descriptor.depthTest) this.setupDepthStencilView();\r\n\r\n\r\n        if (descriptor.bindgroups) {\r\n            let group: Bindgroup;\r\n            let resourcesGroups: IShaderResource[][] = [];\r\n            let k = 0;\r\n            for (let z in descriptor.bindgroups) {\r\n\r\n                if (descriptor.bindgroups[z] instanceof Bindgroup) {\r\n\r\n                    const elements = descriptor.bindgroups[z].elements as { name: string, resource: IShaderResource }[];\r\n                    const resources: IShaderResource[] = [];\r\n                    for (let i = 0; i < elements.length; i++) {\r\n                        resources[i] = elements[i].resource;\r\n                    }\r\n\r\n                    resourcesGroups[k++] = resources;\r\n                    descriptor.bindgroups[z].name = z;\r\n                    this.bindGroups.add(descriptor.bindgroups[z] as Bindgroup);\r\n\r\n                } else {\r\n\r\n                    group = new Bindgroup();\r\n                    group.name = z;\r\n                    const g = group.initFromObject(descriptor.bindgroups[z]);\r\n                    resourcesGroups[k++] = g;\r\n\r\n                    this.bindGroups.add(group);\r\n                }\r\n\r\n\r\n            }\r\n\r\n\r\n\r\n            if (descriptor.bindgroups.default) {\r\n                if (descriptor.bindgroups.default.buffer) {\r\n                    const attributes = (descriptor.bindgroups.default.buffer as VertexBuffer).attributes;\r\n                    for (let z in attributes) {\r\n                        if (descriptor[z]) descriptor[z] = attributes[z];\r\n                    }\r\n                }\r\n            }\r\n\r\n\r\n        }\r\n\r\n\r\n        const createArrayOfObjects = (obj: any) => {\r\n            const result = [];\r\n            let o: any;\r\n            for (let z in obj) {\r\n                o = obj[z];\r\n                result.push({ name: z, ...o })\r\n            }\r\n            return result;\r\n        }\r\n\r\n\r\n        this.vertexShader = new VertexShader();\r\n\r\n        if (typeof descriptor.vertexShader === \"string\") {\r\n            this.vertexShader.main.text = descriptor.vertexShader;\r\n        } else {\r\n\r\n            if(descriptor.vertexShader instanceof VertexShader){\r\n                this.vertexShader = descriptor.vertexShader;\r\n            }else{\r\n                if (descriptor.vertexShader.constants) this.vertexShader.constants.text = descriptor.vertexShader.constants;\r\n                this.vertexShader.main.text = descriptor.vertexShader.main;\r\n            }   \r\n\r\n            this.vertexShader.inputs = createArrayOfObjects(descriptor.vertexShader.inputs);\r\n            this.vertexShader.outputs = createArrayOfObjects(descriptor.vertexShader.outputs);\r\n           \r\n        }\r\n\r\n\r\n\r\n        if (descriptor.fragmentShader) {\r\n            this.fragmentShader = new FragmentShader();\r\n\r\n            if (typeof descriptor.fragmentShader === \"string\") {\r\n                this.fragmentShader.main.text = descriptor.fragmentShader;\r\n            } else {\r\n\r\n                if(descriptor.fragmentShader instanceof FragmentShader){\r\n                    this.fragmentShader = descriptor.fragmentShader;\r\n                }else{\r\n                    if (descriptor.fragmentShader.constants) this.fragmentShader.constants.text = descriptor.fragmentShader.constants;\r\n                    this.fragmentShader.main.text = descriptor.fragmentShader.main;\r\n                }\r\n\r\n                this.fragmentShader.inputs = createArrayOfObjects(descriptor.fragmentShader.inputs);;\r\n                this.fragmentShader.outputs = createArrayOfObjects(descriptor.fragmentShader.outputs);;\r\n                \r\n            }\r\n\r\n        }\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_INIT_FROM_OBJECT,descriptor);\r\n        return descriptor;\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createColorAttachment",
                "returnType": "any",
                "params": [
                  {
                    "name": "rgba",
                    "type": "{ r: number; g: number; b: number; a: number; }"
                  },
                  {
                    "name": "view",
                    "type": "GPUTextureView"
                  }
                ],
                "visibility": "public",
                "rawText": "public createColorAttachment(rgba: { r: number, g: number, b: number, a: number }, view: GPUTextureView = undefined): any {\r\n\r\n\r\n        const colorAttachment = {\r\n            view: view,\r\n            clearValue: rgba,\r\n            loadOp: \"clear\",\r\n            storeOp: \"store\"\r\n        }\r\n\r\n        this.renderPassDescriptor.colorAttachments.push(colorAttachment);\r\n\r\n\r\n\r\n        return colorAttachment;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupDraw",
                "returnType": "void",
                "params": [
                  {
                    "name": "o",
                    "type": "{ vertexCount: number; instanceCount?: number; firstVertexId?: number; firstInstanceId?: number; indexBuffer?: IndexBuffer; baseVertex?: number; }"
                  }
                ],
                "visibility": "public",
                "rawText": "public setupDraw(o: { vertexCount: number, instanceCount?: number, firstVertexId?: number, firstInstanceId?: number, indexBuffer?: IndexBuffer, baseVertex?: number }) {\r\n\r\n\r\n\r\n        if (o.instanceCount !== undefined) this.drawConfig.instanceCount = o.instanceCount;\r\n        if (o.vertexCount !== undefined) this.drawConfig.vertexCount = o.vertexCount;\r\n        if (o.firstVertexId !== undefined) this.drawConfig.firstVertexId = o.firstVertexId;\r\n        if (o.firstInstanceId !== undefined) this.drawConfig.firstInstanceId = o.firstInstanceId;\r\n        if (o.indexBuffer !== undefined) this.drawConfig.indexBuffer = o.indexBuffer;\r\n        if (o.baseVertex !== undefined) this.drawConfig.baseVertex = o.baseVertex;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupMultiSampleView",
                "returnType": "void",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "{ size?: GPUExtent3D; format?: GPUTextureFormat; usage?: GPUTextureUsageFlags; sampleCount?: GPUSize32; alphaToCoverageEnabled?: boolean; mask?: number; resolveTarget?: GPUTextureView; }"
                  }
                ],
                "visibility": "public",
                "rawText": "public setupMultiSampleView(descriptor?: {\r\n        size?: GPUExtent3D,\r\n        format?: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: GPUSize32,\r\n        alphaToCoverageEnabled?: boolean,\r\n        mask?: number,\r\n        resolveTarget?: GPUTextureView\r\n    }) {\r\n\r\n        if (!this.renderer) {\r\n            this.waitingMultisampleTexture = true;\r\n            this.multiSampleTextureDescriptor = descriptor;\r\n            return;\r\n        }\r\n\r\n\r\n        if (this.multisampleTexture) this.multisampleTexture.destroy();\r\n        if (!descriptor) descriptor = {};\r\n        if (!descriptor.size) descriptor.size = [this.renderer.width, this.renderer.height];\r\n        this.multisampleTexture = new MultiSampleTexture(descriptor as any);\r\n\r\n        this.description.multisample = {\r\n            count: this.multisampleTexture.description.count\r\n        }\r\n\r\n        if (this._depthStencilTexture) {\r\n\r\n            this.renderPassDescriptor.description.sampleCount = 4;\r\n            this._depthStencilTexture.create();\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupDepthStencilView",
                "returnType": "void",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "{ size?: GPUExtent3D; format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\"; usage?: GPUTextureUsageFlags; sampleCount?: number; }"
                  },
                  {
                    "name": "depthStencilDescription",
                    "type": "{ depthWriteEnabled: boolean; depthCompare: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\"; }"
                  },
                  {
                    "name": "depthStencilAttachmentOptions",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public setupDepthStencilView(\r\n        descriptor?: {\r\n            size?: GPUExtent3D,\r\n            format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\",\r\n            usage?: GPUTextureUsageFlags,\r\n            sampleCount?: number,\r\n        },\r\n        depthStencilDescription?: {\r\n            depthWriteEnabled: boolean,\r\n            depthCompare: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\",\r\n\r\n        },\r\n        depthStencilAttachmentOptions?: any\r\n\r\n    ) {\r\n\r\n        if (!this.renderer) {\r\n            this.waitingDepthStencilTexture = true;\r\n            this.depthStencilTextureDescriptor = descriptor;\r\n            return;\r\n        }\r\n\r\n\r\n        if (!depthStencilAttachmentOptions) depthStencilAttachmentOptions = {};\r\n\r\n\r\n        if (!descriptor) descriptor = {}\r\n        if (!descriptor.size) descriptor.size = [this.renderer.width, this.renderer.height];\r\n        if (this.multisampleTexture) descriptor.sampleCount = 4;\r\n        else descriptor.sampleCount = 1;\r\n\r\n\r\n        if (this._depthStencilTexture) this._depthStencilTexture.destroy();\r\n        this._depthStencilTexture = new DepthStencilTexture(descriptor as any, depthStencilDescription, depthStencilAttachmentOptions)\r\n\r\n\r\n        this.renderPassDescriptor.depthStencilAttachment = this.depthStencilTexture.attachment;\r\n        this.description.depthStencil = this.depthStencilTexture.description;\r\n\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "clearAfterDeviceLostAndRebuild",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public clearAfterDeviceLostAndRebuild() {\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_DEVICE_LOST)\r\n        if (this.onRebuildStartAfterDeviceLost) this.onRebuildStartAfterDeviceLost();\r\n\r\n        this.gpuPipeline = null;\r\n        if (this.drawConfig.indexBuffer) this.drawConfig.indexBuffer.createGpuResource();\r\n        if (this.multisampleTexture) this.multisampleTexture.resize(this.renderer.width, this.renderer.height);\r\n        if (this.depthStencilTexture) this.depthStencilTexture.resize(this.renderer.width, this.renderer.height);\r\n        if (this.renderPassTexture) this.renderPassTexture.resize(this.renderer.width, this.renderer.height);\r\n\r\n        this.rebuildingAfterDeviceLost = true;\r\n        super.clearAfterDeviceLostAndRebuild();\r\n\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "buildGpuPipeline",
                "returnType": "GPURenderPipeline",
                "visibility": "public",
                "rawText": "public buildGpuPipeline(): GPURenderPipeline {\r\n        if (this.gpuPipeline || this.buildingPipeline) return this.gpuPipeline;\r\n        this.buildingPipeline = true;\r\n        //console.warn(\"BUILD GPUPIPELINE\")\r\n\r\n        this.bindGroups.handleRenderPipelineResourceIOs();\r\n\r\n        this.initPipelineResources(this);\r\n\r\n\r\n        const o = this.bindGroups.build();\r\n\r\n\r\n        if (o.description.layout) this.description.layout = o.description.layout;\r\n        else this.description.layout = \"auto\";\r\n\r\n\r\n        if (!this.rebuildingAfterDeviceLost) {\r\n\r\n            const buffers: VertexBuffer[] = o.buffers;\r\n            this.description.vertex = o.description.vertex;\r\n\r\n\r\n\r\n\r\n            //setup vertexShader inputs ------\r\n            const vertexInput: ShaderStruct = new ShaderStruct(\"Input\", this.cleanInputs());;\r\n\r\n            if (buffers.length) {\r\n                let buffer: VertexBuffer;\r\n                let arrays: VertexAttribute[];\r\n                let builtin: number = 0;\r\n                for (let i = 0; i < buffers.length; i++) {\r\n                    buffer = buffers[i];\r\n                    arrays = buffer.vertexArrays;\r\n                    for (let j = 0; j < arrays.length; j++) {\r\n                        vertexInput.addProperty({ name: arrays[j].name, type: arrays[j].varType, builtin: \"@location(\" + builtin + \")\" })\r\n                        builtin++;\r\n                    }\r\n                }\r\n            }\r\n\r\n            //---------------------------------\r\n\r\n\r\n            const vertexShader: { code: string, output: ShaderStruct } = this.vertexShader.build(this, vertexInput);\r\n\r\n            this.dispatchEvent(RenderPipeline.ON_VERTEX_SHADER_CODE_BUILT,vertexShader)\r\n           \r\n\r\n\r\n            let fragmentShader: { code: string, output: ShaderStruct };\r\n            if (this.fragmentShader) {\r\n                fragmentShader = this.fragmentShader.build(this, vertexShader.output.getInputFromOutput());\r\n                this.dispatchEvent(RenderPipeline.ON_FRAGMENT_SHADER_CODE_BUILT,fragmentShader)\r\n            }\r\n\r\n\r\n            this.description.vertex = {\r\n                code: vertexShader.code,\r\n                entryPoint: \"main\",\r\n                buffers: o.description.vertex.buffers\r\n            }\r\n\r\n            if (this.fragmentShader) {\r\n\r\n                this.description.fragment = {\r\n                    code: fragmentShader.code,\r\n                    entryPoint: \"main\",\r\n                    targets: [\r\n                        this.getFragmentShaderColorOptions()\r\n                    ]\r\n\r\n                }\r\n            }\r\n\r\n        }\r\n\r\n        this.description.vertex.module = XGPU.device.createShaderModule({ code: this.description.vertex.code })\r\n\r\n        if (this.description.fragment) {\r\n            this.description.fragment.module = XGPU.device.createShaderModule({ code: this.description.fragment.code })\r\n        }\r\n\r\n\r\n        this.rebuildingAfterDeviceLost = false;\r\n        this.gpuPipeline = XGPU.createRenderPipeline(this.description);\r\n\r\n        let resources:{name:string,resource:any}[][] = this.bindGroups.resources.types;\r\n        for(let type in resources){\r\n            (resources[type] as any[]).forEach((o)=>{\r\n                if(o.resource.gpuResource){\r\n                    o.resource.gpuResource.label = o.name;\r\n                }\r\n               \r\n            });\r\n        }\r\n\r\n        if (this.resources.__DEBUG__) {\r\n\r\n            this.vertexShaderDebuggerPipeline = new VertexShaderDebuggerPipeline();\r\n            this.vertexShaderDebuggerPipeline.init(this, this.debugVertexCount)\r\n            this.vertexShaderDebuggerPipeline.onLog = (o) => {\r\n                \r\n                this.dispatchEvent(RenderPipeline.ON_LOG, o);\r\n                //this._onLog(o);\r\n            }\r\n        }\r\n        this.buildingPipeline = false;\r\n        this.dispatchEvent(RenderPipeline.ON_GPU_PIPELINE_BUILT)\r\n        return this.gpuPipeline;\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "beginRenderPass",
                "returnType": "GPURenderPassEncoder",
                "params": [
                  {
                    "name": "commandEncoder",
                    "type": "GPUCommandEncoder"
                  },
                  {
                    "name": "outputView",
                    "type": "GPUTextureView"
                  },
                  {
                    "name": "drawCallId",
                    "type": "number"
                  },
                  {
                    "name": "usingRenderPassTexture",
                    "type": "boolean"
                  }
                ],
                "visibility": "public",
                "rawText": "public beginRenderPass(commandEncoder: GPUCommandEncoder, outputView?: GPUTextureView, drawCallId?: number, usingRenderPassTexture: boolean = false): GPURenderPassEncoder {\r\n        if (!this.resourceDefined) return null;\r\n\r\n\r\n\r\n        if (this.vertexShaderDebuggerPipeline) this.vertexShaderDebuggerPipeline.nextFrame();\r\n\r\n\r\n\r\n\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_DRAW_BEGIN);\r\n\r\n        if (usingRenderPassTexture) {\r\n            //console.log(\"usingRenderPassTexture\")\r\n            this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\"\r\n\r\n        } else {\r\n            if (this.renderPassDescriptor.colorAttachments[0]) {\r\n                this._clearValue = this.renderPassDescriptor.colorAttachments[0].clearValue\r\n            }\r\n\r\n\r\n            //console.log(\"not usingRenderPassTexture\")\r\n\r\n            let rendererUseSinglePipeline: boolean = this.renderer.renderPipelines.length == 1 && this.pipelineCount === 1;\r\n\r\n            if (this.rendererUseSinglePipeline !== rendererUseSinglePipeline) {\r\n                this.clearOpReady = false;\r\n                this.rendererUseSinglePipeline = rendererUseSinglePipeline;\r\n            }\r\n\r\n            if (this.clearOpReady === false && this.renderPassDescriptor.colorAttachments[0] || this.pipelineCount > 1) {\r\n                this.clearOpReady = true;\r\n\r\n                /*if (this.useRenderPassTexture && this.renderPassDescriptor.colorAttachments[0]) {\r\n                    this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\"\r\n                } else {*/\r\n                if (rendererUseSinglePipeline && this.pipelineCount == 1) this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\";\r\n                else {\r\n                    if (this.pipelineCount === 1) {\r\n                        if (this.renderer.renderPipelines[0] === this) this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\";\r\n                        else this.renderPassDescriptor.colorAttachments[0].loadOp = \"load\";\r\n                    } else {\r\n\r\n                        this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\";\r\n                        if (drawCallId === 0) { }\r\n                        else this.renderPassDescriptor.colorAttachments[0].loadOp = \"load\";\r\n                    }\r\n\r\n                }\r\n                //}\r\n\r\n            }\r\n\r\n\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n\r\n        if (!this.gpuPipeline) this.buildGpuPipeline();\r\n\r\n        if (outputView && this.outputColor) this.handleOutputColor(outputView);\r\n\r\n\r\n\r\n\r\n        return commandEncoder.beginRenderPass(this.renderPassDescriptor);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "update",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public update(): void {\r\n        //console.log(\"renderPipeline.update start gpuPipeline = \", this.gpuPipeline)\r\n        if (!this.gpuPipeline) return;\r\n\r\n\r\n        if (this.renderPassTexture) this.renderPassTexture.update();\r\n        this.bindGroups.update();\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_UPDATE_RESOURCES);\r\n        //console.log(\"renderPipeline.update end\")\r\n    }"
              },
              {
                "objectType": "method",
                "name": "draw",
                "returnType": "void",
                "params": [
                  {
                    "name": "renderPass",
                    "type": "GPURenderPassEncoder"
                  }
                ],
                "visibility": "public",
                "rawText": "public draw(renderPass: GPURenderPassEncoder) {\r\n\r\n\r\n        if (!this.resourceDefined) return;\r\n\r\n        //console.log(\"draw\")\r\n        renderPass.setPipeline(this.gpuPipeline);\r\n\r\n        this.bindGroups.apply(renderPass);\r\n        \r\n    }"
              },
              {
                "objectType": "method",
                "name": "end",
                "returnType": "void",
                "params": [
                  {
                    "name": "commandEncoder",
                    "type": "GPUCommandEncoder"
                  },
                  {
                    "name": "renderPass",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public end(commandEncoder: GPUCommandEncoder, renderPass) {\r\n        if (!this.resourceDefined) return;\r\n        renderPass.end();\r\n        \r\n        //console.log(\"end\")\r\n        //------ the arrays of textures may contains GPUTexture so I must use commandEncoder.copyTextureToTexture \r\n        // to update the content from a GPUTexture to the texture_array_2d \r\n        const types = this.bindGroups.resources.types;\r\n\r\n        if (types) {\r\n\r\n            if (!types.textureArrays) {\r\n                let textureArrays = [];\r\n                if (types.imageTextureArrays) textureArrays = textureArrays.concat(types.imageTextureArrays);\r\n                if (types.cubeMapTextureArrays) textureArrays = textureArrays.concat(types.cubeMapTextureArrays);\r\n                if (types.cubeMapTexture) textureArrays = textureArrays.concat(types.cubeMapTexture);\r\n                types.textureArrays = textureArrays;\r\n            }\r\n\r\n            for (let i = 0; i < types.textureArrays.length; i++) {\r\n                (types.textureArrays[i].resource as ImageTextureArray).updateInnerGpuTextures(commandEncoder);\r\n            }\r\n        }\r\n\r\n\r\n        //----------------------------------------------------------------------------------------\r\n\r\n\r\n\r\n        const { width, height } = this.renderer;\r\n\r\n\r\n\r\n\r\n        if (this.renderer.resized) {\r\n\r\n\r\n            if (this.multisampleTexture) {\r\n                this.multisampleTexture.resize(width, height);\r\n            }\r\n            if (this.depthStencilTexture) {\r\n                this.depthStencilTexture.resize(width, height);\r\n            }\r\n            if (this.renderPassTexture) {\r\n                this.renderPassTexture.resize(width, height)\r\n            }\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n        if (this.renderPassTexture && this.renderPassTexture.mustUseCopyTextureToTexture) {\r\n            if (!this.renderPassTexture.gpuResource) this.renderPassTexture.createGpuResource();\r\n\r\n            commandEncoder.copyTextureToTexture({ texture: this.renderer.texture }, { texture: this.renderPassTexture.gpuResource }, [width, height]);\r\n        }\r\n\r\n        if (this.multisampleTexture) this.multisampleTexture.update();\r\n        if (this.depthStencilTexture) this.depthStencilTexture.update();\r\n        if (this.renderPassTexture) this.renderPassTexture.update();\r\n\r\n\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_DRAW_END);\r\n    }"
              }
            ],
            "private": [
              {
                "objectType": "method",
                "name": "getFragmentShaderColorOptions",
                "returnType": "any",
                "visibility": "private",
                "rawText": "private getFragmentShaderColorOptions() {\r\n\r\n        const o: any = {\r\n            format: XGPU.getPreferredCanvasFormat(),\r\n        }\r\n\r\n        if (this.blendMode) o.blend = this.blendMode;\r\n        return o;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "handleOutputColor",
                "returnType": "void",
                "params": [
                  {
                    "name": "outputView",
                    "type": "GPUTextureView"
                  }
                ],
                "visibility": "private",
                "rawText": "private handleOutputColor(outputView: GPUTextureView) {\r\n        if (this.outputColor) {\r\n\r\n            if (this.multisampleTexture) {\r\n                if (!this.multisampleTexture.view) this.multisampleTexture.create();\r\n\r\n\r\n                this.outputColor.view = this.multisampleTexture.view;\r\n\r\n                if (this.multisampleTexture.resolveTarget) this.outputColor.resolveTarget = this.multisampleTexture.resolveTarget;\r\n                else this.outputColor.resolveTarget = outputView;\r\n\r\n            } else {\r\n                this.outputColor.view = outputView;\r\n            }\r\n        }\r\n\r\n    }"
              }
            ],
            "protected": [
              {
                "objectType": "method",
                "name": "cleanInputs",
                "returnType": "any[]",
                "visibility": "protected",
                "rawText": "protected cleanInputs(/*initIO: boolean = false*/) {\r\n        const _inputs = [];\r\n        const t = this.vertexShader.inputs;\r\n        for (let z in t) _inputs.push({ name: z, ...t[z] });\r\n        this.vertexShader.inputs = _inputs;\r\n        return _inputs;\r\n    }"
              }
            ]
          },
          "statics": {
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "ON_ADDED_TO_RENDERER",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_ADDED_TO_RENDERER: string = \"ON_ADDED_TO_RENDERER\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_REMOVED_FROM_RENDERER",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_REMOVED_FROM_RENDERER: string = \"ON_REMOVED_FROM_RENDERER\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_DRAW_BEGIN",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_DRAW_BEGIN: string = \"ON_DRAW_BEGIN\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_DRAW_END",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_DRAW_END: string = \"ON_DRAW_END\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_DRAW",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_DRAW: string = \"ON_DRAW\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_GPU_PIPELINE_BUILT",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_GPU_PIPELINE_BUILT: string = \"ON_GPU_PIPELINE_BUILT\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_LOG",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_LOG: string = \"ON_LOG\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_VERTEX_SHADER_CODE_BUILT",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_VERTEX_SHADER_CODE_BUILT:string = \"ON_VERTEX_SHADER_CODE_BUILT\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_FRAGMENT_SHADER_CODE_BUILT",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_FRAGMENT_SHADER_CODE_BUILT:string = \"ON_FRAGMENT_SHADER_CODE_BUILT\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_INIT_FROM_OBJECT",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_INIT_FROM_OBJECT:string = \"ON_INIT_FROM_OBJECT\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_DEVICE_LOST",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_DEVICE_LOST:string = \"ON_DEVICE_LOST\";"
                },
                {
                  "objectType": "property",
                  "name": "ON_UPDATE_RESOURCES",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public static ON_UPDATE_RESOURCES:string = \"ON_UPDATE_RESOURCES\";"
                }
              ]
            }
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "params": [
              {
                "name": "bgColor",
                "type": "{ r: number; g: number; b: number; a: number; }"
              }
            ],
            "rawText": "constructor(bgColor: { r: number, g: number, b: number, a: number } = { r: 0, g: 0, b: 0, a: 1 }) {\r\n        super();\r\n\r\n\r\n        this.type = \"render\";\r\n\r\n        this.drawConfig = new DrawConfig(this);\r\n        this.vertexShader = new VertexShader();\r\n        this.fragmentShader = new FragmentShader();\r\n        this.description.primitive = {\r\n            topology: \"triangle-list\",\r\n            cullMode: \"none\",\r\n            frontFace: \"ccw\"\r\n        }\r\n\r\n        if (bgColor !== null) {\r\n            this.outputColor = this.createColorAttachment(bgColor);\r\n        }\r\n\r\n    }"
          },
          "rawText": "export class RenderPipeline extends Pipeline {\r\n\r\n\r\n    public static ON_ADDED_TO_RENDERER: string = \"ON_ADDED_TO_RENDERER\";\r\n    public static ON_REMOVED_FROM_RENDERER: string = \"ON_REMOVED_FROM_RENDERER\";\r\n    public static ON_DRAW_BEGIN: string = \"ON_DRAW_BEGIN\";\r\n    public static ON_DRAW_END: string = \"ON_DRAW_END\";\r\n    public static ON_DRAW: string = \"ON_DRAW\";\r\n    public static ON_GPU_PIPELINE_BUILT: string = \"ON_GPU_PIPELINE_BUILT\";\r\n    public static ON_LOG: string = \"ON_LOG\";\r\n    public static ON_VERTEX_SHADER_CODE_BUILT:string = \"ON_VERTEX_SHADER_CODE_BUILT\";\r\n    public static ON_FRAGMENT_SHADER_CODE_BUILT:string = \"ON_FRAGMENT_SHADER_CODE_BUILT\";\r\n    public static ON_INIT_FROM_OBJECT:string = \"ON_INIT_FROM_OBJECT\";\r\n    public static ON_DEVICE_LOST:string = \"ON_DEVICE_LOST\";\r\n    public static ON_UPDATE_RESOURCES:string = \"ON_UPDATE_RESOURCES\";\r\n  \r\n\r\n    protected _renderer: IRenderer;\r\n    public get renderer(): IRenderer { return this._renderer }\r\n    public set renderer(renderer: IRenderer) {\r\n        if (this._renderer != renderer) {\r\n\r\n\r\n            this._renderer = renderer;\r\n\r\n            if (renderer) {\r\n\r\n                if (this.waitingMultisampleTexture) {\r\n                    this.setupMultiSampleView(this.multiSampleTextureDescriptor)\r\n                    this.waitingMultisampleTexture = false;\r\n                }\r\n\r\n                if (this.waitingDepthStencilTexture) {\r\n                    this.setupDepthStencilView(this.depthStencilTextureDescriptor);\r\n                    this.waitingDepthStencilTexture = false;\r\n                }\r\n                //console.log(\"dispatch\")\r\n                this.dispatchEvent(RenderPipeline.ON_ADDED_TO_RENDERER);\r\n\r\n            } else {\r\n                this.dispatchEvent(RenderPipeline.ON_REMOVED_FROM_RENDERER);\r\n            }\r\n\r\n        }\r\n    }\r\n\r\n\r\n    public drawConfig: DrawConfig;\r\n\r\n\r\n    protected multiSampleTextureDescriptor: any;\r\n    protected waitingMultisampleTexture: boolean = false;\r\n    protected multisampleTexture: MultiSampleTexture;\r\n\r\n    protected waitingDepthStencilTexture: boolean = false;\r\n    protected depthStencilTextureDescriptor: any;\r\n    protected _depthStencilTexture: DepthStencilTexture;\r\n\r\n\r\n\r\n\r\n    protected renderPassTexture: RenderPassTexture;\r\n\r\n    public outputColor: any;\r\n    public renderPassDescriptor: any = { colorAttachments: [] }\r\n\r\n\r\n    protected vertexShaderDebuggerPipeline: VertexShaderDebuggerPipeline = null;\r\n\r\n    protected gpuPipeline: GPURenderPipeline;\r\n\r\n    public debug: string = \"renderPipeline\";\r\n\r\n\r\n    constructor(bgColor: { r: number, g: number, b: number, a: number } = { r: 0, g: 0, b: 0, a: 1 }) {\r\n        super();\r\n\r\n\r\n        this.type = \"render\";\r\n\r\n        this.drawConfig = new DrawConfig(this);\r\n        this.vertexShader = new VertexShader();\r\n        this.fragmentShader = new FragmentShader();\r\n        this.description.primitive = {\r\n            topology: \"triangle-list\",\r\n            cullMode: \"none\",\r\n            frontFace: \"ccw\"\r\n        }\r\n\r\n        if (bgColor !== null) {\r\n            this.outputColor = this.createColorAttachment(bgColor);\r\n        }\r\n\r\n    }\r\n\r\n\r\n\r\n\r\n    /*\r\n    public get canvas(): any {\r\n        if (!this.renderer) return null;\r\n        return this.renderer.canvas;\r\n    }\r\n    */\r\n    public get depthStencilTexture(): DepthStencilTexture { return this._depthStencilTexture; }\r\n\r\n\r\n    public destroy() {\r\n        this.bindGroups.destroy();\r\n        if (this.multisampleTexture) this.multisampleTexture.destroy();\r\n        if (this.renderPassTexture) this.renderPassTexture.destroyGpuResource();\r\n        if (this.depthStencilTexture) this.depthStencilTexture.destroy();\r\n        for (let z in this.description) this.description[z] = null;\r\n        for (let z in this) {\r\n            try {\r\n                (this[z] as any).destroy();\r\n            } catch (e) {\r\n                try {\r\n                    (this[z] as any).destroyGpuResource();\r\n                } catch (e) {\r\n\r\n                }\r\n            }\r\n\r\n            this[z] = null;\r\n        }\r\n      \r\n    }\r\n\r\n    public initFromObject(descriptor: {\r\n        //description primitive : \r\n        cullMode?: \"front\" | \"back\" | \"none\",\r\n        topology?: \"point-list\" | \"line-list\" | \"line-strip\" | \"triangle-list\" | \"triangle-strip\",\r\n        frontFace?: \"ccw\" | \"cw\",\r\n        stripIndexFormat?: \"uint16\" | \"uint32\",\r\n        keepRendererAspectRatio?: boolean,\r\n        vertexCount?: number,\r\n        instanceCount?: number,\r\n        debugVertexCount?: number,\r\n        antiAliasing?: boolean,\r\n        useDepthTexture?: boolean,\r\n        depthTextureSize?: number,\r\n        depthTest?: boolean,\r\n        clearColor?: { r: number, g: number, b: number, a: number },\r\n        blendMode?: BlendMode,\r\n        bindgroups?: any,\r\n        indexBuffer?: IndexBuffer,\r\n\r\n\r\n        vertexShader: {\r\n            main: string\r\n            outputs?: any,\r\n            inputs?: any,\r\n            constants?: string,\r\n        } | string|VertexShader,\r\n        fragmentShader?: {\r\n            main: string,\r\n            outputs?: any,\r\n            inputs?: any,\r\n            constants?: string\r\n        } | string|FragmentShader\r\n        , [key: string]: unknown\r\n    }): any {\r\n\r\n\r\n\r\n        this._resources = {};\r\n        this.vertexShader = null;\r\n        this.fragmentShader = null;\r\n        this.gpuPipeline = null;\r\n        this.bindGroups.destroy();\r\n        this.bindGroups = new Bindgroups(this, \"pipeline\");\r\n\r\n\r\n\r\n        descriptor = HighLevelParser.parse(descriptor, \"render\", this.drawConfig);\r\n\r\n\r\n        super.initFromObject(descriptor);\r\n\r\n        if (!descriptor.cullMode) this.description.primitive.cullMode = \"none\";\r\n        else this.description.primitive.cullMode = descriptor.cullMode;\r\n\r\n        if (!descriptor.topology) this.description.primitive.topology = \"triangle-list\";\r\n        else {\r\n            this.description.primitive.topology = descriptor.topology;\r\n            if (descriptor.topology === \"line-strip\" || descriptor.topology === \"triangle-strip\") {\r\n                if (!descriptor.stripIndexFormat) {\r\n                    throw new Error(\"You must define a 'stripIndexFormat' in order to use a topology 'triangle-strip' or 'line-strip'. See https://www.w3.org/TR/webgpu/#enumdef-gpuindexformat for more details\")\r\n                } else {\r\n                    this.description.primitive.stripIndexFormat = descriptor.stripIndexFormat;\r\n                }\r\n            }\r\n        }\r\n\r\n        if (!descriptor.frontFace) this.description.primitive.frontFace = \"ccw\";\r\n        else this.description.primitive.frontFace = descriptor.frontFace;\r\n\r\n\r\n        if (descriptor.indexBuffer) {\r\n            this.drawConfig.indexBuffer = descriptor.indexBuffer;\r\n        }\r\n\r\n        if (this.outputColor) {\r\n            if (descriptor.clearColor) this.outputColor.clearValue = descriptor.clearColor;\r\n            else descriptor.clearColor = this.outputColor.clearValue;\r\n        }\r\n\r\n\r\n\r\n        if (descriptor.blendMode) this.blendMode = descriptor.blendMode;\r\n\r\n        if (descriptor.antiAliasing) this.setupMultiSampleView();\r\n\r\n        if (descriptor.useDepthTexture) {\r\n            let depthTextureSize: number = 1024;\r\n            if (descriptor.depthTextureSize) depthTextureSize = descriptor.depthTextureSize;\r\n            this.setupDepthStencilView({\r\n                size: [depthTextureSize, depthTextureSize, 1],\r\n                format: \"depth32float\",\r\n                usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING\r\n            })\r\n        } else if (descriptor.depthTest) this.setupDepthStencilView();\r\n\r\n\r\n        if (descriptor.bindgroups) {\r\n            let group: Bindgroup;\r\n            let resourcesGroups: IShaderResource[][] = [];\r\n            let k = 0;\r\n            for (let z in descriptor.bindgroups) {\r\n\r\n                if (descriptor.bindgroups[z] instanceof Bindgroup) {\r\n\r\n                    const elements = descriptor.bindgroups[z].elements as { name: string, resource: IShaderResource }[];\r\n                    const resources: IShaderResource[] = [];\r\n                    for (let i = 0; i < elements.length; i++) {\r\n                        resources[i] = elements[i].resource;\r\n                    }\r\n\r\n                    resourcesGroups[k++] = resources;\r\n                    descriptor.bindgroups[z].name = z;\r\n                    this.bindGroups.add(descriptor.bindgroups[z] as Bindgroup);\r\n\r\n                } else {\r\n\r\n                    group = new Bindgroup();\r\n                    group.name = z;\r\n                    const g = group.initFromObject(descriptor.bindgroups[z]);\r\n                    resourcesGroups[k++] = g;\r\n\r\n                    this.bindGroups.add(group);\r\n                }\r\n\r\n\r\n            }\r\n\r\n\r\n\r\n            if (descriptor.bindgroups.default) {\r\n                if (descriptor.bindgroups.default.buffer) {\r\n                    const attributes = (descriptor.bindgroups.default.buffer as VertexBuffer).attributes;\r\n                    for (let z in attributes) {\r\n                        if (descriptor[z]) descriptor[z] = attributes[z];\r\n                    }\r\n                }\r\n            }\r\n\r\n\r\n        }\r\n\r\n\r\n        const createArrayOfObjects = (obj: any) => {\r\n            const result = [];\r\n            let o: any;\r\n            for (let z in obj) {\r\n                o = obj[z];\r\n                result.push({ name: z, ...o })\r\n            }\r\n            return result;\r\n        }\r\n\r\n\r\n        this.vertexShader = new VertexShader();\r\n\r\n        if (typeof descriptor.vertexShader === \"string\") {\r\n            this.vertexShader.main.text = descriptor.vertexShader;\r\n        } else {\r\n\r\n            if(descriptor.vertexShader instanceof VertexShader){\r\n                this.vertexShader = descriptor.vertexShader;\r\n            }else{\r\n                if (descriptor.vertexShader.constants) this.vertexShader.constants.text = descriptor.vertexShader.constants;\r\n                this.vertexShader.main.text = descriptor.vertexShader.main;\r\n            }   \r\n\r\n            this.vertexShader.inputs = createArrayOfObjects(descriptor.vertexShader.inputs);\r\n            this.vertexShader.outputs = createArrayOfObjects(descriptor.vertexShader.outputs);\r\n           \r\n        }\r\n\r\n\r\n\r\n        if (descriptor.fragmentShader) {\r\n            this.fragmentShader = new FragmentShader();\r\n\r\n            if (typeof descriptor.fragmentShader === \"string\") {\r\n                this.fragmentShader.main.text = descriptor.fragmentShader;\r\n            } else {\r\n\r\n                if(descriptor.fragmentShader instanceof FragmentShader){\r\n                    this.fragmentShader = descriptor.fragmentShader;\r\n                }else{\r\n                    if (descriptor.fragmentShader.constants) this.fragmentShader.constants.text = descriptor.fragmentShader.constants;\r\n                    this.fragmentShader.main.text = descriptor.fragmentShader.main;\r\n                }\r\n\r\n                this.fragmentShader.inputs = createArrayOfObjects(descriptor.fragmentShader.inputs);;\r\n                this.fragmentShader.outputs = createArrayOfObjects(descriptor.fragmentShader.outputs);;\r\n                \r\n            }\r\n\r\n        }\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_INIT_FROM_OBJECT,descriptor);\r\n        return descriptor;\r\n\r\n    }\r\n\r\n    protected _clearValue: { r: number, g: number, b: number, a: number } = null;\r\n    public get clearValue(): { r: number, g: number, b: number, a: number } {\r\n        return this._clearValue;\r\n        //if (!this.renderPassDescriptor.colorAttachment) return null;\r\n        //return this.renderPassDescriptor.colorAttachment.clearValue;\r\n    }\r\n    public createColorAttachment(rgba: { r: number, g: number, b: number, a: number }, view: GPUTextureView = undefined): any {\r\n\r\n\r\n        const colorAttachment = {\r\n            view: view,\r\n            clearValue: rgba,\r\n            loadOp: \"clear\",\r\n            storeOp: \"store\"\r\n        }\r\n\r\n        this.renderPassDescriptor.colorAttachments.push(colorAttachment);\r\n\r\n\r\n\r\n        return colorAttachment;\r\n    }\r\n\r\n\r\n\r\n    //-----------------\r\n\r\n\r\n\r\n    public setupDraw(o: { vertexCount: number, instanceCount?: number, firstVertexId?: number, firstInstanceId?: number, indexBuffer?: IndexBuffer, baseVertex?: number }) {\r\n\r\n\r\n\r\n        if (o.instanceCount !== undefined) this.drawConfig.instanceCount = o.instanceCount;\r\n        if (o.vertexCount !== undefined) this.drawConfig.vertexCount = o.vertexCount;\r\n        if (o.firstVertexId !== undefined) this.drawConfig.firstVertexId = o.firstVertexId;\r\n        if (o.firstInstanceId !== undefined) this.drawConfig.firstInstanceId = o.firstInstanceId;\r\n        if (o.indexBuffer !== undefined) this.drawConfig.indexBuffer = o.indexBuffer;\r\n        if (o.baseVertex !== undefined) this.drawConfig.baseVertex = o.baseVertex;\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n    public get debugVertexCount(): number { return this.resources.debugVertexCount }\r\n    public set debugVertexCount(n: number) { this.resources.debugVertexCount = n; }\r\n\r\n    public get vertexCount(): number { return this.drawConfig.vertexCount }\r\n    public set vertexCount(n: number) { this.drawConfig.vertexCount = n; }\r\n\r\n    public get instanceCount(): number { return this.drawConfig.instanceCount }\r\n    public set instanceCount(n: number) { this.drawConfig.instanceCount = n; }\r\n\r\n    public get firstVertexId(): number { return this.drawConfig.firstVertexId }\r\n    public set firstVertexId(n: number) { this.drawConfig.firstVertexId = n; }\r\n\r\n    public get firstInstanceId(): number { return this.drawConfig.firstInstanceId }\r\n    public set firstInstanceId(n: number) { this.drawConfig.firstInstanceId = n; }\r\n\r\n    public get baseVertex(): number { return this.drawConfig.baseVertex }\r\n    public set baseVertex(n: number) { this.drawConfig.baseVertex = n; }\r\n\r\n    //------------------------------------------------\r\n\r\n    public setupMultiSampleView(descriptor?: {\r\n        size?: GPUExtent3D,\r\n        format?: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: GPUSize32,\r\n        alphaToCoverageEnabled?: boolean,\r\n        mask?: number,\r\n        resolveTarget?: GPUTextureView\r\n    }) {\r\n\r\n        if (!this.renderer) {\r\n            this.waitingMultisampleTexture = true;\r\n            this.multiSampleTextureDescriptor = descriptor;\r\n            return;\r\n        }\r\n\r\n\r\n        if (this.multisampleTexture) this.multisampleTexture.destroy();\r\n        if (!descriptor) descriptor = {};\r\n        if (!descriptor.size) descriptor.size = [this.renderer.width, this.renderer.height];\r\n        this.multisampleTexture = new MultiSampleTexture(descriptor as any);\r\n\r\n        this.description.multisample = {\r\n            count: this.multisampleTexture.description.count\r\n        }\r\n\r\n        if (this._depthStencilTexture) {\r\n\r\n            this.renderPassDescriptor.description.sampleCount = 4;\r\n            this._depthStencilTexture.create();\r\n        }\r\n    }\r\n\r\n    //---------------------------\r\n\r\n    public setupDepthStencilView(\r\n        descriptor?: {\r\n            size?: GPUExtent3D,\r\n            format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\",\r\n            usage?: GPUTextureUsageFlags,\r\n            sampleCount?: number,\r\n        },\r\n        depthStencilDescription?: {\r\n            depthWriteEnabled: boolean,\r\n            depthCompare: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\",\r\n\r\n        },\r\n        depthStencilAttachmentOptions?: any\r\n\r\n    ) {\r\n\r\n        if (!this.renderer) {\r\n            this.waitingDepthStencilTexture = true;\r\n            this.depthStencilTextureDescriptor = descriptor;\r\n            return;\r\n        }\r\n\r\n\r\n        if (!depthStencilAttachmentOptions) depthStencilAttachmentOptions = {};\r\n\r\n\r\n        if (!descriptor) descriptor = {}\r\n        if (!descriptor.size) descriptor.size = [this.renderer.width, this.renderer.height];\r\n        if (this.multisampleTexture) descriptor.sampleCount = 4;\r\n        else descriptor.sampleCount = 1;\r\n\r\n\r\n        if (this._depthStencilTexture) this._depthStencilTexture.destroy();\r\n        this._depthStencilTexture = new DepthStencilTexture(descriptor as any, depthStencilDescription, depthStencilAttachmentOptions)\r\n\r\n\r\n        this.renderPassDescriptor.depthStencilAttachment = this.depthStencilTexture.attachment;\r\n        this.description.depthStencil = this.depthStencilTexture.description;\r\n\r\n\r\n    }\r\n    //----------------------------------------\r\n\r\n    public get renderPassView(): GPUTextureView { return this.renderPass.view }\r\n    public get renderPass(): RenderPassTexture {\r\n        if (!this.renderPassTexture) {\r\n            this.renderPassTexture = new RenderPassTexture(this)\r\n        }\r\n        return this.renderPassTexture;\r\n    }\r\n\r\n    public get useRenderPassTexture(): boolean {\r\n        return !!this.renderPassTexture;\r\n    }\r\n\r\n\r\n\r\n    protected cleanInputs(/*initIO: boolean = false*/) {\r\n        const _inputs = [];\r\n        const t = this.vertexShader.inputs;\r\n        for (let z in t) _inputs.push({ name: z, ...t[z] });\r\n        this.vertexShader.inputs = _inputs;\r\n        return _inputs;\r\n    }\r\n\r\n\r\n    public blendMode: BlendMode;\r\n    private getFragmentShaderColorOptions() {\r\n\r\n        const o: any = {\r\n            format: XGPU.getPreferredCanvasFormat(),\r\n        }\r\n\r\n        if (this.blendMode) o.blend = this.blendMode;\r\n        return o;\r\n    }\r\n\r\n\r\n    protected rebuildingAfterDeviceLost: boolean = false;\r\n    public onRebuildStartAfterDeviceLost: () => void;\r\n    public clearAfterDeviceLostAndRebuild() {\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_DEVICE_LOST)\r\n        if (this.onRebuildStartAfterDeviceLost) this.onRebuildStartAfterDeviceLost();\r\n\r\n        this.gpuPipeline = null;\r\n        if (this.drawConfig.indexBuffer) this.drawConfig.indexBuffer.createGpuResource();\r\n        if (this.multisampleTexture) this.multisampleTexture.resize(this.renderer.width, this.renderer.height);\r\n        if (this.depthStencilTexture) this.depthStencilTexture.resize(this.renderer.width, this.renderer.height);\r\n        if (this.renderPassTexture) this.renderPassTexture.resize(this.renderer.width, this.renderer.height);\r\n\r\n        this.rebuildingAfterDeviceLost = true;\r\n        super.clearAfterDeviceLostAndRebuild();\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n\r\n    private buildingPipeline: boolean = false;\r\n    public buildGpuPipeline(): GPURenderPipeline {\r\n        if (this.gpuPipeline || this.buildingPipeline) return this.gpuPipeline;\r\n        this.buildingPipeline = true;\r\n        //console.warn(\"BUILD GPUPIPELINE\")\r\n\r\n        this.bindGroups.handleRenderPipelineResourceIOs();\r\n\r\n        this.initPipelineResources(this);\r\n\r\n\r\n        const o = this.bindGroups.build();\r\n\r\n\r\n        if (o.description.layout) this.description.layout = o.description.layout;\r\n        else this.description.layout = \"auto\";\r\n\r\n\r\n        if (!this.rebuildingAfterDeviceLost) {\r\n\r\n            const buffers: VertexBuffer[] = o.buffers;\r\n            this.description.vertex = o.description.vertex;\r\n\r\n\r\n\r\n\r\n            //setup vertexShader inputs ------\r\n            const vertexInput: ShaderStruct = new ShaderStruct(\"Input\", this.cleanInputs());;\r\n\r\n            if (buffers.length) {\r\n                let buffer: VertexBuffer;\r\n                let arrays: VertexAttribute[];\r\n                let builtin: number = 0;\r\n                for (let i = 0; i < buffers.length; i++) {\r\n                    buffer = buffers[i];\r\n                    arrays = buffer.vertexArrays;\r\n                    for (let j = 0; j < arrays.length; j++) {\r\n                        vertexInput.addProperty({ name: arrays[j].name, type: arrays[j].varType, builtin: \"@location(\" + builtin + \")\" })\r\n                        builtin++;\r\n                    }\r\n                }\r\n            }\r\n\r\n            //---------------------------------\r\n\r\n\r\n            const vertexShader: { code: string, output: ShaderStruct } = this.vertexShader.build(this, vertexInput);\r\n\r\n            this.dispatchEvent(RenderPipeline.ON_VERTEX_SHADER_CODE_BUILT,vertexShader)\r\n           \r\n\r\n\r\n            let fragmentShader: { code: string, output: ShaderStruct };\r\n            if (this.fragmentShader) {\r\n                fragmentShader = this.fragmentShader.build(this, vertexShader.output.getInputFromOutput());\r\n                this.dispatchEvent(RenderPipeline.ON_FRAGMENT_SHADER_CODE_BUILT,fragmentShader)\r\n            }\r\n\r\n\r\n            this.description.vertex = {\r\n                code: vertexShader.code,\r\n                entryPoint: \"main\",\r\n                buffers: o.description.vertex.buffers\r\n            }\r\n\r\n            if (this.fragmentShader) {\r\n\r\n                this.description.fragment = {\r\n                    code: fragmentShader.code,\r\n                    entryPoint: \"main\",\r\n                    targets: [\r\n                        this.getFragmentShaderColorOptions()\r\n                    ]\r\n\r\n                }\r\n            }\r\n\r\n        }\r\n\r\n        this.description.vertex.module = XGPU.device.createShaderModule({ code: this.description.vertex.code })\r\n\r\n        if (this.description.fragment) {\r\n            this.description.fragment.module = XGPU.device.createShaderModule({ code: this.description.fragment.code })\r\n        }\r\n\r\n\r\n        this.rebuildingAfterDeviceLost = false;\r\n        this.gpuPipeline = XGPU.createRenderPipeline(this.description);\r\n\r\n        let resources:{name:string,resource:any}[][] = this.bindGroups.resources.types;\r\n        for(let type in resources){\r\n            (resources[type] as any[]).forEach((o)=>{\r\n                if(o.resource.gpuResource){\r\n                    o.resource.gpuResource.label = o.name;\r\n                }\r\n               \r\n            });\r\n        }\r\n\r\n        if (this.resources.__DEBUG__) {\r\n\r\n            this.vertexShaderDebuggerPipeline = new VertexShaderDebuggerPipeline();\r\n            this.vertexShaderDebuggerPipeline.init(this, this.debugVertexCount)\r\n            this.vertexShaderDebuggerPipeline.onLog = (o) => {\r\n                \r\n                this.dispatchEvent(RenderPipeline.ON_LOG, o);\r\n                //this._onLog(o);\r\n            }\r\n        }\r\n        this.buildingPipeline = false;\r\n        this.dispatchEvent(RenderPipeline.ON_GPU_PIPELINE_BUILT)\r\n        return this.gpuPipeline;\r\n\r\n    }\r\n\r\n    //-------------------------------------------\r\n\r\n    private clearOpReady: boolean = false;\r\n    private rendererUseSinglePipeline: boolean = true;\r\n\r\n    public beginRenderPass(commandEncoder: GPUCommandEncoder, outputView?: GPUTextureView, drawCallId?: number, usingRenderPassTexture: boolean = false): GPURenderPassEncoder {\r\n        if (!this.resourceDefined) return null;\r\n\r\n\r\n\r\n        if (this.vertexShaderDebuggerPipeline) this.vertexShaderDebuggerPipeline.nextFrame();\r\n\r\n\r\n\r\n\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_DRAW_BEGIN);\r\n\r\n        if (usingRenderPassTexture) {\r\n            //console.log(\"usingRenderPassTexture\")\r\n            this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\"\r\n\r\n        } else {\r\n            if (this.renderPassDescriptor.colorAttachments[0]) {\r\n                this._clearValue = this.renderPassDescriptor.colorAttachments[0].clearValue\r\n            }\r\n\r\n\r\n            //console.log(\"not usingRenderPassTexture\")\r\n\r\n            let rendererUseSinglePipeline: boolean = this.renderer.renderPipelines.length == 1 && this.pipelineCount === 1;\r\n\r\n            if (this.rendererUseSinglePipeline !== rendererUseSinglePipeline) {\r\n                this.clearOpReady = false;\r\n                this.rendererUseSinglePipeline = rendererUseSinglePipeline;\r\n            }\r\n\r\n            if (this.clearOpReady === false && this.renderPassDescriptor.colorAttachments[0] || this.pipelineCount > 1) {\r\n                this.clearOpReady = true;\r\n\r\n                /*if (this.useRenderPassTexture && this.renderPassDescriptor.colorAttachments[0]) {\r\n                    this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\"\r\n                } else {*/\r\n                if (rendererUseSinglePipeline && this.pipelineCount == 1) this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\";\r\n                else {\r\n                    if (this.pipelineCount === 1) {\r\n                        if (this.renderer.renderPipelines[0] === this) this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\";\r\n                        else this.renderPassDescriptor.colorAttachments[0].loadOp = \"load\";\r\n                    } else {\r\n\r\n                        this.renderPassDescriptor.colorAttachments[0].loadOp = \"clear\";\r\n                        if (drawCallId === 0) { }\r\n                        else this.renderPassDescriptor.colorAttachments[0].loadOp = \"load\";\r\n                    }\r\n\r\n                }\r\n                //}\r\n\r\n            }\r\n\r\n\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n\r\n        if (!this.gpuPipeline) this.buildGpuPipeline();\r\n\r\n        if (outputView && this.outputColor) this.handleOutputColor(outputView);\r\n\r\n\r\n\r\n\r\n        return commandEncoder.beginRenderPass(this.renderPassDescriptor);\r\n    }\r\n\r\n    private handleOutputColor(outputView: GPUTextureView) {\r\n        if (this.outputColor) {\r\n\r\n            if (this.multisampleTexture) {\r\n                if (!this.multisampleTexture.view) this.multisampleTexture.create();\r\n\r\n\r\n                this.outputColor.view = this.multisampleTexture.view;\r\n\r\n                if (this.multisampleTexture.resolveTarget) this.outputColor.resolveTarget = this.multisampleTexture.resolveTarget;\r\n                else this.outputColor.resolveTarget = outputView;\r\n\r\n            } else {\r\n                this.outputColor.view = outputView;\r\n            }\r\n        }\r\n\r\n    }\r\n\r\n    //----------------------------------------------------------------------\r\n\r\n    public update(): void {\r\n        //console.log(\"renderPipeline.update start gpuPipeline = \", this.gpuPipeline)\r\n        if (!this.gpuPipeline) return;\r\n\r\n\r\n        if (this.renderPassTexture) this.renderPassTexture.update();\r\n        this.bindGroups.update();\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_UPDATE_RESOURCES);\r\n        //console.log(\"renderPipeline.update end\")\r\n    }\r\n\r\n\r\n    public draw(renderPass: GPURenderPassEncoder) {\r\n\r\n\r\n        if (!this.resourceDefined) return;\r\n\r\n        //console.log(\"draw\")\r\n        renderPass.setPipeline(this.gpuPipeline);\r\n\r\n        this.bindGroups.apply(renderPass);\r\n        \r\n    }\r\n\r\n\r\n    //-------------------------------\r\n\r\n    public end(commandEncoder: GPUCommandEncoder, renderPass) {\r\n        if (!this.resourceDefined) return;\r\n        renderPass.end();\r\n        \r\n        //console.log(\"end\")\r\n        //------ the arrays of textures may contains GPUTexture so I must use commandEncoder.copyTextureToTexture \r\n        // to update the content from a GPUTexture to the texture_array_2d \r\n        const types = this.bindGroups.resources.types;\r\n\r\n        if (types) {\r\n\r\n            if (!types.textureArrays) {\r\n                let textureArrays = [];\r\n                if (types.imageTextureArrays) textureArrays = textureArrays.concat(types.imageTextureArrays);\r\n                if (types.cubeMapTextureArrays) textureArrays = textureArrays.concat(types.cubeMapTextureArrays);\r\n                if (types.cubeMapTexture) textureArrays = textureArrays.concat(types.cubeMapTexture);\r\n                types.textureArrays = textureArrays;\r\n            }\r\n\r\n            for (let i = 0; i < types.textureArrays.length; i++) {\r\n                (types.textureArrays[i].resource as ImageTextureArray).updateInnerGpuTextures(commandEncoder);\r\n            }\r\n        }\r\n\r\n\r\n        //----------------------------------------------------------------------------------------\r\n\r\n\r\n\r\n        const { width, height } = this.renderer;\r\n\r\n\r\n\r\n\r\n        if (this.renderer.resized) {\r\n\r\n\r\n            if (this.multisampleTexture) {\r\n                this.multisampleTexture.resize(width, height);\r\n            }\r\n            if (this.depthStencilTexture) {\r\n                this.depthStencilTexture.resize(width, height);\r\n            }\r\n            if (this.renderPassTexture) {\r\n                this.renderPassTexture.resize(width, height)\r\n            }\r\n        }\r\n\r\n\r\n\r\n\r\n\r\n        if (this.renderPassTexture && this.renderPassTexture.mustUseCopyTextureToTexture) {\r\n            if (!this.renderPassTexture.gpuResource) this.renderPassTexture.createGpuResource();\r\n\r\n            commandEncoder.copyTextureToTexture({ texture: this.renderer.texture }, { texture: this.renderPassTexture.gpuResource }, [width, height]);\r\n        }\r\n\r\n        if (this.multisampleTexture) this.multisampleTexture.update();\r\n        if (this.depthStencilTexture) this.depthStencilTexture.update();\r\n        if (this.renderPassTexture) this.renderPassTexture.update();\r\n\r\n\r\n\r\n        this.dispatchEvent(RenderPipeline.ON_DRAW_END);\r\n    }\r\n\r\n\r\n    public get resourceDefined(): boolean {\r\n        const bool = !!this.bindGroups.resources.all\r\n        if (!bool) {\r\n            //some very basic shader can run without any resource\r\n            if (this.drawConfig.vertexCount > 0) {\r\n                if (this.vertexShader.main.text != \"\" && this.fragmentShader.main.text != \"\") {\r\n                    return true;\r\n                }\r\n            }\r\n\r\n            return false;\r\n        }\r\n        return true\r\n    }\r\n\r\n    public get pipeline(): GPURenderPipeline { return this.gpuPipeline }\r\n\r\n    public get cullMode(): \"front\" | \"back\" | \"none\" { return this.description.primitive.cullMode }\r\n    public set cullMode(s: \"front\" | \"back\" | \"none\") { this.description.primitive.cullMode = s }\r\n\r\n    public get topology(): \"point-list\" | \"line-list\" | \"line-strip\" | \"triangle-list\" | \"triangle-strip\" { return this.description.primitive.topology }\r\n    public set topology(s: \"point-list\" | \"line-list\" | \"line-strip\" | \"triangle-list\" | \"triangle-strip\") { this.description.primitive.topology = s }\r\n\r\n    public get frontFace(): \"ccw\" | \"cw\" { return this.description.primitive.frontFace }\r\n    public set frontFace(s: \"ccw\" | \"cw\") { this.description.primitive.frontFace = s }\r\n\r\n    public get stripIndexFormat(): \"uint16\" | \"uint32\" { return this.description.primitive.stripIndexFormat }\r\n    public set stripIndexFormat(s: \"uint16\" | \"uint32\") { this.description.primitive.stripIndexFormat = s }\r\n}"
        }
      ],
      "VertexShaderDebuggerPipeline": [
        {
          "objectType": "class",
          "name": "VertexShaderDebuggerPipeline",
          "filePath": "xGPU.pipelines.VertexShaderDebuggerPipeline",
          "extends": [
            "ComputePipeline",
            "Pipeline",
            "EventDispatcher"
          ],
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "onLog",
                "type": "(o: { config: any; results: any[]; nbValueByFieldName: any; renderPipeline: RenderPipeline; dataTypeByFieldname: any; }) => void",
                "visibility": "public",
                "rawText": "public onLog: (o: {\r\n        config: any,\r\n        results: any[],\r\n        nbValueByFieldName: any\r\n        renderPipeline: RenderPipeline,\r\n        dataTypeByFieldname: any,\r\n    }) => void;"
              }
            ],
            "private": [
              {
                "objectType": "property",
                "name": "temporaryIndex",
                "type": "number",
                "visibility": "private",
                "rawText": "private temporaryIndex: number = 0;"
              }
            ],
            "protected": [
              {
                "objectType": "property",
                "name": "config",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected config: any;"
              },
              {
                "objectType": "property",
                "name": "vertexShaderInputs",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected vertexShaderInputs: any;"
              },
              {
                "objectType": "property",
                "name": "renderPipeline",
                "type": "RenderPipeline",
                "visibility": "protected",
                "rawText": "protected renderPipeline: RenderPipeline;"
              },
              {
                "objectType": "property",
                "name": "computeShaderObj",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected computeShaderObj: any;"
              },
              {
                "objectType": "property",
                "name": "resourceByType",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected resourceByType: any;"
              },
              {
                "objectType": "property",
                "name": "indexBuffer",
                "type": "IndexBuffer",
                "visibility": "protected",
                "rawText": "protected indexBuffer: IndexBuffer;"
              },
              {
                "objectType": "property",
                "name": "results",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected results: any;"
              },
              {
                "objectType": "property",
                "name": "resultBufferStructure",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected resultBufferStructure: any = {};"
              },
              {
                "objectType": "property",
                "name": "nbValueByFieldIndex",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected nbValueByFieldIndex: any = {};"
              },
              {
                "objectType": "property",
                "name": "nbValueByFieldName",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected nbValueByFieldName: any = {};"
              },
              {
                "objectType": "property",
                "name": "dataTypeByFieldname",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected dataTypeByFieldname: any = {};"
              },
              {
                "objectType": "property",
                "name": "fieldNames",
                "type": "string[]",
                "visibility": "protected",
                "rawText": "protected fieldNames: string[] = [];"
              },
              {
                "objectType": "property",
                "name": "fieldNewNames",
                "type": "string[]",
                "visibility": "protected",
                "rawText": "protected fieldNewNames: string[] = [];"
              },
              {
                "objectType": "property",
                "name": "fieldIndexByName",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected fieldIndexByName: any = {};"
              },
              {
                "objectType": "property",
                "name": "attributes",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected attributes: any = {};"
              },
              {
                "objectType": "property",
                "name": "vertexIdName",
                "type": "string",
                "visibility": "protected",
                "rawText": "protected vertexIdName: string;"
              },
              {
                "objectType": "property",
                "name": "instanceIdName",
                "type": "string",
                "visibility": "protected",
                "rawText": "protected instanceIdName: string;"
              },
              {
                "objectType": "property",
                "name": "renderUniformBuffers",
                "type": "{ name: string; resource: UniformBuffer; }[]",
                "visibility": "protected",
                "rawText": "protected renderUniformBuffers: { name: string, resource: UniformBuffer }[]"
              },
              {
                "objectType": "property",
                "name": "renderVertexBuffers",
                "type": "{ name: string; resource: VertexBuffer; }[]",
                "visibility": "protected",
                "rawText": "protected renderVertexBuffers: { name: string, resource: VertexBuffer }[];"
              },
              {
                "objectType": "property",
                "name": "bufferNameByAttributeName",
                "type": "string[]",
                "visibility": "protected",
                "rawText": "protected bufferNameByAttributeName: string[];"
              },
              {
                "objectType": "property",
                "name": "vertexBufferIO",
                "type": "VertexBufferIO",
                "visibility": "protected",
                "rawText": "protected vertexBufferIO: VertexBufferIO;"
              },
              {
                "objectType": "property",
                "name": "firstPass",
                "type": "boolean",
                "visibility": "protected",
                "rawText": "protected firstPass: boolean = true;"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "init",
                "returnType": "void",
                "params": [
                  {
                    "name": "renderPipeline",
                    "type": "RenderPipeline"
                  },
                  {
                    "name": "nbVertex",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "public init(renderPipeline: RenderPipeline, nbVertex: number) {\r\n\r\n        if (!nbVertex) nbVertex = 1;\r\n\r\n        this.config = { nbVertex };\r\n        this.computeShaderObj = {\r\n            bindgroups: {\r\n                io: {}, //computeShaders have a reserved bindgroup 'io' , dedicated to the ping-pong process \r\n            }\r\n        };\r\n\r\n\r\n\r\n\r\n        this.initRenderPipeline(renderPipeline);\r\n        this.setupIndexBuffer();\r\n        this.setupDataStructure();\r\n        this.setupVertexShaderBuiltIns();\r\n        this.setupUniformBuffers();\r\n        this.setupVertexBuffers();\r\n        this.setupComputeShaderVertexBufferIO();\r\n        this.buildComputeShader();\r\n\r\n\r\n\r\n        this.onComputeBegin = () => {\r\n            this.copyUniformsFromRenderToCompute();\r\n        }\r\n\r\n\r\n    }"
              }
            ],
            "private": [
              {
                "objectType": "method",
                "name": "convertLetIntoVar",
                "returnType": "string",
                "params": [
                  {
                    "name": "shader",
                    "type": "string"
                  }
                ],
                "visibility": "private",
                "rawText": "private convertLetIntoVar(shader: string): string {\r\n        let result = \"\"\r\n        let lines: string[] = shader.split(\"\\n\");\r\n        let line: string;\r\n        let chars = \"abcdefghijklmnopqrstuvwxyz/\"\r\n        chars += chars.toUpperCase();\r\n\r\n        const getFirstCharId = (line: string) => {\r\n            for (let i = 0; i < line.length; i++) {\r\n                if (chars.includes(line[i])) return i;\r\n            }\r\n            return line.length - 1\r\n        }\r\n\r\n\r\n        for (let i = 0; i < lines.length; i++) {\r\n            line = lines[i];\r\n            line = line.slice(getFirstCharId(line));\r\n            if (line.slice(0, 4) === \"let \") {\r\n                line = \"var \" + line.slice(4);\r\n            }\r\n\r\n            //adding a first empty char is a dirty fix to another process \r\n            result += \" \" + line + \"\\n\";\r\n        }\r\n\r\n\r\n        return result;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "removeVar",
                "returnType": "string",
                "params": [
                  {
                    "name": "shader",
                    "type": "string"
                  }
                ],
                "visibility": "private",
                "rawText": "private removeVar(shader: string): string {\r\n        let result = \"\"\r\n        let lines: string[] = shader.split(\"\\n\");\r\n        let line: string;\r\n\r\n\r\n        for (let i = 0; i < lines.length; i++) {\r\n            line = lines[i];\r\n            if (line.slice(0, 5) === \" var \") line = line.slice(5);\r\n            result += \" \" + line + \"\\n\";\r\n        }\r\n\r\n\r\n        return result;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "writeArrayTemplate",
                "returnType": "string",
                "params": [
                  {
                    "name": "shader",
                    "type": "string"
                  },
                  {
                    "name": "computeMatrixName",
                    "type": "string"
                  },
                  {
                    "name": "arrayLen",
                    "type": "number"
                  },
                  {
                    "name": "primitiveType",
                    "type": "\"u32\" | \"f32\" | \"mat4\" | \"i32\""
                  }
                ],
                "visibility": "private",
                "rawText": "private writeArrayTemplate(shader: string, computeMatrixName: string, arrayLen: number, primitiveType: \"f32\" | \"i32\" | \"u32\" | \"mat4\"): string {\r\n        let abc = \"abcdefghijklmnopqrstuvwxyz0123456789\"\r\n        abc += abc.toUpperCase();\r\n        let lines: string[] = shader.split(\"\\n\");\r\n        let line: string;\r\n\r\n        const isComplexVal = (val: string): boolean => {\r\n            for (let i = 0; i < val.length; i++) {\r\n                if (abc.includes(val[i])) continue;\r\n                else return true;\r\n            }\r\n            return false;\r\n        }\r\n\r\n\r\n\r\n        let tempName: string;\r\n\r\n\r\n\r\n        const writeTemplate = (computeName: string, matrixName: string): string => {\r\n            let result = \"\";\r\n            let nb = arrayLen;\r\n            let isArrayMatrix = primitiveType == \"mat4\";\r\n\r\n            for (let i = 0; i < nb; i++) {\r\n                if (!isArrayMatrix) result += `computeResult.${computeName}_ar${i} = ${matrixName}[${i}];\\n`;\r\n                else {\r\n                    result += `computeResult.${computeName}_ar${i}_m0 = ${matrixName}[${i}][0];\\n`;\r\n                    result += `computeResult.${computeName}_ar${i}_m1 = ${matrixName}[${i}][1];\\n`;\r\n                    result += `computeResult.${computeName}_ar${i}_m2 = ${matrixName}[${i}][2];\\n`;\r\n                    result += `computeResult.${computeName}_ar${i}_m3 = ${matrixName}[${i}][3];\\n`;\r\n                }\r\n            }\r\n            result += \"\\n\";\r\n            return result;\r\n        }\r\n\r\n        let newLine = \"\";\r\n        for (let i = 0; i < lines.length; i++) {\r\n            line = lines[i];\r\n            //console.log(i, \" line = \", computeMatrixName, line);\r\n            if (line.includes(\"computeResult.\" + computeMatrixName) == true) {\r\n                newLine = \"\";\r\n                let val = line.split(\"=\")[1].split(\";\")[0].trim();\r\n                //console.log(\"val = \", val)\r\n\r\n                let j = i;\r\n                if (isComplexVal(val)) {\r\n\r\n                    if (line.includes(\";\") === false) {\r\n\r\n                        for (j = i + 1; j < lines.length; j++) {\r\n\r\n                            if (lines[j].includes(\";\") == false) {\r\n                                val += lines[j] + \"\\n\";\r\n                                lines[j] = \"\";\r\n                            } else {\r\n                                val += lines[j].split(\";\")[0] + \"\";\r\n                                lines[j] = \"\";\r\n                                break;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n\r\n                    tempName = \"temporaryVariable_\" + this.temporaryIndex++;\r\n                    if (primitiveType === \"mat4\") newLine = \"let \" + tempName + \":array<mat4x4<f32>,\" + arrayLen + \"> = \" + val + \";\\n\";\r\n                    else newLine = \"let \" + tempName + \":array<vec4<\" + primitiveType + \"> = \" + val + \";\\n\";\r\n                    val = tempName;\r\n                }\r\n\r\n                newLine += writeTemplate(computeMatrixName, val);\r\n                lines[i] = newLine;\r\n\r\n\r\n                break;\r\n\r\n            }\r\n\r\n        }\r\n\r\n        return lines.join(\"\\n\");\r\n\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "writeMatrixTemplate",
                "returnType": "string",
                "params": [
                  {
                    "name": "shader",
                    "type": "string"
                  },
                  {
                    "name": "computeMatrixName",
                    "type": "string"
                  },
                  {
                    "name": "mat4x4",
                    "type": "boolean"
                  }
                ],
                "visibility": "private",
                "rawText": "private writeMatrixTemplate(shader: string, computeMatrixName: string, mat4x4: boolean = true): string {\r\n        let abc = \"abcdefghijklmnopqrstuvwxyz0123456789\"\r\n        abc += abc.toUpperCase();\r\n        let lines: string[] = shader.split(\"\\n\");\r\n        let line: string;\r\n\r\n        const isComplexVal = (val: string): boolean => {\r\n            for (let i = 0; i < val.length; i++) {\r\n                if (abc.includes(val[i])) continue;\r\n                else return true;\r\n            }\r\n            return false;\r\n        }\r\n\r\n\r\n\r\n        let tempName: string;\r\n\r\n\r\n\r\n        const writeTemplate = (computeName: string, matrixName: string): string => {\r\n            let result = \"\";\r\n            let nb = 4;\r\n            if (mat4x4 == false) nb = 3;\r\n            //console.log(computeName + \" => mat4x4:\", mat4x4);\r\n            for (let i = 0; i < nb; i++) {\r\n                result += `computeResult.${computeName}_m${nb}${i} = ${matrixName}[${i}];\\n`;\r\n            }\r\n            result += \"\\n\";\r\n            return result;\r\n        }\r\n\r\n        let newLine = \"\";\r\n        for (let i = 0; i < lines.length; i++) {\r\n            line = lines[i];\r\n            //console.log(i, \" line = \", computeMatrixName, line);\r\n            if (line.includes(\"computeResult.\" + computeMatrixName) == true) {\r\n                newLine = \"\";\r\n                let val = line.split(\"=\")[1].split(\";\")[0].trim();\r\n                //console.log(\"val = \", val)\r\n\r\n                let j = i;\r\n                if (isComplexVal(val)) {\r\n\r\n                    if (line.includes(\";\") === false) {\r\n\r\n                        for (j = i + 1; j < lines.length; j++) {\r\n\r\n                            if (lines[j].includes(\";\") == false) {\r\n                                val += lines[j] + \"\\n\";\r\n                                lines[j] = \"\";\r\n                            } else {\r\n                                val += lines[j].split(\";\")[0] + \"\";\r\n                                lines[j] = \"\";\r\n                                break;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n\r\n                    tempName = \"temporaryVariable_\" + this.temporaryIndex++;\r\n                    if (mat4x4) newLine = \"let \" + tempName + \":mat4x4<f32> = \" + val + \";\\n\";\r\n                    else newLine = \"let \" + tempName + \":mat3x3<f32> = \" + val + \";\\n\";\r\n                    val = tempName;\r\n                }\r\n\r\n                newLine += writeTemplate(computeMatrixName, val);\r\n                lines[i] = newLine;\r\n\r\n\r\n                break;\r\n\r\n            }\r\n\r\n        }\r\n\r\n        return lines.join(\"\\n\");\r\n\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createEmptyArray",
                "returnType": "number[]",
                "params": [
                  {
                    "name": "len",
                    "type": "number"
                  }
                ],
                "visibility": "private",
                "rawText": "private createEmptyArray(len: number): number[] {\r\n        const arr = [];\r\n        for (let i = 0; i < len; i++) arr[i] = 0;\r\n        return arr;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getObjectByType",
                "returnType": "any",
                "params": [
                  {
                    "name": "type",
                    "type": "string"
                  }
                ],
                "visibility": "private",
                "rawText": "private getObjectByType(type: string): any {\r\n        if (type === \"f32\") return VertexAttribute.Float();\r\n        if (type === \"vec2<f32>\") return VertexAttribute.Vec2();\r\n        if (type === \"vec3<f32>\") return VertexAttribute.Vec3();\r\n        if (type === \"vec4<f32>\") return VertexAttribute.Vec4();\r\n        return null;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getNbValueByType",
                "returnType": "number",
                "params": [
                  {
                    "name": "type",
                    "type": "string"
                  }
                ],
                "visibility": "private",
                "rawText": "private getNbValueByType(type: string): number {\r\n        if (type === \"f32\") return 1;\r\n        if (type === \"vec2<f32>\") return 2;\r\n        if (type === \"vec3<f32>\") return 3;\r\n        if (type === \"vec4<f32>\") return 4;\r\n        return 0;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getNewInstanceByType",
                "returnType": "string",
                "params": [
                  {
                    "name": "type",
                    "type": "string"
                  }
                ],
                "visibility": "private",
                "rawText": "private getNewInstanceByType(type: string): string {\r\n        if (type === \"f32\") return \"0.0\";\r\n        if (type === \"vec2<f32>\") return \"vec2(0.0)\";\r\n        if (type === \"vec3<f32>\") return \"vec3(0.0)\";\r\n        if (type === \"vec4<f32>\") return \"vec4(0.0)\";\r\n        return \"\";\r\n    }"
              }
            ],
            "protected": [
              {
                "objectType": "method",
                "name": "initRenderPipeline",
                "returnType": "void",
                "params": [
                  {
                    "name": "renderPipeline",
                    "type": "RenderPipeline"
                  }
                ],
                "visibility": "protected",
                "rawText": "protected initRenderPipeline(renderPipeline: RenderPipeline): void {\r\n        this.renderPipeline = renderPipeline;\r\n\r\n\r\n        renderPipeline.bindGroups.setupDraw(true);\r\n        this.resourceByType = renderPipeline.bindGroups.resources.types;\r\n        this.vertexShaderInputs = renderPipeline.vertexShader.inputs;\r\n        this.renderUniformBuffers = this.resourceByType.uniformBuffers;\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupIndexBuffer",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected setupIndexBuffer() {\r\n        /*\r\n       we check if the renderPipeline use an indexBuffer.\r\n       If yes, we create a vertexBuffer to represent it \r\n       */\r\n\r\n\r\n        let indexBuffer: IndexBuffer = null\r\n        if (this.renderPipeline.resources.indexBuffer) {\r\n            indexBuffer = this.renderPipeline.resources.indexBuffer;\r\n            this.computeShaderObj[\"indexBuffer\"] = new VertexBuffer({ id: VertexAttribute.Uint() }, {\r\n                stepMode: \"vertex\",\r\n                datas: indexBuffer.datas\r\n            })\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupDataStructure",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected setupDataStructure() {\r\n        this.results = {};\r\n        this.resultBufferStructure = {};\r\n        this.nbValueByFieldIndex = {};\r\n        this.nbValueByFieldName = {};\r\n        this.dataTypeByFieldname = {};\r\n        this.fieldNames = [];\r\n        this.fieldNewNames = [];\r\n        this.fieldIndexByName = {};\r\n        this.attributes = {};\r\n\r\n        //const vertexShaderOutputs = this.renderPipeline.vertexShader.outputs;\r\n        const vertexShaderDebugs = this.renderPipeline.resources.__DEBUG__.objectById;\r\n\r\n        let nb: number, name: string;\r\n        let debug: { name: string, newName: string, type: string, builtin?: string, nbValue: number };\r\n        for (let i = 0; i < vertexShaderDebugs.length; i++) {\r\n            debug = vertexShaderDebugs[i];\r\n            name = debug.name;\r\n            nb = this.getNbValueByType(debug.type)\r\n\r\n            //console.log(i, debug.name, debug.newName)\r\n\r\n            //used to write the shader code\r\n            this.fieldNames[i] = name;\r\n            this.fieldNewNames[i] = debug.newName;\r\n            this.fieldIndexByName[name] = i;\r\n            this.nbValueByFieldIndex[i] = debug.nbValue;\r\n            this.dataTypeByFieldname[name] = debug.type;\r\n\r\n\r\n            //used to fill the vertexBufferIO with the appropriate property names and the correct data structure\r\n            this.resultBufferStructure[name] = this.createEmptyArray(nb)\r\n\r\n            //used to manipule the data outside of this class\r\n            this.nbValueByFieldName[name] = nb;\r\n\r\n            //console.log(\"debug.type = \", debug)\r\n            this.attributes[debug.newName] = this.getObjectByType(debug.type)\r\n\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupVertexShaderBuiltIns",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected setupVertexShaderBuiltIns() {\r\n        let input: { name: string, type: string, builtin?: string };\r\n\r\n        /*\r\n        we first convert the Builtins \"vertex_index\" and \"instance_index\" (if they exists) into an uniform used in the computeShader\r\n        with the name used in the vertexShader\r\n        */\r\n\r\n\r\n\r\n        for (let i = 0; i < this.vertexShaderInputs.length; i++) {\r\n            input = this.vertexShaderInputs[i];\r\n            if (input.builtin) {\r\n                if (input.builtin === \"@builtin(vertex_index)\") {\r\n                    this.vertexIdName = input.name;\r\n                    //this.computeUniforms[input.name] = new Uint(this.config.startVertexId, true)\r\n                } else if (input.builtin === \"@builtin(instance_index)\") {\r\n                    this.instanceIdName = input.name;\r\n                    //this.computeUniforms[input.name] = new Uint(this.config.instanceId, true)\r\n                }\r\n            }\r\n        }\r\n\r\n        if (!this.vertexIdName) {\r\n            this.vertexIdName = \"VERTEX_ID\";\r\n            //this.computeUniforms[this.vertexIdName] = new Uint(this.config.startVertexId, true)\r\n        }\r\n\r\n        if (!this.instanceIdName) {\r\n            this.instanceIdName = \"INSTANCE_ID\";\r\n            //this.computeUniforms[this.instanceIdName] = new Uint(this.config.startVertexId, true)\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupUniformBuffers",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected setupUniformBuffers() {\r\n\r\n        let ub: { name: string, resource: UniformBuffer };\r\n\r\n        const cloneUniformBuffer = (buf: UniformBuffer) => {\r\n\r\n            const result: any = {};\r\n\r\n            for (let i = 0; i < buf.itemNames.length; i++) {\r\n                result[buf.itemNames[i]] = buf.items[buf.itemNames[i]].clone();\r\n                //result[buf.itemNames[i]].datas\r\n            }\r\n\r\n            return new UniformBuffer(result, { useLocalVariable: buf.descriptor.useLocalVariable })\r\n        }\r\n\r\n        if (this.renderUniformBuffers) {\r\n            for (let i = 0; i < this.renderUniformBuffers.length; i++) {\r\n                ub = this.renderUniformBuffers[i];\r\n                this.computeShaderObj[ub.name] = cloneUniformBuffer(ub.resource);\r\n            }\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupVertexBuffers",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected setupVertexBuffers() {\r\n        this.renderVertexBuffers = this.resourceByType.vertexBuffers;\r\n        this.bufferNameByAttributeName = [];\r\n\r\n        let vb: { name: string, resource: VertexBuffer };\r\n        let vBuffer: VertexBuffer;\r\n\r\n\r\n        if (this.renderVertexBuffers) {\r\n\r\n\r\n\r\n            for (let i = 0; i < this.renderVertexBuffers.length; i++) {\r\n                vb = this.renderVertexBuffers[i];\r\n                vBuffer = vb.resource;\r\n\r\n                let attributes = vBuffer.attributeDescriptor;\r\n                for (let z in attributes) {\r\n                    this.bufferNameByAttributeName[z] = vb.name;\r\n                }\r\n\r\n\r\n                this.computeShaderObj[vb.name] = new VertexBuffer(vBuffer.attributeDescriptor, {\r\n                    stepMode: vBuffer.stepMode,\r\n                    datas: vBuffer.datas\r\n                })\r\n\r\n            }\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupComputeShaderVertexBufferIO",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected setupComputeShaderVertexBufferIO() {\r\n        this.vertexBufferIO = new VertexBufferIO(this.attributes);\r\n        this.vertexBufferIO.createVertexInstances(this.config.nbVertex, () => {\r\n            return this.resultBufferStructure;\r\n        })\r\n\r\n\r\n        let outputResultId;\r\n        this.vertexBufferIO.onOutputData = (data) => {\r\n\r\n            const result = new Float32Array(data);\r\n\r\n            outputResultId = 0;\r\n            let outputResults = [];\r\n            this.vertexBufferIO.getVertexInstances(result, (o) => {\r\n                //the object received in this function is reused all the time\r\n                //so I need to clone it in order to be able to use it outside of the \"callback-loop\"\r\n\r\n                let result = {};\r\n                for (let z in o) result[z] = { ...o[z] };\r\n\r\n\r\n                outputResults[outputResultId++] = result;\r\n                if (this.onLog && outputResultId == this.config.nbVertex) {\r\n                    this.onLog({\r\n                        config: this.config,\r\n                        results: outputResults,\r\n                        nbValueByFieldName: this.nbValueByFieldName,\r\n                        renderPipeline: this.renderPipeline,\r\n                        dataTypeByFieldname: this.dataTypeByFieldname\r\n                    });\r\n                }\r\n                //console.log(\"RESULT = \", result);\r\n\r\n            })\r\n\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "writeComputeShader",
                "returnType": "string",
                "visibility": "protected",
                "rawText": "protected writeComputeShader(): string {\r\n\r\n        /*\r\n        the vertexShader outputs must be replaced by local variables\r\n        */\r\n        let outputVariables = \"\";\r\n        let outputs = this.renderPipeline.vertexShader.outputs;\r\n        for (let i = 0; i < outputs.length; i++) {\r\n            //console.log(i, outputs[i])\r\n            outputVariables += `var output_${outputs[i].name} = ${this.getNewInstanceByType(outputs[i].type)};\\n`\r\n        }\r\n\r\n\r\n\r\n        /*\r\n        the VertexAttributes used as input of the vertexShader must be redefined in the computeShader in \r\n        order to target a particular vertex in the buffer, to mimic the behaviour of a vertexShader\r\n        */\r\n        let computeShader: string = ``;\r\n        if (this.indexBuffer) computeShader += `let index:u32 = indexBuffer[global_id.x].id;`;\r\n        else computeShader += `let index = global_id.x;`;\r\n        computeShader += `\r\n        ${outputVariables}\r\n        let nbResult = arrayLength(&result);\r\n        if(index >= nbResult){\r\n            return;\r\n        }\r\n\r\n        var computeResult = result[index];\r\n        var ${this.vertexIdName}:u32 = 0;\r\n        var ${this.instanceIdName}:u32 = 0;\r\n        `;\r\n\r\n        let input: any;\r\n        for (let i = 0; i < this.vertexShaderInputs.length; i++) {\r\n            input = this.vertexShaderInputs[i];\r\n            //console.log(\"input.type = \", input)\r\n            if (input.builtin.slice(0, 8) != \"@builtin\") { //if it's not explicitly a builtin, it's a vertexAttribute\r\n                computeShader += `var computed_vertex_${input.name}:${input.type};\\n`;\r\n            }\r\n        }\r\n\r\n\r\n        let usedNames: any = {};\r\n        const vertexShaderDebugs = this.renderPipeline.resources.__DEBUG__.objectById;\r\n        for (let i = 0; i < vertexShaderDebugs.length; i++) {\r\n            //console.log(i, vertexShaderDebugs[i].name)\r\n            if (!usedNames[vertexShaderDebugs[i].name]) {\r\n                usedNames[vertexShaderDebugs[i].name] = true;\r\n                computeShader += this.writeVertexShader(vertexShaderDebugs[i]);\r\n            }\r\n\r\n        }\r\n\r\n\r\n\r\n        if (XGPU.showVertexDebuggerShader) {\r\n            console.log(\"------------- VERTEX DEBUGGER SHADER --------------\")\r\n            console.log(computeShader)\r\n            console.log(\"---------------------------------------------------\")\r\n        }\r\n\r\n        return computeShader;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "writeVertexShader",
                "returnType": "string",
                "params": [
                  {
                    "name": "debugObject",
                    "type": "any"
                  }
                ],
                "visibility": "protected",
                "rawText": "protected writeVertexShader(debugObject: any): string {\r\n\r\n        const { vertexId, instanceId, name } = debugObject;\r\n\r\n        let mainCode: string = `\r\n        ${this.vertexIdName} = ${vertexId};\r\n        ${this.instanceIdName} = ${instanceId};\r\n\r\n        `;\r\n\r\n\r\n        let input: any;\r\n        for (let i = 0; i < this.vertexShaderInputs.length; i++) {\r\n            input = this.vertexShaderInputs[i];\r\n\r\n            if (input.builtin.slice(0, 8) != \"@builtin\") { //if it's not explicitly a builtin, it's a vertexAttribute\r\n                mainCode += `computed_vertex_${input.name} = ${this.bufferNameByAttributeName[input.name]}[${this.vertexIdName}+index].${input.name};\\n`;\r\n            }\r\n        }\r\n\r\n\r\n        /*\r\n        we need to update the code of the vertexShader in order to replace the attribute's name\r\n        used in the code by our computed_vertex_${input.name} \r\n        */\r\n\r\n        const searchAndReplace = (shaderCode: string, wordToReplace: string, replacement: string) => {\r\n            const regex = new RegExp(`(?<=[^\\\\w.])\\\\b${wordToReplace}\\\\b`, 'g');\r\n            return shaderCode.replace(regex, replacement);\r\n        }\r\n\r\n\r\n        let attributeNames: string[] = [];\r\n        let vertexShaderText = this.renderPipeline.resources.vertexShader.debugVersion;\r\n\r\n        for (let i = 0; i < this.vertexShaderInputs.length; i++) {\r\n            input = this.vertexShaderInputs[i];\r\n            if (input.builtin.slice(0, 8) != \"@builtin\") {\r\n                attributeNames[this.fieldIndexByName[input.name]] = input.name;\r\n                vertexShaderText = searchAndReplace(vertexShaderText, input.name, \"computed_vertex_\" + input.name);\r\n            }\r\n        }\r\n\r\n\r\n        /*\r\n        we also need to update the code that involve the keyword 'debug' in order to target our result buffer instead\r\n        */\r\n\r\n\r\n        const lines = vertexShaderText.split(\"\\n\");\r\n        const chars = \"abcdefghijklmnopqrstuvwxyz/\"\r\n        const isChars = {};\r\n        for (let i = 0; i < chars.length; i++) {\r\n            isChars[chars[i]] = true;\r\n            isChars[chars[i].toUpperCase()] = true;\r\n        }\r\n\r\n        const getFirstCharId = (line: string) => {\r\n            for (let i = 0; i < line.length; i++) {\r\n                if (isChars[line[i]]) return i;\r\n            }\r\n            return line.length - 1\r\n        }\r\n\r\n        for (let i = 0; i < lines.length; i++) {\r\n            lines[i] = \" \" + lines[i].slice(getFirstCharId(lines[i]));\r\n        }\r\n\r\n        vertexShaderText = lines.join(\"\\n\");\r\n\r\n        vertexShaderText = searchAndReplace(vertexShaderText, \"output.\", \"output_\");\r\n        let vertexResultText = searchAndReplace(vertexShaderText, \"debug\", \"computeResult\");\r\n\r\n\r\n        /*\r\n        we keep only the computeResult value related to the debug-object we are processing\r\n        in order to not replace the previously computed values \r\n        (the function \"vertexShader\" will be called multiple times, shering the same string-output)\r\n        */\r\n        function keepCurrentResourceDeclarationOnly(code: string, searchBase: string, search: string) {\r\n\r\n            /*\r\n            we keep every line that : \r\n            - are not empty\r\n            - doesn't contain \"computeResult.\"\r\n            - contain \"computeResult.${debugObject.name}\"\r\n            */\r\n\r\n            const lines = code.split(\"\\n\");\r\n            let result = \"\";\r\n            let line;\r\n            let alphaNumeric = \"abcdefghijklmnopqrstuvwxyz0123456789\";\r\n            let trimLine: string;\r\n            alphaNumeric += alphaNumeric.toUpperCase();\r\n\r\n            for (let i = 0; i < lines.length; i++) {\r\n                line = lines[i];\r\n                if (line.includes(searchBase)) {\r\n                    if (line.includes(search)) {\r\n                        const array = line.split(search);\r\n                        let bool = true;\r\n                        for (let j = 0; j < array.length; j++) {\r\n                            if (alphaNumeric.includes(array[j][0])) {\r\n                                bool = false;\r\n                                break;\r\n                            }\r\n                        }\r\n                        if (bool) result += line + \"\\n\";\r\n                    }\r\n\r\n                } else {\r\n                    trimLine = line.trim();\r\n                    if (trimLine.length != 0) {\r\n                        result += line + \"\\n\";\r\n                    }\r\n\r\n                }\r\n            }\r\n            return result;\r\n        }\r\n        vertexResultText = keepCurrentResourceDeclarationOnly(vertexResultText, \"computeResult.\", \"computeResult.\" + debugObject.name);\r\n\r\n\r\n\r\n        /*\r\n        if we call the vertexShader function multiple times, we must keep the \"var \" only for the first pass. \r\n        We also must convert the \"let \" into \"var \"   \r\n        */\r\n\r\n\r\n\r\n\r\n\r\n        vertexResultText = this.convertLetIntoVar(vertexResultText);\r\n\r\n        if (!this.firstPass) vertexResultText = this.removeVar(vertexResultText);\r\n\r\n\r\n\r\n\r\n\r\n        mainCode += vertexResultText + \"\\n\";\r\n\r\n        /*\r\n        we put the vertexData in our result buffer\r\n        */\r\n\r\n\r\n\r\n        for (let i = 0; i < this.fieldNames.length; i++) {\r\n            //console.log(i, this.fieldNewNames[i], this.fieldNames[i], debugObject.name)\r\n\r\n            if (this.fieldNewNames[i].includes(debugObject.name)) {\r\n\r\n\r\n                mainCode += `result_out[index].${this.fieldNewNames[i]} =  computeResult.${this.fieldNewNames[i]};\\n`;\r\n\r\n\r\n\r\n            }\r\n        }\r\n\r\n\r\n        const debugById = this.renderPipeline.resources.__DEBUG__.objectById;\r\n        let debug: any;\r\n        let alreadyDefined: any = {};\r\n        let temp: string;\r\n        let isMatrix4x4;\r\n        for (let i = 0; i < debugById.length; i++) {\r\n            debug = debugById[i];\r\n            if (debug.name != name) continue;\r\n\r\n            if (debug.isMatrix) {\r\n\r\n                isMatrix4x4 = debug.newName.includes(\"_m4\");\r\n\r\n                if (isMatrix4x4) temp = debug.newName.split(\"_m4\")[0];\r\n                else temp = debug.newName.split(\"_m3\")[0];\r\n\r\n                if (!alreadyDefined[temp]) {\r\n                    alreadyDefined[temp] = true;\r\n                    mainCode = this.writeMatrixTemplate(mainCode, temp, isMatrix4x4)\r\n                }\r\n            } else if (debug.isArray) {\r\n\r\n                temp = debug.newName.split(\"_ar\")[0];\r\n                if (!alreadyDefined[temp]) {\r\n                    alreadyDefined[temp] = true;\r\n                    mainCode = this.writeArrayTemplate(mainCode, temp, debug.len, debug.primitiveType)\r\n                }\r\n\r\n            }\r\n        }\r\n\r\n        this.firstPass = false;\r\n        return mainCode;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "buildComputeShader",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected buildComputeShader() {\r\n        //this.computeShaderObj.computeUniforms = new UniformBuffer(this.computeUniforms)\r\n        this.computeShaderObj.result = this.vertexBufferIO;\r\n        this.computeShaderObj.global_id = BuiltIns.computeInputs.globalInvocationId;\r\n        this.computeShaderObj.computeShader = {\r\n            constants: this.renderPipeline.vertexShader.constants.text,\r\n            main: this.writeComputeShader(),\r\n        }\r\n\r\n        this.initFromObject(this.computeShaderObj)\r\n\r\n        let groups = this.bindGroups.groups;\r\n        for (let i = 0; i < groups.length; i++) groups[i].mustRefreshBindgroup = true;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "copyUniformsFromRenderToCompute",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected copyUniformsFromRenderToCompute(): void {\r\n        if (!this.renderUniformBuffers) return;\r\n\r\n        let ub;\r\n        let itemNames: string[];\r\n        for (let i = 0; i < this.renderUniformBuffers.length; i++) {\r\n            ub = this.renderUniformBuffers[i];\r\n            itemNames = ub.resource.itemNames;\r\n\r\n            for (let j = 0; j < itemNames.length; j++) {\r\n                //console.log(itemNames[j], ub.resource.items[itemNames[j]])\r\n                this.computeShaderObj[ub.name].items[itemNames[j]].set(ub.resource.items[itemNames[j]]);\r\n            }\r\n        }\r\n    }"
              }
            ]
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "rawText": "constructor() {\r\n        super();\r\n    }"
          },
          "rawText": "export class VertexShaderDebuggerPipeline extends ComputePipeline {\r\n\r\n\r\n\r\n    public onLog: (o: {\r\n        config: any,\r\n        results: any[],\r\n        nbValueByFieldName: any\r\n        renderPipeline: RenderPipeline,\r\n        dataTypeByFieldname: any,\r\n    }) => void;\r\n\r\n\r\n    protected config: any;\r\n\r\n    constructor() {\r\n        super();\r\n    }\r\n\r\n\r\n    protected vertexShaderInputs: any;\r\n    protected renderPipeline: RenderPipeline;\r\n    protected computeShaderObj: any;\r\n    protected resourceByType: any;\r\n\r\n    protected initRenderPipeline(renderPipeline: RenderPipeline): void {\r\n        this.renderPipeline = renderPipeline;\r\n\r\n\r\n        renderPipeline.bindGroups.setupDraw(true);\r\n        this.resourceByType = renderPipeline.bindGroups.resources.types;\r\n        this.vertexShaderInputs = renderPipeline.vertexShader.inputs;\r\n        this.renderUniformBuffers = this.resourceByType.uniformBuffers;\r\n\r\n    }\r\n\r\n    protected indexBuffer: IndexBuffer;\r\n    protected setupIndexBuffer() {\r\n        /*\r\n       we check if the renderPipeline use an indexBuffer.\r\n       If yes, we create a vertexBuffer to represent it \r\n       */\r\n\r\n\r\n        let indexBuffer: IndexBuffer = null\r\n        if (this.renderPipeline.resources.indexBuffer) {\r\n            indexBuffer = this.renderPipeline.resources.indexBuffer;\r\n            this.computeShaderObj[\"indexBuffer\"] = new VertexBuffer({ id: VertexAttribute.Uint() }, {\r\n                stepMode: \"vertex\",\r\n                datas: indexBuffer.datas\r\n            })\r\n        }\r\n    }\r\n\r\n    protected results: any;\r\n    protected resultBufferStructure: any = {};\r\n    protected nbValueByFieldIndex: any = {};\r\n    protected nbValueByFieldName: any = {};\r\n    protected dataTypeByFieldname: any = {};\r\n    protected fieldNames: string[] = [];\r\n    protected fieldNewNames: string[] = [];\r\n    protected fieldIndexByName: any = {};\r\n    protected attributes: any = {};\r\n\r\n    protected setupDataStructure() {\r\n        this.results = {};\r\n        this.resultBufferStructure = {};\r\n        this.nbValueByFieldIndex = {};\r\n        this.nbValueByFieldName = {};\r\n        this.dataTypeByFieldname = {};\r\n        this.fieldNames = [];\r\n        this.fieldNewNames = [];\r\n        this.fieldIndexByName = {};\r\n        this.attributes = {};\r\n\r\n        //const vertexShaderOutputs = this.renderPipeline.vertexShader.outputs;\r\n        const vertexShaderDebugs = this.renderPipeline.resources.__DEBUG__.objectById;\r\n\r\n        let nb: number, name: string;\r\n        let debug: { name: string, newName: string, type: string, builtin?: string, nbValue: number };\r\n        for (let i = 0; i < vertexShaderDebugs.length; i++) {\r\n            debug = vertexShaderDebugs[i];\r\n            name = debug.name;\r\n            nb = this.getNbValueByType(debug.type)\r\n\r\n            //console.log(i, debug.name, debug.newName)\r\n\r\n            //used to write the shader code\r\n            this.fieldNames[i] = name;\r\n            this.fieldNewNames[i] = debug.newName;\r\n            this.fieldIndexByName[name] = i;\r\n            this.nbValueByFieldIndex[i] = debug.nbValue;\r\n            this.dataTypeByFieldname[name] = debug.type;\r\n\r\n\r\n            //used to fill the vertexBufferIO with the appropriate property names and the correct data structure\r\n            this.resultBufferStructure[name] = this.createEmptyArray(nb)\r\n\r\n            //used to manipule the data outside of this class\r\n            this.nbValueByFieldName[name] = nb;\r\n\r\n            //console.log(\"debug.type = \", debug)\r\n            this.attributes[debug.newName] = this.getObjectByType(debug.type)\r\n\r\n        }\r\n    }\r\n\r\n\r\n    protected vertexIdName: string;// = \"vertexId\";\r\n    protected instanceIdName: string;// = \"instanceId\";\r\n    //protected computeUniforms = {};\r\n\r\n    protected setupVertexShaderBuiltIns() {\r\n        let input: { name: string, type: string, builtin?: string };\r\n\r\n        /*\r\n        we first convert the Builtins \"vertex_index\" and \"instance_index\" (if they exists) into an uniform used in the computeShader\r\n        with the name used in the vertexShader\r\n        */\r\n\r\n\r\n\r\n        for (let i = 0; i < this.vertexShaderInputs.length; i++) {\r\n            input = this.vertexShaderInputs[i];\r\n            if (input.builtin) {\r\n                if (input.builtin === \"@builtin(vertex_index)\") {\r\n                    this.vertexIdName = input.name;\r\n                    //this.computeUniforms[input.name] = new Uint(this.config.startVertexId, true)\r\n                } else if (input.builtin === \"@builtin(instance_index)\") {\r\n                    this.instanceIdName = input.name;\r\n                    //this.computeUniforms[input.name] = new Uint(this.config.instanceId, true)\r\n                }\r\n            }\r\n        }\r\n\r\n        if (!this.vertexIdName) {\r\n            this.vertexIdName = \"VERTEX_ID\";\r\n            //this.computeUniforms[this.vertexIdName] = new Uint(this.config.startVertexId, true)\r\n        }\r\n\r\n        if (!this.instanceIdName) {\r\n            this.instanceIdName = \"INSTANCE_ID\";\r\n            //this.computeUniforms[this.instanceIdName] = new Uint(this.config.startVertexId, true)\r\n        }\r\n    }\r\n\r\n    protected renderUniformBuffers: { name: string, resource: UniformBuffer }[]\r\n    protected setupUniformBuffers() {\r\n\r\n        let ub: { name: string, resource: UniformBuffer };\r\n\r\n        const cloneUniformBuffer = (buf: UniformBuffer) => {\r\n\r\n            const result: any = {};\r\n\r\n            for (let i = 0; i < buf.itemNames.length; i++) {\r\n                result[buf.itemNames[i]] = buf.items[buf.itemNames[i]].clone();\r\n                //result[buf.itemNames[i]].datas\r\n            }\r\n\r\n            return new UniformBuffer(result, { useLocalVariable: buf.descriptor.useLocalVariable })\r\n        }\r\n\r\n        if (this.renderUniformBuffers) {\r\n            for (let i = 0; i < this.renderUniformBuffers.length; i++) {\r\n                ub = this.renderUniformBuffers[i];\r\n                this.computeShaderObj[ub.name] = cloneUniformBuffer(ub.resource);\r\n            }\r\n        }\r\n    }\r\n\r\n    protected renderVertexBuffers: { name: string, resource: VertexBuffer }[];\r\n    protected bufferNameByAttributeName: string[];\r\n    protected setupVertexBuffers() {\r\n        this.renderVertexBuffers = this.resourceByType.vertexBuffers;\r\n        this.bufferNameByAttributeName = [];\r\n\r\n        let vb: { name: string, resource: VertexBuffer };\r\n        let vBuffer: VertexBuffer;\r\n\r\n\r\n        if (this.renderVertexBuffers) {\r\n\r\n\r\n\r\n            for (let i = 0; i < this.renderVertexBuffers.length; i++) {\r\n                vb = this.renderVertexBuffers[i];\r\n                vBuffer = vb.resource;\r\n\r\n                let attributes = vBuffer.attributeDescriptor;\r\n                for (let z in attributes) {\r\n                    this.bufferNameByAttributeName[z] = vb.name;\r\n                }\r\n\r\n\r\n                this.computeShaderObj[vb.name] = new VertexBuffer(vBuffer.attributeDescriptor, {\r\n                    stepMode: vBuffer.stepMode,\r\n                    datas: vBuffer.datas\r\n                })\r\n\r\n            }\r\n        }\r\n    }\r\n\r\n    protected vertexBufferIO: VertexBufferIO;\r\n    protected setupComputeShaderVertexBufferIO() {\r\n        this.vertexBufferIO = new VertexBufferIO(this.attributes);\r\n        this.vertexBufferIO.createVertexInstances(this.config.nbVertex, () => {\r\n            return this.resultBufferStructure;\r\n        })\r\n\r\n\r\n        let outputResultId;\r\n        this.vertexBufferIO.onOutputData = (data) => {\r\n\r\n            const result = new Float32Array(data);\r\n\r\n            outputResultId = 0;\r\n            let outputResults = [];\r\n            this.vertexBufferIO.getVertexInstances(result, (o) => {\r\n                //the object received in this function is reused all the time\r\n                //so I need to clone it in order to be able to use it outside of the \"callback-loop\"\r\n\r\n                let result = {};\r\n                for (let z in o) result[z] = { ...o[z] };\r\n\r\n\r\n                outputResults[outputResultId++] = result;\r\n                if (this.onLog && outputResultId == this.config.nbVertex) {\r\n                    this.onLog({\r\n                        config: this.config,\r\n                        results: outputResults,\r\n                        nbValueByFieldName: this.nbValueByFieldName,\r\n                        renderPipeline: this.renderPipeline,\r\n                        dataTypeByFieldname: this.dataTypeByFieldname\r\n                    });\r\n                }\r\n                //console.log(\"RESULT = \", result);\r\n\r\n            })\r\n\r\n        }\r\n    }\r\n\r\n\r\n\r\n    private convertLetIntoVar(shader: string): string {\r\n        let result = \"\"\r\n        let lines: string[] = shader.split(\"\\n\");\r\n        let line: string;\r\n        let chars = \"abcdefghijklmnopqrstuvwxyz/\"\r\n        chars += chars.toUpperCase();\r\n\r\n        const getFirstCharId = (line: string) => {\r\n            for (let i = 0; i < line.length; i++) {\r\n                if (chars.includes(line[i])) return i;\r\n            }\r\n            return line.length - 1\r\n        }\r\n\r\n\r\n        for (let i = 0; i < lines.length; i++) {\r\n            line = lines[i];\r\n            line = line.slice(getFirstCharId(line));\r\n            if (line.slice(0, 4) === \"let \") {\r\n                line = \"var \" + line.slice(4);\r\n            }\r\n\r\n            //adding a first empty char is a dirty fix to another process \r\n            result += \" \" + line + \"\\n\";\r\n        }\r\n\r\n\r\n        return result;\r\n    }\r\n\r\n    private removeVar(shader: string): string {\r\n        let result = \"\"\r\n        let lines: string[] = shader.split(\"\\n\");\r\n        let line: string;\r\n\r\n\r\n        for (let i = 0; i < lines.length; i++) {\r\n            line = lines[i];\r\n            if (line.slice(0, 5) === \" var \") line = line.slice(5);\r\n            result += \" \" + line + \"\\n\";\r\n        }\r\n\r\n\r\n        return result;\r\n    }\r\n\r\n\r\n    protected writeComputeShader(): string {\r\n\r\n        /*\r\n        the vertexShader outputs must be replaced by local variables\r\n        */\r\n        let outputVariables = \"\";\r\n        let outputs = this.renderPipeline.vertexShader.outputs;\r\n        for (let i = 0; i < outputs.length; i++) {\r\n            //console.log(i, outputs[i])\r\n            outputVariables += `var output_${outputs[i].name} = ${this.getNewInstanceByType(outputs[i].type)};\\n`\r\n        }\r\n\r\n\r\n\r\n        /*\r\n        the VertexAttributes used as input of the vertexShader must be redefined in the computeShader in \r\n        order to target a particular vertex in the buffer, to mimic the behaviour of a vertexShader\r\n        */\r\n        let computeShader: string = ``;\r\n        if (this.indexBuffer) computeShader += `let index:u32 = indexBuffer[global_id.x].id;`;\r\n        else computeShader += `let index = global_id.x;`;\r\n        computeShader += `\r\n        ${outputVariables}\r\n        let nbResult = arrayLength(&result);\r\n        if(index >= nbResult){\r\n            return;\r\n        }\r\n\r\n        var computeResult = result[index];\r\n        var ${this.vertexIdName}:u32 = 0;\r\n        var ${this.instanceIdName}:u32 = 0;\r\n        `;\r\n\r\n        let input: any;\r\n        for (let i = 0; i < this.vertexShaderInputs.length; i++) {\r\n            input = this.vertexShaderInputs[i];\r\n            //console.log(\"input.type = \", input)\r\n            if (input.builtin.slice(0, 8) != \"@builtin\") { //if it's not explicitly a builtin, it's a vertexAttribute\r\n                computeShader += `var computed_vertex_${input.name}:${input.type};\\n`;\r\n            }\r\n        }\r\n\r\n\r\n        let usedNames: any = {};\r\n        const vertexShaderDebugs = this.renderPipeline.resources.__DEBUG__.objectById;\r\n        for (let i = 0; i < vertexShaderDebugs.length; i++) {\r\n            //console.log(i, vertexShaderDebugs[i].name)\r\n            if (!usedNames[vertexShaderDebugs[i].name]) {\r\n                usedNames[vertexShaderDebugs[i].name] = true;\r\n                computeShader += this.writeVertexShader(vertexShaderDebugs[i]);\r\n            }\r\n\r\n        }\r\n\r\n\r\n\r\n        if (XGPU.showVertexDebuggerShader) {\r\n            console.log(\"------------- VERTEX DEBUGGER SHADER --------------\")\r\n            console.log(computeShader)\r\n            console.log(\"---------------------------------------------------\")\r\n        }\r\n\r\n        return computeShader;\r\n    }\r\n\r\n\r\n    protected firstPass: boolean = true;\r\n    protected writeVertexShader(debugObject: any): string {\r\n\r\n        const { vertexId, instanceId, name } = debugObject;\r\n\r\n        let mainCode: string = `\r\n        ${this.vertexIdName} = ${vertexId};\r\n        ${this.instanceIdName} = ${instanceId};\r\n\r\n        `;\r\n\r\n\r\n        let input: any;\r\n        for (let i = 0; i < this.vertexShaderInputs.length; i++) {\r\n            input = this.vertexShaderInputs[i];\r\n\r\n            if (input.builtin.slice(0, 8) != \"@builtin\") { //if it's not explicitly a builtin, it's a vertexAttribute\r\n                mainCode += `computed_vertex_${input.name} = ${this.bufferNameByAttributeName[input.name]}[${this.vertexIdName}+index].${input.name};\\n`;\r\n            }\r\n        }\r\n\r\n\r\n        /*\r\n        we need to update the code of the vertexShader in order to replace the attribute's name\r\n        used in the code by our computed_vertex_${input.name} \r\n        */\r\n\r\n        const searchAndReplace = (shaderCode: string, wordToReplace: string, replacement: string) => {\r\n            const regex = new RegExp(`(?<=[^\\\\w.])\\\\b${wordToReplace}\\\\b`, 'g');\r\n            return shaderCode.replace(regex, replacement);\r\n        }\r\n\r\n\r\n        let attributeNames: string[] = [];\r\n        let vertexShaderText = this.renderPipeline.resources.vertexShader.debugVersion;\r\n\r\n        for (let i = 0; i < this.vertexShaderInputs.length; i++) {\r\n            input = this.vertexShaderInputs[i];\r\n            if (input.builtin.slice(0, 8) != \"@builtin\") {\r\n                attributeNames[this.fieldIndexByName[input.name]] = input.name;\r\n                vertexShaderText = searchAndReplace(vertexShaderText, input.name, \"computed_vertex_\" + input.name);\r\n            }\r\n        }\r\n\r\n\r\n        /*\r\n        we also need to update the code that involve the keyword 'debug' in order to target our result buffer instead\r\n        */\r\n\r\n\r\n        const lines = vertexShaderText.split(\"\\n\");\r\n        const chars = \"abcdefghijklmnopqrstuvwxyz/\"\r\n        const isChars = {};\r\n        for (let i = 0; i < chars.length; i++) {\r\n            isChars[chars[i]] = true;\r\n            isChars[chars[i].toUpperCase()] = true;\r\n        }\r\n\r\n        const getFirstCharId = (line: string) => {\r\n            for (let i = 0; i < line.length; i++) {\r\n                if (isChars[line[i]]) return i;\r\n            }\r\n            return line.length - 1\r\n        }\r\n\r\n        for (let i = 0; i < lines.length; i++) {\r\n            lines[i] = \" \" + lines[i].slice(getFirstCharId(lines[i]));\r\n        }\r\n\r\n        vertexShaderText = lines.join(\"\\n\");\r\n\r\n        vertexShaderText = searchAndReplace(vertexShaderText, \"output.\", \"output_\");\r\n        let vertexResultText = searchAndReplace(vertexShaderText, \"debug\", \"computeResult\");\r\n\r\n\r\n        /*\r\n        we keep only the computeResult value related to the debug-object we are processing\r\n        in order to not replace the previously computed values \r\n        (the function \"vertexShader\" will be called multiple times, shering the same string-output)\r\n        */\r\n        function keepCurrentResourceDeclarationOnly(code: string, searchBase: string, search: string) {\r\n\r\n            /*\r\n            we keep every line that : \r\n            - are not empty\r\n            - doesn't contain \"computeResult.\"\r\n            - contain \"computeResult.${debugObject.name}\"\r\n            */\r\n\r\n            const lines = code.split(\"\\n\");\r\n            let result = \"\";\r\n            let line;\r\n            let alphaNumeric = \"abcdefghijklmnopqrstuvwxyz0123456789\";\r\n            let trimLine: string;\r\n            alphaNumeric += alphaNumeric.toUpperCase();\r\n\r\n            for (let i = 0; i < lines.length; i++) {\r\n                line = lines[i];\r\n                if (line.includes(searchBase)) {\r\n                    if (line.includes(search)) {\r\n                        const array = line.split(search);\r\n                        let bool = true;\r\n                        for (let j = 0; j < array.length; j++) {\r\n                            if (alphaNumeric.includes(array[j][0])) {\r\n                                bool = false;\r\n                                break;\r\n                            }\r\n                        }\r\n                        if (bool) result += line + \"\\n\";\r\n                    }\r\n\r\n                } else {\r\n                    trimLine = line.trim();\r\n                    if (trimLine.length != 0) {\r\n                        result += line + \"\\n\";\r\n                    }\r\n\r\n                }\r\n            }\r\n            return result;\r\n        }\r\n        vertexResultText = keepCurrentResourceDeclarationOnly(vertexResultText, \"computeResult.\", \"computeResult.\" + debugObject.name);\r\n\r\n\r\n\r\n        /*\r\n        if we call the vertexShader function multiple times, we must keep the \"var \" only for the first pass. \r\n        We also must convert the \"let \" into \"var \"   \r\n        */\r\n\r\n\r\n\r\n\r\n\r\n        vertexResultText = this.convertLetIntoVar(vertexResultText);\r\n\r\n        if (!this.firstPass) vertexResultText = this.removeVar(vertexResultText);\r\n\r\n\r\n\r\n\r\n\r\n        mainCode += vertexResultText + \"\\n\";\r\n\r\n        /*\r\n        we put the vertexData in our result buffer\r\n        */\r\n\r\n\r\n\r\n        for (let i = 0; i < this.fieldNames.length; i++) {\r\n            //console.log(i, this.fieldNewNames[i], this.fieldNames[i], debugObject.name)\r\n\r\n            if (this.fieldNewNames[i].includes(debugObject.name)) {\r\n\r\n\r\n                mainCode += `result_out[index].${this.fieldNewNames[i]} =  computeResult.${this.fieldNewNames[i]};\\n`;\r\n\r\n\r\n\r\n            }\r\n        }\r\n\r\n\r\n        const debugById = this.renderPipeline.resources.__DEBUG__.objectById;\r\n        let debug: any;\r\n        let alreadyDefined: any = {};\r\n        let temp: string;\r\n        let isMatrix4x4;\r\n        for (let i = 0; i < debugById.length; i++) {\r\n            debug = debugById[i];\r\n            if (debug.name != name) continue;\r\n\r\n            if (debug.isMatrix) {\r\n\r\n                isMatrix4x4 = debug.newName.includes(\"_m4\");\r\n\r\n                if (isMatrix4x4) temp = debug.newName.split(\"_m4\")[0];\r\n                else temp = debug.newName.split(\"_m3\")[0];\r\n\r\n                if (!alreadyDefined[temp]) {\r\n                    alreadyDefined[temp] = true;\r\n                    mainCode = this.writeMatrixTemplate(mainCode, temp, isMatrix4x4)\r\n                }\r\n            } else if (debug.isArray) {\r\n\r\n                temp = debug.newName.split(\"_ar\")[0];\r\n                if (!alreadyDefined[temp]) {\r\n                    alreadyDefined[temp] = true;\r\n                    mainCode = this.writeArrayTemplate(mainCode, temp, debug.len, debug.primitiveType)\r\n                }\r\n\r\n            }\r\n        }\r\n\r\n        this.firstPass = false;\r\n        return mainCode;\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n    private writeArrayTemplate(shader: string, computeMatrixName: string, arrayLen: number, primitiveType: \"f32\" | \"i32\" | \"u32\" | \"mat4\"): string {\r\n        let abc = \"abcdefghijklmnopqrstuvwxyz0123456789\"\r\n        abc += abc.toUpperCase();\r\n        let lines: string[] = shader.split(\"\\n\");\r\n        let line: string;\r\n\r\n        const isComplexVal = (val: string): boolean => {\r\n            for (let i = 0; i < val.length; i++) {\r\n                if (abc.includes(val[i])) continue;\r\n                else return true;\r\n            }\r\n            return false;\r\n        }\r\n\r\n\r\n\r\n        let tempName: string;\r\n\r\n\r\n\r\n        const writeTemplate = (computeName: string, matrixName: string): string => {\r\n            let result = \"\";\r\n            let nb = arrayLen;\r\n            let isArrayMatrix = primitiveType == \"mat4\";\r\n\r\n            for (let i = 0; i < nb; i++) {\r\n                if (!isArrayMatrix) result += `computeResult.${computeName}_ar${i} = ${matrixName}[${i}];\\n`;\r\n                else {\r\n                    result += `computeResult.${computeName}_ar${i}_m0 = ${matrixName}[${i}][0];\\n`;\r\n                    result += `computeResult.${computeName}_ar${i}_m1 = ${matrixName}[${i}][1];\\n`;\r\n                    result += `computeResult.${computeName}_ar${i}_m2 = ${matrixName}[${i}][2];\\n`;\r\n                    result += `computeResult.${computeName}_ar${i}_m3 = ${matrixName}[${i}][3];\\n`;\r\n                }\r\n            }\r\n            result += \"\\n\";\r\n            return result;\r\n        }\r\n\r\n        let newLine = \"\";\r\n        for (let i = 0; i < lines.length; i++) {\r\n            line = lines[i];\r\n            //console.log(i, \" line = \", computeMatrixName, line);\r\n            if (line.includes(\"computeResult.\" + computeMatrixName) == true) {\r\n                newLine = \"\";\r\n                let val = line.split(\"=\")[1].split(\";\")[0].trim();\r\n                //console.log(\"val = \", val)\r\n\r\n                let j = i;\r\n                if (isComplexVal(val)) {\r\n\r\n                    if (line.includes(\";\") === false) {\r\n\r\n                        for (j = i + 1; j < lines.length; j++) {\r\n\r\n                            if (lines[j].includes(\";\") == false) {\r\n                                val += lines[j] + \"\\n\";\r\n                                lines[j] = \"\";\r\n                            } else {\r\n                                val += lines[j].split(\";\")[0] + \"\";\r\n                                lines[j] = \"\";\r\n                                break;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n\r\n                    tempName = \"temporaryVariable_\" + this.temporaryIndex++;\r\n                    if (primitiveType === \"mat4\") newLine = \"let \" + tempName + \":array<mat4x4<f32>,\" + arrayLen + \"> = \" + val + \";\\n\";\r\n                    else newLine = \"let \" + tempName + \":array<vec4<\" + primitiveType + \"> = \" + val + \";\\n\";\r\n                    val = tempName;\r\n                }\r\n\r\n                newLine += writeTemplate(computeMatrixName, val);\r\n                lines[i] = newLine;\r\n\r\n\r\n                break;\r\n\r\n            }\r\n\r\n        }\r\n\r\n        return lines.join(\"\\n\");\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n    private temporaryIndex: number = 0;\r\n    private writeMatrixTemplate(shader: string, computeMatrixName: string, mat4x4: boolean = true): string {\r\n        let abc = \"abcdefghijklmnopqrstuvwxyz0123456789\"\r\n        abc += abc.toUpperCase();\r\n        let lines: string[] = shader.split(\"\\n\");\r\n        let line: string;\r\n\r\n        const isComplexVal = (val: string): boolean => {\r\n            for (let i = 0; i < val.length; i++) {\r\n                if (abc.includes(val[i])) continue;\r\n                else return true;\r\n            }\r\n            return false;\r\n        }\r\n\r\n\r\n\r\n        let tempName: string;\r\n\r\n\r\n\r\n        const writeTemplate = (computeName: string, matrixName: string): string => {\r\n            let result = \"\";\r\n            let nb = 4;\r\n            if (mat4x4 == false) nb = 3;\r\n            //console.log(computeName + \" => mat4x4:\", mat4x4);\r\n            for (let i = 0; i < nb; i++) {\r\n                result += `computeResult.${computeName}_m${nb}${i} = ${matrixName}[${i}];\\n`;\r\n            }\r\n            result += \"\\n\";\r\n            return result;\r\n        }\r\n\r\n        let newLine = \"\";\r\n        for (let i = 0; i < lines.length; i++) {\r\n            line = lines[i];\r\n            //console.log(i, \" line = \", computeMatrixName, line);\r\n            if (line.includes(\"computeResult.\" + computeMatrixName) == true) {\r\n                newLine = \"\";\r\n                let val = line.split(\"=\")[1].split(\";\")[0].trim();\r\n                //console.log(\"val = \", val)\r\n\r\n                let j = i;\r\n                if (isComplexVal(val)) {\r\n\r\n                    if (line.includes(\";\") === false) {\r\n\r\n                        for (j = i + 1; j < lines.length; j++) {\r\n\r\n                            if (lines[j].includes(\";\") == false) {\r\n                                val += lines[j] + \"\\n\";\r\n                                lines[j] = \"\";\r\n                            } else {\r\n                                val += lines[j].split(\";\")[0] + \"\";\r\n                                lines[j] = \"\";\r\n                                break;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n\r\n                    tempName = \"temporaryVariable_\" + this.temporaryIndex++;\r\n                    if (mat4x4) newLine = \"let \" + tempName + \":mat4x4<f32> = \" + val + \";\\n\";\r\n                    else newLine = \"let \" + tempName + \":mat3x3<f32> = \" + val + \";\\n\";\r\n                    val = tempName;\r\n                }\r\n\r\n                newLine += writeTemplate(computeMatrixName, val);\r\n                lines[i] = newLine;\r\n\r\n\r\n                break;\r\n\r\n            }\r\n\r\n        }\r\n\r\n        return lines.join(\"\\n\");\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\n    protected buildComputeShader() {\r\n        //this.computeShaderObj.computeUniforms = new UniformBuffer(this.computeUniforms)\r\n        this.computeShaderObj.result = this.vertexBufferIO;\r\n        this.computeShaderObj.global_id = BuiltIns.computeInputs.globalInvocationId;\r\n        this.computeShaderObj.computeShader = {\r\n            constants: this.renderPipeline.vertexShader.constants.text,\r\n            main: this.writeComputeShader(),\r\n        }\r\n\r\n        this.initFromObject(this.computeShaderObj)\r\n\r\n        let groups = this.bindGroups.groups;\r\n        for (let i = 0; i < groups.length; i++) groups[i].mustRefreshBindgroup = true;\r\n    }\r\n\r\n\r\n    protected copyUniformsFromRenderToCompute(): void {\r\n        if (!this.renderUniformBuffers) return;\r\n\r\n        let ub;\r\n        let itemNames: string[];\r\n        for (let i = 0; i < this.renderUniformBuffers.length; i++) {\r\n            ub = this.renderUniformBuffers[i];\r\n            itemNames = ub.resource.itemNames;\r\n\r\n            for (let j = 0; j < itemNames.length; j++) {\r\n                //console.log(itemNames[j], ub.resource.items[itemNames[j]])\r\n                this.computeShaderObj[ub.name].items[itemNames[j]].set(ub.resource.items[itemNames[j]]);\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n    public init(renderPipeline: RenderPipeline, nbVertex: number) {\r\n\r\n        if (!nbVertex) nbVertex = 1;\r\n\r\n        this.config = { nbVertex };\r\n        this.computeShaderObj = {\r\n            bindgroups: {\r\n                io: {}, //computeShaders have a reserved bindgroup 'io' , dedicated to the ping-pong process \r\n            }\r\n        };\r\n\r\n\r\n\r\n\r\n        this.initRenderPipeline(renderPipeline);\r\n        this.setupIndexBuffer();\r\n        this.setupDataStructure();\r\n        this.setupVertexShaderBuiltIns();\r\n        this.setupUniformBuffers();\r\n        this.setupVertexBuffers();\r\n        this.setupComputeShaderVertexBufferIO();\r\n        this.buildComputeShader();\r\n\r\n\r\n\r\n        this.onComputeBegin = () => {\r\n            this.copyUniformsFromRenderToCompute();\r\n        }\r\n\r\n\r\n    }\r\n\r\n\r\n    private createEmptyArray(len: number): number[] {\r\n        const arr = [];\r\n        for (let i = 0; i < len; i++) arr[i] = 0;\r\n        return arr;\r\n    }\r\n\r\n\r\n    private getObjectByType(type: string): any {\r\n        if (type === \"f32\") return VertexAttribute.Float();\r\n        if (type === \"vec2<f32>\") return VertexAttribute.Vec2();\r\n        if (type === \"vec3<f32>\") return VertexAttribute.Vec3();\r\n        if (type === \"vec4<f32>\") return VertexAttribute.Vec4();\r\n        return null;\r\n    }\r\n    private getNbValueByType(type: string): number {\r\n        if (type === \"f32\") return 1;\r\n        if (type === \"vec2<f32>\") return 2;\r\n        if (type === \"vec3<f32>\") return 3;\r\n        if (type === \"vec4<f32>\") return 4;\r\n        return 0;\r\n    }\r\n    private getNewInstanceByType(type: string): string {\r\n        if (type === \"f32\") return \"0.0\";\r\n        if (type === \"vec2<f32>\") return \"vec2(0.0)\";\r\n        if (type === \"vec3<f32>\") return \"vec3(0.0)\";\r\n        if (type === \"vec4<f32>\") return \"vec4(0.0)\";\r\n        return \"\";\r\n    }\r\n}"
        }
      ],
      "resources": {
        "DrawConfig": [
          {
            "objectType": "class",
            "name": "DrawConfig",
            "filePath": "xGPU.pipelines.resources.DrawConfig",
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "vertexCount",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public vertexCount: number = -1;"
                },
                {
                  "objectType": "property",
                  "name": "instanceCount",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public instanceCount: number = 1;"
                },
                {
                  "objectType": "property",
                  "name": "firstVertexId",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public firstVertexId: number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "firstInstanceId",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public firstInstanceId: number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "baseVertex",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public baseVertex: number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "indexBuffer",
                  "type": "IndexBuffer",
                  "visibility": "public",
                  "rawText": "public indexBuffer: IndexBuffer;"
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "pipeline",
                  "type": "RenderPipeline",
                  "visibility": "protected",
                  "rawText": "protected pipeline: RenderPipeline;"
                },
                {
                  "objectType": "property",
                  "name": "setupDrawCompleted",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected setupDrawCompleted: boolean = false;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "draw",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "renderPass",
                      "type": "GPURenderPassEncoder"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public draw(renderPass: GPURenderPassEncoder) {\r\n        //console.log(\"DrawConfig.draw\")\r\n        if (this.indexBuffer) {\r\n            //console.log(this.indexBuffer.nbPoint, this.instanceCount, this.firstVertexId, this.baseVertex, this.firstInstanceId)\r\n            renderPass.setIndexBuffer(this.indexBuffer.gpuResource, this.indexBuffer.dataType, this.indexBuffer.offset, this.indexBuffer.getBufferSize())\r\n            renderPass.drawIndexed(this.indexBuffer.nbPoint, this.instanceCount, this.firstVertexId, this.baseVertex, this.firstInstanceId);\r\n        } else {\r\n            renderPass.draw(this.vertexCount, this.instanceCount, this.firstVertexId, this.firstInstanceId);\r\n        }\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "renderPipeline",
                  "type": "RenderPipeline"
                }
              ],
              "rawText": "constructor(renderPipeline: RenderPipeline) {\r\n        this.pipeline = renderPipeline;\r\n    }"
            },
            "rawText": "export class DrawConfig {\r\n\r\n    public vertexCount: number = -1;\r\n    public instanceCount: number = 1;\r\n    public firstVertexId: number = 0;\r\n    public firstInstanceId: number = 0;\r\n    public baseVertex: number = 0;\r\n    public indexBuffer: IndexBuffer;\r\n\r\n    protected pipeline: RenderPipeline;\r\n    protected setupDrawCompleted: boolean = false;\r\n\r\n    constructor(renderPipeline: RenderPipeline) {\r\n        this.pipeline = renderPipeline;\r\n    }\r\n\r\n    public draw(renderPass: GPURenderPassEncoder) {\r\n        //console.log(\"DrawConfig.draw\")\r\n        if (this.indexBuffer) {\r\n            //console.log(this.indexBuffer.nbPoint, this.instanceCount, this.firstVertexId, this.baseVertex, this.firstInstanceId)\r\n            renderPass.setIndexBuffer(this.indexBuffer.gpuResource, this.indexBuffer.dataType, this.indexBuffer.offset, this.indexBuffer.getBufferSize())\r\n            renderPass.drawIndexed(this.indexBuffer.nbPoint, this.instanceCount, this.firstVertexId, this.baseVertex, this.firstInstanceId);\r\n        } else {\r\n            renderPass.draw(this.vertexCount, this.instanceCount, this.firstVertexId, this.firstInstanceId);\r\n        }\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n}"
          }
        ],
        "IndexBuffer": [
          {
            "objectType": "type",
            "name": "IndexBufferDescriptor",
            "type": "IndexBufferDescriptor",
            "rawText": "export type IndexBufferDescriptor = {\r\n    nbPoint?: number,\r\n    dataType?: \"uint16\" | \"uint32\",\r\n    datas?: Uint16Array | Uint32Array,\r\n    offset?: number\r\n}"
          },
          {
            "objectType": "class",
            "name": "IndexBuffer",
            "filePath": "xGPU.pipelines.resources.IndexBuffer",
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "gpuResource",
                  "type": "GPUBuffer",
                  "visibility": "public",
                  "rawText": "public gpuResource: GPUBuffer;"
                },
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "IndexBufferDescriptor",
                  "visibility": "public",
                  "rawText": "public descriptor: IndexBufferDescriptor;"
                },
                {
                  "objectType": "property",
                  "name": "mustUpdateData",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public mustUpdateData: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "dataType",
                  "type": "GPUIndexFormat",
                  "visibility": "public",
                  "rawText": "public get dataType(): GPUIndexFormat { return this.descriptor.dataType; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "nbPoint",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get nbPoint(): number { return this.descriptor.nbPoint; }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "offset",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get offset(): number { return this.descriptor.offset; }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "datas",
                  "type": "Uint32Array | Uint16Array",
                  "visibility": "public",
                  "rawText": "public set datas(indices: Uint32Array | Uint16Array) {\r\n        this.mustUpdateData = true;\r\n\r\n        if (indices instanceof Uint16Array) this.descriptor.dataType = \"uint16\";\r\n        else this.descriptor.dataType = \"uint32\";\r\n\r\n        if (!this._datas || indices.length > this._datas.length || indices != this._datas) {\r\n            this._datas = indices;\r\n            this.createGpuResource();\r\n        }\r\n        this.update();\r\n\r\n    }",
                  "set": true,
                  "get": true
                }
              ],
              "private": [
                {
                  "objectType": "property",
                  "name": "_datas",
                  "type": "Uint32Array | Uint16Array",
                  "visibility": "private",
                  "rawText": "private _datas: Uint32Array | Uint16Array;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "destroyGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public destroyGpuResource(): void {\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n        this.gpuResource = null;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public createGpuResource(): void {\r\n        if (!this._datas) console.warn(\"create index resource \", this.getBufferSize())\r\n\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n        this.gpuResource = XGPU.device.createBuffer({\r\n            size: this.getBufferSize(),\r\n            usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,\r\n            mappedAtCreation: false\r\n        });\r\n        (this.gpuResource as any).dataType = this.dataType;\r\n        (this.gpuResource as any).nbPoint = this.nbPoint;\r\n\r\n        if (this._datas) {\r\n            this.mustUpdateData = true;\r\n            this.update();\r\n        }\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getBufferSize",
                  "returnType": "number",
                  "visibility": "public",
                  "rawText": "public getBufferSize(): number {\r\n\r\n\r\n        if (this.dataType === \"uint16\") return this.datas.length * Uint16Array.BYTES_PER_ELEMENT;\r\n        return this.datas.length * Uint32Array.BYTES_PER_ELEMENT;\r\n\r\n\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "updateDatas",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "indices",
                      "type": "Uint32Array | Uint16Array"
                    },
                    {
                      "name": "offset",
                      "type": "number"
                    },
                    {
                      "name": "len",
                      "type": "number"
                    },
                    {
                      "name": "extraBufferSize",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public updateDatas(indices: Uint32Array | Uint16Array, offset: number, len: number, extraBufferSize?: number) {\r\n        this.mustUpdateData = true;\r\n\r\n        if (!extraBufferSize) extraBufferSize = 1000;\r\n\r\n        //if (this.datas) console.log(this.datas.length + \" VS \" + (offset + len))\r\n\r\n        if (!this._datas || this._datas.length < offset + len) {\r\n\r\n\r\n            if (indices instanceof Uint16Array) this.descriptor.dataType = \"uint16\";\r\n            else this.descriptor.dataType = \"uint32\";\r\n\r\n\r\n\r\n            if (!this._datas) {\r\n                this._datas = indices;\r\n                this.createGpuResource();\r\n            } else if ((offset + len) - this._datas.length >= extraBufferSize) {\r\n                this._datas = indices;\r\n                this.createGpuResource();\r\n            } else {\r\n\r\n                //console.log(\"B\")\r\n\r\n                if (indices instanceof Uint16Array) this._datas = new Uint16Array(this._datas.length + extraBufferSize);\r\n                else this._datas = new Uint32Array(this._datas.length + extraBufferSize);\r\n                this._datas.set(indices);\r\n                this.createGpuResource();\r\n            }\r\n        } else {\r\n            //console.log(\"A \", indices.slice(offset, offset + len))\r\n            if (offset && len) this._datas.set(indices.slice(offset, offset + len), offset)\r\n            else this._datas.set(indices);\r\n        }\r\n\r\n        this.update();\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public update(): void {\r\n        if (this.mustUpdateData) {\r\n            this.mustUpdateData = false;\r\n            //console.log(\"write indexBuffer\")\r\n            XGPU.device.queue.writeBuffer(this.gpuResource, 0, this._datas.buffer)\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "apply",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "renderPass",
                      "type": "GPURenderPassEncoder"
                    },
                    {
                      "name": "drawConfig",
                      "type": "DrawConfig"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public apply(renderPass: GPURenderPassEncoder, drawConfig: DrawConfig): void {\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        renderPass.setIndexBuffer(this.gpuResource, this.dataType, this.offset, this.getBufferSize());\r\n        renderPass.drawIndexed(this.nbPoint, drawConfig.instanceCount, drawConfig.firstVertexId, drawConfig.baseVertex, drawConfig.firstInstanceId);\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "descriptor",
                  "type": "{ nbPoint?: number; dataType?: \"uint16\" | \"uint32\"; datas?: Uint32Array | Uint16Array; offset?: number; }"
                }
              ],
              "rawText": "constructor(descriptor?: {\r\n        nbPoint?: number,\r\n        dataType?: \"uint16\" | \"uint32\",\r\n        datas?: Uint16Array | Uint32Array,\r\n        offset?: number\r\n    }) {\r\n        if (!descriptor) descriptor = { nbPoint: 3 } as any;\r\n        if (undefined === descriptor.dataType) {\r\n            if (descriptor.datas) {\r\n                if (descriptor.datas instanceof Uint16Array) descriptor.dataType = \"uint16\";\r\n                else descriptor.dataType = \"uint32\";\r\n            } else {\r\n                descriptor.dataType = \"uint16\";\r\n            }\r\n        }\r\n\r\n\r\n\r\n        if (undefined === descriptor.offset) descriptor.offset = 0;\r\n        this.descriptor = descriptor;\r\n\r\n        if (descriptor.nbPoint) this.nbPoint = descriptor.nbPoint;\r\n\r\n        if (undefined === descriptor.datas) descriptor.datas = new Uint32Array([0, 0, 0]);\r\n        else this.datas = descriptor.datas;\r\n\r\n\r\n    }"
            },
            "rawText": "export class IndexBuffer {\r\n\r\n    public gpuResource: GPUBuffer;\r\n    public descriptor: IndexBufferDescriptor;\r\n\r\n    public mustUpdateData: boolean = false;\r\n\r\n    constructor(descriptor?: {\r\n        nbPoint?: number,\r\n        dataType?: \"uint16\" | \"uint32\",\r\n        datas?: Uint16Array | Uint32Array,\r\n        offset?: number\r\n    }) {\r\n        if (!descriptor) descriptor = { nbPoint: 3 } as any;\r\n        if (undefined === descriptor.dataType) {\r\n            if (descriptor.datas) {\r\n                if (descriptor.datas instanceof Uint16Array) descriptor.dataType = \"uint16\";\r\n                else descriptor.dataType = \"uint32\";\r\n            } else {\r\n                descriptor.dataType = \"uint16\";\r\n            }\r\n        }\r\n\r\n\r\n\r\n        if (undefined === descriptor.offset) descriptor.offset = 0;\r\n        this.descriptor = descriptor;\r\n\r\n        if (descriptor.nbPoint) this.nbPoint = descriptor.nbPoint;\r\n\r\n        if (undefined === descriptor.datas) descriptor.datas = new Uint32Array([0, 0, 0]);\r\n        else this.datas = descriptor.datas;\r\n\r\n\r\n    }\r\n\r\n\r\n    public destroyGpuResource(): void {\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n        this.gpuResource = null;\r\n    }\r\n    public createGpuResource(): void {\r\n        if (!this._datas) console.warn(\"create index resource \", this.getBufferSize())\r\n\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n        this.gpuResource = XGPU.device.createBuffer({\r\n            size: this.getBufferSize(),\r\n            usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,\r\n            mappedAtCreation: false\r\n        });\r\n        (this.gpuResource as any).dataType = this.dataType;\r\n        (this.gpuResource as any).nbPoint = this.nbPoint;\r\n\r\n        if (this._datas) {\r\n            this.mustUpdateData = true;\r\n            this.update();\r\n        }\r\n\r\n    }\r\n\r\n    public getBufferSize(): number {\r\n\r\n\r\n        if (this.dataType === \"uint16\") return this.datas.length * Uint16Array.BYTES_PER_ELEMENT;\r\n        return this.datas.length * Uint32Array.BYTES_PER_ELEMENT;\r\n\r\n\r\n\r\n    }\r\n\r\n    public get dataType(): GPUIndexFormat { return this.descriptor.dataType; }\r\n\r\n    public get nbPoint(): number { return this.descriptor.nbPoint; }\r\n    public set nbPoint(n: number) { this.descriptor.nbPoint = n; }\r\n\r\n    public get offset(): number { return this.descriptor.offset; }\r\n    public set offset(n: number) { this.descriptor.offset = n; }\r\n\r\n    private _datas: Uint32Array | Uint16Array;\r\n\r\n    public set datas(indices: Uint32Array | Uint16Array) {\r\n        this.mustUpdateData = true;\r\n\r\n        if (indices instanceof Uint16Array) this.descriptor.dataType = \"uint16\";\r\n        else this.descriptor.dataType = \"uint32\";\r\n\r\n        if (!this._datas || indices.length > this._datas.length || indices != this._datas) {\r\n            this._datas = indices;\r\n            this.createGpuResource();\r\n        }\r\n        this.update();\r\n\r\n    }\r\n\r\n    public updateDatas(indices: Uint32Array | Uint16Array, offset: number, len: number, extraBufferSize?: number) {\r\n        this.mustUpdateData = true;\r\n\r\n        if (!extraBufferSize) extraBufferSize = 1000;\r\n\r\n        //if (this.datas) console.log(this.datas.length + \" VS \" + (offset + len))\r\n\r\n        if (!this._datas || this._datas.length < offset + len) {\r\n\r\n\r\n            if (indices instanceof Uint16Array) this.descriptor.dataType = \"uint16\";\r\n            else this.descriptor.dataType = \"uint32\";\r\n\r\n\r\n\r\n            if (!this._datas) {\r\n                this._datas = indices;\r\n                this.createGpuResource();\r\n            } else if ((offset + len) - this._datas.length >= extraBufferSize) {\r\n                this._datas = indices;\r\n                this.createGpuResource();\r\n            } else {\r\n\r\n                //console.log(\"B\")\r\n\r\n                if (indices instanceof Uint16Array) this._datas = new Uint16Array(this._datas.length + extraBufferSize);\r\n                else this._datas = new Uint32Array(this._datas.length + extraBufferSize);\r\n                this._datas.set(indices);\r\n                this.createGpuResource();\r\n            }\r\n        } else {\r\n            //console.log(\"A \", indices.slice(offset, offset + len))\r\n            if (offset && len) this._datas.set(indices.slice(offset, offset + len), offset)\r\n            else this._datas.set(indices);\r\n        }\r\n\r\n        this.update();\r\n    }\r\n\r\n    public get datas(): Uint32Array | Uint16Array { return this._datas }\r\n\r\n    public update(): void {\r\n        if (this.mustUpdateData) {\r\n            this.mustUpdateData = false;\r\n            //console.log(\"write indexBuffer\")\r\n            XGPU.device.queue.writeBuffer(this.gpuResource, 0, this._datas.buffer)\r\n        }\r\n    }\r\n\r\n    public apply(renderPass: GPURenderPassEncoder, drawConfig: DrawConfig): void {\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        renderPass.setIndexBuffer(this.gpuResource, this.dataType, this.offset, this.getBufferSize());\r\n        renderPass.drawIndexed(this.nbPoint, drawConfig.instanceCount, drawConfig.firstVertexId, drawConfig.baseVertex, drawConfig.firstInstanceId);\r\n    }\r\n\r\n}"
          }
        ],
        "textures": {
          "DepthStencilTexture": [
            {
              "objectType": "type",
              "name": "DepthStencilTextureDescriptor",
              "type": "DepthStencilTextureDescriptor",
              "rawText": "export type DepthStencilTextureDescriptor = {\r\n    size: GPUExtent3D,\r\n    format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\",\r\n}"
            },
            {
              "objectType": "class",
              "name": "DepthStencilTexture",
              "filePath": "xGPU.pipelines.resources.textures.DepthStencilTexture",
              "extends": [
                "Texture",
                "EventDispatcher"
              ],
              "implements": [
                "IShaderResource"
              ],
              "properties": {
                "public": [
                  {
                    "objectType": "property",
                    "name": "description",
                    "type": "{ depthWriteEnabled: boolean; depthCompare: string; format: string; sampleCount?: number; }",
                    "visibility": "public",
                    "rawText": "public get description(): { depthWriteEnabled: boolean, depthCompare: string, format: string, sampleCount?: number } { return this._description; }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "attachment",
                    "type": "any",
                    "visibility": "public",
                    "rawText": "public get attachment(): any { return this._attachment }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "isDepthTexture",
                    "type": "boolean",
                    "visibility": "public",
                    "rawText": "public get isDepthTexture(): boolean { return this._isDepthTexture; }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "mustBeTransfered",
                    "type": "boolean",
                    "visibility": "public",
                    "rawText": "public mustBeTransfered: boolean = false;"
                  }
                ],
                "private": [
                  {
                    "objectType": "property",
                    "name": "_description",
                    "type": "{ depthWriteEnabled: boolean; depthCompare: string; format: string; sampleCount?: number; }",
                    "visibility": "private",
                    "rawText": "private _description: { depthWriteEnabled: boolean, depthCompare: string, format: string, sampleCount?: number };"
                  },
                  {
                    "objectType": "property",
                    "name": "_attachment",
                    "type": "any",
                    "visibility": "private",
                    "rawText": "private _attachment: any;"
                  }
                ],
                "protected": [
                  {
                    "objectType": "property",
                    "name": "_isDepthTexture",
                    "type": "boolean",
                    "visibility": "protected",
                    "rawText": "protected _isDepthTexture: boolean = false;"
                  },
                  {
                    "objectType": "property",
                    "name": "_visibility",
                    "type": "GPUShaderStageFlags",
                    "visibility": "protected",
                    "rawText": "protected _visibility: GPUShaderStageFlags = GPUShaderStage.FRAGMENT;"
                  }
                ]
              },
              "methods": {
                "public": [
                  {
                    "objectType": "method",
                    "name": "setPipelineType",
                    "returnType": "void",
                    "params": [
                      {
                        "name": "pipelineType",
                        "type": "\"render\" | \"compute\" | \"compute_mixed\""
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType === \"render\") this._visibility = GPUShaderStage.FRAGMENT;\r\n        else if (pipelineType === \"compute_mixed\") this._visibility = GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;\r\n        else if (pipelineType === \"compute\") this._visibility = GPUShaderStage.COMPUTE;\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "createBindGroupEntry",
                    "returnType": "{ binding: number; resource: GPUTextureView; }",
                    "params": [
                      {
                        "name": "bindingId",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public createBindGroupEntry(bindingId: number) {\r\n        //console.log(\"view = \", this._view)\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view\r\n        }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "createBindGroupLayoutEntry",
                    "returnType": "{ binding: number; visibility: number; texture: { sampleType: string; }; }",
                    "params": [
                      {
                        "name": "bindingId",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public createBindGroupLayoutEntry(bindingId: number) {\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.VERTEX,\r\n            texture: {\r\n                sampleType: \"depth\",\r\n            }\r\n        }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "createDeclaration",
                    "returnType": "string",
                    "params": [
                      {
                        "name": "varName",
                        "type": "string"
                      },
                      {
                        "name": "bindingId",
                        "type": "number"
                      },
                      {
                        "name": "groupId",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public createDeclaration(varName: string, bindingId: number, groupId: number): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_depth_2d;\\n\";\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "createGpuResource",
                    "returnType": "void",
                    "visibility": "public",
                    "rawText": "public createGpuResource() {\r\n        //console.log(\"depthTexture create\")\r\n        this.create()\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "destroyGpuResource",
                    "returnType": "void",
                    "visibility": "public",
                    "rawText": "public destroyGpuResource() {\r\n        if (this.gpuResource) {\r\n            //console.warn(\"depthTexture destroy \")\r\n            this._view = null;\r\n            this.gpuResource.destroy();\r\n            this.gpuResource = null;\r\n            this.create()\r\n        }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "resize",
                    "returnType": "void",
                    "params": [
                      {
                        "name": "width",
                        "type": "number"
                      },
                      {
                        "name": "height",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public resize(width: number, height: number): void {\r\n        super.resize(width, height);\r\n        this._attachment.view = this._view;\r\n\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "clone",
                    "returnType": "DepthStencilTexture",
                    "visibility": "public",
                    "rawText": "public clone(): DepthStencilTexture {\r\n        return new DepthStencilTexture(this.descriptor as any);\r\n    }"
                  }
                ]
              },
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "{ size: GPUExtent3D; format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\"; usage?: GPUTextureUsageFlags; sampleCount?: number; }"
                  },
                  {
                    "name": "depthStencilDescription",
                    "type": "{ depthWriteEnabled: boolean; depthCompare: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\"; }"
                  },
                  {
                    "name": "depthStencilAttachmentOptions",
                    "type": "any"
                  }
                ],
                "rawText": "constructor(descriptor: {\r\n        size: GPUExtent3D,\r\n        format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\",\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: number,\r\n    }, depthStencilDescription: {\r\n        depthWriteEnabled: boolean,\r\n        depthCompare: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\",\r\n    } = null, depthStencilAttachmentOptions: any = null) {\r\n\r\n        if (undefined === descriptor.format) descriptor.format = \"depth24plus\";\r\n        if (undefined === descriptor.sampleCount) descriptor.sampleCount = 1;\r\n\r\n        super(descriptor as any)\r\n\r\n        this.createGpuResource();\r\n\r\n        //--------\r\n        if (!depthStencilDescription) {\r\n            depthStencilDescription = {\r\n                depthWriteEnabled: true,\r\n                depthCompare: \"less\",\r\n                format: this.gpuResource.format\r\n\r\n            } as any\r\n        }\r\n        this._description = { format: this.gpuResource.format, ...depthStencilDescription };\r\n\r\n        //--------\r\n        this._attachment = {\r\n            view: this._view,\r\n            depthClearValue: 1,\r\n            depthLoadOp: 'clear',\r\n            depthStoreOp: 'store',\r\n        }\r\n\r\n        if (descriptor.format === \"depth24plus-stencil8\") {\r\n            this._attachment.stencilClearValue = 0;\r\n            this._attachment.stencilLoadOp = \"clear\";\r\n            this._attachment.stencilStoreOp = \"store\";\r\n        } else if (descriptor.format === \"depth32float\") {\r\n            this._isDepthTexture = true;\r\n\r\n        }\r\n\r\n        for (let z in depthStencilAttachmentOptions) {\r\n            this._attachment[z] = depthStencilAttachmentOptions[z];\r\n        }\r\n\r\n\r\n    }"
              },
              "rawText": "export class DepthStencilTexture extends Texture implements IShaderResource {\r\n\r\n    /*\r\n    When you apply a shadow to a renderPipeline , you actually create a ShadowPipeline that store information in the DepthStencilTexture.\r\n    This texture is then used as IShaderResource in the renderPipeline. \r\n    Because it can be an IShaderResource , we must implement the IShaderResource interface\r\n    */\r\n\r\n\r\n\r\n    protected _isDepthTexture: boolean = false;\r\n\r\n    private _description: { depthWriteEnabled: boolean, depthCompare: string, format: string, sampleCount?: number };\r\n    public get description(): { depthWriteEnabled: boolean, depthCompare: string, format: string, sampleCount?: number } { return this._description; }\r\n\r\n    private _attachment: any;\r\n    public get attachment(): any { return this._attachment };\r\n\r\n    constructor(descriptor: {\r\n        size: GPUExtent3D,\r\n        format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\",\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: number,\r\n    }, depthStencilDescription: {\r\n        depthWriteEnabled: boolean,\r\n        depthCompare: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\",\r\n    } = null, depthStencilAttachmentOptions: any = null) {\r\n\r\n        if (undefined === descriptor.format) descriptor.format = \"depth24plus\";\r\n        if (undefined === descriptor.sampleCount) descriptor.sampleCount = 1;\r\n\r\n        super(descriptor as any)\r\n\r\n        this.createGpuResource();\r\n\r\n        //--------\r\n        if (!depthStencilDescription) {\r\n            depthStencilDescription = {\r\n                depthWriteEnabled: true,\r\n                depthCompare: \"less\",\r\n                format: this.gpuResource.format\r\n\r\n            } as any\r\n        }\r\n        this._description = { format: this.gpuResource.format, ...depthStencilDescription };\r\n\r\n        //--------\r\n        this._attachment = {\r\n            view: this._view,\r\n            depthClearValue: 1,\r\n            depthLoadOp: 'clear',\r\n            depthStoreOp: 'store',\r\n        }\r\n\r\n        if (descriptor.format === \"depth24plus-stencil8\") {\r\n            this._attachment.stencilClearValue = 0;\r\n            this._attachment.stencilLoadOp = \"clear\";\r\n            this._attachment.stencilStoreOp = \"store\";\r\n        } else if (descriptor.format === \"depth32float\") {\r\n            this._isDepthTexture = true;\r\n\r\n        }\r\n\r\n        for (let z in depthStencilAttachmentOptions) {\r\n            this._attachment[z] = depthStencilAttachmentOptions[z];\r\n        }\r\n\r\n\r\n    }\r\n    public get isDepthTexture(): boolean { return this._isDepthTexture; }\r\n\r\n    //--------------------------------- IShaderResource ---------------------------------------------------------\r\n\r\n    public mustBeTransfered: boolean = false;\r\n    protected _visibility: GPUShaderStageFlags = GPUShaderStage.FRAGMENT;\r\n\r\n    public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType === \"render\") this._visibility = GPUShaderStage.FRAGMENT;\r\n        else if (pipelineType === \"compute_mixed\") this._visibility = GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;\r\n        else if (pipelineType === \"compute\") this._visibility = GPUShaderStage.COMPUTE;\r\n    }\r\n\r\n    public createBindGroupEntry(bindingId: number) {\r\n        //console.log(\"view = \", this._view)\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view\r\n        }\r\n    }\r\n    public createBindGroupLayoutEntry(bindingId: number) {\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.VERTEX,\r\n            texture: {\r\n                sampleType: \"depth\",\r\n            }\r\n        }\r\n    }\r\n    public createDeclaration(varName: string, bindingId: number, groupId: number): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_depth_2d;\\n\";\r\n    }\r\n\r\n    public createGpuResource() {\r\n        //console.log(\"depthTexture create\")\r\n        this.create()\r\n    }\r\n\r\n    public destroyGpuResource() {\r\n        if (this.gpuResource) {\r\n            //console.warn(\"depthTexture destroy \")\r\n            this._view = null;\r\n            this.gpuResource.destroy();\r\n            this.gpuResource = null;\r\n            this.create()\r\n        }\r\n    }\r\n\r\n\r\n    public resize(width: number, height: number): void {\r\n        super.resize(width, height);\r\n        this._attachment.view = this._view;\r\n\r\n    }\r\n    public clone(): DepthStencilTexture {\r\n        return new DepthStencilTexture(this.descriptor as any);\r\n    }\r\n\r\n}"
            }
          ],
          "DepthTextureArray": [
            {
              "objectType": "class",
              "name": "DepthTextureArray",
              "filePath": "xGPU.pipelines.resources.textures.DepthTextureArray",
              "extends": [
                "ImageTextureArray",
                "ImageTexture",
                "EventDispatcher"
              ],
              "properties": {
                "public": [
                  {
                    "objectType": "property",
                    "name": "description",
                    "type": "{ depthWriteEnabled: boolean; depthCompare: string; format: string; sampleCount?: number; }",
                    "visibility": "public",
                    "rawText": "public get description(): { depthWriteEnabled: boolean, depthCompare: string, format: string, sampleCount?: number } { return this._description; }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "attachment",
                    "type": "any",
                    "visibility": "public",
                    "rawText": "public get attachment(): any { return this._attachment }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "isDepthTexture",
                    "type": "boolean",
                    "visibility": "public",
                    "rawText": "public get isDepthTexture(): boolean { return true; }",
                    "get": true
                  }
                ],
                "private": [
                  {
                    "objectType": "property",
                    "name": "_description",
                    "type": "{ depthWriteEnabled: boolean; depthCompare: string; format: string; sampleCount?: number; }",
                    "visibility": "private",
                    "rawText": "private _description: { depthWriteEnabled: boolean, depthCompare: string, format: string, sampleCount?: number };"
                  },
                  {
                    "objectType": "property",
                    "name": "_attachment",
                    "type": "any",
                    "visibility": "private",
                    "rawText": "private _attachment: any;"
                  }
                ],
                "protected": [
                  {
                    "objectType": "property",
                    "name": "_visibility",
                    "type": "GPUShaderStageFlags",
                    "visibility": "protected",
                    "rawText": "protected _visibility: GPUShaderStageFlags = GPUShaderStage.FRAGMENT;"
                  }
                ]
              },
              "methods": {
                "public": [
                  {
                    "objectType": "method",
                    "name": "setPipelineType",
                    "returnType": "void",
                    "params": [
                      {
                        "name": "pipelineType",
                        "type": "\"render\" | \"compute\" | \"compute_mixed\""
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType === \"render\") this._visibility = GPUShaderStage.FRAGMENT;\r\n        else if (pipelineType === \"compute_mixed\") this._visibility = GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;\r\n        else if (pipelineType === \"compute\") this._visibility = GPUShaderStage.COMPUTE;\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "createBindGroupLayoutEntry",
                    "returnType": "{ binding: number; visibility: number; texture: GPUTextureBindingLayout; }",
                    "params": [
                      {
                        "name": "bindingId",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, texture: GPUTextureBindingLayout } {\r\n\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: this._visibility,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"2d-array\",\r\n                multisampled: false\r\n            },\r\n        }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "createDeclaration",
                    "returnType": "string",
                    "params": [
                      {
                        "name": "varName",
                        "type": "string"
                      },
                      {
                        "name": "bindingId",
                        "type": "number"
                      },
                      {
                        "name": "groupId",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public createDeclaration(varName: string, bindingId: number, groupId: number): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_depth_2d_array;\\n\";\r\n    }"
                  }
                ]
              },
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "{ source: DepthStencilTexture[] | GPUTexture[]; size: GPUExtent3D; format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\"; usage?: GPUTextureUsageFlags; sampleCount?: number; }"
                  },
                  {
                    "name": "depthStencilDescription",
                    "type": "{ depthWriteEnabled: boolean; depthCompare: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\"; }"
                  }
                ],
                "rawText": "constructor(descriptor: {\r\n        source: DepthStencilTexture[] | GPUTexture[],\r\n        size: GPUExtent3D,\r\n        format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\",\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: number,\r\n    }, depthStencilDescription: {\r\n        depthWriteEnabled: boolean,\r\n        depthCompare: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\",\r\n    } = null) {\r\n\r\n        if (undefined === descriptor.format) descriptor.format = \"depth32float\";\r\n        if (undefined === descriptor.sampleCount) descriptor.sampleCount = 1;\r\n\r\n\r\n        if (descriptor.source[0] instanceof DepthStencilTexture) {\r\n            for (let i = 0; i < descriptor.source.length; i++) {\r\n                descriptor.source[i] = (descriptor.source[i] as DepthStencilTexture).gpuResource as GPUTexture;\r\n            }\r\n        }\r\n\r\n        if (undefined === descriptor.usage) {\r\n            descriptor.usage = (descriptor.source[0] as GPUTexture).usage;\r\n        }\r\n\r\n\r\n        super(descriptor as any);\r\n\r\n        //--------\r\n        if (!depthStencilDescription) {\r\n            depthStencilDescription = {\r\n                depthWriteEnabled: true,\r\n                depthCompare: \"less\",\r\n                format: this.gpuResource.format\r\n\r\n            } as any\r\n        }\r\n        this._description = { format: this.gpuResource.format, ...depthStencilDescription };\r\n\r\n    }"
              },
              "rawText": "export class DepthTextureArray extends ImageTextureArray {\r\n\r\n    private _description: { depthWriteEnabled: boolean, depthCompare: string, format: string, sampleCount?: number };\r\n    public get description(): { depthWriteEnabled: boolean, depthCompare: string, format: string, sampleCount?: number } { return this._description; }\r\n\r\n    private _attachment: any;\r\n    public get attachment(): any { return this._attachment };\r\n\r\n    constructor(descriptor: {\r\n        source: DepthStencilTexture[] | GPUTexture[],\r\n        size: GPUExtent3D,\r\n        format?: \"stencil8\" | \"depth16unorm\" | \"depth24plus\" | \"depth24plus-stencil8\" | \"depth32float\",\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: number,\r\n    }, depthStencilDescription: {\r\n        depthWriteEnabled: boolean,\r\n        depthCompare: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\",\r\n    } = null) {\r\n\r\n        if (undefined === descriptor.format) descriptor.format = \"depth32float\";\r\n        if (undefined === descriptor.sampleCount) descriptor.sampleCount = 1;\r\n\r\n\r\n        if (descriptor.source[0] instanceof DepthStencilTexture) {\r\n            for (let i = 0; i < descriptor.source.length; i++) {\r\n                descriptor.source[i] = (descriptor.source[i] as DepthStencilTexture).gpuResource as GPUTexture;\r\n            }\r\n        }\r\n\r\n        if (undefined === descriptor.usage) {\r\n            descriptor.usage = (descriptor.source[0] as GPUTexture).usage;\r\n        }\r\n\r\n\r\n        super(descriptor as any);\r\n\r\n        //--------\r\n        if (!depthStencilDescription) {\r\n            depthStencilDescription = {\r\n                depthWriteEnabled: true,\r\n                depthCompare: \"less\",\r\n                format: this.gpuResource.format\r\n\r\n            } as any\r\n        }\r\n        this._description = { format: this.gpuResource.format, ...depthStencilDescription };\r\n\r\n    }\r\n\r\n\r\n    protected _visibility: GPUShaderStageFlags = GPUShaderStage.FRAGMENT;\r\n\r\n    public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType === \"render\") this._visibility = GPUShaderStage.FRAGMENT;\r\n        else if (pipelineType === \"compute_mixed\") this._visibility = GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;\r\n        else if (pipelineType === \"compute\") this._visibility = GPUShaderStage.COMPUTE;\r\n    }\r\n\r\n\r\n    public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, texture: GPUTextureBindingLayout } {\r\n\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: this._visibility,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"2d-array\",\r\n                multisampled: false\r\n            },\r\n        }\r\n    }\r\n\r\n    public get isDepthTexture(): boolean { return true; }\r\n\r\n    public createDeclaration(varName: string, bindingId: number, groupId: number): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_depth_2d_array;\\n\";\r\n    }\r\n\r\n\r\n}"
            }
          ],
          "MultiSampleTexture": [
            {
              "objectType": "type",
              "name": "MultiSampleTextureDescriptor",
              "type": "MultiSampleTextureDescriptor",
              "rawText": "export type MultiSampleTextureDescriptor = {\r\n    size: GPUExtent3D,\r\n    format?: GPUTextureFormat,\r\n    usage?: GPUTextureUsageFlags,\r\n    sampleCount?: GPUSize32,\r\n    alphaToCoverageEnabled?: boolean,\r\n    mask?: number,\r\n    resolveTarget?: GPUTextureView\r\n}"
            },
            {
              "objectType": "class",
              "name": "MultiSampleTexture",
              "filePath": "xGPU.pipelines.resources.textures.MultiSampleTexture",
              "extends": [
                "Texture",
                "EventDispatcher"
              ],
              "properties": {
                "public": [
                  {
                    "objectType": "property",
                    "name": "description",
                    "type": "{ count: number; mask: number; alphaToCoverageEnabled: boolean; }",
                    "visibility": "public",
                    "rawText": "public get description(): { count: number, mask: number, alphaToCoverageEnabled: boolean } { return this._description }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "resolveTarget",
                    "type": "any",
                    "visibility": "public",
                    "rawText": "public get resolveTarget(): any { return (this.descriptor as MultiSampleTextureDescriptor).resolveTarget }",
                    "get": true
                  }
                ],
                "private": [
                  {
                    "objectType": "property",
                    "name": "_description",
                    "type": "{ count: number; mask: number; alphaToCoverageEnabled: boolean; }",
                    "visibility": "private",
                    "rawText": "private _description: { count: number, mask: number, alphaToCoverageEnabled: boolean };"
                  }
                ]
              },
              "methods": {
                "public": [
                  {
                    "objectType": "method",
                    "name": "create",
                    "returnType": "void",
                    "visibility": "public",
                    "rawText": "public create(): void {\r\n        super.create();\r\n    }"
                  }
                ]
              },
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "{ size: GPUExtent3D; format?: GPUTextureFormat; usage?: GPUTextureUsageFlags; sampleCount?: GPUSize32; alphaToCoverageEnabled?: boolean; mask?: number; resolveTarget?: GPUTextureView; }"
                  }
                ],
                "rawText": "constructor(descriptor: {\r\n        size: GPUExtent3D,\r\n        format?: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: GPUSize32,\r\n        alphaToCoverageEnabled?: boolean,\r\n        mask?: number,\r\n        resolveTarget?: GPUTextureView\r\n    }) {\r\n\r\n        if (undefined === descriptor.format) descriptor.format = XGPU.getPreferredCanvasFormat();\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (undefined === descriptor.sampleCount) descriptor.sampleCount = 4;\r\n        if (undefined === descriptor.alphaToCoverageEnabled) descriptor.alphaToCoverageEnabled = false;\r\n        if (undefined === descriptor.mask) descriptor.mask = 0xFFFFFFFF;\r\n        if (undefined === descriptor.resolveTarget) descriptor.resolveTarget = null;\r\n\r\n        super(descriptor as TextureDescriptor);\r\n\r\n        this._description = {\r\n            count: descriptor.sampleCount,\r\n            mask: descriptor.mask,\r\n            alphaToCoverageEnabled: descriptor.alphaToCoverageEnabled\r\n        }\r\n    }"
              },
              "rawText": "export class MultiSampleTexture extends Texture {\r\n\r\n    private _description: { count: number, mask: number, alphaToCoverageEnabled: boolean };\r\n    public get description(): { count: number, mask: number, alphaToCoverageEnabled: boolean } { return this._description }\r\n\r\n    constructor(descriptor: {\r\n        size: GPUExtent3D,\r\n        format?: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: GPUSize32,\r\n        alphaToCoverageEnabled?: boolean,\r\n        mask?: number,\r\n        resolveTarget?: GPUTextureView\r\n    }) {\r\n\r\n        if (undefined === descriptor.format) descriptor.format = XGPU.getPreferredCanvasFormat();\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (undefined === descriptor.sampleCount) descriptor.sampleCount = 4;\r\n        if (undefined === descriptor.alphaToCoverageEnabled) descriptor.alphaToCoverageEnabled = false;\r\n        if (undefined === descriptor.mask) descriptor.mask = 0xFFFFFFFF;\r\n        if (undefined === descriptor.resolveTarget) descriptor.resolveTarget = null;\r\n\r\n        super(descriptor as TextureDescriptor);\r\n\r\n        this._description = {\r\n            count: descriptor.sampleCount,\r\n            mask: descriptor.mask,\r\n            alphaToCoverageEnabled: descriptor.alphaToCoverageEnabled\r\n        }\r\n    }\r\n\r\n    public create(): void {\r\n        super.create();\r\n    }\r\n\r\n    public get resolveTarget(): any { return (this.descriptor as MultiSampleTextureDescriptor).resolveTarget }\r\n\r\n\r\n\r\n}"
            }
          ],
          "RenderPassTexture": [
            {
              "objectType": "type",
              "name": "RenderPassTextureDescriptor",
              "type": "RenderPassTextureDescriptor",
              "rawText": "export type RenderPassTextureDescriptor = {\r\n    size: GPUExtent3D,\r\n    format?: GPUTextureFormat,\r\n    usage?: GPUTextureUsageFlags,\r\n    mipLevelCount?: GPUIntegerCoordinate,\r\n    sampleCount?: GPUSize32,\r\n    dimension?: GPUTextureDimension,\r\n    viewFormats?: GPUTextureFormat[],\r\n    label?: string,\r\n}"
            },
            {
              "objectType": "class",
              "name": "RenderPassTexture",
              "filePath": "xGPU.pipelines.resources.textures.RenderPassTexture",
              "extends": [
                "ImageTexture",
                "EventDispatcher"
              ],
              "properties": {
                "public": [
                  {
                    "objectType": "property",
                    "name": "renderPipeline",
                    "type": "RenderPipeline",
                    "visibility": "public",
                    "rawText": "public renderPipeline: RenderPipeline;"
                  },
                  {
                    "objectType": "property",
                    "name": "mustUseCopyTextureToTexture",
                    "type": "boolean",
                    "visibility": "public",
                    "rawText": "public get mustUseCopyTextureToTexture(): boolean { return this._mustUseCopyTextureToTexture }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "width",
                    "type": "number",
                    "visibility": "public",
                    "rawText": "public get width(): number { return this.descriptor.size[0] }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "height",
                    "type": "number",
                    "visibility": "public",
                    "rawText": "public get height(): number { return this.descriptor.size[1] }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "isRenderPass",
                    "type": "boolean",
                    "visibility": "public",
                    "rawText": "public get isRenderPass(): boolean { return true; }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "source",
                    "type": "any",
                    "visibility": "public",
                    "rawText": "public get source(): ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture { return null }",
                    "get": true,
                    "set": true
                  }
                ],
                "private": [
                  {
                    "objectType": "property",
                    "name": "ready",
                    "type": "boolean",
                    "visibility": "private",
                    "rawText": "private ready: boolean = false;"
                  }
                ],
                "protected": [
                  {
                    "objectType": "property",
                    "name": "_mustUseCopyTextureToTexture",
                    "type": "boolean",
                    "visibility": "protected",
                    "rawText": "protected _mustUseCopyTextureToTexture: boolean = false;"
                  },
                  {
                    "objectType": "property",
                    "name": "frameId",
                    "type": "number",
                    "visibility": "protected",
                    "rawText": "protected frameId: number = -1;"
                  }
                ]
              },
              "methods": {
                "public": [
                  {
                    "objectType": "method",
                    "name": "applyRenderPass",
                    "returnType": "void",
                    "params": [
                      {
                        "name": "pipeline",
                        "type": "Pipeline"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public applyRenderPass(pipeline: Pipeline) {\r\n\r\n\r\n        if (this.renderPipeline === pipeline) {\r\n            this._mustUseCopyTextureToTexture = true;\r\n            return\r\n        } else {\r\n            if (!this.ready) {\r\n                if (pipeline instanceof RenderPipeline && pipeline.renderer) {\r\n                    this.renderPipeline.renderer = pipeline.renderer;\r\n                    this.ready = true;\r\n                } else {\r\n                    return;\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        if (pipeline instanceof RenderPipeline && pipeline.renderer) {\r\n            this.renderPipeline.renderer = pipeline.renderer\r\n            //console.log(\"this.renderPipeline.renderer.frameId = \", pipeline.renderer.frameId)\r\n\r\n        }\r\n\r\n\r\n\r\n        if (this.frameId != this.renderPipeline.renderer.frameId) { //avoid potential useless renderPass\r\n\r\n            const commandEncoder: GPUCommandEncoder = this.renderPipeline.renderer.commandEncoder;\r\n            if (commandEncoder) {\r\n                this.frameId = this.renderPipeline.renderer.frameId;\r\n                if (!this.renderPipeline.pipeline) {\r\n                    this.renderPipeline.buildGpuPipeline();\r\n                }\r\n                this.renderPipeline.update();\r\n\r\n                const renderPass: GPURenderPassEncoder = this.renderPipeline.beginRenderPass(commandEncoder, this.view, 0, true);\r\n                for (let j = 0; j < this.renderPipeline.pipelineCount; j++) {\r\n                    this.renderPipeline.dispatchEvent(RenderPipeline.ON_DRAW, j);\r\n                    this.renderPipeline.draw(renderPass);\r\n                }\r\n                this.renderPipeline.end(commandEncoder, renderPass);\r\n\r\n\r\n\r\n            }\r\n        }\r\n\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "resize",
                    "returnType": "ImageTexture",
                    "params": [
                      {
                        "name": "w",
                        "type": "number"
                      },
                      {
                        "name": "h",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public resize(w: number, h: number): ImageTexture {\r\n        //if (this.useOutsideTexture) return null;\r\n        this.descriptor.size = [w, h];\r\n        this.createGpuResource()\r\n        this.dispatchEvent(RenderPassTexture.RESOURCE_CHANGED);\r\n        return this;\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "createBindGroupEntry",
                    "returnType": "{ binding: number; resource: GPUTextureView; }",
                    "params": [
                      {
                        "name": "bindingId",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public createBindGroupEntry(bindingId: number): { binding: number; resource: GPUTextureView; } {\r\n        if (this.deviceId !== XGPU.deviceId) {\r\n            this.deviceId = XGPU.deviceId;\r\n            this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor)\r\n            this._view = this.gpuResource.createView();\r\n        }\r\n        return super.createBindGroupEntry(bindingId)\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "update",
                    "returnType": "void",
                    "visibility": "public",
                    "rawText": "public update(): void {\r\n        //nothing here\r\n\r\n        //console.log(this.deviceId === XGPU.deviceId, this.gpuResource)\r\n    }"
                  }
                ]
              },
              "statics": {
                "properties": {
                  "public": [
                    {
                      "objectType": "property",
                      "name": "RESOURCE_CHANGED",
                      "type": "string",
                      "visibility": "public",
                      "rawText": "public static RESOURCE_CHANGED: string = \"RESOURCE_CHANGED\";"
                    }
                  ]
                }
              },
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "pipeline",
                    "type": "RenderPipeline"
                  },
                  {
                    "name": "descriptor",
                    "type": "{ size: GPUExtent3D; format?: GPUTextureFormat; usage?: GPUTextureUsageFlags; mipLevelCount?: GPUIntegerCoordinate; sampleCount?: GPUSize32; dimension?: GPUTextureDimension; viewFormats?: GPUTextureFormat[]; label?: string; }"
                  }
                ],
                "rawText": "constructor(pipeline: RenderPipeline, descriptor?: {\r\n        size: GPUExtent3D,\r\n        format?: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        mipLevelCount?: GPUIntegerCoordinate,\r\n        sampleCount?: GPUSize32,\r\n        dimension?: GPUTextureDimension,\r\n        viewFormats?: GPUTextureFormat[],\r\n        label?: string,\r\n    }) {\r\n\r\n        if (!descriptor) {\r\n\r\n            if (pipeline.renderer) descriptor = { size: [pipeline.renderer.width, pipeline.renderer.height] };\r\n            else descriptor = { size: [1, 1] };\r\n\r\n        } if (!descriptor.format) descriptor.format = XGPU.getPreferredCanvasFormat();\r\n        if (!descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (!descriptor.mipLevelCount) descriptor.mipLevelCount = 1;\r\n        if (!descriptor.sampleCount) descriptor.sampleCount = 1;\r\n        if (!descriptor.dimension) descriptor.dimension = \"2d\";\r\n        if (!descriptor.viewFormats) descriptor.viewFormats = [];\r\n        if (!descriptor.label) descriptor.label = \"RenderPassTexture\";\r\n\r\n        super(descriptor)\r\n\r\n\r\n        if (!pipeline.renderer) {\r\n            this.ready = false;\r\n            //console.log(\"wait event\")\r\n            pipeline.addEventListener(RenderPipeline.ON_ADDED_TO_RENDERER, () => {\r\n                this.ready = true;\r\n                //console.log(\"resize\")\r\n                this.resize(pipeline.renderer.width, pipeline.renderer.height)\r\n\r\n            }, true);\r\n        } else {\r\n            this.ready = true;\r\n        }\r\n\r\n\r\n        this.renderPipeline = pipeline;\r\n        this.createGpuResource();\r\n        //this.useOutsideTexture = true;\r\n    }"
              },
              "rawText": "export class RenderPassTexture extends ImageTexture {\r\n\r\n    public static RESOURCE_CHANGED: string = \"RESOURCE_CHANGED\";\r\n\r\n    private ready: boolean = false;\r\n\r\n    constructor(pipeline: RenderPipeline, descriptor?: {\r\n        size: GPUExtent3D,\r\n        format?: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        mipLevelCount?: GPUIntegerCoordinate,\r\n        sampleCount?: GPUSize32,\r\n        dimension?: GPUTextureDimension,\r\n        viewFormats?: GPUTextureFormat[],\r\n        label?: string,\r\n    }) {\r\n\r\n        if (!descriptor) {\r\n\r\n            if (pipeline.renderer) descriptor = { size: [pipeline.renderer.width, pipeline.renderer.height] };\r\n            else descriptor = { size: [1, 1] };\r\n\r\n        } if (!descriptor.format) descriptor.format = XGPU.getPreferredCanvasFormat();\r\n        if (!descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (!descriptor.mipLevelCount) descriptor.mipLevelCount = 1;\r\n        if (!descriptor.sampleCount) descriptor.sampleCount = 1;\r\n        if (!descriptor.dimension) descriptor.dimension = \"2d\";\r\n        if (!descriptor.viewFormats) descriptor.viewFormats = [];\r\n        if (!descriptor.label) descriptor.label = \"RenderPassTexture\";\r\n\r\n        super(descriptor)\r\n\r\n\r\n        if (!pipeline.renderer) {\r\n            this.ready = false;\r\n            //console.log(\"wait event\")\r\n            pipeline.addEventListener(RenderPipeline.ON_ADDED_TO_RENDERER, () => {\r\n                this.ready = true;\r\n                //console.log(\"resize\")\r\n                this.resize(pipeline.renderer.width, pipeline.renderer.height)\r\n\r\n            }, true);\r\n        } else {\r\n            this.ready = true;\r\n        }\r\n\r\n\r\n        this.renderPipeline = pipeline;\r\n        this.createGpuResource();\r\n        //this.useOutsideTexture = true;\r\n    }\r\n\r\n    public renderPipeline: RenderPipeline;\r\n\r\n    protected _mustUseCopyTextureToTexture: boolean = false;\r\n    public get mustUseCopyTextureToTexture(): boolean { return this._mustUseCopyTextureToTexture }\r\n\r\n    protected frameId: number = -1;\r\n    public applyRenderPass(pipeline: Pipeline) {\r\n\r\n\r\n        if (this.renderPipeline === pipeline) {\r\n            this._mustUseCopyTextureToTexture = true;\r\n            return\r\n        } else {\r\n            if (!this.ready) {\r\n                if (pipeline instanceof RenderPipeline && pipeline.renderer) {\r\n                    this.renderPipeline.renderer = pipeline.renderer;\r\n                    this.ready = true;\r\n                } else {\r\n                    return;\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        if (pipeline instanceof RenderPipeline && pipeline.renderer) {\r\n            this.renderPipeline.renderer = pipeline.renderer\r\n            //console.log(\"this.renderPipeline.renderer.frameId = \", pipeline.renderer.frameId)\r\n\r\n        }\r\n\r\n\r\n\r\n        if (this.frameId != this.renderPipeline.renderer.frameId) { //avoid potential useless renderPass\r\n\r\n            const commandEncoder: GPUCommandEncoder = this.renderPipeline.renderer.commandEncoder;\r\n            if (commandEncoder) {\r\n                this.frameId = this.renderPipeline.renderer.frameId;\r\n                if (!this.renderPipeline.pipeline) {\r\n                    this.renderPipeline.buildGpuPipeline();\r\n                }\r\n                this.renderPipeline.update();\r\n\r\n                const renderPass: GPURenderPassEncoder = this.renderPipeline.beginRenderPass(commandEncoder, this.view, 0, true);\r\n                for (let j = 0; j < this.renderPipeline.pipelineCount; j++) {\r\n                    this.renderPipeline.dispatchEvent(RenderPipeline.ON_DRAW, j);\r\n                    this.renderPipeline.draw(renderPass);\r\n                }\r\n                this.renderPipeline.end(commandEncoder, renderPass);\r\n\r\n\r\n\r\n            }\r\n        }\r\n\r\n    }\r\n\r\n    public resize(w: number, h: number): ImageTexture {\r\n        //if (this.useOutsideTexture) return null;\r\n        this.descriptor.size = [w, h];\r\n        this.createGpuResource()\r\n        this.dispatchEvent(RenderPassTexture.RESOURCE_CHANGED);\r\n        return this;\r\n    }\r\n\r\n    public createBindGroupEntry(bindingId: number): { binding: number; resource: GPUTextureView; } {\r\n        if (this.deviceId !== XGPU.deviceId) {\r\n            this.deviceId = XGPU.deviceId;\r\n            this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor)\r\n            this._view = this.gpuResource.createView();\r\n        }\r\n        return super.createBindGroupEntry(bindingId)\r\n    }\r\n\r\n    public get width(): number { return this.descriptor.size[0] }\r\n    public get height(): number { return this.descriptor.size[1] }\r\n    public get isRenderPass(): boolean { return true; }\r\n\r\n    public update(): void {\r\n        //nothing here\r\n\r\n        //console.log(this.deviceId === XGPU.deviceId, this.gpuResource)\r\n    }\r\n\r\n    public get source(): ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture { return null }\r\n    public set source(bmp: ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture) { if (bmp) return }\r\n}"
            }
          ],
          "Texture": [
            {
              "objectType": "type",
              "name": "TextureDescriptor",
              "type": "TextureDescriptor",
              "rawText": "export type TextureDescriptor = {\r\n    size: GPUExtent3D,\r\n    format: GPUTextureFormat,\r\n    usage?: GPUTextureUsageFlags,\r\n    sampleCount?: GPUSize32,\r\n    label?: string,\r\n}"
            },
            {
              "objectType": "class",
              "name": "Texture",
              "filePath": "xGPU.pipelines.resources.textures.Texture",
              "extends": [
                "EventDispatcher"
              ],
              "properties": {
                "public": [
                  {
                    "objectType": "property",
                    "name": "descriptor",
                    "type": "TextureDescriptor",
                    "visibility": "public",
                    "rawText": "public descriptor: TextureDescriptor;"
                  },
                  {
                    "objectType": "property",
                    "name": "gpuResource",
                    "type": "GPUTexture",
                    "visibility": "public",
                    "rawText": "public gpuResource: GPUTexture = null;"
                  },
                  {
                    "objectType": "property",
                    "name": "sampleCount",
                    "type": "number",
                    "visibility": "public",
                    "rawText": "public get sampleCount(): number { return this.descriptor.sampleCount }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "format",
                    "type": "any",
                    "visibility": "public",
                    "rawText": "public get format(): any { return this.descriptor.format }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "size",
                    "type": "GPUExtent3D",
                    "visibility": "public",
                    "rawText": "public get size(): GPUExtent3D { return this.descriptor.size }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "usage",
                    "type": "number",
                    "visibility": "public",
                    "rawText": "public get usage(): number { return this.descriptor.usage }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "view",
                    "type": "GPUTextureView",
                    "visibility": "public",
                    "rawText": "public get view(): GPUTextureView {\r\n\r\n        if (!this._view) this.create();\r\n        return this._view;\r\n    }",
                    "get": true
                  },
                  {
                    "objectType": "property",
                    "name": "time",
                    "type": "number",
                    "visibility": "public",
                    "rawText": "public time: number;"
                  }
                ],
                "protected": [
                  {
                    "objectType": "property",
                    "name": "_view",
                    "type": "GPUTextureView",
                    "visibility": "protected",
                    "rawText": "protected _view: GPUTextureView = null;"
                  },
                  {
                    "objectType": "property",
                    "name": "deviceId",
                    "type": "number",
                    "visibility": "protected",
                    "rawText": "protected deviceId: number;"
                  }
                ]
              },
              "methods": {
                "public": [
                  {
                    "objectType": "method",
                    "name": "destroy",
                    "returnType": "void",
                    "visibility": "public",
                    "rawText": "public destroy(): void {\r\n        if (this.gpuResource) {\r\n            (this.gpuResource as any).xgpuObject = null;\r\n            this.gpuResource.destroy();\r\n        }\r\n        this.gpuResource = null;\r\n        this._view = null;\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "create",
                    "returnType": "void",
                    "visibility": "public",
                    "rawText": "public create(): void {\r\n\r\n        /*if (this.time && new Date().getTime() - this.time < 100 && XGPU.loseDeviceRecently) {\r\n            return;\r\n        }*/\r\n        this.time = new Date().getTime();\r\n\r\n\r\n        if (XGPU.loseDeviceRecently && this.deviceId === XGPU.deviceId) return\r\n\r\n        if (this.gpuResource) {\r\n            (this.gpuResource as any).xgpuObject = null;\r\n            this.gpuResource.destroy();\r\n        }\r\n        //console.warn(\"createTexture \", this.deviceId)\r\n\r\n\r\n\r\n        this.deviceId = XGPU.deviceId;\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        (this.gpuResource as any).xgpuObject = this;\r\n        this.createView();\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "createGpuResource",
                    "returnType": "void",
                    "visibility": "public",
                    "rawText": "public createGpuResource(): void {\r\n        this.create();\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "update",
                    "returnType": "void",
                    "visibility": "public",
                    "rawText": "public update() {\r\n        if (this.deviceId !== XGPU.deviceId) {\r\n\r\n            this.create();\r\n\r\n        }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "resize",
                    "returnType": "void",
                    "params": [
                      {
                        "name": "width",
                        "type": "number"
                      },
                      {
                        "name": "height",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public resize(width: number, height: number): void {\r\n        this.descriptor.size = [width, height];\r\n        this.create();\r\n    }"
                  }
                ],
                "private": [
                  {
                    "objectType": "method",
                    "name": "createView",
                    "returnType": "void",
                    "visibility": "private",
                    "rawText": "private createView(): void {\r\n        if (!this.gpuResource) this.create();\r\n        this._view = this.gpuResource.createView();\r\n        //(this._view as any).texture = this;\r\n    }"
                  }
                ]
              },
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "{ size: GPUExtent3D; format: GPUTextureFormat; usage?: GPUTextureUsageFlags; sampleCount?: GPUSize32; label?: string; }"
                  }
                ],
                "rawText": "constructor(descriptor: {\r\n        size: GPUExtent3D,\r\n        format: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: GPUSize32,\r\n        label?: string\r\n    }) {\r\n\r\n        super();\r\n        //console.log(descriptor.format + \" ::: \" + descriptor.usage)\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (undefined === descriptor.sampleCount && descriptor.format !== \"depth32float\") descriptor.sampleCount = 1;\r\n        if (undefined === descriptor.label) descriptor.label = \"Texture\";\r\n        this.descriptor = descriptor;\r\n\r\n    }"
              },
              "rawText": "export class Texture extends EventDispatcher {\r\n\r\n    public descriptor: TextureDescriptor;\r\n    public gpuResource: GPUTexture = null;\r\n    protected _view: GPUTextureView = null;\r\n\r\n    constructor(descriptor: {\r\n        size: GPUExtent3D,\r\n        format: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        sampleCount?: GPUSize32,\r\n        label?: string\r\n    }) {\r\n\r\n        super();\r\n        //console.log(descriptor.format + \" ::: \" + descriptor.usage)\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (undefined === descriptor.sampleCount && descriptor.format !== \"depth32float\") descriptor.sampleCount = 1;\r\n        if (undefined === descriptor.label) descriptor.label = \"Texture\";\r\n        this.descriptor = descriptor;\r\n\r\n    }\r\n    public get sampleCount(): number { return this.descriptor.sampleCount }\r\n    public get format(): any { return this.descriptor.format }\r\n    public get size(): GPUExtent3D { return this.descriptor.size }\r\n    public get usage(): number { return this.descriptor.usage }\r\n    public get view(): GPUTextureView {\r\n\r\n        if (!this._view) this.create();\r\n        return this._view;\r\n    }\r\n\r\n    public destroy(): void {\r\n        if (this.gpuResource) {\r\n            (this.gpuResource as any).xgpuObject = null;\r\n            this.gpuResource.destroy();\r\n        }\r\n        this.gpuResource = null;\r\n        this._view = null;\r\n    }\r\n\r\n    protected deviceId: number;\r\n    public time: number;\r\n    public create(): void {\r\n\r\n        /*if (this.time && new Date().getTime() - this.time < 100 && XGPU.loseDeviceRecently) {\r\n            return;\r\n        }*/\r\n        this.time = new Date().getTime();\r\n\r\n\r\n        if (XGPU.loseDeviceRecently && this.deviceId === XGPU.deviceId) return\r\n\r\n        if (this.gpuResource) {\r\n            (this.gpuResource as any).xgpuObject = null;\r\n            this.gpuResource.destroy();\r\n        }\r\n        //console.warn(\"createTexture \", this.deviceId)\r\n\r\n\r\n\r\n        this.deviceId = XGPU.deviceId;\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        (this.gpuResource as any).xgpuObject = this;\r\n        this.createView();\r\n    }\r\n\r\n\r\n    public createGpuResource(): void {\r\n        this.create();\r\n    }\r\n\r\n    public update() {\r\n        if (this.deviceId !== XGPU.deviceId) {\r\n\r\n            this.create();\r\n\r\n        }\r\n    }\r\n\r\n    private createView(): void {\r\n        if (!this.gpuResource) this.create();\r\n        this._view = this.gpuResource.createView();\r\n        //(this._view as any).texture = this;\r\n    }\r\n\r\n    public resize(width: number, height: number): void {\r\n        this.descriptor.size = [width, height];\r\n        this.create();\r\n    }\r\n\r\n\r\n}"
            }
          ]
        }
      }
    },
    "shader": {
      "Bindgroup": [
        {
          "objectType": "class",
          "name": "Bindgroup",
          "filePath": "xGPU.shader.Bindgroup",
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "bindgroupId",
                "type": "number",
                "visibility": "public",
                "rawText": "public bindgroupId: number"
              },
              {
                "objectType": "property",
                "name": "parent",
                "type": "Bindgroups",
                "visibility": "public",
                "rawText": "public parent: Bindgroups;"
              },
              {
                "objectType": "property",
                "name": "entries",
                "type": "any[]",
                "visibility": "public",
                "rawText": "public entries: any[] = [];"
              },
              {
                "objectType": "property",
                "name": "elements",
                "type": "{ name: string; resource: IShaderResource; }[]",
                "visibility": "public",
                "rawText": "public elements: { name: string, resource: IShaderResource }[] = [];"
              },
              {
                "objectType": "property",
                "name": "mustRefreshBindgroup",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public mustRefreshBindgroup: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "applyDraw",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public applyDraw: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "name",
                "type": "string",
                "visibility": "public",
                "rawText": "public name: string = \"\";"
              },
              {
                "objectType": "property",
                "name": "vertexBufferIO",
                "type": "VertexBufferIO",
                "visibility": "public",
                "rawText": "public vertexBufferIO: VertexBufferIO;"
              },
              {
                "objectType": "property",
                "name": "textureIO",
                "type": "ImageTextureIO",
                "visibility": "public",
                "rawText": "public textureIO: ImageTextureIO;"
              },
              {
                "objectType": "property",
                "name": "resourcesIOs",
                "type": "(VertexBufferIO | ImageTextureIO)[]",
                "visibility": "public",
                "rawText": "public resourcesIOs: (VertexBufferIO | ImageTextureIO)[] = [];"
              },
              {
                "objectType": "property",
                "name": "setupDrawCompleted",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public setupDrawCompleted: boolean = false;"
              },
              {
                "objectType": "property",
                "name": "useInstances",
                "type": "boolean",
                "visibility": "public",
                "rawText": "public get useInstances(): boolean { return !!this.instances || !!this.instanceResourcesArray }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "debug",
                "type": "any",
                "visibility": "public",
                "rawText": "public debug: any;"
              },
              {
                "objectType": "property",
                "name": "pingPongBindgroup",
                "type": "Bindgroup",
                "visibility": "public",
                "rawText": "public get pingPongBindgroup(): Bindgroup {\r\n        return this._pingPongBindgroup;\r\n    }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "layout",
                "type": "GPUBindGroupLayout",
                "visibility": "public",
                "rawText": "public get layout(): GPUBindGroupLayout {\r\n        if (!this._layout) this.buildLayout();\r\n        return this._layout;\r\n    }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "group",
                "type": "GPUBindGroup",
                "visibility": "public",
                "rawText": "public get group(): GPUBindGroup {\r\n\r\n        if (!this._group || this.mustRefreshBindgroup) {\r\n            this.build();\r\n        }\r\n\r\n        if (this.ioGroups) {\r\n            const group = this.ioGroups[this.io_index++ % 2];\r\n            if (!group._group) group.build();\r\n            return group._group;\r\n        }\r\n\r\n\r\n\r\n        return this._group;\r\n    }",
                "get": true
              }
            ],
            "private": [
              {
                "objectType": "property",
                "name": "setupApplyCompleted",
                "type": "boolean",
                "visibility": "private",
                "rawText": "private setupApplyCompleted: boolean = false;"
              }
            ],
            "protected": [
              {
                "objectType": "property",
                "name": "_layout",
                "type": "GPUBindGroupLayout",
                "visibility": "protected",
                "rawText": "protected _layout: GPUBindGroupLayout;"
              },
              {
                "objectType": "property",
                "name": "_group",
                "type": "GPUBindGroup",
                "visibility": "protected",
                "rawText": "protected _group: GPUBindGroup;"
              },
              {
                "objectType": "property",
                "name": "_pingPongBindgroup",
                "type": "Bindgroup",
                "visibility": "protected",
                "rawText": "protected _pingPongBindgroup: Bindgroup = null;"
              },
              {
                "objectType": "property",
                "name": "deviceId",
                "type": "number",
                "visibility": "protected",
                "rawText": "protected deviceId: number = 0;"
              },
              {
                "objectType": "property",
                "name": "indexBuffer",
                "type": "IndexBuffer",
                "visibility": "protected",
                "rawText": "protected indexBuffer: IndexBuffer;"
              },
              {
                "objectType": "property",
                "name": "vertexBuffers",
                "type": "VertexBuffer[]",
                "visibility": "protected",
                "rawText": "protected vertexBuffers: VertexBuffer[];"
              },
              {
                "objectType": "property",
                "name": "vertexBufferReferenceByName",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected vertexBufferReferenceByName: any;"
              },
              {
                "objectType": "property",
                "name": "elementByName",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected elementByName: any = {};"
              },
              {
                "objectType": "property",
                "name": "instances",
                "type": "any[]",
                "visibility": "protected",
                "rawText": "protected instances: any[];"
              },
              {
                "objectType": "property",
                "name": "instanceResourcesArray",
                "type": "any[]",
                "visibility": "protected",
                "rawText": "protected instanceResourcesArray: any[];"
              },
              {
                "objectType": "property",
                "name": "renderPipelineimageIO",
                "type": "ImageTexture",
                "visibility": "protected",
                "rawText": "protected renderPipelineimageIO: ImageTexture;"
              },
              {
                "objectType": "property",
                "name": "renderPipelineBufferIO",
                "type": "VertexBuffer",
                "visibility": "protected",
                "rawText": "protected renderPipelineBufferIO: VertexBuffer;"
              },
              {
                "objectType": "property",
                "name": "ioGroups",
                "type": "Bindgroup[]",
                "visibility": "protected",
                "rawText": "protected ioGroups: Bindgroup[];"
              },
              {
                "objectType": "property",
                "name": "io_index",
                "type": "number",
                "visibility": "protected",
                "rawText": "protected io_index: number = 0;"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "add",
                "returnType": "IShaderResource",
                "params": [
                  {
                    "name": "name",
                    "type": "string"
                  },
                  {
                    "name": "resource",
                    "type": "IShaderResource"
                  }
                ],
                "visibility": "public",
                "rawText": "public add(name: string, resource: IShaderResource): IShaderResource {\r\n        if (resource instanceof VideoTexture) this.mustRefreshBindgroup = true;\r\n        else if (resource instanceof ImageTexture && (resource.source instanceof GPUTexture || !resource.source)) {\r\n            this.mustRefreshBindgroup = true;\r\n\r\n        }\r\n\r\n        if (resource instanceof IndexBuffer) {\r\n            this.indexBuffer = resource;\r\n            this.elementByName[name] = resource;\r\n            return resource;\r\n        }\r\n\r\n\r\n        //console.log(\"bindgroup.add \", resource)\r\n\r\n        if (resource instanceof VertexBufferIO) {\r\n\r\n\r\n            this.resourcesIOs.push(resource);\r\n\r\n\r\n\r\n            this.mustRefreshBindgroup = true;\r\n            this.vertexBufferIO = resource;\r\n            //console.log(\"group vertexBufferIO \", this.vertexBufferIO)\r\n            this.elements.push({ name: name, resource: resource.buffers[0] });\r\n            this.elements.push({ name: name + \"_out\", resource: resource.buffers[1] });\r\n\r\n\r\n            if (this.parent) this.parent.add(this);\r\n            return resource;\r\n        }\r\n\r\n        if (resource instanceof ImageTextureIO) {\r\n\r\n\r\n            this.resourcesIOs.push(resource);\r\n\r\n\r\n\r\n\r\n            this.mustRefreshBindgroup = true;\r\n            this.textureIO = resource;\r\n            this.elements.push({ name: name, resource: resource.textures[0] });\r\n            this.elements.push({ name: name + \"_out\", resource: resource.textures[1] });\r\n\r\n            if (this.parent) this.parent.add(this);\r\n            return resource;\r\n        }\r\n\r\n        if (resource instanceof VideoTexture) {\r\n            resource.addBindgroup(this);\r\n        }\r\n\r\n\r\n\r\n        this.elements.push({ name, resource });\r\n        if (this.parent) this.parent.add(this);\r\n        return resource;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "set",
                "returnType": "void",
                "params": [
                  {
                    "name": "name",
                    "type": "string"
                  },
                  {
                    "name": "resource",
                    "type": "IShaderResource"
                  }
                ],
                "visibility": "public",
                "rawText": "public set(name: string, resource: IShaderResource) {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (this.elements[i].name === name) {\r\n                this.elements[i].resource = resource;\r\n            }\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "remove",
                "returnType": "void",
                "params": [
                  {
                    "name": "name",
                    "type": "string"
                  }
                ],
                "visibility": "public",
                "rawText": "public remove(name: string) {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (this.elements[i].name === name) {\r\n                this.elements.splice(i, 1);\r\n            }\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getResourceName",
                "returnType": "string",
                "params": [
                  {
                    "name": "resource",
                    "type": "IShaderResource"
                  }
                ],
                "visibility": "public",
                "rawText": "public getResourceName(resource: IShaderResource): string {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (resource === this.elements[i].resource) {\r\n                return this.elements[i].name;\r\n            }\r\n        }\r\n        return null;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "get",
                "returnType": "IShaderResource",
                "params": [
                  {
                    "name": "name",
                    "type": "string"
                  }
                ],
                "visibility": "public",
                "rawText": "public get(name: string): IShaderResource {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n\r\n            if (this.elements[i].name === name) return this.elements[i].resource;\r\n        }\r\n\r\n\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (this.elements[i].resource instanceof UniformBuffer) {\r\n\r\n                if ((this.elements[i].resource as UniformBuffer).items[name]) {\r\n                    return this.elements[i].resource\r\n                }\r\n            }\r\n        }\r\n\r\n        return null;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "initFromObject",
                "returnType": "IShaderResource[]",
                "params": [
                  {
                    "name": "descriptor",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public initFromObject(descriptor: any | any[]): IShaderResource[] {\r\n        //console.log(\"group.initFromObject \", object)\r\n\r\n        let object: any = descriptor;\r\n        let isArray = false;\r\n        if (descriptor instanceof Array) {\r\n            isArray = true;\r\n            object = descriptor[0];\r\n        }\r\n\r\n\r\n        HighLevelParser.parse(object, \"bindgroup\");\r\n\r\n\r\n        const result: IShaderResource[] = [];\r\n        let k = 0;\r\n        let o;\r\n        for (let z in object) {\r\n            o = object[z];\r\n            if (!o) continue;\r\n            //console.log(z + \" : \" + o.create)\r\n            if (o.createGpuResource || o instanceof VertexBufferIO || o instanceof ImageTextureIO) { //if it's a shader resource \r\n                result[k++] = this.add(z, o);\r\n            }\r\n        }\r\n        //console.log(\"object = \", object)\r\n\r\n        if (isArray) {\r\n            for (let i = 0; i < descriptor.length; i++) {\r\n                this.createInstance(descriptor[i]);\r\n            }\r\n        }\r\n\r\n\r\n\r\n        //console.warn(\"bindgroup.initFromObject result = \", result)\r\n        return result;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "clearAfterDeviceLost",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public clearAfterDeviceLost(): void {\r\n        this._layout = null\r\n        this._group = null;\r\n        this.setupApplyCompleted = false;\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            this.elements[i].resource.destroyGpuResource();\r\n        }\r\n\r\n        if (this.instances) {\r\n            let elements: any, resource: IShaderResource;\r\n            let instance: any;\r\n            for (let i = 0; i < this.instances.length; i++) {\r\n                instance = this.instances[i];\r\n                instance.group = undefined;\r\n                elements = instance.elements;\r\n\r\n                if (instance.indexBuffer) (instance.indexBuffer as IndexBuffer).createGpuResource();\r\n\r\n                for (let j = 0; j < elements.length; j++) {\r\n                    resource = elements[j].resource;\r\n                    //console.log(j, resource)\r\n                    if (resource.gpuResource) {\r\n\r\n                        resource.destroyGpuResource();\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "build",
                "returnType": "GPUBindGroup",
                "visibility": "public",
                "rawText": "public build(): GPUBindGroup {\r\n\r\n        if (!this._layout || (this.deviceId != XGPU.deviceId && this.ioGroups)) this.buildLayout();\r\n        this.deviceId = XGPU.deviceId;\r\n        let entries = [];\r\n        let bindingId: number = 0;\r\n        let resource: IShaderResource;\r\n\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (!this.elements[i]) continue\r\n            resource = this.elements[i].resource;\r\n            resource.update();\r\n\r\n            if (resource instanceof VertexBuffer && !(resource as VertexBuffer).io && this.parent.pipeline.type != \"compute\") continue;\r\n\r\n            let entry = resource.createBindGroupEntry(bindingId++)\r\n            //console.warn(\"BINDGROUP.BUILD ::: bindgroup entry \", this.elements[i].name, (bindingId - 1), entry);\r\n            entries.push(entry);\r\n        }\r\n\r\n        this._group = XGPU.device.createBindGroup({ layout: this._layout, entries })\r\n\r\n\r\n        if (!this.setupApplyCompleted && this.parent) {\r\n\r\n            this.setupApplyCompleted = true;\r\n            this.setupApply();\r\n\r\n            if (this.instanceResourcesArray) {\r\n                for (let i = 0; i < this.instanceResourcesArray.length; i++) {\r\n                    this._createInstance(this.instanceResourcesArray[i]);\r\n                }\r\n                this.instanceResourcesArray = undefined;\r\n            }\r\n\r\n        }\r\n\r\n        return this._group;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupDraw",
                "returnType": "void",
                "params": [
                  {
                    "name": "force",
                    "type": "boolean"
                  }
                ],
                "visibility": "public",
                "rawText": "public setupDraw(force: boolean = false) {\r\n\r\n        if (this.vertexBuffers) {\r\n            for (let i = 0; i < this.vertexBuffers.length; i++) {\r\n                if (!this.vertexBuffers[i].gpuResource) {\r\n                    this.vertexBuffers[i].createGpuResource();\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        if (this.parent.drawConfig) { //may be undefined with a computePipeline\r\n\r\n            this.indexBuffer = this.parent.drawConfig.indexBuffer;\r\n            if (force || (!this.indexBuffer && this.parent.drawConfig.vertexCount <= 0)) {\r\n\r\n                if (!force && !this.parent.resources.types.vertexBuffers) {\r\n                    throw new Error(\"a renderPipeline require a vertexBuffer or a drawConfig object in order to draw. You must add a vertexBuffer or call RenderPipeline.setupDraw\")\r\n                }\r\n\r\n                const buffers = this.parent.resources.types.vertexBuffers;\r\n                let buf: VertexBuffer;\r\n                for (let i = 0; i < buffers.length; i++) {\r\n                    buf = buffers[i].resource as VertexBuffer;\r\n                    if (buf.descriptor.stepMode === \"vertex\") {\r\n                        this.parent.drawConfig.vertexCount = this.parent.resources.types.vertexBuffers[i].resource.nbVertex;\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "apply",
                "returnType": "void",
                "params": [
                  {
                    "name": "renderPass",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public apply(renderPass: GPURenderPassEncoder | GPUComputePassEncoder) {\r\n\r\n        if (!this.setupDrawCompleted) {\r\n            this.setupDrawCompleted = true;\r\n            if (undefined === this.bindgroupId) {\r\n                this.bindgroupId = this.parent.groups.indexOf(this);\r\n            }\r\n            this.setupDraw();\r\n        }\r\n\r\n        if (renderPass instanceof GPUComputePassEncoder) {\r\n            this.update(this.parent.pipeline);\r\n\r\n            renderPass.setBindGroup(this.bindgroupId, this.group);\r\n            return;\r\n        }\r\n\r\n\r\n        const instances = this.instances ? this.instances : [{ group: this.group, update: () => { } }]\r\n        const applyDraw = this.applyDraw;\r\n\r\n        //console.log(\"instances.length = \", instances.length)\r\n        for (let i = 0; i < instances.length; i++) {\r\n\r\n            instances[i].update();\r\n            this.update(this.parent.pipeline);\r\n\r\n            renderPass.setBindGroup(this.bindgroupId, instances[i].group);\r\n\r\n            if (this.vertexBuffers) {\r\n\r\n                let buf: any;\r\n                for (let j = 0; j < this.vertexBuffers.length; j++) {\r\n\r\n                    buf = this.vertexBuffers[j].getCurrentBuffer();\r\n                    renderPass.setVertexBuffer(this.vertexBuffers[j].bufferId, buf);\r\n                }\r\n            }\r\n\r\n            if (applyDraw) {\r\n                this.parent.drawConfig.draw(renderPass);\r\n            }\r\n\r\n        }\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createInstance",
                "returnType": "void",
                "params": [
                  {
                    "name": "instanceResources",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public createInstance(instanceResources: any) {\r\n        if (!this.instanceResourcesArray) this.instanceResourcesArray = [];\r\n        this.instanceResourcesArray.push(instanceResources)\r\n    }"
              },
              {
                "objectType": "method",
                "name": "handleComputePipelineResourceIOs",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public handleComputePipelineResourceIOs() {\r\n\r\n        if (this.resourcesIOs.length) {\r\n            let buf0 = [];\r\n            let buf1 = [];\r\n            for (let i = 0; i < this.resourcesIOs.length; i++) {\r\n                if (this.resourcesIOs[i] instanceof VertexBufferIO) {\r\n\r\n                    buf0[i] = (this.resourcesIOs[i] as VertexBufferIO).buffers[0];\r\n                    buf1[i] = (this.resourcesIOs[i] as VertexBufferIO).buffers[1];\r\n\r\n                } else {\r\n                    buf0[i] = (this.resourcesIOs[i] as ImageTextureIO).textures[0];\r\n                    buf1[i] = (this.resourcesIOs[i] as ImageTextureIO).textures[1];\r\n\r\n\r\n                }\r\n\r\n                buf0[i].createGpuResource();\r\n                buf1[i].createGpuResource();\r\n            }\r\n\r\n            this.createPingPongBindgroup(buf0, buf1);\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "createPingPongBindgroup",
                "returnType": "Bindgroup",
                "params": [
                  {
                    "name": "resource1",
                    "type": "IShaderResource[]"
                  },
                  {
                    "name": "resource2",
                    "type": "IShaderResource[]"
                  }
                ],
                "visibility": "public",
                "rawText": "public createPingPongBindgroup(resource1: IShaderResource[], resource2: IShaderResource[]): Bindgroup {\r\n        const group = new Bindgroup();\r\n        group.name = this.name;\r\n        group.mustRefreshBindgroup = this.mustRefreshBindgroup = true;\r\n        group._layout = this.layout;\r\n\r\n        //console.log(\"createPingPong\")\r\n        group.elements = this.swapElements();\r\n\r\n        let res1, res2;\r\n        for (let i = 0; i < resource1.length; i++) {\r\n            res1 = resource1[i];\r\n            res2 = resource2[i];\r\n\r\n            if (res1 instanceof VertexBuffer) {\r\n\r\n                const buffers = [res1.buffer, (res2 as VertexBuffer).buffer];\r\n                (buffers[0] as any).debug = 1;\r\n                (buffers[1] as any).debug = 2;\r\n\r\n                res1.initBufferIO(buffers);\r\n            } else if (res1 instanceof ImageTexture) {\r\n\r\n                if (!res1.gpuResource) res1.createGpuResource();\r\n                if (!res2.gpuResource) res2.createGpuResource();\r\n\r\n                const textures = [res1.gpuResource, res2.gpuResource];\r\n                try {\r\n                    (textures[0] as any).debug = 1;\r\n                    (textures[1] as any).debug = 2;\r\n                } catch (e) {\r\n\r\n                }\r\n\r\n                res1.initTextureIO(textures);\r\n            }\r\n        }\r\n\r\n        this.ioGroups = [group, this];\r\n        //this.ioGroups = [this, group];\r\n        this.debug = 1;\r\n        group.debug = 2;\r\n\r\n        return group;\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "handleRenderPipelineResourceIOs",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public handleRenderPipelineResourceIOs() {\r\n\r\n        //console.warn(\"handleRenderPipelineResourceIOs \", this.elements.length, this.textureIO)\r\n\r\n        if (this.renderPipelineimageIO) {\r\n            (this.renderPipelineimageIO as any).initIO();\r\n            return\r\n        } else if (this.renderPipelineBufferIO) {\r\n            (this.renderPipelineBufferIO as any).initIO();\r\n            return\r\n        }\r\n\r\n        //a vertexBufferIO uses 2 vertexBuffers in a computePipeline \r\n        //but a single one is required in a renderPipeline (same for textures)   \r\n        let resource: IShaderResource;\r\n        let name: string;\r\n        let bufferIOs: VertexBuffer[] = [];\r\n        let textureIOs: ImageTexture[] = [];\r\n\r\n        let parentResources: any = this.parent.resources;\r\n        let foundVertexIO: boolean = false;\r\n        let foundTextureIO: boolean = false;\r\n\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            //console.log(i, this.elements[i], this.parent.pipeline);\r\n            resource = this.elements[i].resource;\r\n            if (resource instanceof VertexBuffer) {\r\n                if (resource.io === 1) {\r\n                    name = this.elements[i].name;\r\n                    parentResources[name] = undefined;\r\n                    parentResources[name + \"_out\"] = undefined;\r\n\r\n                    bufferIOs.push(resource);\r\n                    bufferIOs.push(this.elements[i + 1].resource as VertexBuffer);\r\n                    this.elements.splice(i, 2);\r\n                    foundVertexIO = true;\r\n                    break;\r\n                }\r\n            } else if (resource instanceof ImageTexture) {\r\n\r\n                if (resource.io === 1) {\r\n                    name = this.elements[i].name;\r\n                    parentResources[name] = undefined;\r\n                    parentResources[name + \"_out\"] = undefined;\r\n                    //console.log(\"this.elements[i + 1] = \", this.elements[i + 1])\r\n                    textureIOs.push(resource);\r\n                    textureIOs.push(this.elements[i + 1].resource as ImageTexture);\r\n                    this.elements.splice(i, 2);\r\n                    foundTextureIO = true;\r\n                    break;\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        if (foundVertexIO) {\r\n            //console.log(\"foundVertexIO\")\r\n            //console.log(\"bufferIOs = \", bufferIOs)\r\n            const attributes = bufferIOs[0].attributeDescriptor;\r\n            const stepMode = bufferIOs[0].descriptor.stepMode;\r\n            const vb: VertexBuffer = new VertexBuffer(attributes, { stepMode });\r\n            this.elements.push({ name, resource: vb })\r\n\r\n            let vertexBuffers = parentResources.types.vertexBuffers;\r\n            let buffers: { name: string, resource: VertexBuffer }[] = [];\r\n            for (let i = 0; i < vertexBuffers.length; i++) {\r\n                if (!vertexBuffers[i].resource.io) {\r\n                    buffers.push(vertexBuffers[i]);\r\n                }\r\n            }\r\n            buffers.push({ name, resource: vb });\r\n\r\n            parentResources[name] = vb;\r\n            parentResources.types.vertexBuffers = buffers;\r\n\r\n            (vb as any).initIO = () => {\r\n                vb.initBufferIO([bufferIOs[0].buffer, bufferIOs[1].buffer])\r\n            }\r\n            (vb as any).initIO();\r\n            this.renderPipelineBufferIO = vb;\r\n\r\n\r\n        } else if (foundTextureIO) {\r\n\r\n            //console.log(\"foundTextureIO\")\r\n\r\n            const img = new ImageTexture({ source: textureIOs[0].gpuResource })\r\n            this.elements.push({ name, resource: img })\r\n\r\n            let images = parentResources.types.imageTextures;\r\n            let textures: { name: string, resource: ImageTexture }[] = [];\r\n            for (let i = 0; i < images.length; i++) {\r\n                if (!images[i].resource.io) {\r\n                    textures.push(images[i]);\r\n                }\r\n            }\r\n            textures.push({ name, resource: img });\r\n\r\n            parentResources[name] = img;\r\n            parentResources.types.imageTextures = images;\r\n\r\n            (img as any).initIO = () => {\r\n                //console.log(\"initIO \", textureIOs[0].deviceId, textureIOs[1].deviceId)\r\n                img.source = textureIOs[0].texture;\r\n                img.initTextureIO([textureIOs[0].texture, textureIOs[1].texture])\r\n            }\r\n            (img as any).initIO();\r\n\r\n            this.renderPipelineimageIO = img;\r\n\r\n\r\n        }\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "update",
                "returnType": "void",
                "params": [
                  {
                    "name": "pipeline",
                    "type": "Pipeline"
                  }
                ],
                "visibility": "public",
                "rawText": "public update(pipeline: Pipeline): void {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            this.elements[i].resource.update(pipeline);\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "destroy",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public destroy() {\r\n        //console.log(\"bindgroup.destroy\")\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            //console.log(\"this.elements[i] = \", this.elements[i].resource)\r\n            this.elements[i].resource.destroyGpuResource();\r\n        }\r\n        this.elements = [];\r\n    }"
              }
            ],
            "private": [
              {
                "objectType": "method",
                "name": "setupApply",
                "returnType": "void",
                "visibility": "private",
                "rawText": "private setupApply() {\r\n\r\n        this.bindgroupId = this.parent.groups.indexOf(this);\r\n\r\n        const types = this.parent.resources.types;\r\n        if (!types) return;\r\n        const allVertexBuffers = types.vertexBuffers;\r\n        if (!allVertexBuffers) return;\r\n\r\n        const getBufferId = (o) => {\r\n\r\n            if (!this.instances) {\r\n                for (let i = 0; i < allVertexBuffers.length; i++) {\r\n                    if (allVertexBuffers[i].resource === o) return i;\r\n                }\r\n            } else {\r\n                for (let i = 0; i < allVertexBuffers.length; i++) {\r\n                    if (allVertexBuffers[i].resource.nane === o.name) return i;\r\n                }\r\n            }\r\n\r\n            return -1;\r\n        }\r\n\r\n\r\n        this.vertexBuffers = [];\r\n        this.vertexBufferReferenceByName = {};\r\n        let k = 0;\r\n        let element: { name: string, resource: IShaderResource };\r\n        let resource: IShaderResource;\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            element = this.elements[i];\r\n            resource = element.resource;\r\n            if (resource instanceof VertexBuffer) {\r\n\r\n                if (!(resource as VertexBuffer).io) {\r\n                    (resource as VertexBuffer).bufferId = getBufferId(resource);\r\n\r\n                    this.elementByName[element.name] = resource\r\n                    this.vertexBufferReferenceByName[element.name] = { bufferId: (resource as VertexBuffer).bufferId, resource };\r\n                    this.vertexBuffers[k++] = resource;\r\n                    continue;\r\n                }\r\n            } else {\r\n                this.elementByName[element.name] = resource;\r\n            }\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "swapElements",
                "returnType": "{ name: string; resource: IShaderResource; }[]",
                "visibility": "private",
                "rawText": "private swapElements() {\r\n        let result = this.elements.concat();\r\n        let temp;\r\n        for (let i = 0; i < this.elements.length; i += 2) {\r\n            temp = result[i];\r\n            result[i] = result[i + 1];\r\n            result[i + 1] = temp;\r\n        }\r\n        return result;\r\n    }"
              }
            ],
            "protected": [
              {
                "objectType": "method",
                "name": "buildLayout",
                "returnType": "void",
                "visibility": "protected",
                "rawText": "protected buildLayout(): void {\r\n\r\n        this.deviceId = XGPU.deviceId;\r\n\r\n        this.io_index = 0;\r\n        const layout = { entries: [] }\r\n        let bindingId = 0;\r\n        //console.warn(this.elements)\r\n        let resource: IShaderResource;\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            resource = this.elements[i].resource;\r\n            //console.log(i, resource)\r\n\r\n            if (resource instanceof VertexBuffer && !(resource as VertexBuffer).io && this.parent.pipeline.type != \"compute\") continue;\r\n\r\n            let bgl = resource.createBindGroupLayoutEntry(bindingId++);\r\n            //console.log(\"bindgroupLayout entry \", (bindingId - 1), bgl);\r\n            layout.entries.push(bgl);\r\n        }\r\n\r\n        //console.log(\"BINDGROUP LAYOUT ENTRIES \", layout)\r\n        this._layout = XGPU.device.createBindGroupLayout(layout);\r\n    }"
              },
              {
                "objectType": "method",
                "name": "_createInstance",
                "returnType": "void",
                "params": [
                  {
                    "name": "resourcePerInstance",
                    "type": "any"
                  }
                ],
                "visibility": "protected",
                "rawText": "protected _createInstance(resourcePerInstance: any) {\r\n\r\n        resourcePerInstance = HighLevelParser.parse(resourcePerInstance, \"bindgroup\");\r\n\r\n        if (!this.instances) this.instances = [];\r\n\r\n        let indexBuffer: IndexBuffer;\r\n        let vertexBuffers: VertexBuffer[] = [];\r\n        let result: any = {\r\n            elements: this.elements.concat()\r\n        }\r\n\r\n        let element, resource;\r\n        //console.log(\"---- \", vertexBuffers.length)\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            element = this.elements[i];\r\n\r\n            for (let z in resourcePerInstance) {\r\n\r\n                resource = resourcePerInstance[z];\r\n\r\n                if (resource instanceof IndexBuffer) {\r\n                    indexBuffer = resourcePerInstance[z];\r\n                    continue;\r\n                }\r\n\r\n                if (element.name === z) {\r\n\r\n                    if (resource instanceof VideoTexture || resource instanceof ImageTexture) {\r\n                        //keep source descriptor (the \"source\" option in the descriptor refeer to the media, we)\r\n                    } else {\r\n                        //use \"model\" descriptor (some config options are applyed on VertexBuffer/UniformBuffer/...  and we want to keep it for all the instances)\r\n                        //(whzt I call \"model\" is the source bindgroup used to call 'createInstance')\r\n                        resource.descriptor = element.resource.descriptor;\r\n                    }\r\n\r\n\r\n                    if (!resource.gpuResource) {\r\n                        resource.createGpuResource();\r\n                    }\r\n\r\n                    if (element.resource instanceof VertexBuffer) {\r\n\r\n                        resource.bufferId = (element.resource as VertexBuffer).bufferId;\r\n                        if (vertexBuffers.indexOf(resource) === -1) {\r\n                            vertexBuffers.push(resource);\r\n                        }\r\n                    }\r\n\r\n                    result.elements[i] = { name: z, resource: resource };\r\n\r\n                }\r\n            }\r\n        }\r\n\r\n        if (indexBuffer) result.indexBuffer = indexBuffer;\r\n        result.update = () => {\r\n            let bool = false;\r\n            for (let i = 0; i < this.elements.length; i++) {\r\n\r\n                if (this.elements[i].resource.mustBeTransfered) {\r\n                    this.elements[i].resource.update(this.parent.pipeline);\r\n                    bool = true;\r\n                    break;\r\n                }\r\n            }\r\n\r\n\r\n            this.elements = result.elements;\r\n            this.vertexBuffers = vertexBuffers;\r\n\r\n            if (bool || !result.group) {\r\n                result.group = this.build();\r\n            }\r\n            if (result.indexBuffer) this.parent.drawConfig.indexBuffer = result.indexBuffer;\r\n        }\r\n\r\n        resourcePerInstance._object = result;\r\n        this.instances.push(result);\r\n\r\n    }"
              }
            ]
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "params": [
              {
                "name": "descriptor",
                "type": "any"
              }
            ],
            "rawText": "constructor(descriptor?: any | any[]) {\r\n        if (descriptor) this.initFromObject(descriptor);\r\n    }"
          },
          "rawText": "export class Bindgroup {\r\n\r\n    public bindgroupId: number //the id used in renderPass.setBindgroup\r\n\r\n    public parent: Bindgroups;\r\n    public entries: any[] = [];\r\n    public elements: { name: string, resource: IShaderResource }[] = [];\r\n\r\n    public mustRefreshBindgroup: boolean = false;\r\n    public applyDraw: boolean = false;\r\n\r\n\r\n    protected _layout: GPUBindGroupLayout;\r\n    protected _group: GPUBindGroup;\r\n    public name: string = \"\";\r\n\r\n    protected _pingPongBindgroup: Bindgroup = null; //used in ComputePipeline and VertexBufferIO\r\n    public vertexBufferIO: VertexBufferIO;\r\n    public textureIO: ImageTextureIO;\r\n\r\n\r\n    public resourcesIOs: (VertexBufferIO | ImageTextureIO)[] = [];\r\n\r\n\r\n\r\n    constructor(descriptor?: any | any[]) {\r\n        if (descriptor) this.initFromObject(descriptor);\r\n    }\r\n\r\n\r\n\r\n    public add(name: string, resource: IShaderResource): IShaderResource {\r\n        if (resource instanceof VideoTexture) this.mustRefreshBindgroup = true;\r\n        else if (resource instanceof ImageTexture && (resource.source instanceof GPUTexture || !resource.source)) {\r\n            this.mustRefreshBindgroup = true;\r\n\r\n        }\r\n\r\n        if (resource instanceof IndexBuffer) {\r\n            this.indexBuffer = resource;\r\n            this.elementByName[name] = resource;\r\n            return resource;\r\n        }\r\n\r\n\r\n        //console.log(\"bindgroup.add \", resource)\r\n\r\n        if (resource instanceof VertexBufferIO) {\r\n\r\n\r\n            this.resourcesIOs.push(resource);\r\n\r\n\r\n\r\n            this.mustRefreshBindgroup = true;\r\n            this.vertexBufferIO = resource;\r\n            //console.log(\"group vertexBufferIO \", this.vertexBufferIO)\r\n            this.elements.push({ name: name, resource: resource.buffers[0] });\r\n            this.elements.push({ name: name + \"_out\", resource: resource.buffers[1] });\r\n\r\n\r\n            if (this.parent) this.parent.add(this);\r\n            return resource;\r\n        }\r\n\r\n        if (resource instanceof ImageTextureIO) {\r\n\r\n\r\n            this.resourcesIOs.push(resource);\r\n\r\n\r\n\r\n\r\n            this.mustRefreshBindgroup = true;\r\n            this.textureIO = resource;\r\n            this.elements.push({ name: name, resource: resource.textures[0] });\r\n            this.elements.push({ name: name + \"_out\", resource: resource.textures[1] });\r\n\r\n            if (this.parent) this.parent.add(this);\r\n            return resource;\r\n        }\r\n\r\n        if (resource instanceof VideoTexture) {\r\n            resource.addBindgroup(this);\r\n        }\r\n\r\n\r\n\r\n        this.elements.push({ name, resource });\r\n        if (this.parent) this.parent.add(this);\r\n        return resource;\r\n    }\r\n\r\n\r\n\r\n\r\n    public set(name: string, resource: IShaderResource) {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (this.elements[i].name === name) {\r\n                this.elements[i].resource = resource;\r\n            }\r\n        }\r\n    }\r\n\r\n    public remove(name: string) {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (this.elements[i].name === name) {\r\n                this.elements.splice(i, 1);\r\n            }\r\n        }\r\n    }\r\n\r\n    public getResourceName(resource: IShaderResource): string {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (resource === this.elements[i].resource) {\r\n                return this.elements[i].name;\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n\r\n    public get(name: string): IShaderResource {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n\r\n            if (this.elements[i].name === name) return this.elements[i].resource;\r\n        }\r\n\r\n\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (this.elements[i].resource instanceof UniformBuffer) {\r\n\r\n                if ((this.elements[i].resource as UniformBuffer).items[name]) {\r\n                    return this.elements[i].resource\r\n                }\r\n            }\r\n        }\r\n\r\n        return null;\r\n    }\r\n\r\n\r\n    public initFromObject(descriptor: any | any[]): IShaderResource[] {\r\n        //console.log(\"group.initFromObject \", object)\r\n\r\n        let object: any = descriptor;\r\n        let isArray = false;\r\n        if (descriptor instanceof Array) {\r\n            isArray = true;\r\n            object = descriptor[0];\r\n        }\r\n\r\n\r\n        HighLevelParser.parse(object, \"bindgroup\");\r\n\r\n\r\n        const result: IShaderResource[] = [];\r\n        let k = 0;\r\n        let o;\r\n        for (let z in object) {\r\n            o = object[z];\r\n            if (!o) continue;\r\n            //console.log(z + \" : \" + o.create)\r\n            if (o.createGpuResource || o instanceof VertexBufferIO || o instanceof ImageTextureIO) { //if it's a shader resource \r\n                result[k++] = this.add(z, o);\r\n            }\r\n        }\r\n        //console.log(\"object = \", object)\r\n\r\n        if (isArray) {\r\n            for (let i = 0; i < descriptor.length; i++) {\r\n                this.createInstance(descriptor[i]);\r\n            }\r\n        }\r\n\r\n\r\n\r\n        //console.warn(\"bindgroup.initFromObject result = \", result)\r\n        return result;\r\n    }\r\n    //---------------------------------------------------------------------------\r\n\r\n    public clearAfterDeviceLost(): void {\r\n        this._layout = null\r\n        this._group = null;\r\n        this.setupApplyCompleted = false;\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            this.elements[i].resource.destroyGpuResource();\r\n        }\r\n\r\n        if (this.instances) {\r\n            let elements: any, resource: IShaderResource;\r\n            let instance: any;\r\n            for (let i = 0; i < this.instances.length; i++) {\r\n                instance = this.instances[i];\r\n                instance.group = undefined;\r\n                elements = instance.elements;\r\n\r\n                if (instance.indexBuffer) (instance.indexBuffer as IndexBuffer).createGpuResource();\r\n\r\n                for (let j = 0; j < elements.length; j++) {\r\n                    resource = elements[j].resource;\r\n                    //console.log(j, resource)\r\n                    if (resource.gpuResource) {\r\n\r\n                        resource.destroyGpuResource();\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    };\r\n\r\n    protected deviceId: number = 0;\r\n\r\n    protected buildLayout(): void {\r\n\r\n        this.deviceId = XGPU.deviceId;\r\n\r\n        this.io_index = 0;\r\n        const layout = { entries: [] }\r\n        let bindingId = 0;\r\n        //console.warn(this.elements)\r\n        let resource: IShaderResource;\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            resource = this.elements[i].resource;\r\n            //console.log(i, resource)\r\n\r\n            if (resource instanceof VertexBuffer && !(resource as VertexBuffer).io && this.parent.pipeline.type != \"compute\") continue;\r\n\r\n            let bgl = resource.createBindGroupLayoutEntry(bindingId++);\r\n            //console.log(\"bindgroupLayout entry \", (bindingId - 1), bgl);\r\n            layout.entries.push(bgl);\r\n        }\r\n\r\n        //console.log(\"BINDGROUP LAYOUT ENTRIES \", layout)\r\n        this._layout = XGPU.device.createBindGroupLayout(layout);\r\n    }\r\n\r\n    private setupApplyCompleted: boolean = false;\r\n    public build(): GPUBindGroup {\r\n\r\n        if (!this._layout || (this.deviceId != XGPU.deviceId && this.ioGroups)) this.buildLayout();\r\n        this.deviceId = XGPU.deviceId;\r\n        let entries = [];\r\n        let bindingId: number = 0;\r\n        let resource: IShaderResource;\r\n\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            if (!this.elements[i]) continue\r\n            resource = this.elements[i].resource;\r\n            resource.update();\r\n\r\n            if (resource instanceof VertexBuffer && !(resource as VertexBuffer).io && this.parent.pipeline.type != \"compute\") continue;\r\n\r\n            let entry = resource.createBindGroupEntry(bindingId++)\r\n            //console.warn(\"BINDGROUP.BUILD ::: bindgroup entry \", this.elements[i].name, (bindingId - 1), entry);\r\n            entries.push(entry);\r\n        }\r\n\r\n        this._group = XGPU.device.createBindGroup({ layout: this._layout, entries })\r\n\r\n\r\n        if (!this.setupApplyCompleted && this.parent) {\r\n\r\n            this.setupApplyCompleted = true;\r\n            this.setupApply();\r\n\r\n            if (this.instanceResourcesArray) {\r\n                for (let i = 0; i < this.instanceResourcesArray.length; i++) {\r\n                    this._createInstance(this.instanceResourcesArray[i]);\r\n                }\r\n                this.instanceResourcesArray = undefined;\r\n            }\r\n\r\n        }\r\n\r\n        return this._group;\r\n    }\r\n\r\n\r\n    protected indexBuffer: IndexBuffer;\r\n    protected vertexBuffers: VertexBuffer[];\r\n    protected vertexBufferReferenceByName: any;\r\n    protected elementByName: any = {};\r\n\r\n    private setupApply() {\r\n\r\n        this.bindgroupId = this.parent.groups.indexOf(this);\r\n\r\n        const types = this.parent.resources.types;\r\n        if (!types) return;\r\n        const allVertexBuffers = types.vertexBuffers;\r\n        if (!allVertexBuffers) return;\r\n\r\n        const getBufferId = (o) => {\r\n\r\n            if (!this.instances) {\r\n                for (let i = 0; i < allVertexBuffers.length; i++) {\r\n                    if (allVertexBuffers[i].resource === o) return i;\r\n                }\r\n            } else {\r\n                for (let i = 0; i < allVertexBuffers.length; i++) {\r\n                    if (allVertexBuffers[i].resource.nane === o.name) return i;\r\n                }\r\n            }\r\n\r\n            return -1;\r\n        }\r\n\r\n\r\n        this.vertexBuffers = [];\r\n        this.vertexBufferReferenceByName = {};\r\n        let k = 0;\r\n        let element: { name: string, resource: IShaderResource };\r\n        let resource: IShaderResource;\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            element = this.elements[i];\r\n            resource = element.resource;\r\n            if (resource instanceof VertexBuffer) {\r\n\r\n                if (!(resource as VertexBuffer).io) {\r\n                    (resource as VertexBuffer).bufferId = getBufferId(resource);\r\n\r\n                    this.elementByName[element.name] = resource\r\n                    this.vertexBufferReferenceByName[element.name] = { bufferId: (resource as VertexBuffer).bufferId, resource };\r\n                    this.vertexBuffers[k++] = resource;\r\n                    continue;\r\n                }\r\n            } else {\r\n                this.elementByName[element.name] = resource;\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n    public setupDrawCompleted: boolean = false;\r\n    public setupDraw(force: boolean = false) {\r\n\r\n        if (this.vertexBuffers) {\r\n            for (let i = 0; i < this.vertexBuffers.length; i++) {\r\n                if (!this.vertexBuffers[i].gpuResource) {\r\n                    this.vertexBuffers[i].createGpuResource();\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        if (this.parent.drawConfig) { //may be undefined with a computePipeline\r\n\r\n            this.indexBuffer = this.parent.drawConfig.indexBuffer;\r\n            if (force || (!this.indexBuffer && this.parent.drawConfig.vertexCount <= 0)) {\r\n\r\n                if (!force && !this.parent.resources.types.vertexBuffers) {\r\n                    throw new Error(\"a renderPipeline require a vertexBuffer or a drawConfig object in order to draw. You must add a vertexBuffer or call RenderPipeline.setupDraw\")\r\n                }\r\n\r\n                const buffers = this.parent.resources.types.vertexBuffers;\r\n                let buf: VertexBuffer;\r\n                for (let i = 0; i < buffers.length; i++) {\r\n                    buf = buffers[i].resource as VertexBuffer;\r\n                    if (buf.descriptor.stepMode === \"vertex\") {\r\n                        this.parent.drawConfig.vertexCount = this.parent.resources.types.vertexBuffers[i].resource.nbVertex;\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n\r\n\r\n    public apply(renderPass: GPURenderPassEncoder | GPUComputePassEncoder) {\r\n\r\n        if (!this.setupDrawCompleted) {\r\n            this.setupDrawCompleted = true;\r\n            if (undefined === this.bindgroupId) {\r\n                this.bindgroupId = this.parent.groups.indexOf(this);\r\n            }\r\n            this.setupDraw();\r\n        }\r\n\r\n        if (renderPass instanceof GPUComputePassEncoder) {\r\n            this.update(this.parent.pipeline);\r\n\r\n            renderPass.setBindGroup(this.bindgroupId, this.group);\r\n            return;\r\n        }\r\n\r\n\r\n        const instances = this.instances ? this.instances : [{ group: this.group, update: () => { } }]\r\n        const applyDraw = this.applyDraw;\r\n\r\n        //console.log(\"instances.length = \", instances.length)\r\n        for (let i = 0; i < instances.length; i++) {\r\n\r\n            instances[i].update();\r\n            this.update(this.parent.pipeline);\r\n\r\n            renderPass.setBindGroup(this.bindgroupId, instances[i].group);\r\n\r\n            if (this.vertexBuffers) {\r\n\r\n                let buf: any;\r\n                for (let j = 0; j < this.vertexBuffers.length; j++) {\r\n\r\n                    buf = this.vertexBuffers[j].getCurrentBuffer();\r\n                    renderPass.setVertexBuffer(this.vertexBuffers[j].bufferId, buf);\r\n                }\r\n            }\r\n\r\n            if (applyDraw) {\r\n                this.parent.drawConfig.draw(renderPass);\r\n            }\r\n\r\n        }\r\n\r\n    }\r\n\r\n    protected instances: any[];\r\n    protected instanceResourcesArray: any[];\r\n\r\n    public get useInstances(): boolean { return !!this.instances || !!this.instanceResourcesArray };\r\n\r\n    public createInstance(instanceResources: any) {\r\n        if (!this.instanceResourcesArray) this.instanceResourcesArray = [];\r\n        this.instanceResourcesArray.push(instanceResources)\r\n    }\r\n\r\n    protected _createInstance(resourcePerInstance: any) {\r\n\r\n        resourcePerInstance = HighLevelParser.parse(resourcePerInstance, \"bindgroup\");\r\n\r\n        if (!this.instances) this.instances = [];\r\n\r\n        let indexBuffer: IndexBuffer;\r\n        let vertexBuffers: VertexBuffer[] = [];\r\n        let result: any = {\r\n            elements: this.elements.concat()\r\n        }\r\n\r\n        let element, resource;\r\n        //console.log(\"---- \", vertexBuffers.length)\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            element = this.elements[i];\r\n\r\n            for (let z in resourcePerInstance) {\r\n\r\n                resource = resourcePerInstance[z];\r\n\r\n                if (resource instanceof IndexBuffer) {\r\n                    indexBuffer = resourcePerInstance[z];\r\n                    continue;\r\n                }\r\n\r\n                if (element.name === z) {\r\n\r\n                    if (resource instanceof VideoTexture || resource instanceof ImageTexture) {\r\n                        //keep source descriptor (the \"source\" option in the descriptor refeer to the media, we)\r\n                    } else {\r\n                        //use \"model\" descriptor (some config options are applyed on VertexBuffer/UniformBuffer/...  and we want to keep it for all the instances)\r\n                        //(whzt I call \"model\" is the source bindgroup used to call 'createInstance')\r\n                        resource.descriptor = element.resource.descriptor;\r\n                    }\r\n\r\n\r\n                    if (!resource.gpuResource) {\r\n                        resource.createGpuResource();\r\n                    }\r\n\r\n                    if (element.resource instanceof VertexBuffer) {\r\n\r\n                        resource.bufferId = (element.resource as VertexBuffer).bufferId;\r\n                        if (vertexBuffers.indexOf(resource) === -1) {\r\n                            vertexBuffers.push(resource);\r\n                        }\r\n                    }\r\n\r\n                    result.elements[i] = { name: z, resource: resource };\r\n\r\n                }\r\n            }\r\n        }\r\n\r\n        if (indexBuffer) result.indexBuffer = indexBuffer;\r\n        result.update = () => {\r\n            let bool = false;\r\n            for (let i = 0; i < this.elements.length; i++) {\r\n\r\n                if (this.elements[i].resource.mustBeTransfered) {\r\n                    this.elements[i].resource.update(this.parent.pipeline);\r\n                    bool = true;\r\n                    break;\r\n                }\r\n            }\r\n\r\n\r\n            this.elements = result.elements;\r\n            this.vertexBuffers = vertexBuffers;\r\n\r\n            if (bool || !result.group) {\r\n                result.group = this.build();\r\n            }\r\n            if (result.indexBuffer) this.parent.drawConfig.indexBuffer = result.indexBuffer;\r\n        }\r\n\r\n        resourcePerInstance._object = result;\r\n        this.instances.push(result);\r\n\r\n    }\r\n\r\n    public handleComputePipelineResourceIOs() {\r\n\r\n        if (this.resourcesIOs.length) {\r\n            let buf0 = [];\r\n            let buf1 = [];\r\n            for (let i = 0; i < this.resourcesIOs.length; i++) {\r\n                if (this.resourcesIOs[i] instanceof VertexBufferIO) {\r\n\r\n                    buf0[i] = (this.resourcesIOs[i] as VertexBufferIO).buffers[0];\r\n                    buf1[i] = (this.resourcesIOs[i] as VertexBufferIO).buffers[1];\r\n\r\n                } else {\r\n                    buf0[i] = (this.resourcesIOs[i] as ImageTextureIO).textures[0];\r\n                    buf1[i] = (this.resourcesIOs[i] as ImageTextureIO).textures[1];\r\n\r\n\r\n                }\r\n\r\n                buf0[i].createGpuResource();\r\n                buf1[i].createGpuResource();\r\n            }\r\n\r\n            this.createPingPongBindgroup(buf0, buf1);\r\n        }\r\n    }\r\n\r\n\r\n    private swapElements() {\r\n        let result = this.elements.concat();\r\n        let temp;\r\n        for (let i = 0; i < this.elements.length; i += 2) {\r\n            temp = result[i];\r\n            result[i] = result[i + 1];\r\n            result[i + 1] = temp;\r\n        }\r\n        return result;\r\n    }\r\n\r\n    public createPingPongBindgroup(resource1: IShaderResource[], resource2: IShaderResource[]): Bindgroup {\r\n        const group = new Bindgroup();\r\n        group.name = this.name;\r\n        group.mustRefreshBindgroup = this.mustRefreshBindgroup = true;\r\n        group._layout = this.layout;\r\n\r\n        //console.log(\"createPingPong\")\r\n        group.elements = this.swapElements();\r\n\r\n        let res1, res2;\r\n        for (let i = 0; i < resource1.length; i++) {\r\n            res1 = resource1[i];\r\n            res2 = resource2[i];\r\n\r\n            if (res1 instanceof VertexBuffer) {\r\n\r\n                const buffers = [res1.buffer, (res2 as VertexBuffer).buffer];\r\n                (buffers[0] as any).debug = 1;\r\n                (buffers[1] as any).debug = 2;\r\n\r\n                res1.initBufferIO(buffers);\r\n            } else if (res1 instanceof ImageTexture) {\r\n\r\n                if (!res1.gpuResource) res1.createGpuResource();\r\n                if (!res2.gpuResource) res2.createGpuResource();\r\n\r\n                const textures = [res1.gpuResource, res2.gpuResource];\r\n                try {\r\n                    (textures[0] as any).debug = 1;\r\n                    (textures[1] as any).debug = 2;\r\n                } catch (e) {\r\n\r\n                }\r\n\r\n                res1.initTextureIO(textures);\r\n            }\r\n        }\r\n\r\n        this.ioGroups = [group, this];\r\n        //this.ioGroups = [this, group];\r\n        this.debug = 1;\r\n        group.debug = 2;\r\n\r\n        return group;\r\n\r\n    }\r\n\r\n\r\n\r\n\r\n    /*\r\n    -------------OLD VERSION-----------\r\n    public createPingPongBindgroup(resource1: IShaderResource, resource2: IShaderResource): Bindgroup {\r\n        const group = new Bindgroup(this.name);\r\n        group.mustRefreshBindgroup = this.mustRefreshBindgroup = true;\r\n        group._layout = this.layout;\r\n        group.elements = this.getSwappedElements(resource1, resource2);\r\n        //console.log(\"=> group.elements \", group.elements)\r\n\r\n\r\n\r\n        if (resource1 instanceof VertexBuffer) {\r\n\r\n            const buffers = [resource1.buffer, (resource2 as VertexBuffer).buffer];\r\n            (buffers[0] as any).debug = 1;\r\n            (buffers[1] as any).debug = 2;\r\n\r\n            resource1.initBufferIO(buffers);\r\n        } else if (resource1 instanceof ImageTexture) {\r\n\r\n            if (!resource1.gpuResource) resource1.createGpuResource();\r\n            if (!resource2.gpuResource) resource2.createGpuResource();\r\n\r\n            //console.log(resource1, resource2)\r\n            //console.log(resource1.gpuResource === resource2.gpuResource)\r\n\r\n            const textures = [resource1.gpuResource, resource2.gpuResource];\r\n            try {\r\n                (textures[0] as any).debug = 1;\r\n                (textures[1] as any).debug = 2;\r\n            } catch (e) {\r\n\r\n            }\r\n\r\n\r\n\r\n            resource1.initTextureIO(textures);\r\n        }\r\n\r\n        this.ioGroups = [this, group];\r\n        //console.log(this.ioGroups)\r\n        this.debug = 1;\r\n        group.debug = 2;\r\n\r\n        return group;\r\n\r\n    }\r\n    */\r\n\r\n\r\n    protected renderPipelineimageIO: ImageTexture;\r\n    protected renderPipelineBufferIO: VertexBuffer;\r\n\r\n    public handleRenderPipelineResourceIOs() {\r\n\r\n        //console.warn(\"handleRenderPipelineResourceIOs \", this.elements.length, this.textureIO)\r\n\r\n        if (this.renderPipelineimageIO) {\r\n            (this.renderPipelineimageIO as any).initIO();\r\n            return\r\n        } else if (this.renderPipelineBufferIO) {\r\n            (this.renderPipelineBufferIO as any).initIO();\r\n            return\r\n        }\r\n\r\n        //a vertexBufferIO uses 2 vertexBuffers in a computePipeline \r\n        //but a single one is required in a renderPipeline (same for textures)   \r\n        let resource: IShaderResource;\r\n        let name: string;\r\n        let bufferIOs: VertexBuffer[] = [];\r\n        let textureIOs: ImageTexture[] = [];\r\n\r\n        let parentResources: any = this.parent.resources;\r\n        let foundVertexIO: boolean = false;\r\n        let foundTextureIO: boolean = false;\r\n\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            //console.log(i, this.elements[i], this.parent.pipeline);\r\n            resource = this.elements[i].resource;\r\n            if (resource instanceof VertexBuffer) {\r\n                if (resource.io === 1) {\r\n                    name = this.elements[i].name;\r\n                    parentResources[name] = undefined;\r\n                    parentResources[name + \"_out\"] = undefined;\r\n\r\n                    bufferIOs.push(resource);\r\n                    bufferIOs.push(this.elements[i + 1].resource as VertexBuffer);\r\n                    this.elements.splice(i, 2);\r\n                    foundVertexIO = true;\r\n                    break;\r\n                }\r\n            } else if (resource instanceof ImageTexture) {\r\n\r\n                if (resource.io === 1) {\r\n                    name = this.elements[i].name;\r\n                    parentResources[name] = undefined;\r\n                    parentResources[name + \"_out\"] = undefined;\r\n                    //console.log(\"this.elements[i + 1] = \", this.elements[i + 1])\r\n                    textureIOs.push(resource);\r\n                    textureIOs.push(this.elements[i + 1].resource as ImageTexture);\r\n                    this.elements.splice(i, 2);\r\n                    foundTextureIO = true;\r\n                    break;\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        if (foundVertexIO) {\r\n            //console.log(\"foundVertexIO\")\r\n            //console.log(\"bufferIOs = \", bufferIOs)\r\n            const attributes = bufferIOs[0].attributeDescriptor;\r\n            const stepMode = bufferIOs[0].descriptor.stepMode;\r\n            const vb: VertexBuffer = new VertexBuffer(attributes, { stepMode });\r\n            this.elements.push({ name, resource: vb })\r\n\r\n            let vertexBuffers = parentResources.types.vertexBuffers;\r\n            let buffers: { name: string, resource: VertexBuffer }[] = [];\r\n            for (let i = 0; i < vertexBuffers.length; i++) {\r\n                if (!vertexBuffers[i].resource.io) {\r\n                    buffers.push(vertexBuffers[i]);\r\n                }\r\n            }\r\n            buffers.push({ name, resource: vb });\r\n\r\n            parentResources[name] = vb;\r\n            parentResources.types.vertexBuffers = buffers;\r\n\r\n            (vb as any).initIO = () => {\r\n                vb.initBufferIO([bufferIOs[0].buffer, bufferIOs[1].buffer])\r\n            }\r\n            (vb as any).initIO();\r\n            this.renderPipelineBufferIO = vb;\r\n\r\n\r\n        } else if (foundTextureIO) {\r\n\r\n            //console.log(\"foundTextureIO\")\r\n\r\n            const img = new ImageTexture({ source: textureIOs[0].gpuResource })\r\n            this.elements.push({ name, resource: img })\r\n\r\n            let images = parentResources.types.imageTextures;\r\n            let textures: { name: string, resource: ImageTexture }[] = [];\r\n            for (let i = 0; i < images.length; i++) {\r\n                if (!images[i].resource.io) {\r\n                    textures.push(images[i]);\r\n                }\r\n            }\r\n            textures.push({ name, resource: img });\r\n\r\n            parentResources[name] = img;\r\n            parentResources.types.imageTextures = images;\r\n\r\n            (img as any).initIO = () => {\r\n                //console.log(\"initIO \", textureIOs[0].deviceId, textureIOs[1].deviceId)\r\n                img.source = textureIOs[0].texture;\r\n                img.initTextureIO([textureIOs[0].texture, textureIOs[1].texture])\r\n            }\r\n            (img as any).initIO();\r\n\r\n            this.renderPipelineimageIO = img;\r\n\r\n\r\n        }\r\n\r\n    }\r\n\r\n\r\n    protected ioGroups: Bindgroup[];\r\n\r\n    protected io_index: number = 0;\r\n    public debug: any;\r\n\r\n\r\n\r\n    public get pingPongBindgroup(): Bindgroup {\r\n        return this._pingPongBindgroup;\r\n    }\r\n\r\n\r\n    public get layout(): GPUBindGroupLayout {\r\n        if (!this._layout) this.buildLayout();\r\n        return this._layout;\r\n    }\r\n    public get group(): GPUBindGroup {\r\n\r\n        if (!this._group || this.mustRefreshBindgroup) {\r\n            this.build();\r\n        }\r\n\r\n        if (this.ioGroups) {\r\n            const group = this.ioGroups[this.io_index++ % 2];\r\n            if (!group._group) group.build();\r\n            return group._group;\r\n        }\r\n\r\n\r\n\r\n        return this._group;\r\n    }\r\n\r\n    public update(pipeline: Pipeline): void {\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            this.elements[i].resource.update(pipeline);\r\n        }\r\n    }\r\n\r\n\r\n    public destroy() {\r\n        //console.log(\"bindgroup.destroy\")\r\n        for (let i = 0; i < this.elements.length; i++) {\r\n            //console.log(\"this.elements[i] = \", this.elements[i].resource)\r\n            this.elements[i].resource.destroyGpuResource();\r\n        }\r\n        this.elements = [];\r\n    }\r\n}"
        }
      ],
      "Bindgroups": [
        {
          "objectType": "class",
          "name": "Bindgroups",
          "filePath": "xGPU.shader.Bindgroups",
          "properties": {
            "public": [
              {
                "objectType": "property",
                "name": "pipeline",
                "type": "Pipeline",
                "visibility": "public",
                "rawText": "public pipeline: Pipeline;"
              },
              {
                "objectType": "property",
                "name": "parent",
                "type": "Bindgroups",
                "visibility": "public",
                "rawText": "public parent: Bindgroups;"
              },
              {
                "objectType": "property",
                "name": "groups",
                "type": "Bindgroup[]",
                "visibility": "public",
                "rawText": "public groups: Bindgroup[] = [];"
              },
              {
                "objectType": "property",
                "name": "name",
                "type": "string",
                "visibility": "public",
                "rawText": "public get name(): string { return this._name; }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "resources",
                "type": "any",
                "visibility": "public",
                "rawText": "public get resources(): any { return this._resources }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "drawConfig",
                "type": "DrawConfig",
                "visibility": "public",
                "rawText": "public get drawConfig(): DrawConfig {\r\n\r\n        return (this.pipeline as any).drawConfig || null\r\n    }",
                "get": true
              },
              {
                "objectType": "property",
                "name": "current",
                "type": "Bindgroup",
                "visibility": "public",
                "rawText": "public get current(): Bindgroup {\r\n        return this.groups[this.groups.length - 1]\r\n    }",
                "get": true
              }
            ],
            "private": [
              {
                "objectType": "property",
                "name": "_name",
                "type": "string",
                "visibility": "private",
                "rawText": "private _name: string;"
              }
            ],
            "protected": [
              {
                "objectType": "property",
                "name": "temp",
                "type": "{ result: string; variables: string; }",
                "visibility": "protected",
                "rawText": "protected temp: { result: string, variables: string };"
              },
              {
                "objectType": "property",
                "name": "_resources",
                "type": "any",
                "visibility": "protected",
                "rawText": "protected _resources: any = {};"
              }
            ]
          },
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "clearAfterDeviceLost",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public clearAfterDeviceLost() {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].clearAfterDeviceLost();\r\n        }\r\n\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "build",
                "returnType": "{ description: any; bindgroups: GPUBindGroup[]; buffers: VertexBuffer[]; nbVertex: number; }",
                "params": [
                  {
                    "name": "autoLayout",
                    "type": "boolean"
                  }
                ],
                "visibility": "public",
                "rawText": "public build(autoLayout: boolean = false) {\r\n\r\n        const description: any = {};\r\n        const layouts: GPUBindGroupLayout[] = [];\r\n        const bindgroups: GPUBindGroup[] = [];\r\n\r\n\r\n        this.groups = this.groups.sort((a: Bindgroup, b: Bindgroup) => {\r\n            if (a.useInstances && !b.useInstances) return 1;\r\n            if (!a.useInstances && b.useInstances) return -1;\r\n            return 0;\r\n        })\r\n\r\n        if (this.groups.length) {\r\n            this.groups[this.groups.length - 1].applyDraw = true;\r\n        } else {\r\n            this.groups[0] = new Bindgroup();\r\n            this.groups[0].parent = this;\r\n            this.groups[0].applyDraw = true;\r\n        }\r\n\r\n\r\n\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            //console.log(i, \" group = \", this.groups[i])\r\n            if (!autoLayout) layouts[i] = this.groups[i].layout;\r\n            bindgroups[i] = this.groups[i].group;\r\n        }\r\n\r\n        if (autoLayout) description.layout = \"auto\";\r\n        else {\r\n            //console.log(\"pipelineLayout = \", layouts)\r\n            description.layout = XGPU.createPipelineLayout({ bindGroupLayouts: layouts });\r\n        }\r\n\r\n\r\n        const { vertexLayouts, buffers, nbVertex } = this.createVertexBufferLayout();\r\n\r\n        //console.log(this.pipeline.type,vertexLayouts)\r\n\r\n        description.vertex = {\r\n            buffers: vertexLayouts\r\n        }\r\n\r\n        return {\r\n            description,\r\n            bindgroups,\r\n            buffers,\r\n            nbVertex\r\n        }\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getBindgroupByResource",
                "returnType": "Bindgroup",
                "params": [
                  {
                    "name": "resource",
                    "type": "IShaderResource"
                  }
                ],
                "visibility": "public",
                "rawText": "public getBindgroupByResource(resource: IShaderResource): Bindgroup {\r\n        let group: Bindgroup, element: IShaderResource;\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            for (let j = 0; j < group.elements.length; j++) {\r\n                element = group.elements[j].resource;\r\n                if (element === resource) return group;\r\n            }\r\n        }\r\n        return null;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "apply",
                "returnType": "void",
                "params": [
                  {
                    "name": "passEncoder",
                    "type": "any"
                  }
                ],
                "visibility": "public",
                "rawText": "public apply(passEncoder: GPURenderPassEncoder | GPUComputePassEncoder): void {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].apply(passEncoder)\r\n        }\r\n        /*if (passEncoder instanceof GPURenderPassEncoder) {\r\n            this.drawConfig.draw(passEncoder);\r\n        }*/\r\n\r\n    }"
              },
              {
                "objectType": "method",
                "name": "update",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public update(): void {\r\n        //console.log(\"Bindgroups.update groupLen = \", this.groups.length)\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].update(this.pipeline);\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getVertexShaderDeclaration",
                "returnType": "{ result: string; variables: string; }",
                "params": [
                  {
                    "name": "fromFragmentShader",
                    "type": "boolean"
                  }
                ],
                "visibility": "public",
                "rawText": "public getVertexShaderDeclaration(fromFragmentShader: boolean = false): { result: string, variables: string } {\r\n        if (fromFragmentShader) return this.temp;\r\n        //console.log(\"getVertexShaderDeclaration\")\r\n        let result: string = \"\";\r\n        let group: Bindgroup;\r\n        let resources: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let name: string;\r\n        let k: number = 0;\r\n\r\n        const obj = { result: \"\", variables: \"\" };\r\n\r\n        /*\r\n        const structNames: string[] = [];\r\n        const removeAlreadyDefinedStruct = (source: string) => {\r\n            let lines: string[] = source.split(\"\\n\");\r\n            let result: string = \"\";\r\n            let openStruct: boolean = false;\r\n            let canWrite: boolean = true;\r\n            let line: string;\r\n            let delay: number = 0;\r\n\r\n            for (let i = 0; i < lines.length; i++) {\r\n                line = lines[i].trim();\r\n\r\n                if (line.substring(0, \"struct \".length) === \"struct \") {\r\n                    const name = line.split(\" \")[1].split(\"{\")[0];\r\n                    openStruct = true;\r\n                    if (structNames.indexOf(name) === -1) {\r\n                        structNames.push(name);\r\n                        canWrite = true;\r\n                    } else {\r\n                        canWrite = false;\r\n                    }\r\n                } else {\r\n                    if (openStruct && line.indexOf(\"}\") !== -1) {\r\n                        openStruct = false;\r\n                        if (!canWrite) delay = 1;\r\n                        canWrite = true;\r\n                    }\r\n                }\r\n\r\n                if (canWrite && delay-- <= 0) result += lines[i] + \"\\n\";\r\n            }\r\n\r\n            return result;\r\n        }\r\n        */\r\n        //---------------\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            resources = group.elements;\r\n            k = 0;\r\n            for (let j = 0; j < resources.length; j++) {\r\n\r\n                //console.log(i, j, resources[j]);\r\n\r\n                resource = resources[j].resource;\r\n                if (resource instanceof VertexBuffer) continue;\r\n                name = resources[j].name;\r\n\r\n\r\n                if (resource instanceof UniformBuffer) {\r\n\r\n                    /*if (resource.group.name) {\r\n                        resource.group = resource.group.clone();\r\n                        resource.group.name = undefined;\r\n                    }*/\r\n\r\n                    const s: { struct: string, localVariables: string } = resource.createStruct(name);\r\n                    obj.variables += s.localVariables;\r\n                    //result += removeAlreadyDefinedStruct(s.struct);\r\n                    result += s.struct;\r\n\r\n                }\r\n\r\n                result += resource.createDeclaration(name, k++, i) + \"\\n\";\r\n\r\n\r\n\r\n\r\n            }\r\n\r\n        }\r\n        obj.result = result;\r\n        this.temp = obj;\r\n        return obj;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getFragmentShaderDeclaration",
                "returnType": "{ result: string; variables: string; }",
                "visibility": "public",
                "rawText": "public getFragmentShaderDeclaration(): { result: string, variables: string } {\r\n        let result: string = \"\";\r\n        let group: Bindgroup;\r\n        let resources: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let name: string;\r\n        let k: number = 0;\r\n\r\n        const obj = { result: \"\", variables: \"\" };\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            resources = group.elements;\r\n            k = 0;\r\n            for (let j = 0; j < resources.length; j++) {\r\n                resource = resources[j].resource;\r\n                if (resource instanceof VertexBuffer) continue;\r\n                name = resources[j].name;\r\n                if (resource instanceof UniformBuffer) {\r\n                    let item;\r\n                    for (let z in resource.items) {\r\n                        item = resource.items[z];\r\n                        let _name = name.substring(0, 1).toLowerCase() + name.slice(1);\r\n                        if (item.propertyNames) result += item.createStruct() + \"\\n\";\r\n                        if (item.createVariableInsideMain) obj.variables += item.createVariable(_name) + \"\\n\"\r\n                    }\r\n                    result += resource.createStruct(name).struct + \"\\n\";\r\n\r\n                }\r\n                result += resource.createDeclaration(name, k++, i) + \"\\n\";\r\n            }\r\n        }\r\n        obj.result = result;\r\n        return obj;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getComputeShaderDeclaration",
                "returnType": "{ result: string; variables: string; }",
                "visibility": "public",
                "rawText": "public getComputeShaderDeclaration(): { result: string, variables: string } {\r\n        let result: string = \"\";\r\n        let group: Bindgroup;\r\n        let resources: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let name: string;\r\n        let k: number = 0;\r\n\r\n        const obj = { result: \"\", variables: \"\" };\r\n        //console.log(\"#################################################################\")\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            //console.log(group)\r\n            resources = group.elements;\r\n            k = 0;\r\n            for (let j = 0; j < resources.length; j++) {\r\n                resource = resources[j].resource;\r\n                name = resources[j].name;\r\n\r\n                if (resource instanceof VertexBuffer) {\r\n\r\n\r\n\r\n\r\n                } else if (resource instanceof UniformBuffer) {\r\n                    //console.log(resource)\r\n                    let item;\r\n                    for (let z in resource.items) {\r\n                        item = resource.items[z];\r\n                        let _name = name.substring(0, 1).toLowerCase() + name.slice(1);\r\n                        //if (item.propertyNames) result += item.createStruct() + \"\\n\";\r\n                        if (item.createVariableInsideMain) obj.variables += item.createVariable(_name) + \"\\n\"\r\n                    }\r\n\r\n                    const struct = resource.createStruct(name).struct + \"\\n\";\r\n                    //console.log(\" struct => \", struct)\r\n                    result += struct;\r\n                }\r\n\r\n                const declaration = resource.createDeclaration(name, k++, i) + \"\\n\"\r\n                //console.log(\"declaration = \", declaration)\r\n                result += declaration;\r\n            }\r\n        }\r\n\r\n        //console.log(\"getComputeShaderDeclaration result = \", result)\r\n        //console.log(\"#################################################################\")\r\n        obj.result = result;\r\n        return obj;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "handleRenderPipelineResourceIOs",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public handleRenderPipelineResourceIOs() {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].handleRenderPipelineResourceIOs();\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "handleComputePipelineResourceIOs",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public handleComputePipelineResourceIOs() {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            //console.log(i, this.groups[i])\r\n            this.groups[i].handleComputePipelineResourceIOs();\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "add",
                "returnType": "Bindgroups | Bindgroup",
                "params": [
                  {
                    "name": "bindgroup",
                    "type": "Bindgroups | Bindgroup"
                  }
                ],
                "visibility": "public",
                "rawText": "public add(bindgroup: Bindgroup | Bindgroups): (Bindgroup | Bindgroups) {\r\n\r\n        bindgroup.parent = this;\r\n        let resource = this._resources\r\n        if (!this._resources.all) this._resources.all = [];\r\n        if (!this._resources.types) this._resources.types = {};\r\n\r\n        const types = this._resources.types;\r\n\r\n        //console.warn(\"add bindgroup \", bindgroup)\r\n\r\n\r\n        const addResources = (res: any, elements: { name: string, resource: IShaderResource }[]) => {\r\n            //console.warn(\"call addResource \", elements)\r\n            let element: { name: string, resource: IShaderResource };\r\n            let r: IShaderResource;\r\n            for (let i = 0; i < elements.length; i++) {\r\n                element = elements[i];\r\n                //console.log(element.name)\r\n                if (res[element.name]) continue;\r\n                //console.log(\"addResources \", i, element)\r\n                r = element.resource;\r\n                if (this._resources.all.indexOf(r) === -1) this._resources.all.push(r);\r\n                res[element.name] = element.resource;\r\n\r\n                if (r instanceof DepthTextureArray) {\r\n                    if (!types.depthTextureArrays) types.depthTextureArrays = [];\r\n                    if (types.depthTextureArrays.indexOf(element) === -1) types.depthTextureArrays.push(element);\r\n                } else if (r instanceof CubeMapTextureArray) {\r\n                    if (!types.cubeMapTextureArrays) types.cubeMapTextureArrays = [];\r\n                    if (types.cubeMapTextureArrays.indexOf(element) === -1) types.cubeMapTextureArrays.push(element);\r\n                } else if (r instanceof ImageTextureArray) {\r\n                    if (!types.imageTextureArrays) types.imageTextureArrays = [];\r\n                    if (types.imageTextureArrays.indexOf(element) === -1) types.imageTextureArrays.push(element);\r\n                } else if (r instanceof UniformBuffer) {\r\n                    if (!types.uniformBuffers) types.uniformBuffers = [];\r\n                    if (types.uniformBuffers.indexOf(element) === -1) types.uniformBuffers.push(element);\r\n                } else if (r instanceof VertexBuffer) {\r\n                    if (!types.vertexBuffers) types.vertexBuffers = [];\r\n                    if (types.vertexBuffers.indexOf(element) === -1) types.vertexBuffers.push(element);\r\n                } else if (r instanceof CubeMapTexture) {\r\n                    if (!types.cubeMapTexture) types.cubeMapTexture = [];\r\n                    if (types.cubeMapTexture.indexOf(element) === -1) types.cubeMapTexture.push(element);\r\n                } else if (r instanceof ImageTexture) {\r\n                    if (!types.imageTextures) types.imageTextures = [];\r\n                    if (types.imageTextures.indexOf(element) === -1) types.imageTextures.push(element);\r\n                } else if (r instanceof VideoTexture) {\r\n                    if (!types.videoTexture) types.videoTexture = [];\r\n                    if (types.videoTexture.indexOf(element) === -1) types.videoTexture.push(element);\r\n                } else if (r instanceof TextureSampler) {\r\n                    if (!types.sampler) types.sampler = [];\r\n                    if (types.sampler.indexOf(element) === -1) types.sampler.push(element);\r\n                } else if (r instanceof DepthStencilTexture) {\r\n                    if (!types.depthStencilTextures) types.depthStencilTextures = [];\r\n                    if (types.depthStencilTextures.indexOf(element) === -1) types.depthStencilTextures.push(element);\r\n                }\r\n\r\n            }\r\n\r\n            //console.log(\"this.resources = \", this.resources.all.length)\r\n        }\r\n\r\n\r\n        const addGroup = (o: Bindgroup) => {\r\n            //console.log(\"addGroup \", o.name, o.elements)\r\n            const res: any = resource[o.name] = {};\r\n            if (!res.types) res.types = {};\r\n\r\n            addResources(res, o.elements)\r\n\r\n            this.groups.push(o);\r\n        }\r\n\r\n\r\n        if (bindgroup instanceof Bindgroup) {\r\n            if (this.groups.indexOf(bindgroup) === -1) addGroup(bindgroup);\r\n            else {\r\n                //console.log(\"=> \", bindgroup.name)\r\n                addResources(resource[bindgroup.name], bindgroup.elements)\r\n            }\r\n        } else {\r\n            bindgroup.pipeline = this.pipeline;\r\n            resource = resource[bindgroup.name] = {};\r\n            let o;\r\n            for (let i = 0; i < bindgroup.groups.length; i++) {\r\n                o = bindgroup.groups[i];\r\n                if (this.groups.indexOf(o) === -1) addGroup(o);\r\n            }\r\n        }\r\n\r\n        return bindgroup;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "copy",
                "returnType": "Bindgroups",
                "params": [
                  {
                    "name": "options",
                    "type": "{ oldGroups: Bindgroup[]; replacedGroup: Bindgroup[]; }"
                  }
                ],
                "visibility": "public",
                "rawText": "public copy(options?: { oldGroups: Bindgroup[], replacedGroup: Bindgroup[] }): Bindgroups {\r\n        const obj = new Bindgroups(this.pipeline, this._name);\r\n        const groups = this.groups.concat();\r\n        if (options) {\r\n            for (let i = 0; i < options.oldGroups.length; i++) {\r\n                groups.splice(groups.indexOf(options.oldGroups[i]), 1, options.replacedGroup[i]);\r\n            }\r\n        }\r\n\r\n        obj.groups = groups;\r\n        return obj;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "propertyNameIsUsed",
                "returnType": "boolean",
                "params": [
                  {
                    "name": "propertyName",
                    "type": "string"
                  }
                ],
                "visibility": "public",
                "rawText": "public propertyNameIsUsed(propertyName: string): boolean {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            if (this.groups[i].get(propertyName)) return true\r\n        }\r\n        return false;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "get",
                "returnType": "IShaderResource",
                "params": [
                  {
                    "name": "propertyName",
                    "type": "string"
                  }
                ],
                "visibility": "public",
                "rawText": "public get(propertyName: string): IShaderResource {\r\n        let o: IShaderResource;\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            o = this.groups[i].get(propertyName);\r\n            if (o) return o;\r\n        }\r\n        return null;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getGroupByPropertyName",
                "returnType": "Bindgroup",
                "params": [
                  {
                    "name": "name",
                    "type": "string"
                  }
                ],
                "visibility": "public",
                "rawText": "public getGroupByPropertyName(name: string): Bindgroup {\r\n        let o: IShaderResource;\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            o = this.groups[i].get(name);\r\n            if (o) return this.groups[i];\r\n        }\r\n        return null;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getGroupByName",
                "returnType": "Bindgroup",
                "params": [
                  {
                    "name": "name",
                    "type": "string"
                  }
                ],
                "visibility": "public",
                "rawText": "public getGroupByName(name: string): Bindgroup {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            if (this.groups[i].name === name) return this.groups[i];\r\n        }\r\n        return null;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "getNameByResource",
                "returnType": "string",
                "params": [
                  {
                    "name": "resource",
                    "type": "PrimitiveFloatUniform | PrimitiveIntUniform | PrimitiveUintUniform | IShaderResource"
                  }
                ],
                "visibility": "public",
                "rawText": "public getNameByResource(resource: IShaderResource | PrimitiveFloatUniform | PrimitiveIntUniform | PrimitiveUintUniform): string {\r\n\r\n        if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n            return resource.name;\r\n        }\r\n\r\n\r\n        let elements: { name: string, resource: IShaderResource }[];\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            elements = this.groups[i].elements;\r\n            for (let j = 0; j < elements.length; j++) {\r\n                if (elements[j].resource === resource) {\r\n                    return elements[j].name;\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n\r\n\r\n        return null;\r\n    }"
              },
              {
                "objectType": "method",
                "name": "setupDraw",
                "returnType": "void",
                "params": [
                  {
                    "name": "force",
                    "type": "boolean"
                  }
                ],
                "visibility": "public",
                "rawText": "public setupDraw(force: boolean = false) {\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            if (!this.groups[i].setupDrawCompleted) {\r\n                this.groups[i].setupDraw(force);\r\n            }\r\n        }\r\n    }"
              },
              {
                "objectType": "method",
                "name": "destroy",
                "returnType": "void",
                "visibility": "public",
                "rawText": "public destroy() {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].destroy();\r\n            this.groups[i] = undefined;\r\n        }\r\n        this.groups = [];\r\n        this._resources = {};\r\n    }"
              }
            ],
            "protected": [
              {
                "objectType": "method",
                "name": "createVertexBufferLayout",
                "returnType": "{ vertexLayouts: Iterable<GPUVertexBufferLayout>; buffers: VertexBuffer[]; nbVertex: number; }",
                "visibility": "protected",
                "rawText": "protected createVertexBufferLayout(): { vertexLayouts: Iterable<GPUVertexBufferLayout>, buffers: VertexBuffer[], nbVertex: number } {\r\n        const vertexLayouts: Iterable<GPUVertexBufferLayout> = [];\r\n        const buffers: VertexBuffer[] = [];\r\n\r\n        let group: Bindgroup;\r\n        let resources: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n\r\n        let k: number = 0;\r\n        let builtin: number = 0;\r\n        let nbVertex: number = 0;\r\n        for (let j = 0; j < this.groups.length; j++) {\r\n            group = this.groups[j];\r\n            resources = group.elements;\r\n\r\n\r\n            for (let i = 0; i < resources.length; i++) {\r\n\r\n                resource = resources[i].resource;\r\n                if (resource instanceof VertexBuffer) {\r\n\r\n                    nbVertex = Math.max(nbVertex, resource.nbVertex)\r\n                    buffers[k] = resource;\r\n                    vertexLayouts[k++] = resource.createVertexBufferLayout(builtin);\r\n\r\n                    builtin += resource.vertexArrays.length;\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        return {\r\n            vertexLayouts,\r\n            buffers,\r\n            nbVertex\r\n        }\r\n    }"
              }
            ]
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "params": [
              {
                "name": "pipeline",
                "type": "Pipeline"
              },
              {
                "name": "name",
                "type": "string"
              }
            ],
            "rawText": "constructor(pipeline: Pipeline, name: string) {\r\n        this._name = name;\r\n        this.pipeline = pipeline;\r\n\r\n    }"
          },
          "rawText": "export class Bindgroups {\r\n\r\n\r\n    public pipeline: Pipeline;\r\n    public parent: Bindgroups;\r\n    public groups: Bindgroup[] = [];\r\n    private _name: string;\r\n\r\n\r\n\r\n    constructor(pipeline: Pipeline, name: string) {\r\n        this._name = name;\r\n        this.pipeline = pipeline;\r\n\r\n    }\r\n\r\n\r\n\r\n    public get name(): string { return this._name; }\r\n\r\n    public clearAfterDeviceLost() {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].clearAfterDeviceLost();\r\n        }\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n    public build(autoLayout: boolean = false) {\r\n\r\n        const description: any = {};\r\n        const layouts: GPUBindGroupLayout[] = [];\r\n        const bindgroups: GPUBindGroup[] = [];\r\n\r\n\r\n        this.groups = this.groups.sort((a: Bindgroup, b: Bindgroup) => {\r\n            if (a.useInstances && !b.useInstances) return 1;\r\n            if (!a.useInstances && b.useInstances) return -1;\r\n            return 0;\r\n        })\r\n\r\n        if (this.groups.length) {\r\n            this.groups[this.groups.length - 1].applyDraw = true;\r\n        } else {\r\n            this.groups[0] = new Bindgroup();\r\n            this.groups[0].parent = this;\r\n            this.groups[0].applyDraw = true;\r\n        }\r\n\r\n\r\n\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            //console.log(i, \" group = \", this.groups[i])\r\n            if (!autoLayout) layouts[i] = this.groups[i].layout;\r\n            bindgroups[i] = this.groups[i].group;\r\n        }\r\n\r\n        if (autoLayout) description.layout = \"auto\";\r\n        else {\r\n            //console.log(\"pipelineLayout = \", layouts)\r\n            description.layout = XGPU.createPipelineLayout({ bindGroupLayouts: layouts });\r\n        }\r\n\r\n\r\n        const { vertexLayouts, buffers, nbVertex } = this.createVertexBufferLayout();\r\n\r\n        //console.log(this.pipeline.type,vertexLayouts)\r\n\r\n        description.vertex = {\r\n            buffers: vertexLayouts\r\n        }\r\n\r\n        return {\r\n            description,\r\n            bindgroups,\r\n            buffers,\r\n            nbVertex\r\n        }\r\n\r\n    }\r\n\r\n    public getBindgroupByResource(resource: IShaderResource): Bindgroup {\r\n        let group: Bindgroup, element: IShaderResource;\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            for (let j = 0; j < group.elements.length; j++) {\r\n                element = group.elements[j].resource;\r\n                if (element === resource) return group;\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n\r\n\r\n    public apply(passEncoder: GPURenderPassEncoder | GPUComputePassEncoder): void {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].apply(passEncoder)\r\n        }\r\n        /*if (passEncoder instanceof GPURenderPassEncoder) {\r\n            this.drawConfig.draw(passEncoder);\r\n        }*/\r\n\r\n    }\r\n\r\n    public update(): void {\r\n        //console.log(\"Bindgroups.update groupLen = \", this.groups.length)\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].update(this.pipeline);\r\n        }\r\n    }\r\n\r\n\r\n    protected temp: { result: string, variables: string };\r\n\r\n    public getVertexShaderDeclaration(fromFragmentShader: boolean = false): { result: string, variables: string } {\r\n        if (fromFragmentShader) return this.temp;\r\n        //console.log(\"getVertexShaderDeclaration\")\r\n        let result: string = \"\";\r\n        let group: Bindgroup;\r\n        let resources: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let name: string;\r\n        let k: number = 0;\r\n\r\n        const obj = { result: \"\", variables: \"\" };\r\n\r\n        /*\r\n        const structNames: string[] = [];\r\n        const removeAlreadyDefinedStruct = (source: string) => {\r\n            let lines: string[] = source.split(\"\\n\");\r\n            let result: string = \"\";\r\n            let openStruct: boolean = false;\r\n            let canWrite: boolean = true;\r\n            let line: string;\r\n            let delay: number = 0;\r\n\r\n            for (let i = 0; i < lines.length; i++) {\r\n                line = lines[i].trim();\r\n\r\n                if (line.substring(0, \"struct \".length) === \"struct \") {\r\n                    const name = line.split(\" \")[1].split(\"{\")[0];\r\n                    openStruct = true;\r\n                    if (structNames.indexOf(name) === -1) {\r\n                        structNames.push(name);\r\n                        canWrite = true;\r\n                    } else {\r\n                        canWrite = false;\r\n                    }\r\n                } else {\r\n                    if (openStruct && line.indexOf(\"}\") !== -1) {\r\n                        openStruct = false;\r\n                        if (!canWrite) delay = 1;\r\n                        canWrite = true;\r\n                    }\r\n                }\r\n\r\n                if (canWrite && delay-- <= 0) result += lines[i] + \"\\n\";\r\n            }\r\n\r\n            return result;\r\n        }\r\n        */\r\n        //---------------\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            resources = group.elements;\r\n            k = 0;\r\n            for (let j = 0; j < resources.length; j++) {\r\n\r\n                //console.log(i, j, resources[j]);\r\n\r\n                resource = resources[j].resource;\r\n                if (resource instanceof VertexBuffer) continue;\r\n                name = resources[j].name;\r\n\r\n\r\n                if (resource instanceof UniformBuffer) {\r\n\r\n                    /*if (resource.group.name) {\r\n                        resource.group = resource.group.clone();\r\n                        resource.group.name = undefined;\r\n                    }*/\r\n\r\n                    const s: { struct: string, localVariables: string } = resource.createStruct(name);\r\n                    obj.variables += s.localVariables;\r\n                    //result += removeAlreadyDefinedStruct(s.struct);\r\n                    result += s.struct;\r\n\r\n                }\r\n\r\n                result += resource.createDeclaration(name, k++, i) + \"\\n\";\r\n\r\n\r\n\r\n\r\n            }\r\n\r\n        }\r\n        obj.result = result;\r\n        this.temp = obj;\r\n        return obj;\r\n    }\r\n\r\n    public getFragmentShaderDeclaration(): { result: string, variables: string } {\r\n        let result: string = \"\";\r\n        let group: Bindgroup;\r\n        let resources: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let name: string;\r\n        let k: number = 0;\r\n\r\n        const obj = { result: \"\", variables: \"\" };\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            resources = group.elements;\r\n            k = 0;\r\n            for (let j = 0; j < resources.length; j++) {\r\n                resource = resources[j].resource;\r\n                if (resource instanceof VertexBuffer) continue;\r\n                name = resources[j].name;\r\n                if (resource instanceof UniformBuffer) {\r\n                    let item;\r\n                    for (let z in resource.items) {\r\n                        item = resource.items[z];\r\n                        let _name = name.substring(0, 1).toLowerCase() + name.slice(1);\r\n                        if (item.propertyNames) result += item.createStruct() + \"\\n\";\r\n                        if (item.createVariableInsideMain) obj.variables += item.createVariable(_name) + \"\\n\"\r\n                    }\r\n                    result += resource.createStruct(name).struct + \"\\n\";\r\n\r\n                }\r\n                result += resource.createDeclaration(name, k++, i) + \"\\n\";\r\n            }\r\n        }\r\n        obj.result = result;\r\n        return obj;\r\n    }\r\n\r\n    public getComputeShaderDeclaration(): { result: string, variables: string } {\r\n        let result: string = \"\";\r\n        let group: Bindgroup;\r\n        let resources: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n        let name: string;\r\n        let k: number = 0;\r\n\r\n        const obj = { result: \"\", variables: \"\" };\r\n        //console.log(\"#################################################################\")\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            //console.log(group)\r\n            resources = group.elements;\r\n            k = 0;\r\n            for (let j = 0; j < resources.length; j++) {\r\n                resource = resources[j].resource;\r\n                name = resources[j].name;\r\n\r\n                if (resource instanceof VertexBuffer) {\r\n\r\n\r\n\r\n\r\n                } else if (resource instanceof UniformBuffer) {\r\n                    //console.log(resource)\r\n                    let item;\r\n                    for (let z in resource.items) {\r\n                        item = resource.items[z];\r\n                        let _name = name.substring(0, 1).toLowerCase() + name.slice(1);\r\n                        //if (item.propertyNames) result += item.createStruct() + \"\\n\";\r\n                        if (item.createVariableInsideMain) obj.variables += item.createVariable(_name) + \"\\n\"\r\n                    }\r\n\r\n                    const struct = resource.createStruct(name).struct + \"\\n\";\r\n                    //console.log(\" struct => \", struct)\r\n                    result += struct;\r\n                }\r\n\r\n                const declaration = resource.createDeclaration(name, k++, i) + \"\\n\"\r\n                //console.log(\"declaration = \", declaration)\r\n                result += declaration;\r\n            }\r\n        }\r\n\r\n        //console.log(\"getComputeShaderDeclaration result = \", result)\r\n        //console.log(\"#################################################################\")\r\n        obj.result = result;\r\n        return obj;\r\n    }\r\n\r\n\r\n    protected createVertexBufferLayout(): { vertexLayouts: Iterable<GPUVertexBufferLayout>, buffers: VertexBuffer[], nbVertex: number } {\r\n        const vertexLayouts: Iterable<GPUVertexBufferLayout> = [];\r\n        const buffers: VertexBuffer[] = [];\r\n\r\n        let group: Bindgroup;\r\n        let resources: { name: string, resource: IShaderResource }[];\r\n        let resource: IShaderResource;\r\n\r\n        let k: number = 0;\r\n        let builtin: number = 0;\r\n        let nbVertex: number = 0;\r\n        for (let j = 0; j < this.groups.length; j++) {\r\n            group = this.groups[j];\r\n            resources = group.elements;\r\n\r\n\r\n            for (let i = 0; i < resources.length; i++) {\r\n\r\n                resource = resources[i].resource;\r\n                if (resource instanceof VertexBuffer) {\r\n\r\n                    nbVertex = Math.max(nbVertex, resource.nbVertex)\r\n                    buffers[k] = resource;\r\n                    vertexLayouts[k++] = resource.createVertexBufferLayout(builtin);\r\n\r\n                    builtin += resource.vertexArrays.length;\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        return {\r\n            vertexLayouts,\r\n            buffers,\r\n            nbVertex\r\n        }\r\n    }\r\n\r\n\r\n\r\n    public handleRenderPipelineResourceIOs() {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].handleRenderPipelineResourceIOs();\r\n        }\r\n    }\r\n\r\n    public handleComputePipelineResourceIOs() {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            //console.log(i, this.groups[i])\r\n            this.groups[i].handleComputePipelineResourceIOs();\r\n        }\r\n    }\r\n\r\n\r\n    protected _resources: any = {};\r\n    public get resources(): any { return this._resources }\r\n\r\n    public add(bindgroup: Bindgroup | Bindgroups): (Bindgroup | Bindgroups) {\r\n\r\n        bindgroup.parent = this;\r\n        let resource = this._resources\r\n        if (!this._resources.all) this._resources.all = [];\r\n        if (!this._resources.types) this._resources.types = {};\r\n\r\n        const types = this._resources.types;\r\n\r\n        //console.warn(\"add bindgroup \", bindgroup)\r\n\r\n\r\n        const addResources = (res: any, elements: { name: string, resource: IShaderResource }[]) => {\r\n            //console.warn(\"call addResource \", elements)\r\n            let element: { name: string, resource: IShaderResource };\r\n            let r: IShaderResource;\r\n            for (let i = 0; i < elements.length; i++) {\r\n                element = elements[i];\r\n                //console.log(element.name)\r\n                if (res[element.name]) continue;\r\n                //console.log(\"addResources \", i, element)\r\n                r = element.resource;\r\n                if (this._resources.all.indexOf(r) === -1) this._resources.all.push(r);\r\n                res[element.name] = element.resource;\r\n\r\n                if (r instanceof DepthTextureArray) {\r\n                    if (!types.depthTextureArrays) types.depthTextureArrays = [];\r\n                    if (types.depthTextureArrays.indexOf(element) === -1) types.depthTextureArrays.push(element);\r\n                } else if (r instanceof CubeMapTextureArray) {\r\n                    if (!types.cubeMapTextureArrays) types.cubeMapTextureArrays = [];\r\n                    if (types.cubeMapTextureArrays.indexOf(element) === -1) types.cubeMapTextureArrays.push(element);\r\n                } else if (r instanceof ImageTextureArray) {\r\n                    if (!types.imageTextureArrays) types.imageTextureArrays = [];\r\n                    if (types.imageTextureArrays.indexOf(element) === -1) types.imageTextureArrays.push(element);\r\n                } else if (r instanceof UniformBuffer) {\r\n                    if (!types.uniformBuffers) types.uniformBuffers = [];\r\n                    if (types.uniformBuffers.indexOf(element) === -1) types.uniformBuffers.push(element);\r\n                } else if (r instanceof VertexBuffer) {\r\n                    if (!types.vertexBuffers) types.vertexBuffers = [];\r\n                    if (types.vertexBuffers.indexOf(element) === -1) types.vertexBuffers.push(element);\r\n                } else if (r instanceof CubeMapTexture) {\r\n                    if (!types.cubeMapTexture) types.cubeMapTexture = [];\r\n                    if (types.cubeMapTexture.indexOf(element) === -1) types.cubeMapTexture.push(element);\r\n                } else if (r instanceof ImageTexture) {\r\n                    if (!types.imageTextures) types.imageTextures = [];\r\n                    if (types.imageTextures.indexOf(element) === -1) types.imageTextures.push(element);\r\n                } else if (r instanceof VideoTexture) {\r\n                    if (!types.videoTexture) types.videoTexture = [];\r\n                    if (types.videoTexture.indexOf(element) === -1) types.videoTexture.push(element);\r\n                } else if (r instanceof TextureSampler) {\r\n                    if (!types.sampler) types.sampler = [];\r\n                    if (types.sampler.indexOf(element) === -1) types.sampler.push(element);\r\n                } else if (r instanceof DepthStencilTexture) {\r\n                    if (!types.depthStencilTextures) types.depthStencilTextures = [];\r\n                    if (types.depthStencilTextures.indexOf(element) === -1) types.depthStencilTextures.push(element);\r\n                }\r\n\r\n            }\r\n\r\n            //console.log(\"this.resources = \", this.resources.all.length)\r\n        }\r\n\r\n\r\n        const addGroup = (o: Bindgroup) => {\r\n            //console.log(\"addGroup \", o.name, o.elements)\r\n            const res: any = resource[o.name] = {};\r\n            if (!res.types) res.types = {};\r\n\r\n            addResources(res, o.elements)\r\n\r\n            this.groups.push(o);\r\n        }\r\n\r\n\r\n        if (bindgroup instanceof Bindgroup) {\r\n            if (this.groups.indexOf(bindgroup) === -1) addGroup(bindgroup);\r\n            else {\r\n                //console.log(\"=> \", bindgroup.name)\r\n                addResources(resource[bindgroup.name], bindgroup.elements)\r\n            }\r\n        } else {\r\n            bindgroup.pipeline = this.pipeline;\r\n            resource = resource[bindgroup.name] = {};\r\n            let o;\r\n            for (let i = 0; i < bindgroup.groups.length; i++) {\r\n                o = bindgroup.groups[i];\r\n                if (this.groups.indexOf(o) === -1) addGroup(o);\r\n            }\r\n        }\r\n\r\n        return bindgroup;\r\n    }\r\n\r\n    public copy(options?: { oldGroups: Bindgroup[], replacedGroup: Bindgroup[] }): Bindgroups {\r\n        const obj = new Bindgroups(this.pipeline, this._name);\r\n        const groups = this.groups.concat();\r\n        if (options) {\r\n            for (let i = 0; i < options.oldGroups.length; i++) {\r\n                groups.splice(groups.indexOf(options.oldGroups[i]), 1, options.replacedGroup[i]);\r\n            }\r\n        }\r\n\r\n        obj.groups = groups;\r\n        return obj;\r\n    }\r\n\r\n\r\n    public propertyNameIsUsed(propertyName: string): boolean {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            if (this.groups[i].get(propertyName)) return true\r\n        }\r\n        return false;\r\n    }\r\n    public get(propertyName: string): IShaderResource {\r\n        let o: IShaderResource;\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            o = this.groups[i].get(propertyName);\r\n            if (o) return o;\r\n        }\r\n        return null;\r\n    }\r\n\r\n    public getGroupByPropertyName(name: string): Bindgroup {\r\n        let o: IShaderResource;\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            o = this.groups[i].get(name);\r\n            if (o) return this.groups[i];\r\n        }\r\n        return null;\r\n    }\r\n\r\n    public getGroupByName(name: string): Bindgroup {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            if (this.groups[i].name === name) return this.groups[i];\r\n        }\r\n        return null;\r\n    }\r\n\r\n    public getNameByResource(resource: IShaderResource | PrimitiveFloatUniform | PrimitiveIntUniform | PrimitiveUintUniform): string {\r\n\r\n        if (resource instanceof PrimitiveFloatUniform || resource instanceof PrimitiveIntUniform || resource instanceof PrimitiveUintUniform) {\r\n            return resource.name;\r\n        }\r\n\r\n\r\n        let elements: { name: string, resource: IShaderResource }[];\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            elements = this.groups[i].elements;\r\n            for (let j = 0; j < elements.length; j++) {\r\n                if (elements[j].resource === resource) {\r\n                    return elements[j].name;\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n\r\n\r\n        return null;\r\n    }\r\n\r\n    public setupDraw(force: boolean = false) {\r\n\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            if (!this.groups[i].setupDrawCompleted) {\r\n                this.groups[i].setupDraw(force);\r\n            }\r\n        }\r\n    }\r\n\r\n    public get drawConfig(): DrawConfig {\r\n\r\n        return (this.pipeline as any).drawConfig || null\r\n    }\r\n\r\n    public get current(): Bindgroup {\r\n        return this.groups[this.groups.length - 1]\r\n    }\r\n\r\n\r\n    public destroy() {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].destroy();\r\n            this.groups[i] = undefined;\r\n        }\r\n        this.groups = [];\r\n        this._resources = {};\r\n    }\r\n}"
        }
      ],
      "ComputeShader": [
        {
          "objectType": "class",
          "name": "ComputeShader",
          "filePath": "xGPU.shader.ComputeShader",
          "extends": [
            "ShaderStage"
          ],
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "build",
                "returnType": "{ code: string; output: ShaderStruct; }",
                "params": [
                  {
                    "name": "shaderPipeline",
                    "type": "ComputePipeline"
                  },
                  {
                    "name": "inputs",
                    "type": "ShaderStruct"
                  }
                ],
                "visibility": "public",
                "rawText": "public build(shaderPipeline: ComputePipeline, inputs: ShaderStruct): { code: string, output: ShaderStruct } {\r\n\r\n        if (this._shaderInfos) return this._shaderInfos;\r\n\r\n\r\n\r\n        let result = \"\";\r\n        const obj = shaderPipeline.bindGroups.getComputeShaderDeclaration();\r\n        result += obj.result + \"\\n\\n\";\r\n\r\n\r\n        //------\r\n\r\n        const w = shaderPipeline.workgroups;\r\n\r\n        //this.unwrapVariableInMainFunction(obj.variables)//handleVariables();\r\n        let constants = this.unwrapVariableInWGSL(obj.variables, this.constants.value);\r\n        result += constants + \"\\n\\n\";\r\n\r\n\r\n        let mainFunc = this.unwrapVariableInWGSL(obj.variables, this.main.value);\r\n\r\n        result += \"@compute @workgroup_size(\" + w[0] + \",\" + w[1] + \",\" + w[2] + \")\\n\";\r\n        result += \"fn main(\" + inputs.getFunctionParams() + \") {\\n\";\r\n        //result += obj.variables + \"\\n\";\r\n        //result += this.main.value;\r\n        result += mainFunc;\r\n        result += \"}\\n\";\r\n\r\n       \r\n        \r\n        this._shaderInfos = { code: result, output: null };\r\n\r\n        if (XGPU.showComputeShader) {\r\n            setTimeout(()=>{\r\n                console.log(\"------------- COMPUTE SHADER --------------\")\r\n\r\n                console.log(this.formatWGSLCode(this._shaderInfos.code));\r\n                //console.log(formated)\r\n                console.log(\"-------------------------------------------\")\r\n            },100)\r\n           \r\n        }\r\n\r\n        return this._shaderInfos;\r\n\r\n\r\n\r\n\r\n    }"
              }
            ]
          },
          "statics": {
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "removeStructDefinitionAndReplaceStructDeclarationName",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "shaderCode",
                      "type": "string"
                    },
                    {
                      "name": "structName",
                      "type": "string"
                    },
                    {
                      "name": "newStructName",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public static removeStructDefinitionAndReplaceStructDeclarationName(shaderCode: string, structName: string, newStructName: string): string {\r\n        // Expression régulière pour capturer la définition complète de la structure `structName`\r\n        const structRegex = new RegExp(`struct\\\\s+${structName}\\\\s*\\\\{[^}]*\\\\}`, 'g');\r\n        \r\n        // Supprimer la définition de `structName`\r\n        shaderCode = shaderCode.replace(structRegex, '');\r\n        \r\n        // Remplacer toutes les occurrences de `structName` par `newStructName`\r\n        const nameRegex = new RegExp(`\\\\b${structName}\\\\b`, 'g');\r\n        shaderCode = shaderCode.replace(nameRegex, newStructName);\r\n        \r\n        return shaderCode;\r\n      }"
                }
              ]
            }
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "rawText": "constructor() {\r\n        super(\"compute\");\r\n\r\n    }"
          },
          "rawText": "export class ComputeShader extends ShaderStage {\r\n\r\n\r\n\r\n    constructor() {\r\n        super(\"compute\");\r\n\r\n    }\r\n\r\n    public build(shaderPipeline: ComputePipeline, inputs: ShaderStruct): { code: string, output: ShaderStruct } {\r\n\r\n        if (this._shaderInfos) return this._shaderInfos;\r\n\r\n\r\n\r\n        let result = \"\";\r\n        const obj = shaderPipeline.bindGroups.getComputeShaderDeclaration();\r\n        result += obj.result + \"\\n\\n\";\r\n\r\n\r\n        //------\r\n\r\n        const w = shaderPipeline.workgroups;\r\n\r\n        //this.unwrapVariableInMainFunction(obj.variables)//handleVariables();\r\n        let constants = this.unwrapVariableInWGSL(obj.variables, this.constants.value);\r\n        result += constants + \"\\n\\n\";\r\n\r\n\r\n        let mainFunc = this.unwrapVariableInWGSL(obj.variables, this.main.value);\r\n\r\n        result += \"@compute @workgroup_size(\" + w[0] + \",\" + w[1] + \",\" + w[2] + \")\\n\";\r\n        result += \"fn main(\" + inputs.getFunctionParams() + \") {\\n\";\r\n        //result += obj.variables + \"\\n\";\r\n        //result += this.main.value;\r\n        result += mainFunc;\r\n        result += \"}\\n\";\r\n\r\n       \r\n        \r\n        this._shaderInfos = { code: result, output: null };\r\n\r\n        if (XGPU.showComputeShader) {\r\n            setTimeout(()=>{\r\n                console.log(\"------------- COMPUTE SHADER --------------\")\r\n\r\n                console.log(this.formatWGSLCode(this._shaderInfos.code));\r\n                //console.log(formated)\r\n                console.log(\"-------------------------------------------\")\r\n            },100)\r\n           \r\n        }\r\n\r\n        return this._shaderInfos;\r\n\r\n\r\n\r\n\r\n    }\r\n\r\n\r\n    public static removeStructDefinitionAndReplaceStructDeclarationName(shaderCode: string, structName: string, newStructName: string): string {\r\n        // Expression régulière pour capturer la définition complète de la structure `structName`\r\n        const structRegex = new RegExp(`struct\\\\s+${structName}\\\\s*\\\\{[^}]*\\\\}`, 'g');\r\n        \r\n        // Supprimer la définition de `structName`\r\n        shaderCode = shaderCode.replace(structRegex, '');\r\n        \r\n        // Remplacer toutes les occurrences de `structName` par `newStructName`\r\n        const nameRegex = new RegExp(`\\\\b${structName}\\\\b`, 'g');\r\n        shaderCode = shaderCode.replace(nameRegex, newStructName);\r\n        \r\n        return shaderCode;\r\n      }\r\n      \r\n     \r\n      \r\n      \r\n\r\n}"
        }
      ],
      "FragmentShader": [
        {
          "objectType": "class",
          "name": "FragmentShader",
          "filePath": "xGPU.shader.FragmentShader",
          "extends": [
            "ShaderStage"
          ],
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "build",
                "returnType": "{ code: string; output: ShaderStruct; }",
                "params": [
                  {
                    "name": "shaderPipeline",
                    "type": "any"
                  },
                  {
                    "name": "inputs",
                    "type": "ShaderStruct"
                  }
                ],
                "visibility": "public",
                "rawText": "public build(shaderPipeline: any, inputs: ShaderStruct): { code: string, output: ShaderStruct } {\r\n        if (this._shaderInfos) return this._shaderInfos;\r\n\r\n\r\n\r\n\r\n\r\n        let result = \"\";\r\n        const obj = shaderPipeline.bindGroups.getVertexShaderDeclaration(true);\r\n        result += obj.result;\r\n\r\n        //console.log(\"-------- FRAGMENT -----------\");\r\n        //console.log(result)\r\n\r\n        for (let i = 0; i < this.inputs.length; i++) {\r\n            inputs.addProperty(this.inputs[i]);\r\n        }\r\n\r\n        if (this.outputs.length === 0) {\r\n            this.outputs[0] = { name: \"color\", ...BuiltIns.fragmentOutputs.color }\r\n        }\r\n        const output: ShaderStruct = new ShaderStruct(\"Output\", this.outputs);\r\n        result += output.struct + \"\\n\"\r\n\r\n\r\n\r\n        //------\r\n\r\n        //const mainFunc = this.unwrapVariableInMainFunction(obj.variables)//handleVariables();\r\n        let constants = this.unwrapVariableInWGSL(obj.variables, this.constants.value);\r\n        result += constants + \"\\n\\n\";\r\n\r\n\r\n        let mainFunc = this.unwrapVariableInWGSL(obj.variables, this.main.value);\r\n\r\n        result += \"@fragment\\n\";\r\n        result += \"fn main(\" + inputs.getFunctionParams() + \") -> \" + output.name + \"{\\n\";\r\n        //result += obj.variables + \"\\n\";\r\n        result += \"   var output:Output;\\n\";\r\n        //result += this.main.value;\r\n        result += mainFunc;\r\n        result += \"   return output;\\n\"\r\n        result += \"}\\n\";\r\n\r\n        result = this.formatWGSLCode(result)\r\n\r\n        if (XGPU.showFragmentShader) {\r\n            console.log(\"------------- FRAGMENT SHADER --------------\")\r\n            console.log(result)\r\n            console.log(\"--------------------------------------------\")\r\n        }\r\n\r\n\r\n        this._shaderInfos = { code: result, output: output };\r\n        \r\n        return this._shaderInfos;\r\n    }"
              }
            ]
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "rawText": "constructor() {\r\n        super(\"fragment\");\r\n    }"
          },
          "rawText": "export class FragmentShader extends ShaderStage {\r\n\r\n\r\n\r\n    constructor() {\r\n        super(\"fragment\");\r\n    }\r\n\r\n    public build(shaderPipeline: any, inputs: ShaderStruct): { code: string, output: ShaderStruct } {\r\n        if (this._shaderInfos) return this._shaderInfos;\r\n\r\n\r\n\r\n\r\n\r\n        let result = \"\";\r\n        const obj = shaderPipeline.bindGroups.getVertexShaderDeclaration(true);\r\n        result += obj.result;\r\n\r\n        //console.log(\"-------- FRAGMENT -----------\");\r\n        //console.log(result)\r\n\r\n        for (let i = 0; i < this.inputs.length; i++) {\r\n            inputs.addProperty(this.inputs[i]);\r\n        }\r\n\r\n        if (this.outputs.length === 0) {\r\n            this.outputs[0] = { name: \"color\", ...BuiltIns.fragmentOutputs.color }\r\n        }\r\n        const output: ShaderStruct = new ShaderStruct(\"Output\", this.outputs);\r\n        result += output.struct + \"\\n\"\r\n\r\n\r\n\r\n        //------\r\n\r\n        //const mainFunc = this.unwrapVariableInMainFunction(obj.variables)//handleVariables();\r\n        let constants = this.unwrapVariableInWGSL(obj.variables, this.constants.value);\r\n        result += constants + \"\\n\\n\";\r\n\r\n\r\n        let mainFunc = this.unwrapVariableInWGSL(obj.variables, this.main.value);\r\n\r\n        result += \"@fragment\\n\";\r\n        result += \"fn main(\" + inputs.getFunctionParams() + \") -> \" + output.name + \"{\\n\";\r\n        //result += obj.variables + \"\\n\";\r\n        result += \"   var output:Output;\\n\";\r\n        //result += this.main.value;\r\n        result += mainFunc;\r\n        result += \"   return output;\\n\"\r\n        result += \"}\\n\";\r\n\r\n        result = this.formatWGSLCode(result)\r\n\r\n        if (XGPU.showFragmentShader) {\r\n            console.log(\"------------- FRAGMENT SHADER --------------\")\r\n            console.log(result)\r\n            console.log(\"--------------------------------------------\")\r\n        }\r\n\r\n\r\n        this._shaderInfos = { code: result, output: output };\r\n        \r\n        return this._shaderInfos;\r\n    }\r\n}"
        }
      ],
      "ShaderType": [
        {
          "objectType": "class",
          "name": "ShaderType",
          "filePath": "xGPU.shader.ShaderType",
          "statics": {
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "Float",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static Float = { type: \"f32\" };"
                },
                {
                  "objectType": "property",
                  "name": "Vec2",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static Vec2 = { type: \"vec2<f32>\" };"
                },
                {
                  "objectType": "property",
                  "name": "Vec3",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static Vec3 = { type: \"vec3<f32>\" };"
                },
                {
                  "objectType": "property",
                  "name": "Vec4",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static Vec4 = { type: \"vec4<f32>\" };"
                },
                {
                  "objectType": "property",
                  "name": "Int",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static Int = { type: \"i32\" };"
                },
                {
                  "objectType": "property",
                  "name": "IVec2",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static IVec2 = { type: \"vec2<i32>\" };"
                },
                {
                  "objectType": "property",
                  "name": "IVec3",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static IVec3 = { type: \"vec3<i32>\" };"
                },
                {
                  "objectType": "property",
                  "name": "IVec4",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static IVec4 = { type: \"vec4<i32>\" };"
                },
                {
                  "objectType": "property",
                  "name": "Uint",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static Uint = { type: \"u32\" };"
                },
                {
                  "objectType": "property",
                  "name": "UVec2",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static UVec2 = { type: \"vec2<u32>\" };"
                },
                {
                  "objectType": "property",
                  "name": "UVec3",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static UVec3 = { type: \"vec3<u32>\" };"
                },
                {
                  "objectType": "property",
                  "name": "UVec4",
                  "type": "{ type: string; }",
                  "visibility": "public",
                  "rawText": "public static UVec4 = { type: \"vec4<u32>\" };"
                }
              ]
            }
          },
          "rawText": "export class ShaderType {\r\n\r\n    public static Float = { type: \"f32\" };\r\n    public static Vec2 = { type: \"vec2<f32>\" };\r\n    public static Vec3 = { type: \"vec3<f32>\" };\r\n    public static Vec4 = { type: \"vec4<f32>\" };\r\n\r\n    public static Int = { type: \"i32\" };\r\n    public static IVec2 = { type: \"vec2<i32>\" };\r\n    public static IVec3 = { type: \"vec3<i32>\" };\r\n    public static IVec4 = { type: \"vec4<i32>\" };\r\n\r\n    public static Uint = { type: \"u32\" };\r\n    public static UVec2 = { type: \"vec2<u32>\" };\r\n    public static UVec3 = { type: \"vec3<u32>\" };\r\n    public static UVec4 = { type: \"vec4<u32>\" };\r\n\r\n}"
        }
      ],
      "VertexShader": [
        {
          "objectType": "class",
          "name": "VertexShader",
          "filePath": "xGPU.shader.VertexShader",
          "extends": [
            "ShaderStage"
          ],
          "methods": {
            "public": [
              {
                "objectType": "method",
                "name": "build",
                "returnType": "{ code: string; output: ShaderStruct; }",
                "params": [
                  {
                    "name": "pipeline",
                    "type": "RenderPipeline"
                  },
                  {
                    "name": "input",
                    "type": "ShaderStruct"
                  }
                ],
                "visibility": "public",
                "rawText": "public build(pipeline: RenderPipeline, input: ShaderStruct): { code: string, output: ShaderStruct } {\r\n\r\n        //this.main.text = this.extractDebugInfo(this.main.text);\r\n\r\n        let result = \"\"\r\n        //if (this.keepRendererAspectRatio) result += \"const xgpuRendererAspectRatio = \" + (pipeline.renderer.width / pipeline.renderer.height).toFixed(4) + \";\\n\\n\";\r\n        const obj = pipeline.bindGroups.getVertexShaderDeclaration();\r\n        result += obj.result;\r\n\r\n        //-----\r\n        //if the renderPipeline is \"fed\" by a computePipeline, the shaderStruct \"input\"\r\n        //contains the output vertexBuffer from the computePipeline\r\n        result += input.getComputeVariableDeclaration();\r\n\r\n        //-----\r\n\r\n        let bool = false;\r\n        for (let i = 0; i < this.outputs.length; i++) {\r\n            if (this.outputs[i].builtin === BuiltIns.vertexOutputs.position.builtin) {\r\n                bool = true;\r\n            }\r\n        }\r\n        if (!bool) {\r\n\r\n\r\n            this.outputs.unshift({ name: \"position\", ...BuiltIns.vertexOutputs.position });\r\n        }\r\n\r\n\r\n        let output: ShaderStruct = new ShaderStruct(\"Output\", [...this.outputs]);\r\n        result += output.struct + \"\\n\"\r\n\r\n\r\n\r\n        //let mainFunc = this.unwrapVariableInMainFunction(obj.variables)//handleVariables();\r\n        let constants = this.unwrapVariableInWGSL(obj.variables, this.constants.value);\r\n        result += constants + \"\\n\\n\";\r\n\r\n\r\n        let mainFunc = this.unwrapVariableInWGSL(obj.variables, this.main.value);\r\n\r\n\r\n        //------\r\n        //console.log(\"VertexShader.variables = \", obj.variables)\r\n        result += \"@vertex\\n\";\r\n        result += \"fn main(\" + input.getFunctionParams() + \") -> \" + output.name + \"{\\n\";\r\n        result += \"   var output:Output;\\n\";\r\n        result += mainFunc;\r\n        result += \"   return output;\\n\"\r\n        result += \"}\\n\";\r\n\r\n        result = this.formatWGSLCode(result)\r\n\r\n        if (XGPU.showVertexShader) {\r\n\r\n            console.log(\"------------- VERTEX SHADER --------------\")\r\n            console.log(result);\r\n            console.log(\"------------------------------------------\")\r\n        }\r\n\r\n        this._shaderInfos = { code: result, output: output };\r\n        \r\n\r\n        return this._shaderInfos;\r\n    }"
              }
            ]
          },
          "constructor": {
            "objectType": "constructor",
            "name": "constructor",
            "rawText": "constructor() {\r\n        super(\"vertex\");\r\n    }"
          },
          "rawText": "export class VertexShader extends ShaderStage {\r\n\r\n    //public keepRendererAspectRatio: boolean = true;\r\n\r\n    constructor() {\r\n        super(\"vertex\");\r\n    }\r\n\r\n\r\n\r\n\r\n    public build(pipeline: RenderPipeline, input: ShaderStruct): { code: string, output: ShaderStruct } {\r\n\r\n        //this.main.text = this.extractDebugInfo(this.main.text);\r\n\r\n        let result = \"\"\r\n        //if (this.keepRendererAspectRatio) result += \"const xgpuRendererAspectRatio = \" + (pipeline.renderer.width / pipeline.renderer.height).toFixed(4) + \";\\n\\n\";\r\n        const obj = pipeline.bindGroups.getVertexShaderDeclaration();\r\n        result += obj.result;\r\n\r\n        //-----\r\n        //if the renderPipeline is \"fed\" by a computePipeline, the shaderStruct \"input\"\r\n        //contains the output vertexBuffer from the computePipeline\r\n        result += input.getComputeVariableDeclaration();\r\n\r\n        //-----\r\n\r\n        let bool = false;\r\n        for (let i = 0; i < this.outputs.length; i++) {\r\n            if (this.outputs[i].builtin === BuiltIns.vertexOutputs.position.builtin) {\r\n                bool = true;\r\n            }\r\n        }\r\n        if (!bool) {\r\n\r\n\r\n            this.outputs.unshift({ name: \"position\", ...BuiltIns.vertexOutputs.position });\r\n        }\r\n\r\n\r\n        let output: ShaderStruct = new ShaderStruct(\"Output\", [...this.outputs]);\r\n        result += output.struct + \"\\n\"\r\n\r\n\r\n\r\n        //let mainFunc = this.unwrapVariableInMainFunction(obj.variables)//handleVariables();\r\n        let constants = this.unwrapVariableInWGSL(obj.variables, this.constants.value);\r\n        result += constants + \"\\n\\n\";\r\n\r\n\r\n        let mainFunc = this.unwrapVariableInWGSL(obj.variables, this.main.value);\r\n\r\n\r\n        //------\r\n        //console.log(\"VertexShader.variables = \", obj.variables)\r\n        result += \"@vertex\\n\";\r\n        result += \"fn main(\" + input.getFunctionParams() + \") -> \" + output.name + \"{\\n\";\r\n        result += \"   var output:Output;\\n\";\r\n        result += mainFunc;\r\n        result += \"   return output;\\n\"\r\n        result += \"}\\n\";\r\n\r\n        result = this.formatWGSLCode(result)\r\n\r\n        if (XGPU.showVertexShader) {\r\n\r\n            console.log(\"------------- VERTEX SHADER --------------\")\r\n            console.log(result);\r\n            console.log(\"------------------------------------------\")\r\n        }\r\n\r\n        this._shaderInfos = { code: result, output: output };\r\n        \r\n\r\n        return this._shaderInfos;\r\n    }\r\n}"
        }
      ],
      "resources": {
        "CubeMapTexture": [
          {
            "objectType": "type",
            "name": "CubeMapTextureDescriptor",
            "type": "CubeMapTextureDescriptor",
            "rawText": "export type CubeMapTextureDescriptor = {\r\n    source?: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas)[],\r\n    size: GPUExtent3D,\r\n    usage?: GPUTextureUsageFlags,\r\n    dimension: string,\r\n    defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n    sampledType?: \"f32\" | \"i32\" | \"u32\"\r\n}"
          },
          {
            "objectType": "class",
            "name": "CubeMapTexture",
            "filePath": "xGPU.shader.resources.CubeMapTexture",
            "extends": [
              "ImageTextureArray",
              "ImageTexture",
              "EventDispatcher"
            ],
            "implements": [
              "IShaderResource"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "declare public descriptor: any;"
                },
                {
                  "objectType": "property",
                  "name": "right",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public set right(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n\r\n        this._bitmaps[0] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }",
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "left",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public set left(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[1] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }",
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "bottom",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public set bottom(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[2] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }",
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "top",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public set top(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[3] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }",
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "back",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public set back(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[4] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }",
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "front",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public set front(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[5] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }",
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "sides",
                  "type": "any[]",
                  "visibility": "public",
                  "rawText": "public set sides(images: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[]) {\r\n        for (let i = 0; i < 6; i++) this._bitmaps[i] = images[i];\r\n        this.mustBeTransfered = true;\r\n        this.update();\r\n    }",
                  "set": true,
                  "get": true
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "CubeMapTexture",
                  "visibility": "public",
                  "rawText": "public clone(): CubeMapTexture {\r\n        if (!this.descriptor.source) this.descriptor.source = this._bitmaps;\r\n        return new CubeMapTexture(this.descriptor);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public createGpuResource(): void {\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        this._view = this.gpuResource.createView({ dimension: 'cube' });\r\n\r\n        for (let i = 0; i < this.mustUpdate.length; i++) this.mustUpdate[i] = true;\r\n        this.mustBeTransfered = true;\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "varName",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_cube<\" + this.sampledType + \">;\\n\";\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupLayoutEntry",
                  "returnType": "{ binding: number; visibility: number; texture: GPUTextureBindingLayout; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, texture: GPUTextureBindingLayout } {\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"cube\",\r\n                multisampled: false\r\n            },\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupEntry",
                  "returnType": "{ binding: number; resource: GPUTextureView; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUTextureView } {\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view,\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setPipelineType",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "pipelineType",
                      "type": "\"render\" | \"compute\" | \"compute_mixed\""
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType) { }\r\n\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "descriptor",
                  "type": "{ source?: any[]; size: GPUExtent3D; usage?: GPUTextureUsageFlags; defaultViewDescriptor?: GPUTextureViewDescriptor; dimension?: string; sampledType?: \"u32\" | \"f32\" | \"i32\"; }"
                }
              ],
              "rawText": "constructor(descriptor: {\r\n        source?: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[], ////front,back,left,right,top,bottom\r\n        size: GPUExtent3D,\r\n        usage?: GPUTextureUsageFlags,\r\n        defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n        dimension?: string,\r\n        sampledType?: \"f32\" | \"i32\" | \"u32\"\r\n    }) {\r\n\r\n        descriptor = { ...descriptor };\r\n        if (!descriptor.dimension) descriptor.dimension = \"2d\"\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\r\n\r\n        super(descriptor as any);\r\n        if (descriptor.source) this.sides = descriptor.source\r\n\r\n    }"
            },
            "rawText": "export class CubeMapTexture extends ImageTextureArray implements IShaderResource {\r\n\r\n    declare public descriptor: any;\r\n\r\n\r\n\r\n    constructor(descriptor: {\r\n        source?: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[], ////front,back,left,right,top,bottom\r\n        size: GPUExtent3D,\r\n        usage?: GPUTextureUsageFlags,\r\n        defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n        dimension?: string,\r\n        sampledType?: \"f32\" | \"i32\" | \"u32\"\r\n    }) {\r\n\r\n        descriptor = { ...descriptor };\r\n        if (!descriptor.dimension) descriptor.dimension = \"2d\"\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\r\n\r\n        super(descriptor as any);\r\n        if (descriptor.source) this.sides = descriptor.source\r\n\r\n    }\r\n\r\n\r\n    public clone(): CubeMapTexture {\r\n        if (!this.descriptor.source) this.descriptor.source = this._bitmaps;\r\n        return new CubeMapTexture(this.descriptor);\r\n    }\r\n\r\n\r\n    public set right(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n\r\n        this._bitmaps[0] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }\r\n    public set left(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[1] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }\r\n    public set bottom(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[2] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }\r\n    public set top(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[3] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }\r\n    public set back(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[4] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }\r\n    public set front(bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture) {\r\n        if (!this.descriptor.source) this.descriptor.source = {};\r\n        this._bitmaps[5] = bmp;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public set sides(images: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[]) {\r\n        for (let i = 0; i < 6; i++) this._bitmaps[i] = images[i];\r\n        this.mustBeTransfered = true;\r\n        this.update();\r\n    }\r\n    public get sides(): (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[] { return this._bitmaps; }\r\n\r\n    public createGpuResource(): void {\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        this._view = this.gpuResource.createView({ dimension: 'cube' });\r\n\r\n        for (let i = 0; i < this.mustUpdate.length; i++) this.mustUpdate[i] = true;\r\n        this.mustBeTransfered = true;\r\n\r\n    }\r\n\r\n\r\n\r\n    //-----\r\n\r\n    public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_cube<\" + this.sampledType + \">;\\n\";\r\n    }\r\n\r\n\r\n    public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, texture: GPUTextureBindingLayout } {\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"cube\",\r\n                multisampled: false\r\n            },\r\n        }\r\n    }\r\n\r\n\r\n    public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUTextureView } {\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view,\r\n        }\r\n    }\r\n\r\n    public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType) { }\r\n\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n    }\r\n}"
          }
        ],
        "CubeMapTextureArray": [
          {
            "objectType": "type",
            "name": "ImageTextureArrayDescriptor",
            "type": "ImageTextureArrayDescriptor",
            "rawText": "export type ImageTextureArrayDescriptor = {\r\n    source?: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas)[],\r\n    size: GPUExtent3D,\r\n    usage?: GPUTextureUsageFlags,\r\n    dimension: string,\r\n    defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n    sampledType?: \"f32\" | \"i32\" | \"u32\"\r\n}"
          },
          {
            "objectType": "class",
            "name": "CubeMapTextureArray",
            "filePath": "xGPU.shader.resources.CubeMapTextureArray",
            "extends": [
              "ImageTextureArray",
              "ImageTexture",
              "EventDispatcher"
            ],
            "implements": [
              "IShaderResource"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "declare public descriptor: any;"
                },
                {
                  "objectType": "property",
                  "name": "bitmaps",
                  "type": "any[]",
                  "visibility": "public",
                  "rawText": "public set bitmaps(images: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[]) {\r\n\r\n        if (images.length === 0 || images.length % 6 !== 0) {\r\n            throw new Error(\"CubeMapTextureArray error : descriptor.source must contains an array of (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas) with a length greater than 0 and multiple of 6.\")\r\n        }\r\n\r\n        for (let i = 0; i < images.length; i++) {\r\n            this._bitmaps[i] = images[i];\r\n            this.mustUpdate[i] = true;\r\n        }\r\n        this.mustBeTransfered = true;\r\n        this.update();\r\n    }",
                  "set": true,
                  "get": true
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "CubeMapTextureArray",
                  "visibility": "public",
                  "rawText": "public clone(): CubeMapTextureArray {\r\n        if (!this.descriptor.source) this.descriptor.source = this._bitmaps;\r\n        return new CubeMapTextureArray(this.descriptor);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setCubeSideById",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "cubeid",
                      "type": "number"
                    },
                    {
                      "name": "sideId",
                      "type": "number"
                    },
                    {
                      "name": "image",
                      "type": "any"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setCubeSideById(cubeid: number, sideId: number, image: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)) {\r\n\r\n        if (this._bitmaps[cubeid * 6 + sideId] instanceof ImageBitmap) (this._bitmaps[cubeid * 6 + sideId] as ImageBitmap).close();\r\n\r\n        this._bitmaps[cubeid * 6 + sideId] = image;\r\n        this.mustUpdate[cubeid * 6 + sideId] = true;\r\n        this.mustBeTransfered = true;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public createGpuResource(): void {\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n        //console.log(\"cubemap createtexture \", this.descriptor)\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        this._view = this.gpuResource.createView({ dimension: 'cube-array', arrayLayerCount: this._bitmaps.length });\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "varName",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_cube_array<\" + this.sampledType + \">;\\n\";\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupLayoutEntry",
                  "returnType": "{ binding: number; visibility: number; texture: GPUTextureBindingLayout; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, texture: GPUTextureBindingLayout } {\r\n\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"cube-array\",\r\n                multisampled: false\r\n            },\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupEntry",
                  "returnType": "{ binding: number; resource: GPUTextureView; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUTextureView } {\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view,\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setPipelineType",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "pipelineType",
                      "type": "\"render\" | \"compute\" | \"compute_mixed\""
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType) { }\r\n\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "descriptor",
                  "type": "ImageTextureArrayDescriptor"
                }
              ],
              "rawText": "constructor(descriptor: ImageTextureArrayDescriptor) {\r\n\r\n        descriptor = { ...descriptor };\r\n\r\n        if (descriptor.source) {\r\n            if (descriptor.source.length === 0 || descriptor.source.length % 6 !== 0) {\r\n                throw new Error(\"CubeMapTextureArray error : descriptor.source must contains an array of (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas) with a length greater than 0 and multiple of 6.\")\r\n            }\r\n        }\r\n\r\n\r\n        if (!descriptor.dimension) descriptor.dimension = \"2d\"\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\r\n\r\n        super(descriptor as any);\r\n        if (descriptor.source) this.bitmaps = descriptor.source\r\n\r\n    }"
            },
            "rawText": "export class CubeMapTextureArray extends ImageTextureArray implements IShaderResource {\r\n\r\n\r\n    declare public descriptor: any;\r\n\r\n\r\n    constructor(descriptor: ImageTextureArrayDescriptor) {\r\n\r\n        descriptor = { ...descriptor };\r\n\r\n        if (descriptor.source) {\r\n            if (descriptor.source.length === 0 || descriptor.source.length % 6 !== 0) {\r\n                throw new Error(\"CubeMapTextureArray error : descriptor.source must contains an array of (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas) with a length greater than 0 and multiple of 6.\")\r\n            }\r\n        }\r\n\r\n\r\n        if (!descriptor.dimension) descriptor.dimension = \"2d\"\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\r\n\r\n        super(descriptor as any);\r\n        if (descriptor.source) this.bitmaps = descriptor.source\r\n\r\n    }\r\n\r\n\r\n    public clone(): CubeMapTextureArray {\r\n        if (!this.descriptor.source) this.descriptor.source = this._bitmaps;\r\n        return new CubeMapTextureArray(this.descriptor);\r\n    }\r\n\r\n\r\n\r\n\r\n    public set bitmaps(images: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[]) {\r\n\r\n        if (images.length === 0 || images.length % 6 !== 0) {\r\n            throw new Error(\"CubeMapTextureArray error : descriptor.source must contains an array of (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas) with a length greater than 0 and multiple of 6.\")\r\n        }\r\n\r\n        for (let i = 0; i < images.length; i++) {\r\n            this._bitmaps[i] = images[i];\r\n            this.mustUpdate[i] = true;\r\n        }\r\n        this.mustBeTransfered = true;\r\n        this.update();\r\n    }\r\n    public get bitmaps(): (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[] { return this._bitmaps; }\r\n\r\n    public setCubeSideById(cubeid: number, sideId: number, image: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)) {\r\n\r\n        if (this._bitmaps[cubeid * 6 + sideId] instanceof ImageBitmap) (this._bitmaps[cubeid * 6 + sideId] as ImageBitmap).close();\r\n\r\n        this._bitmaps[cubeid * 6 + sideId] = image;\r\n        this.mustUpdate[cubeid * 6 + sideId] = true;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public createGpuResource(): void {\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n        //console.log(\"cubemap createtexture \", this.descriptor)\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        this._view = this.gpuResource.createView({ dimension: 'cube-array', arrayLayerCount: this._bitmaps.length });\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\n    //-----\r\n\r\n    public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_cube_array<\" + this.sampledType + \">;\\n\";\r\n    }\r\n\r\n\r\n    public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, texture: GPUTextureBindingLayout } {\r\n\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"cube-array\",\r\n                multisampled: false\r\n            },\r\n        }\r\n    }\r\n\r\n\r\n    public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUTextureView } {\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view,\r\n        }\r\n    }\r\n\r\n    public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType) { }\r\n\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n    }\r\n}"
          }
        ],
        "IShaderResource": [
          {
            "objectType": "interface",
            "name": "IShaderResource",
            "methods": [
              {
                "objectType": "method",
                "name": "setPipelineType",
                "returnType": "any",
                "params": [
                  {
                    "name": "pipelineType",
                    "type": "\"render\" | \"compute\" | \"compute_mixed\""
                  }
                ],
                "visibility": "public",
                "rawText": "setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\");"
              },
              {
                "objectType": "method",
                "name": "createDeclaration",
                "returnType": "string",
                "params": [
                  {
                    "name": "varName",
                    "type": "string"
                  },
                  {
                    "name": "bindingId",
                    "type": "number"
                  },
                  {
                    "name": "groupId",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "createDeclaration(varName: string, bindingId: number, groupId: number): string;"
              },
              {
                "objectType": "method",
                "name": "createBindGroupLayoutEntry",
                "returnType": "any",
                "params": [
                  {
                    "name": "bindingId",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "createBindGroupLayoutEntry(bindingId: number): any;"
              },
              {
                "objectType": "method",
                "name": "createBindGroupEntry",
                "returnType": "any",
                "params": [
                  {
                    "name": "bindingId",
                    "type": "number"
                  }
                ],
                "visibility": "public",
                "rawText": "createBindGroupEntry(bindingId: number): any;"
              },
              {
                "objectType": "method",
                "name": "createGpuResource",
                "returnType": "any",
                "visibility": "public",
                "rawText": "createGpuResource();"
              },
              {
                "objectType": "method",
                "name": "destroyGpuResource",
                "returnType": "any",
                "visibility": "public",
                "rawText": "destroyGpuResource();"
              },
              {
                "objectType": "method",
                "name": "update",
                "returnType": "any",
                "params": [
                  {
                    "name": "pipeline",
                    "type": "Pipeline"
                  }
                ],
                "visibility": "public",
                "rawText": "update(pipeline?: Pipeline);"
              },
              {
                "objectType": "method",
                "name": "clone",
                "returnType": "IShaderResource",
                "visibility": "public",
                "rawText": "clone(): IShaderResource;"
              }
            ],
            "properties": [
              {
                "objectType": "property",
                "name": "mustBeTransfered",
                "type": "boolean",
                "get": false,
                "set": false,
                "visibility": "public",
                "rawText": "mustBeTransfered: boolean;"
              },
              {
                "objectType": "property",
                "name": "gpuResource",
                "type": "any",
                "get": false,
                "set": false,
                "visibility": "public",
                "rawText": "gpuResource: any;"
              },
              {
                "objectType": "property",
                "name": "descriptor",
                "type": "any",
                "get": false,
                "set": false,
                "visibility": "public",
                "rawText": "descriptor: any;"
              }
            ],
            "filePath": "xGPU.shader.resources.IShaderResource",
            "rawText": "export interface IShaderResource {\r\n\r\n    mustBeTransfered: boolean;\r\n    gpuResource: any;\r\n    descriptor: any;\r\n\r\n    setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\"); //used to handle particular cases in descriptor relative to the nature of pipeline\r\n\r\n    createDeclaration(varName: string, bindingId: number, groupId: number): string;\r\n    createBindGroupLayoutEntry(bindingId: number): any;\r\n    createBindGroupEntry(bindingId: number): any;\r\n\r\n    createGpuResource();\r\n    destroyGpuResource();\r\n    update(pipeline?: Pipeline);\r\n\r\n    clone(): IShaderResource;\r\n\r\n}"
          }
        ],
        "ImageTexture": [
          {
            "objectType": "type",
            "name": "ImageTextureDescriptor",
            "type": "ImageTextureDescriptor",
            "rawText": "export type ImageTextureDescriptor = {\r\n    source?: ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture | RenderPassTexture\r\n    size?: GPUExtent3D,\r\n    usage?: GPUTextureUsageFlags,\r\n    format?: GPUTextureFormat,\r\n    defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n    sampledType?: \"f32\" | \"i32\" | \"u32\",\r\n    label?: string,\r\n}"
          },
          {
            "objectType": "class",
            "name": "ImageTexture",
            "filePath": "xGPU.shader.resources.ImageTexture",
            "extends": [
              "EventDispatcher"
            ],
            "implements": [
              "IShaderResource"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "resourceIO",
                  "type": "ImageTextureIO",
                  "visibility": "public",
                  "rawText": "public resourceIO: ImageTextureIO;"
                },
                {
                  "objectType": "property",
                  "name": "io",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public io: number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "mustBeTransfered",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public mustBeTransfered: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "ImageTextureDescriptor",
                  "visibility": "public",
                  "rawText": "public descriptor: ImageTextureDescriptor"
                },
                {
                  "objectType": "property",
                  "name": "gpuResource",
                  "type": "GPUTexture",
                  "visibility": "public",
                  "rawText": "public gpuResource: GPUTexture;"
                },
                {
                  "objectType": "property",
                  "name": "sampledType",
                  "type": "\"u32\" | \"f32\" | \"i32\"",
                  "visibility": "public",
                  "rawText": "public get sampledType(): \"f32\" | \"i32\" | \"u32\" { return this.descriptor.sampledType }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "isRenderPass",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public get isRenderPass(): boolean { return false; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "texture",
                  "type": "GPUTexture",
                  "visibility": "public",
                  "rawText": "public get texture(): GPUTexture {\r\n\r\n        //if (this.gpuTextureIOs) return this.gpuTextureIOs[this.gpuTextureIO_index++ % 2]\r\n        return this.gpuResource;\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "view",
                  "type": "GPUTextureView",
                  "visibility": "public",
                  "rawText": "public get view(): GPUTextureView {\r\n        //console.log(\"aaa\")\r\n        if (!this._view) this.createGpuResource();\r\n        return this._view;\r\n\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "source",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public get source(): ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture | RenderPassTexture { return this.descriptor.source }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "deviceId",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public deviceId: number;"
                },
                {
                  "objectType": "property",
                  "name": "time",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public time: number;"
                },
                {
                  "objectType": "property",
                  "name": "textureType",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public get textureType(): any { return this._textureType }",
                  "get": true,
                  "set": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "_view",
                  "type": "GPUTextureView",
                  "visibility": "protected",
                  "rawText": "protected _view: GPUTextureView;"
                },
                {
                  "objectType": "property",
                  "name": "viewDescriptor",
                  "type": "GPUTextureViewDescriptor",
                  "visibility": "protected",
                  "rawText": "protected viewDescriptor: GPUTextureViewDescriptor = undefined;"
                },
                {
                  "objectType": "property",
                  "name": "useOutsideTexture",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected useOutsideTexture: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "renderPassTexture",
                  "type": "RenderPassTexture",
                  "visibility": "protected",
                  "rawText": "protected renderPassTexture: RenderPassTexture;"
                },
                {
                  "objectType": "property",
                  "name": "gpuTextureIOs",
                  "type": "GPUTexture[]",
                  "visibility": "protected",
                  "rawText": "protected gpuTextureIOs: GPUTexture[];"
                },
                {
                  "objectType": "property",
                  "name": "gpuTextureIO_index",
                  "type": "number",
                  "visibility": "protected",
                  "rawText": "protected gpuTextureIO_index: number = 1;"
                },
                {
                  "objectType": "property",
                  "name": "_textureType",
                  "type": "{ texture: any; } | { storageTexture: any; }",
                  "visibility": "protected",
                  "rawText": "protected _textureType: { texture: any } | { storageTexture: any };"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "ImageTexture",
                  "visibility": "public",
                  "rawText": "public clone(): ImageTexture {\r\n        return new ImageTexture(this.descriptor);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "initTextureIO",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "textures",
                      "type": "GPUTexture[]"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public initTextureIO(textures: GPUTexture[]) {\r\n        this.gpuTextureIOs = textures;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getCurrentTexture",
                  "returnType": "GPUTexture",
                  "visibility": "public",
                  "rawText": "public getCurrentTexture(): GPUTexture {\r\n        //if (this.gpuTextureIOs) return this.gpuTextureIOs[(this.gpuTextureIO_index + 1) % 2]\r\n        return this.gpuResource;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createView",
                  "returnType": "GPUTextureView",
                  "params": [
                    {
                      "name": "viewDescriptor",
                      "type": "GPUTextureViewDescriptor"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createView(viewDescriptor?: GPUTextureViewDescriptor): GPUTextureView {\r\n        if (this.useOutsideTexture) return null;\r\n        let desc: GPUTextureViewDescriptor = this.viewDescriptor;\r\n        if (viewDescriptor) desc = viewDescriptor;\r\n        return this.gpuResource.createView(desc);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "resize",
                  "returnType": "ImageTexture",
                  "params": [
                    {
                      "name": "w",
                      "type": "number"
                    },
                    {
                      "name": "h",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public resize(w: number, h: number): ImageTexture {\r\n        if (this.useOutsideTexture) return null;\r\n        this.descriptor.size = [w, h];\r\n        this.createGpuResource()\r\n        return this;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "pipeline",
                      "type": "Pipeline"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public update(pipeline: Pipeline): void {\r\n\r\n\r\n\r\n        if (this.renderPassTexture && !this.renderPassTexture.mustUseCopyTextureToTexture) this.renderPassTexture.applyRenderPass(pipeline);\r\n        if (this.useOutsideTexture) return;\r\n\r\n        if (!this.gpuResource) this.createGpuResource()\r\n\r\n\r\n\r\n        if (this.descriptor.source) {\r\n            if (this.descriptor.source.width !== this.gpuResource.width || this.descriptor.source.height !== this.gpuResource.height) {\r\n                //console.log(\"source = \", this.descriptor.source)\r\n                this.descriptor.size = [this.descriptor.source.width, this.descriptor.source.height]\r\n                this.createGpuResource();\r\n                this.mustBeTransfered = true;\r\n            }\r\n        }\r\n\r\n\r\n\r\n        if (this.mustBeTransfered) {\r\n            this.mustBeTransfered = false;\r\n            //console.log(\"updateTexture\")\r\n            XGPU.device.queue.copyExternalImageToTexture(\r\n                { source: this.descriptor.source as any, flipY: true },\r\n                { texture: this.gpuResource },\r\n                this.descriptor.size\r\n            );\r\n\r\n\r\n        }\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public createGpuResource(): void {\r\n        //console.warn(\"imageTexture.createGpuResource \", this.deviceId, XGPU.deviceId, this.useOutsideTexture, this.descriptor.source)\r\n\r\n        if (this.useOutsideTexture && this.gpuResource) {\r\n            if (this.deviceId != XGPU.deviceId) {\r\n                const o = (this.gpuResource as any).xgpuObject;\r\n                if (o) {\r\n                    o.createGpuResource();\r\n                    //console.log(\"o = \", o)\r\n                    this.gpuResource = o.gpuResource;\r\n                    this._view = o.view;\r\n                }\r\n\r\n            }\r\n        }\r\n\r\n\r\n\r\n\r\n        this.deviceId = XGPU.deviceId;\r\n        if (this.useOutsideTexture || this.gpuTextureIOs) return;\r\n\r\n        if (this.gpuResource) {\r\n            (this.gpuResource as any).xgpuObject = null;\r\n            this.gpuResource.destroy();\r\n        }\r\n\r\n\r\n\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        (this.gpuResource as any).xgpuObject = this;\r\n\r\n        this._view = this.gpuResource.createView();\r\n        if (this.descriptor.source) this.mustBeTransfered = true;\r\n\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "destroyGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public destroyGpuResource() {\r\n\r\n        if (this.time && new Date().getTime() - this.time < 100 && XGPU.loseDeviceRecently) {\r\n            //this.createGpuResource()\r\n            return;\r\n        }\r\n        this.time = new Date().getTime();\r\n\r\n\r\n        if (this.io && XGPU.loseDeviceRecently) {\r\n\r\n            if (this.io === 1) {\r\n                const vbio = this.resourceIO;\r\n                const vbs = vbio.textures;\r\n\r\n                let temp = vbs[0].gpuTextureIOs;\r\n                vbs[0].gpuTextureIOs = null;\r\n                vbs[0].createGpuResource();\r\n                vbs[0].gpuTextureIOs = temp;\r\n\r\n                temp = vbs[1].gpuTextureIOs;\r\n                vbs[1].gpuTextureIOs = null;\r\n                vbs[1].createGpuResource();\r\n                vbs[1].gpuTextureIOs = temp;\r\n\r\n                vbs[0].gpuTextureIOs[0] = vbs[0].gpuResource;\r\n                vbs[0].gpuTextureIOs[1] = vbs[1].gpuResource;\r\n\r\n\r\n            }\r\n            return\r\n\r\n        }\r\n\r\n\r\n\r\n\r\n        if (this.resourceIO) this.resourceIO.destroy();\r\n        if (this.useOutsideTexture || this.gpuTextureIOs) return;\r\n\r\n        if (this.gpuResource) {\r\n            (this.gpuResource as any).xgpuObject = null;\r\n            this.gpuResource.destroy();\r\n        }\r\n        this._view = null;\r\n        this.gpuResource = null;\r\n        this.resourceIO = null;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "varName",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n\r\n        if (this.io != 2) return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_2d<\" + this.sampledType + \">;\\n\";\r\n\r\n        return \" @binding(\" + (bindingId) + \") @group(\" + groupId + \") var \" + varName + \" : texture_storage_2d<rgba8unorm, write>;\\n\";\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupLayoutEntry",
                  "returnType": "{ binding: number; visibility: number; storageTexture?: GPUStorageTextureBindingLayout; texture?: GPUTextureBindingLayout; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, storageTexture?: GPUStorageTextureBindingLayout, texture?: GPUTextureBindingLayout } {\r\n\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        //console.warn(\"createBindGroupLayoutEntry \", this.io)\r\n\r\n\r\n        if (this.io != 2) return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,\r\n            ...this.textureType,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"2d\",\r\n                multisampled: false\r\n            },\r\n\r\n        }\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,\r\n\r\n            storageTexture: {\r\n                access: \"write-only\",\r\n                format: \"rgba8unorm\"\r\n            },\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupEntry",
                  "returnType": "{ binding: number; resource: GPUTextureView; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUTextureView } {\r\n        if (!this.gpuResource || this.deviceId != XGPU.deviceId) this.createGpuResource();\r\n\r\n        //console.log(\"ImageTexture.createBindgroupEntry \", this.deviceId)\r\n\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setPipelineType",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "pipelineType",
                      "type": "\"render\" | \"compute\" | \"compute_mixed\""
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n\r\n        if (pipelineType === \"render\") {\r\n\r\n            this.descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT;\r\n\r\n        } else if (pipelineType === \"compute_mixed\") { //the image is processed from a ComputePipeline and use inside a RenderPipeline\r\n\r\n            if (this.io === 1) { //read buffer\r\n                this.descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST;\r\n\r\n            } else if (this.io === 2) { //write buffer\r\n                this.descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.STORAGE_BINDING;\r\n            }\r\n\r\n        } else if (pipelineType === \"compute\") {\r\n\r\n            if (this.io !== 0) {\r\n                this.descriptor.usage = GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.STORAGE_BINDING;\r\n            }\r\n        }\r\n    }"
                }
              ],
              "private": [
                {
                  "objectType": "method",
                  "name": "initFromTexture",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "tex",
                      "type": "GPUTexture"
                    }
                  ],
                  "visibility": "private",
                  "rawText": "private initFromTexture(tex: GPUTexture) {\r\n        this.gpuResource = tex;\r\n        this.descriptor.format = tex.format;\r\n        this.descriptor.usage = tex.usage;\r\n        this._view = this.gpuResource.createView();\r\n        this.descriptor.source = undefined;\r\n        this.useOutsideTexture = true;\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "descriptor",
                  "type": "{ source?: any; size?: GPUExtent3D; usage?: GPUTextureUsageFlags; format?: GPUTextureFormat; defaultViewDescriptor?: GPUTextureViewDescriptor; sampledType?: \"u32\" | \"f32\" | \"i32\"; label?: string; }"
                }
              ],
              "rawText": "constructor(descriptor: {\r\n        source?: ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture | RenderPassTexture\r\n        size?: GPUExtent3D,\r\n        usage?: GPUTextureUsageFlags,\r\n        format?: GPUTextureFormat,\r\n        defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n        sampledType?: \"f32\" | \"i32\" | \"u32\",\r\n        label?: string,\r\n    }) {\r\n\r\n        super();\r\n        descriptor = { ...descriptor };\r\n        this.descriptor = descriptor as any;\r\n\r\n        //console.warn(\"imageTExture descriptor = \", descriptor);\r\n        if (undefined === descriptor.sampledType) descriptor.sampledType = \"f32\";\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (undefined === descriptor.format) descriptor.format = \"rgba8unorm\";\r\n        if (undefined === descriptor.label) descriptor.label = \"ImageTexture\";\r\n        if (undefined === descriptor.size) {\r\n            if (descriptor.source) {\r\n\r\n                descriptor.size = [descriptor.source.width, descriptor.source.height];\r\n\r\n\r\n\r\n                if (descriptor.source instanceof GPUTexture) {\r\n                    this.initFromTexture(descriptor.source);\r\n                } else if (descriptor.source instanceof ImageTexture && descriptor.source.isRenderPass) {\r\n                    //I canoot use instanceof in the constructor of ImageTexture with a class that extends it.\r\n                    //but I wanted to write 'if (descriptor.source instanceof RenderPassTexture){' \r\n\r\n                    this.renderPassTexture = descriptor.source;\r\n                    //console.log(\"wait resource changed\")\r\n                    this.renderPassTexture.addEventListener(\"RESOURCE_CHANGED\", () => {\r\n                        //console.log(\"ON_RESOURCE_CHANGED\")\r\n                        this.initFromTexture(this.renderPassTexture.texture)\r\n                    });\r\n                    this.initFromTexture(descriptor.source.texture)\r\n                }\r\n\r\n            }\r\n            else descriptor.size = [1, 1];\r\n        }\r\n\r\n\r\n\r\n        if (descriptor.source) this.mustBeTransfered = true;\r\n\r\n\r\n        //this.createGpuResource()\r\n    }"
            },
            "rawText": "export class ImageTexture extends EventDispatcher implements IShaderResource {\r\n\r\n    public resourceIO: ImageTextureIO;\r\n    public io: number = 0;\r\n    public mustBeTransfered: boolean = false;\r\n    public descriptor: ImageTextureDescriptor\r\n    public gpuResource: GPUTexture;\r\n\r\n\r\n    protected _view: GPUTextureView;\r\n    protected viewDescriptor: GPUTextureViewDescriptor = undefined;\r\n    protected useOutsideTexture: boolean = false;\r\n\r\n    protected renderPassTexture: RenderPassTexture;\r\n\r\n    constructor(descriptor: {\r\n        source?: ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture | RenderPassTexture\r\n        size?: GPUExtent3D,\r\n        usage?: GPUTextureUsageFlags,\r\n        format?: GPUTextureFormat,\r\n        defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n        sampledType?: \"f32\" | \"i32\" | \"u32\",\r\n        label?: string,\r\n    }) {\r\n\r\n        super();\r\n        descriptor = { ...descriptor };\r\n        this.descriptor = descriptor as any;\r\n\r\n        //console.warn(\"imageTExture descriptor = \", descriptor);\r\n        if (undefined === descriptor.sampledType) descriptor.sampledType = \"f32\";\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (undefined === descriptor.format) descriptor.format = \"rgba8unorm\";\r\n        if (undefined === descriptor.label) descriptor.label = \"ImageTexture\";\r\n        if (undefined === descriptor.size) {\r\n            if (descriptor.source) {\r\n\r\n                descriptor.size = [descriptor.source.width, descriptor.source.height];\r\n\r\n\r\n\r\n                if (descriptor.source instanceof GPUTexture) {\r\n                    this.initFromTexture(descriptor.source);\r\n                } else if (descriptor.source instanceof ImageTexture && descriptor.source.isRenderPass) {\r\n                    //I canoot use instanceof in the constructor of ImageTexture with a class that extends it.\r\n                    //but I wanted to write 'if (descriptor.source instanceof RenderPassTexture){' \r\n\r\n                    this.renderPassTexture = descriptor.source;\r\n                    //console.log(\"wait resource changed\")\r\n                    this.renderPassTexture.addEventListener(\"RESOURCE_CHANGED\", () => {\r\n                        //console.log(\"ON_RESOURCE_CHANGED\")\r\n                        this.initFromTexture(this.renderPassTexture.texture)\r\n                    });\r\n                    this.initFromTexture(descriptor.source.texture)\r\n                }\r\n\r\n            }\r\n            else descriptor.size = [1, 1];\r\n        }\r\n\r\n\r\n\r\n        if (descriptor.source) this.mustBeTransfered = true;\r\n\r\n\r\n        //this.createGpuResource()\r\n    }\r\n\r\n\r\n    private initFromTexture(tex: GPUTexture) {\r\n        this.gpuResource = tex;\r\n        this.descriptor.format = tex.format;\r\n        this.descriptor.usage = tex.usage;\r\n        this._view = this.gpuResource.createView();\r\n        this.descriptor.source = undefined;\r\n        this.useOutsideTexture = true;\r\n    }\r\n\r\n\r\n    public clone(): ImageTexture {\r\n        return new ImageTexture(this.descriptor);\r\n    }\r\n\r\n    public get sampledType(): \"f32\" | \"i32\" | \"u32\" { return this.descriptor.sampledType }\r\n    public set sampledType(type: \"f32\" | \"i32\" | \"u32\") { this.descriptor.sampledType = type; }\r\n    public get isRenderPass(): boolean { return false; }\r\n\r\n\r\n    protected gpuTextureIOs: GPUTexture[];\r\n    protected gpuTextureIO_index: number = 1;\r\n    public initTextureIO(textures: GPUTexture[]) {\r\n        this.gpuTextureIOs = textures;\r\n    }\r\n\r\n    public get texture(): GPUTexture {\r\n\r\n        //if (this.gpuTextureIOs) return this.gpuTextureIOs[this.gpuTextureIO_index++ % 2]\r\n        return this.gpuResource;\r\n    }\r\n\r\n    public getCurrentTexture(): GPUTexture {\r\n        //if (this.gpuTextureIOs) return this.gpuTextureIOs[(this.gpuTextureIO_index + 1) % 2]\r\n        return this.gpuResource;\r\n    }\r\n\r\n\r\n\r\n\r\n    public createView(viewDescriptor?: GPUTextureViewDescriptor): GPUTextureView {\r\n        if (this.useOutsideTexture) return null;\r\n        let desc: GPUTextureViewDescriptor = this.viewDescriptor;\r\n        if (viewDescriptor) desc = viewDescriptor;\r\n        return this.gpuResource.createView(desc);\r\n    }\r\n\r\n\r\n\r\n    public resize(w: number, h: number): ImageTexture {\r\n        if (this.useOutsideTexture) return null;\r\n        this.descriptor.size = [w, h];\r\n        this.createGpuResource()\r\n        return this;\r\n    }\r\n\r\n    public get view(): GPUTextureView {\r\n        //console.log(\"aaa\")\r\n        if (!this._view) this.createGpuResource();\r\n        return this._view;\r\n\r\n    }\r\n\r\n\r\n\r\n    public get source(): ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture | RenderPassTexture { return this.descriptor.source }\r\n    public set source(bmp: ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture | RenderPassTexture) {\r\n        this.useOutsideTexture = bmp instanceof GPUTexture || (bmp instanceof ImageTexture && bmp.isRenderPass);\r\n\r\n        //console.warn(\"SOURCE ==============================================   source = \", bmp)\r\n\r\n        if (this.useOutsideTexture) {\r\n            if (bmp instanceof GPUTexture) {\r\n                this.gpuResource = bmp as GPUTexture;\r\n                this._view = this.gpuResource.createView();\r\n            } else {\r\n                this.renderPassTexture = bmp as any;\r\n                this.renderPassTexture.clearEvents(\"RESOURCE_CHANGED\");\r\n                this.renderPassTexture.addEventListener(\"RESOURCE_CHANGED\", () => {\r\n                    //console.log(\"ON_RESOURCE_CHANGED\")\r\n                    this.initFromTexture(this.renderPassTexture.texture)\r\n                });\r\n\r\n\r\n\r\n                this.gpuResource = (bmp as ImageTexture).texture;\r\n                this._view = this.gpuResource.createView();\r\n            }\r\n\r\n\r\n        } else this.mustBeTransfered = true;\r\n        this.descriptor.source = bmp;\r\n\r\n\r\n    }\r\n\r\n    public update(pipeline: Pipeline): void {\r\n\r\n\r\n\r\n        if (this.renderPassTexture && !this.renderPassTexture.mustUseCopyTextureToTexture) this.renderPassTexture.applyRenderPass(pipeline);\r\n        if (this.useOutsideTexture) return;\r\n\r\n        if (!this.gpuResource) this.createGpuResource()\r\n\r\n\r\n\r\n        if (this.descriptor.source) {\r\n            if (this.descriptor.source.width !== this.gpuResource.width || this.descriptor.source.height !== this.gpuResource.height) {\r\n                //console.log(\"source = \", this.descriptor.source)\r\n                this.descriptor.size = [this.descriptor.source.width, this.descriptor.source.height]\r\n                this.createGpuResource();\r\n                this.mustBeTransfered = true;\r\n            }\r\n        }\r\n\r\n\r\n\r\n        if (this.mustBeTransfered) {\r\n            this.mustBeTransfered = false;\r\n            //console.log(\"updateTexture\")\r\n            XGPU.device.queue.copyExternalImageToTexture(\r\n                { source: this.descriptor.source as any, flipY: true },\r\n                { texture: this.gpuResource },\r\n                this.descriptor.size\r\n            );\r\n\r\n\r\n        }\r\n\r\n    }\r\n\r\n    public deviceId: number;\r\n\r\n    public createGpuResource(): void {\r\n        //console.warn(\"imageTexture.createGpuResource \", this.deviceId, XGPU.deviceId, this.useOutsideTexture, this.descriptor.source)\r\n\r\n        if (this.useOutsideTexture && this.gpuResource) {\r\n            if (this.deviceId != XGPU.deviceId) {\r\n                const o = (this.gpuResource as any).xgpuObject;\r\n                if (o) {\r\n                    o.createGpuResource();\r\n                    //console.log(\"o = \", o)\r\n                    this.gpuResource = o.gpuResource;\r\n                    this._view = o.view;\r\n                }\r\n\r\n            }\r\n        }\r\n\r\n\r\n\r\n\r\n        this.deviceId = XGPU.deviceId;\r\n        if (this.useOutsideTexture || this.gpuTextureIOs) return;\r\n\r\n        if (this.gpuResource) {\r\n            (this.gpuResource as any).xgpuObject = null;\r\n            this.gpuResource.destroy();\r\n        }\r\n\r\n\r\n\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        (this.gpuResource as any).xgpuObject = this;\r\n\r\n        this._view = this.gpuResource.createView();\r\n        if (this.descriptor.source) this.mustBeTransfered = true;\r\n\r\n\r\n    }\r\n\r\n\r\n    public time: number;\r\n    public destroyGpuResource() {\r\n\r\n        if (this.time && new Date().getTime() - this.time < 100 && XGPU.loseDeviceRecently) {\r\n            //this.createGpuResource()\r\n            return;\r\n        }\r\n        this.time = new Date().getTime();\r\n\r\n\r\n        if (this.io && XGPU.loseDeviceRecently) {\r\n\r\n            if (this.io === 1) {\r\n                const vbio = this.resourceIO;\r\n                const vbs = vbio.textures;\r\n\r\n                let temp = vbs[0].gpuTextureIOs;\r\n                vbs[0].gpuTextureIOs = null;\r\n                vbs[0].createGpuResource();\r\n                vbs[0].gpuTextureIOs = temp;\r\n\r\n                temp = vbs[1].gpuTextureIOs;\r\n                vbs[1].gpuTextureIOs = null;\r\n                vbs[1].createGpuResource();\r\n                vbs[1].gpuTextureIOs = temp;\r\n\r\n                vbs[0].gpuTextureIOs[0] = vbs[0].gpuResource;\r\n                vbs[0].gpuTextureIOs[1] = vbs[1].gpuResource;\r\n\r\n\r\n            }\r\n            return\r\n\r\n        }\r\n\r\n\r\n\r\n\r\n        if (this.resourceIO) this.resourceIO.destroy();\r\n        if (this.useOutsideTexture || this.gpuTextureIOs) return;\r\n\r\n        if (this.gpuResource) {\r\n            (this.gpuResource as any).xgpuObject = null;\r\n            this.gpuResource.destroy();\r\n        }\r\n        this._view = null;\r\n        this.gpuResource = null;\r\n        this.resourceIO = null;\r\n    }\r\n\r\n    public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n\r\n        if (this.io != 2) return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_2d<\" + this.sampledType + \">;\\n\";\r\n\r\n        return \" @binding(\" + (bindingId) + \") @group(\" + groupId + \") var \" + varName + \" : texture_storage_2d<rgba8unorm, write>;\\n\";\r\n    }\r\n\r\n    protected _textureType: { texture: any } | { storageTexture: any };\r\n    public get textureType(): any { return this._textureType }\r\n    public set textureType(o: any) {\r\n        //console.log(\"set textureType \", o)\r\n        this._textureType = o;\r\n    }\r\n    public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, storageTexture?: GPUStorageTextureBindingLayout, texture?: GPUTextureBindingLayout } {\r\n\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        //console.warn(\"createBindGroupLayoutEntry \", this.io)\r\n\r\n\r\n        if (this.io != 2) return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,\r\n            ...this.textureType,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"2d\",\r\n                multisampled: false\r\n            },\r\n\r\n        }\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,\r\n\r\n            storageTexture: {\r\n                access: \"write-only\",\r\n                format: \"rgba8unorm\"\r\n            },\r\n        }\r\n    }\r\n\r\n\r\n    public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUTextureView } {\r\n        if (!this.gpuResource || this.deviceId != XGPU.deviceId) this.createGpuResource();\r\n\r\n        //console.log(\"ImageTexture.createBindgroupEntry \", this.deviceId)\r\n\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view\r\n        }\r\n    }\r\n\r\n    public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n\r\n        if (pipelineType === \"render\") {\r\n\r\n            this.descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT;\r\n\r\n        } else if (pipelineType === \"compute_mixed\") { //the image is processed from a ComputePipeline and use inside a RenderPipeline\r\n\r\n            if (this.io === 1) { //read buffer\r\n                this.descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST;\r\n\r\n            } else if (this.io === 2) { //write buffer\r\n                this.descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.STORAGE_BINDING;\r\n            }\r\n\r\n        } else if (pipelineType === \"compute\") {\r\n\r\n            if (this.io !== 0) {\r\n                this.descriptor.usage = GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.STORAGE_BINDING;\r\n            }\r\n        }\r\n    }\r\n\r\n}"
          }
        ],
        "ImageTextureArray": [
          {
            "objectType": "type",
            "name": "ImageTextureArrayDescriptor",
            "type": "ImageTextureArrayDescriptor",
            "rawText": "export type ImageTextureArrayDescriptor = {\r\n    source?: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[],\r\n    size: GPUExtent3D,\r\n    usage?: GPUTextureUsageFlags,\r\n    dimension: string,\r\n    defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n    sampledType?: \"f32\" | \"i32\" | \"u32\"\r\n}"
          },
          {
            "objectType": "class",
            "name": "ImageTextureArray",
            "filePath": "xGPU.shader.resources.ImageTextureArray",
            "extends": [
              "ImageTexture",
              "EventDispatcher"
            ],
            "implements": [
              "IShaderResource"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "declare public descriptor: any;"
                },
                {
                  "objectType": "property",
                  "name": "bitmaps",
                  "type": "any[]",
                  "visibility": "public",
                  "rawText": "public set bitmaps(images: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[]) {\r\n        for (let i = 0; i < images.length; i++) {\r\n            this._bitmaps[i] = images[i];\r\n            this.mustUpdate[i] = true;\r\n        }\r\n        this.mustBeTransfered = true;\r\n        this.update();\r\n    }",
                  "set": true,
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "_bitmaps",
                  "type": "any[]",
                  "visibility": "protected",
                  "rawText": "protected _bitmaps: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "mustUpdate",
                  "type": "boolean[]",
                  "visibility": "protected",
                  "rawText": "protected mustUpdate: boolean[] = [];"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "ImageTextureArray",
                  "visibility": "public",
                  "rawText": "public clone(): ImageTextureArray {\r\n        if (!this.descriptor.source) this.descriptor.source = this._bitmaps;\r\n        return new ImageTextureArray(this.descriptor);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setImageById",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "image",
                      "type": "any"
                    },
                    {
                      "name": "id",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setImageById(image: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture), id: number) {\r\n        this._bitmaps[id] = image;\r\n        this.mustUpdate[id] = true;\r\n        this.mustBeTransfered = true;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public createGpuResource(): void {\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n        //console.log(\"cubemap createtexture \", this.descriptor)\r\n\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        this._view = this.gpuResource.createView({ dimension: '2d-array', arrayLayerCount: this._bitmaps.length });\r\n\r\n        for (let i = 0; i < this.mustUpdate.length; i++) this.mustUpdate[i] = true;\r\n        this.mustBeTransfered = true;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "updateInnerGpuTextures",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "commandEncoder",
                      "type": "GPUCommandEncoder"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public updateInnerGpuTextures(commandEncoder: GPUCommandEncoder) {\r\n        let bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture;\r\n        for (let i = 0; i < this._bitmaps.length; i++) {\r\n            bmp = this.bitmaps[i];\r\n            if (bmp instanceof GPUTexture) {\r\n                commandEncoder.copyTextureToTexture({ texture: bmp }, { texture: this.gpuResource }, [this.gpuResource.width, this.gpuResource.height, i])\r\n            }\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public update(): void {\r\n\r\n\r\n        if (this.mustBeTransfered) {\r\n            //console.log(\"update textureArray\")\r\n            if (!this.gpuResource) this.createGpuResource();\r\n\r\n            let bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture;\r\n            for (let i = 0; i < this._bitmaps.length; i++) {\r\n                bmp = this.bitmaps[i];\r\n\r\n                if (!(bmp instanceof GPUTexture) && this.mustUpdate[i]) {\r\n                    XGPU.device.queue.copyExternalImageToTexture(\r\n                        { source: bmp },\r\n                        { texture: this.gpuResource, origin: [0, 0, i] },\r\n                        [bmp.width, bmp.height]\r\n                    );\r\n                    this.mustUpdate[i] = false;\r\n                }\r\n            }\r\n\r\n            this.mustBeTransfered = false;\r\n        }\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "varName",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_2d_array<\" + this.sampledType + \">;\\n\";\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupLayoutEntry",
                  "returnType": "{ binding: number; visibility: number; texture: GPUTextureBindingLayout; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, texture: GPUTextureBindingLayout } {\r\n\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"2d-array\",\r\n                multisampled: false\r\n            },\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupEntry",
                  "returnType": "{ binding: number; resource: GPUTextureView; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUTextureView } {\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view,\r\n        }\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "descriptor",
                  "type": "{ source?: (HTMLCanvasElement | ImageBitmap | HTMLVideoElement | OffscreenCanvas)[]; size: GPUExtent3D; usage?: GPUTextureUsageFlags; defaultViewDescriptor?: GPUTextureViewDescriptor; dimension?: string; sampledType?: \"u32\" | ... 1 more ... | \"i32\"; }"
                }
              ],
              "rawText": "constructor(descriptor: {\r\n        source?: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas)[], ////front,back,left,right,top,bottom\r\n        size: GPUExtent3D,\r\n        usage?: GPUTextureUsageFlags,\r\n        defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n        dimension?: string,\r\n        sampledType?: \"f32\" | \"i32\" | \"u32\"\r\n    }) {\r\n\r\n        descriptor = { ...descriptor };\r\n\r\n        if (descriptor.source && !descriptor.size) {\r\n            descriptor.size = [descriptor.source[0].width, descriptor.source[0].height, descriptor.source.length]\r\n        }\r\n\r\n        if (!descriptor.dimension) descriptor.dimension = \"2d\"\r\n\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\r\n\r\n        super(descriptor as any);\r\n        if (descriptor.source) this.bitmaps = descriptor.source\r\n\r\n    }"
            },
            "rawText": "export class ImageTextureArray extends ImageTexture implements IShaderResource {\r\n\r\n\r\n    declare public descriptor: any;\r\n\r\n    protected _bitmaps: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[] = [];\r\n    protected mustUpdate: boolean[] = [];\r\n    constructor(descriptor: {\r\n        source?: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas)[], ////front,back,left,right,top,bottom\r\n        size: GPUExtent3D,\r\n        usage?: GPUTextureUsageFlags,\r\n        defaultViewDescriptor?: GPUTextureViewDescriptor,\r\n        dimension?: string,\r\n        sampledType?: \"f32\" | \"i32\" | \"u32\"\r\n    }) {\r\n\r\n        descriptor = { ...descriptor };\r\n\r\n        if (descriptor.source && !descriptor.size) {\r\n            descriptor.size = [descriptor.source[0].width, descriptor.source[0].height, descriptor.source.length]\r\n        }\r\n\r\n        if (!descriptor.dimension) descriptor.dimension = \"2d\"\r\n\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\r\n\r\n        super(descriptor as any);\r\n        if (descriptor.source) this.bitmaps = descriptor.source\r\n\r\n    }\r\n\r\n\r\n    public clone(): ImageTextureArray {\r\n        if (!this.descriptor.source) this.descriptor.source = this._bitmaps;\r\n        return new ImageTextureArray(this.descriptor);\r\n    }\r\n\r\n\r\n\r\n\r\n    public set bitmaps(images: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[]) {\r\n        for (let i = 0; i < images.length; i++) {\r\n            this._bitmaps[i] = images[i];\r\n            this.mustUpdate[i] = true;\r\n        }\r\n        this.mustBeTransfered = true;\r\n        this.update();\r\n    }\r\n    public get bitmaps(): (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture)[] { return this._bitmaps; }\r\n\r\n    public setImageById(image: (ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture), id: number) {\r\n        this._bitmaps[id] = image;\r\n        this.mustUpdate[id] = true;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public createGpuResource(): void {\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n        //console.log(\"cubemap createtexture \", this.descriptor)\r\n\r\n        this.gpuResource = XGPU.device.createTexture(this.descriptor as GPUTextureDescriptor);\r\n        this._view = this.gpuResource.createView({ dimension: '2d-array', arrayLayerCount: this._bitmaps.length });\r\n\r\n        for (let i = 0; i < this.mustUpdate.length; i++) this.mustUpdate[i] = true;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n    public updateInnerGpuTextures(commandEncoder: GPUCommandEncoder) {\r\n        let bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture;\r\n        for (let i = 0; i < this._bitmaps.length; i++) {\r\n            bmp = this.bitmaps[i];\r\n            if (bmp instanceof GPUTexture) {\r\n                commandEncoder.copyTextureToTexture({ texture: bmp }, { texture: this.gpuResource }, [this.gpuResource.width, this.gpuResource.height, i])\r\n            }\r\n        }\r\n    }\r\n\r\n    public update(): void {\r\n\r\n\r\n        if (this.mustBeTransfered) {\r\n            //console.log(\"update textureArray\")\r\n            if (!this.gpuResource) this.createGpuResource();\r\n\r\n            let bmp: ImageBitmap | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | GPUTexture;\r\n            for (let i = 0; i < this._bitmaps.length; i++) {\r\n                bmp = this.bitmaps[i];\r\n\r\n                if (!(bmp instanceof GPUTexture) && this.mustUpdate[i]) {\r\n                    XGPU.device.queue.copyExternalImageToTexture(\r\n                        { source: bmp },\r\n                        { texture: this.gpuResource, origin: [0, 0, i] },\r\n                        [bmp.width, bmp.height]\r\n                    );\r\n                    this.mustUpdate[i] = false;\r\n                }\r\n            }\r\n\r\n            this.mustBeTransfered = false;\r\n        }\r\n\r\n    }\r\n\r\n    //-----\r\n\r\n    public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_2d_array<\" + this.sampledType + \">;\\n\";\r\n    }\r\n\r\n\r\n    public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, texture: GPUTextureBindingLayout } {\r\n\r\n        let sampleType: GPUTextureSampleType = \"float\";\r\n        if (this.sampledType === \"i32\") sampleType = \"sint\";\r\n        else if (this.sampledType === \"u32\") sampleType = \"uint\";\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT,\r\n            texture: {\r\n                sampleType,\r\n                viewDimension: \"2d-array\",\r\n                multisampled: false\r\n            },\r\n        }\r\n    }\r\n\r\n\r\n    public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUTextureView } {\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        return {\r\n            binding: bindingId,\r\n            resource: this._view,\r\n        }\r\n    }\r\n\r\n\r\n}"
          }
        ],
        "ImageTextureIO": [
          {
            "objectType": "class",
            "name": "ImageTextureIO",
            "filePath": "xGPU.shader.resources.ImageTextureIO",
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "textures",
                  "type": "ImageTexture[]",
                  "visibility": "public",
                  "rawText": "public textures: ImageTexture[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "{ size: GPUExtent3D; format: GPUTextureFormat; usage?: number; }",
                  "visibility": "public",
                  "rawText": "public descriptor: { size: GPUExtent3D, format: GPUTextureFormat, usage?: number }"
                },
                {
                  "objectType": "property",
                  "name": "onOutputData",
                  "type": "(data: Uint32Array) => void",
                  "visibility": "public",
                  "rawText": "public onOutputData: (data: Uint32Array) => void;"
                },
                {
                  "objectType": "property",
                  "name": "width",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get width(): number { return this.textures[0].gpuResource.width }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "height",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get height(): number { return this.textures[0].gpuResource.height }",
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "stagingBuffer",
                  "type": "GPUBuffer",
                  "visibility": "protected",
                  "rawText": "protected stagingBuffer: GPUBuffer;"
                },
                {
                  "objectType": "property",
                  "name": "canCallMapAsync",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected canCallMapAsync: boolean = true;"
                },
                {
                  "objectType": "property",
                  "name": "outputBuffer",
                  "type": "GPUBuffer",
                  "visibility": "protected",
                  "rawText": "protected outputBuffer: GPUBuffer;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "ImageTextureIO",
                  "visibility": "public",
                  "rawText": "public clone(): ImageTextureIO {\r\n        const obj = {\r\n            source: this.textures[0].gpuResource,\r\n            width: this.descriptor.size[0],\r\n            height: this.descriptor.size[1],\r\n            format: this.descriptor.format\r\n        }\r\n        return new ImageTextureIO(obj);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(name: string, bindingId: number, groupId: number): string {\r\n\r\n\r\n\r\n        let result = \"\";\r\n        const varName = name.substring(0, 1).toLowerCase() + name.slice(1);\r\n        result += \" @binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \" : texture_2d<f32>;\\n\";\r\n        result += \" @binding(\" + (bindingId + 1) + \") @group(\" + groupId + \") var \" + varName + \"_out\" + \" : texture_storage_2d<rgba8unorm, write>;\\n\";\r\n        return result;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "destroy",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public destroy() {\r\n        if (this.stagingBuffer) this.stagingBuffer.destroy();\r\n        this.textures = undefined;\r\n        this.onOutputData = undefined;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getOutputData",
                  "returnType": "Promise<void>",
                  "visibility": "public",
                  "rawText": "public async getOutputData() {\r\n\r\n        if (!this.onOutputData || !this.canCallMapAsync) return;\r\n\r\n        if (!this.outputBuffer) {\r\n\r\n            this.outputBuffer = XGPU.device.createBuffer({\r\n                size: this.width * this.height * 4 * 4,\r\n                usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,\r\n                mappedAtCreation: false,\r\n            })\r\n\r\n            this.stagingBuffer = XGPU.createStagingBuffer(this.outputBuffer.size);\r\n        }\r\n\r\n        var texture = this.textures[0].gpuResource;\r\n        const copyEncoder = XGPU.device.createCommandEncoder();\r\n        const stage = this.stagingBuffer;\r\n\r\n        copyEncoder.copyTextureToBuffer({ texture: texture }, { buffer: this.outputBuffer, bytesPerRow: Math.ceil((this.width * 4) / 256) * 256, rowsPerImage: this.height }, [this.width, this.height, 1]);\r\n        copyEncoder.copyBufferToBuffer(this.outputBuffer, 0, stage, 0, stage.size);\r\n\r\n        XGPU.device.queue.submit([copyEncoder.finish()]);\r\n\r\n        this.canCallMapAsync = false;\r\n        await this.stagingBuffer.mapAsync(GPUMapMode.READ, 0, stage.size)\r\n        this.canCallMapAsync = true;\r\n\r\n        const copyArray = stage.getMappedRange(0, stage.size);\r\n        const data = copyArray.slice(0);\r\n        stage.unmap();\r\n\r\n        this.onOutputData(new Uint32Array(data));\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "textureSize",
                  "returnType": "GPUExtent3D",
                  "visibility": "public",
                  "rawText": "public textureSize(): GPUExtent3D { return this.descriptor.size }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "descriptor",
                  "type": "{ source: any; width?: number; height?: number; format?: GPUTextureFormat; }"
                }
              ],
              "rawText": "constructor(descriptor: {\r\n        source: ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture | null,\r\n        width?: number,\r\n        height?: number,\r\n        format?: GPUTextureFormat\r\n    }) {\r\n\r\n        let w, h;\r\n        if (descriptor.source != null) {\r\n            w = descriptor.source.width;\r\n            h = descriptor.source.height;\r\n        } else {\r\n            if (!descriptor.width || !descriptor.height) {\r\n                throw new Error(\"ImageTextureIO width and/or height missing in descriptor\")\r\n            }\r\n            w = descriptor.width;\r\n            h = descriptor.height;\r\n        }\r\n\r\n\r\n        this.descriptor = {\r\n            size: [w, h],\r\n            format: \"rgba8unorm\",\r\n            usage: (descriptor.source instanceof GPUTexture) ? descriptor.source.usage : undefined\r\n        };\r\n        if (descriptor.format) this.descriptor.format = descriptor.format;\r\n\r\n        this.textures[0] = new ImageTexture(this.descriptor);\r\n        this.textures[1] = new ImageTexture(this.descriptor)\r\n\r\n\r\n        this.textures[0].io = 1;\r\n        this.textures[1].io = 2;\r\n\r\n        this.textures[0].resourceIO = this;\r\n        this.textures[1].resourceIO = this;\r\n\r\n        if (descriptor.source != null) this.textures[0].source = descriptor.source;\r\n    }"
            },
            "rawText": "export class ImageTextureIO {\r\n\r\n    public textures: ImageTexture[] = [];\r\n    public descriptor: { size: GPUExtent3D, format: GPUTextureFormat, usage?: number }\r\n\r\n    protected stagingBuffer: GPUBuffer;\r\n    protected canCallMapAsync: boolean = true;\r\n    public onOutputData: (data: Uint32Array) => void;\r\n\r\n    constructor(descriptor: {\r\n        source: ImageBitmap | HTMLCanvasElement | HTMLVideoElement | OffscreenCanvas | GPUTexture | null,\r\n        width?: number,\r\n        height?: number,\r\n        format?: GPUTextureFormat\r\n    }) {\r\n\r\n        let w, h;\r\n        if (descriptor.source != null) {\r\n            w = descriptor.source.width;\r\n            h = descriptor.source.height;\r\n        } else {\r\n            if (!descriptor.width || !descriptor.height) {\r\n                throw new Error(\"ImageTextureIO width and/or height missing in descriptor\")\r\n            }\r\n            w = descriptor.width;\r\n            h = descriptor.height;\r\n        }\r\n\r\n\r\n        this.descriptor = {\r\n            size: [w, h],\r\n            format: \"rgba8unorm\",\r\n            usage: (descriptor.source instanceof GPUTexture) ? descriptor.source.usage : undefined\r\n        };\r\n        if (descriptor.format) this.descriptor.format = descriptor.format;\r\n\r\n        this.textures[0] = new ImageTexture(this.descriptor);\r\n        this.textures[1] = new ImageTexture(this.descriptor)\r\n\r\n\r\n        this.textures[0].io = 1;\r\n        this.textures[1].io = 2;\r\n\r\n        this.textures[0].resourceIO = this;\r\n        this.textures[1].resourceIO = this;\r\n\r\n        if (descriptor.source != null) this.textures[0].source = descriptor.source;\r\n    }\r\n\r\n    public clone(): ImageTextureIO {\r\n        const obj = {\r\n            source: this.textures[0].gpuResource,\r\n            width: this.descriptor.size[0],\r\n            height: this.descriptor.size[1],\r\n            format: this.descriptor.format\r\n        }\r\n        return new ImageTextureIO(obj);\r\n    }\r\n\r\n\r\n    public createDeclaration(name: string, bindingId: number, groupId: number): string {\r\n\r\n\r\n\r\n        let result = \"\";\r\n        const varName = name.substring(0, 1).toLowerCase() + name.slice(1);\r\n        result += \" @binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \" : texture_2d<f32>;\\n\";\r\n        result += \" @binding(\" + (bindingId + 1) + \") @group(\" + groupId + \") var \" + varName + \"_out\" + \" : texture_storage_2d<rgba8unorm, write>;\\n\";\r\n        return result;\r\n    }\r\n\r\n\r\n    protected outputBuffer: GPUBuffer;\r\n\r\n\r\n    public destroy() {\r\n        if (this.stagingBuffer) this.stagingBuffer.destroy();\r\n        this.textures = undefined;\r\n        this.onOutputData = undefined;\r\n    }\r\n\r\n    public async getOutputData() {\r\n\r\n        if (!this.onOutputData || !this.canCallMapAsync) return;\r\n\r\n        if (!this.outputBuffer) {\r\n\r\n            this.outputBuffer = XGPU.device.createBuffer({\r\n                size: this.width * this.height * 4 * 4,\r\n                usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,\r\n                mappedAtCreation: false,\r\n            })\r\n\r\n            this.stagingBuffer = XGPU.createStagingBuffer(this.outputBuffer.size);\r\n        }\r\n\r\n        var texture = this.textures[0].gpuResource;\r\n        const copyEncoder = XGPU.device.createCommandEncoder();\r\n        const stage = this.stagingBuffer;\r\n\r\n        copyEncoder.copyTextureToBuffer({ texture: texture }, { buffer: this.outputBuffer, bytesPerRow: Math.ceil((this.width * 4) / 256) * 256, rowsPerImage: this.height }, [this.width, this.height, 1]);\r\n        copyEncoder.copyBufferToBuffer(this.outputBuffer, 0, stage, 0, stage.size);\r\n\r\n        XGPU.device.queue.submit([copyEncoder.finish()]);\r\n\r\n        this.canCallMapAsync = false;\r\n        await this.stagingBuffer.mapAsync(GPUMapMode.READ, 0, stage.size)\r\n        this.canCallMapAsync = true;\r\n\r\n        const copyArray = stage.getMappedRange(0, stage.size);\r\n        const data = copyArray.slice(0);\r\n        stage.unmap();\r\n\r\n        this.onOutputData(new Uint32Array(data));\r\n\r\n    }\r\n\r\n\r\n\r\n    public get width(): number { return this.textures[0].gpuResource.width }\r\n    public get height(): number { return this.textures[0].gpuResource.height }\r\n\r\n    public textureSize(): GPUExtent3D { return this.descriptor.size }\r\n\r\n}"
          }
        ],
        "StageableBuffer": [
          {
            "objectType": "class",
            "name": "StageableBuffer",
            "filePath": "xGPU.shader.resources.StageableBuffer",
            "extends": [
              "EventDispatcher"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "onOutputData",
                  "type": "(data: ArrayBuffer) => void",
                  "visibility": "public",
                  "rawText": "public onOutputData:((data:ArrayBuffer)=>void)|null = null;"
                },
                {
                  "objectType": "property",
                  "name": "onCanCallMapAsync",
                  "type": "() => void",
                  "visibility": "public",
                  "rawText": "public onCanCallMapAsync:(()=>void)|null = null;"
                },
                {
                  "objectType": "property",
                  "name": "mustOutputData",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public get mustOutputData():boolean{\r\n       return !!this.onOutputData || this.hasEventListener(StageableBuffer.ON_OUTPUT_DATA)\r\n    }",
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "stagingBuffer",
                  "type": "GPUBuffer",
                  "visibility": "protected",
                  "rawText": "protected stagingBuffer:GPUBuffer;"
                },
                {
                  "objectType": "property",
                  "name": "canCallMapAsync",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected canCallMapAsync:boolean = true;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "getOutputData",
                  "returnType": "Promise<void>",
                  "params": [
                    {
                      "name": "buffer",
                      "type": "GPUBuffer"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public async getOutputData(buffer:GPUBuffer){\r\n       if(!this.onOutputData && !this.hasEventListener(StageableBuffer.ON_OUTPUT_DATA)) return;\r\n       \r\n\r\n       if (!this.canCallMapAsync){\r\n           //console.warn(\"the last call of 'getOutputData' is not completed yet. You must wait 'ON_OUTPUT_DATA' to call computePipeline.nextFrame()\" )\r\n           return\r\n       } \r\n\r\n       this.dispatchEvent(StageableBuffer.ON_OUTPUT_PROCESS_START)\r\n       this.canCallMapAsync = false;\r\n       //const buffer:GPUBuffer = this.gpuResource;\r\n\r\n       //console.log(\"getOutputData \",buffer.size+\" vs \"+this.bufferSize);\r\n\r\n       if (!this.stagingBuffer || buffer.size != this.stagingBuffer.size) this.stagingBuffer = XGPU.createStagingBuffer(buffer.size);\r\n       const copyEncoder = XGPU.device.createCommandEncoder();\r\n       const stage = this.stagingBuffer;\r\n\r\n       copyEncoder.copyBufferToBuffer(buffer, 0, stage, 0, stage.size);\r\n       XGPU.device.queue.submit([copyEncoder.finish()]);\r\n\r\n       await this.stagingBuffer.mapAsync(GPUMapMode.READ, 0, stage.size)\r\n      \r\n       const copyArray = stage.getMappedRange(0, stage.size);\r\n       const data = copyArray.slice(0);\r\n       stage.unmap();\r\n       this.canCallMapAsync = true;\r\n       if(this.onCanCallMapAsync) this.onCanCallMapAsync();\r\n\r\n       this.dispatchEvent(StageableBuffer.ON_OUTPUT_DATA,data);\r\n       if(this.onOutputData) this.onOutputData(data);\r\n\r\n    }"
                }
              ]
            },
            "statics": {
              "properties": {
                "public": [
                  {
                    "objectType": "property",
                    "name": "ON_OUTPUT_DATA",
                    "type": "string",
                    "visibility": "public",
                    "rawText": "public static ON_OUTPUT_DATA:string = \"ON_OUTPUT_DATA\";"
                  },
                  {
                    "objectType": "property",
                    "name": "ON_OUTPUT_PROCESS_START",
                    "type": "string",
                    "visibility": "public",
                    "rawText": "public static ON_OUTPUT_PROCESS_START:string = \"ON_OUTPUT_PROCESS_START\";"
                  }
                ]
              }
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "rawText": "constructor(){\r\n        super();\r\n    }"
            },
            "rawText": "export class StageableBuffer extends EventDispatcher {\r\n\r\n    public static ON_OUTPUT_DATA:string = \"ON_OUTPUT_DATA\";\r\n    public static ON_OUTPUT_PROCESS_START:string = \"ON_OUTPUT_PROCESS_START\";\r\n    public onOutputData:((data:ArrayBuffer)=>void)|null = null;\r\n\r\n   \r\n    constructor(){\r\n        super();\r\n    }\r\n\r\n\r\n    protected stagingBuffer:GPUBuffer;\r\n    protected canCallMapAsync:boolean = true;\r\n    public onCanCallMapAsync:(()=>void)|null = null;\r\n   \r\n\r\n    public get mustOutputData():boolean{\r\n       return !!this.onOutputData || this.hasEventListener(StageableBuffer.ON_OUTPUT_DATA)\r\n    }\r\n\r\n    public async getOutputData(buffer:GPUBuffer){\r\n       if(!this.onOutputData && !this.hasEventListener(StageableBuffer.ON_OUTPUT_DATA)) return;\r\n       \r\n\r\n       if (!this.canCallMapAsync){\r\n           //console.warn(\"the last call of 'getOutputData' is not completed yet. You must wait 'ON_OUTPUT_DATA' to call computePipeline.nextFrame()\" )\r\n           return\r\n       } \r\n\r\n       this.dispatchEvent(StageableBuffer.ON_OUTPUT_PROCESS_START)\r\n       this.canCallMapAsync = false;\r\n       //const buffer:GPUBuffer = this.gpuResource;\r\n\r\n       //console.log(\"getOutputData \",buffer.size+\" vs \"+this.bufferSize);\r\n\r\n       if (!this.stagingBuffer || buffer.size != this.stagingBuffer.size) this.stagingBuffer = XGPU.createStagingBuffer(buffer.size);\r\n       const copyEncoder = XGPU.device.createCommandEncoder();\r\n       const stage = this.stagingBuffer;\r\n\r\n       copyEncoder.copyBufferToBuffer(buffer, 0, stage, 0, stage.size);\r\n       XGPU.device.queue.submit([copyEncoder.finish()]);\r\n\r\n       await this.stagingBuffer.mapAsync(GPUMapMode.READ, 0, stage.size)\r\n      \r\n       const copyArray = stage.getMappedRange(0, stage.size);\r\n       const data = copyArray.slice(0);\r\n       stage.unmap();\r\n       this.canCallMapAsync = true;\r\n       if(this.onCanCallMapAsync) this.onCanCallMapAsync();\r\n\r\n       this.dispatchEvent(StageableBuffer.ON_OUTPUT_DATA,data);\r\n       if(this.onOutputData) this.onOutputData(data);\r\n\r\n    }\r\n\r\n}"
          }
        ],
        "TextureSampler": [
          {
            "objectType": "type",
            "name": "TextureSamplerDescriptor",
            "type": "TextureSamplerDescriptor",
            "rawText": "export type TextureSamplerDescriptor = {\r\n    minFilter?: \"nearest\" | \"linear\",\r\n    magFilter?: \"nearest\" | \"linear\",\r\n    addressModeU?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\",\r\n    addressModeV?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\",\r\n    addressModeW?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\",\r\n    mipmapFilter?: \"nearest\" | \"linear\",\r\n    lodMinClamp?: number,\r\n    lodMaxClamp?: number,\r\n    maxAnisotropy?: number\r\n    compare?: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\"\r\n}"
          },
          {
            "objectType": "class",
            "name": "TextureSampler",
            "filePath": "xGPU.shader.resources.TextureSampler",
            "implements": [
              "IShaderResource"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "mustBeTransfered",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public mustBeTransfered: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "gpuResource",
                  "type": "GPUSampler",
                  "visibility": "public",
                  "rawText": "public gpuResource: GPUSampler;"
                },
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "TextureSamplerDescriptor",
                  "visibility": "public",
                  "rawText": "public descriptor: TextureSamplerDescriptor;"
                },
                {
                  "objectType": "property",
                  "name": "isComparison",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public get isComparison(): boolean { return !!this.descriptor.compare }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "isFiltering",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public get isFiltering(): boolean {\r\n        /*\r\n        Note: Comparison samplers may use filtering, but the sampling results will be implementation-dependent and may differ from the normal filtering rules.\r\n        //https://www.w3.org/TR/webgpu/#enumdef-gpucomparefunction\r\n        */\r\n\r\n        return this.descriptor.minFilter === \"linear\" || this.descriptor.magFilter === \"linear\" || this.descriptor.mipmapFilter === \"linear\";\r\n    }",
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "deviceId",
                  "type": "number",
                  "visibility": "protected",
                  "rawText": "protected deviceId: number = 0;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "TextureSampler",
                  "visibility": "public",
                  "rawText": "public clone(): TextureSampler {\r\n        return new TextureSampler(this.descriptor);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setAddressModes",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "u",
                      "type": "GPUAddressMode"
                    },
                    {
                      "name": "v",
                      "type": "GPUAddressMode"
                    },
                    {
                      "name": "w",
                      "type": "GPUAddressMode"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setAddressModes(u: GPUAddressMode = \"clamp-to-edge\", v: GPUAddressMode = \"clamp-to-edge\", w: GPUAddressMode = \"clamp-to-edge\") {\r\n\r\n        this.descriptor.addressModeU = u;\r\n        this.descriptor.addressModeV = v;\r\n        this.descriptor.addressModeW = w;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setFilterModes",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "min",
                      "type": "GPUFilterMode"
                    },
                    {
                      "name": "mag",
                      "type": "GPUFilterMode"
                    },
                    {
                      "name": "mipmap",
                      "type": "GPUMipmapFilterMode"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setFilterModes(min: GPUFilterMode = \"nearest\", mag: GPUFilterMode = \"nearest\", mipmap: GPUMipmapFilterMode = \"nearest\") {\r\n        this.descriptor.minFilter = min;\r\n        this.descriptor.magFilter = mag;\r\n        this.descriptor.mipmapFilter = mipmap;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setClamp",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "min",
                      "type": "number"
                    },
                    {
                      "name": "max",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setClamp(min: number = 0, max: number = 32) {\r\n        this.descriptor.lodMinClamp = min;\r\n        this.descriptor.lodMaxClamp = max;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setCompareFunction",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "compareType",
                      "type": "\"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\""
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setCompareFunction(compareType?: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\") {\r\n        this.descriptor.compare = compareType;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setMaxAnisotropy",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "n",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setMaxAnisotropy(n: number) {\r\n        n = Math.round(n);\r\n        if (n < 1) n = 1;\r\n        if (n > 16) n = 16;\r\n        this.descriptor.maxAnisotropy = n;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public createGpuResource(): void {\r\n\r\n\r\n        //console.log(\"create sampler : \", this.descriptor)\r\n        this.gpuResource = XGPU.device.createSampler(this.descriptor);\r\n        this.deviceId = XGPU.deviceId;\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "destroyGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public destroyGpuResource() {\r\n        this.gpuResource = null;\r\n        /*\r\n        GPUSampler doesn't seem to have a destroy function\r\n        */\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public update() {\r\n        /*\r\n        GPUSampler doesn't require to be updated\r\n        */\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "varName",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        if (this.isComparison) return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":sampler_comparison;\\n\";\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":sampler;\\n\";\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupLayoutEntry",
                  "returnType": "{ binding: number; visibility: number; sampler: { type: string; }; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, sampler: { type: string } } {\r\n\r\n        let type = \"comparison\";\r\n        if (!this.isComparison) {\r\n            type = \"filtering\";\r\n            if (!this.isFiltering) {\r\n                type = \"non-filtering\";\r\n            }\r\n        }\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,\r\n            sampler: {\r\n                type: type\r\n            },\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupEntry",
                  "returnType": "{ binding: number; resource: GPUSampler; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUSampler } {\r\n        if (!this.gpuResource || this.deviceId != XGPU.deviceId) this.createGpuResource();\r\n        return {\r\n            binding: bindingId,\r\n            resource: this.gpuResource\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setPipelineType",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "pipelineType",
                      "type": "\"render\" | \"compute\" | \"compute_mixed\""
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType) { }\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "descriptor",
                  "type": "{ minFilter?: \"nearest\" | \"linear\"; magFilter?: \"nearest\" | \"linear\"; addressModeU?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\"; addressModeV?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\"; ... 5 more ...; compare?: \"never\" | ... 6 more ... | \"always\"; }"
                }
              ],
              "rawText": "constructor(descriptor?: {\r\n        minFilter?: \"nearest\" | \"linear\",\r\n        magFilter?: \"nearest\" | \"linear\",\r\n        addressModeU?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\",\r\n        addressModeV?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\",\r\n        addressModeW?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\",\r\n        mipmapFilter?: \"nearest\" | \"linear\",\r\n        lodMinClamp?: number,\r\n        lodMaxClamp?: number,\r\n        maxAnisotropy?: number\r\n        compare?: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\"\r\n    }) {\r\n\r\n        if (!descriptor) descriptor = {};\r\n\r\n        if (!descriptor.compare) {\r\n\r\n            descriptor = { ...descriptor };\r\n\r\n            if (undefined === descriptor.minFilter) descriptor.minFilter = \"linear\";\r\n            if (undefined === descriptor.magFilter) descriptor.magFilter = \"linear\";\r\n            if (undefined === descriptor.addressModeU) descriptor.addressModeU = \"clamp-to-edge\";\r\n            if (undefined === descriptor.addressModeV) descriptor.addressModeV = \"clamp-to-edge\";\r\n            if (undefined === descriptor.addressModeW) descriptor.addressModeW = \"clamp-to-edge\";\r\n            if (undefined === descriptor.mipmapFilter) descriptor.mipmapFilter = \"nearest\";\r\n            if (undefined === descriptor.lodMinClamp) descriptor.lodMinClamp = 0;\r\n            if (undefined === descriptor.lodMaxClamp) descriptor.lodMaxClamp = 32;\r\n            if (undefined === descriptor.maxAnisotropy) descriptor.maxAnisotropy = 1;\r\n        }\r\n\r\n\r\n\r\n        if (descriptor) this.descriptor = descriptor;\r\n\r\n    }"
            },
            "rawText": "export class TextureSampler implements IShaderResource {\r\n\r\n    public mustBeTransfered: boolean = false; // not applicable with sampler\r\n    public gpuResource: GPUSampler;\r\n    public descriptor: TextureSamplerDescriptor;\r\n\r\n\r\n    constructor(descriptor?: {\r\n        minFilter?: \"nearest\" | \"linear\",\r\n        magFilter?: \"nearest\" | \"linear\",\r\n        addressModeU?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\",\r\n        addressModeV?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\",\r\n        addressModeW?: \"clamp-to-edge\" | \"repeat\" | \"mirror-repeat\",\r\n        mipmapFilter?: \"nearest\" | \"linear\",\r\n        lodMinClamp?: number,\r\n        lodMaxClamp?: number,\r\n        maxAnisotropy?: number\r\n        compare?: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\"\r\n    }) {\r\n\r\n        if (!descriptor) descriptor = {};\r\n\r\n        if (!descriptor.compare) {\r\n\r\n            descriptor = { ...descriptor };\r\n\r\n            if (undefined === descriptor.minFilter) descriptor.minFilter = \"linear\";\r\n            if (undefined === descriptor.magFilter) descriptor.magFilter = \"linear\";\r\n            if (undefined === descriptor.addressModeU) descriptor.addressModeU = \"clamp-to-edge\";\r\n            if (undefined === descriptor.addressModeV) descriptor.addressModeV = \"clamp-to-edge\";\r\n            if (undefined === descriptor.addressModeW) descriptor.addressModeW = \"clamp-to-edge\";\r\n            if (undefined === descriptor.mipmapFilter) descriptor.mipmapFilter = \"nearest\";\r\n            if (undefined === descriptor.lodMinClamp) descriptor.lodMinClamp = 0;\r\n            if (undefined === descriptor.lodMaxClamp) descriptor.lodMaxClamp = 32;\r\n            if (undefined === descriptor.maxAnisotropy) descriptor.maxAnisotropy = 1;\r\n        }\r\n\r\n\r\n\r\n        if (descriptor) this.descriptor = descriptor;\r\n\r\n    }\r\n\r\n    public clone(): TextureSampler {\r\n        return new TextureSampler(this.descriptor);\r\n    }\r\n\r\n    public get isComparison(): boolean { return !!this.descriptor.compare }\r\n    public get isFiltering(): boolean {\r\n        /*\r\n        Note: Comparison samplers may use filtering, but the sampling results will be implementation-dependent and may differ from the normal filtering rules.\r\n        //https://www.w3.org/TR/webgpu/#enumdef-gpucomparefunction\r\n        */\r\n\r\n        return this.descriptor.minFilter === \"linear\" || this.descriptor.magFilter === \"linear\" || this.descriptor.mipmapFilter === \"linear\";\r\n    }\r\n\r\n\r\n    public setAddressModes(u: GPUAddressMode = \"clamp-to-edge\", v: GPUAddressMode = \"clamp-to-edge\", w: GPUAddressMode = \"clamp-to-edge\") {\r\n\r\n        this.descriptor.addressModeU = u;\r\n        this.descriptor.addressModeV = v;\r\n        this.descriptor.addressModeW = w;\r\n    }\r\n\r\n    public setFilterModes(min: GPUFilterMode = \"nearest\", mag: GPUFilterMode = \"nearest\", mipmap: GPUMipmapFilterMode = \"nearest\") {\r\n        this.descriptor.minFilter = min;\r\n        this.descriptor.magFilter = mag;\r\n        this.descriptor.mipmapFilter = mipmap;\r\n    }\r\n\r\n    public setClamp(min: number = 0, max: number = 32) {\r\n        this.descriptor.lodMinClamp = min;\r\n        this.descriptor.lodMaxClamp = max;\r\n    }\r\n\r\n    public setCompareFunction(compareType?: \"never\" | \"less\" | \"equal\" | \"less-equal\" | \"greater\" | \"not-equal\" | \"greater-equal\" | \"always\") {\r\n        this.descriptor.compare = compareType;\r\n    }\r\n\r\n\r\n    public setMaxAnisotropy(n: number) {\r\n        n = Math.round(n);\r\n        if (n < 1) n = 1;\r\n        if (n > 16) n = 16;\r\n        this.descriptor.maxAnisotropy = n;\r\n    }\r\n\r\n    //----------------------------\r\n\r\n    protected deviceId: number = 0;\r\n\r\n    public createGpuResource(): void {\r\n\r\n\r\n        //console.log(\"create sampler : \", this.descriptor)\r\n        this.gpuResource = XGPU.device.createSampler(this.descriptor);\r\n        this.deviceId = XGPU.deviceId;\r\n\r\n    }\r\n    public destroyGpuResource() {\r\n        this.gpuResource = null;\r\n        /*\r\n        GPUSampler doesn't seem to have a destroy function\r\n        */\r\n    }\r\n    public update() {\r\n        /*\r\n        GPUSampler doesn't require to be updated\r\n        */\r\n    }\r\n\r\n\r\n    public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        if (this.isComparison) return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":sampler_comparison;\\n\";\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":sampler;\\n\";\r\n    }\r\n\r\n\r\n    public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, sampler: { type: string } } {\r\n\r\n        let type = \"comparison\";\r\n        if (!this.isComparison) {\r\n            type = \"filtering\";\r\n            if (!this.isFiltering) {\r\n                type = \"non-filtering\";\r\n            }\r\n        }\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE,\r\n            sampler: {\r\n                type: type\r\n            },\r\n        }\r\n    }\r\n\r\n    public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUSampler } {\r\n        if (!this.gpuResource || this.deviceId != XGPU.deviceId) this.createGpuResource();\r\n        return {\r\n            binding: bindingId,\r\n            resource: this.gpuResource\r\n        }\r\n    }\r\n\r\n    public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType) { }\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n    }\r\n}"
          }
        ],
        "UniformBuffer": [
          {
            "objectType": "type",
            "name": "UniformBufferDescriptor",
            "type": "UniformBufferDescriptor",
            "rawText": "export type UniformBufferDescriptor = {\r\n    useLocalVariable?: boolean;\r\n    visibility?: GPUShaderStageFlags;\r\n    accessMode?:\"read\"|\"read_write\";\r\n    \r\n}"
          },
          {
            "objectType": "class",
            "name": "UniformBuffer",
            "filePath": "xGPU.shader.resources.UniformBuffer",
            "extends": [
              "StageableBuffer",
              "EventDispatcher"
            ],
            "implements": [
              "IShaderResource"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "gpuResource",
                  "type": "GPUBuffer",
                  "visibility": "public",
                  "rawText": "public gpuResource: GPUBuffer;"
                },
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "UniformBufferDescriptor",
                  "visibility": "public",
                  "rawText": "public descriptor: UniformBufferDescriptor;"
                },
                {
                  "objectType": "property",
                  "name": "group",
                  "type": "UniformGroup",
                  "visibility": "public",
                  "rawText": "public group: UniformGroup;"
                },
                {
                  "objectType": "property",
                  "name": "mustBeTransfered",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public get mustBeTransfered(): boolean { return this.group.mustBeTransfered; }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "cloned",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public cloned: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "accessMode",
                  "type": "\"read\" | \"read_write\"",
                  "visibility": "public",
                  "rawText": "public get accessMode():\"read\" | \"read_write\"{return this._accessMode;}",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "bufferType",
                  "type": "\"read-only-storage\" | \"storage\" | \"uniform\"",
                  "visibility": "public",
                  "rawText": "public get bufferType(): \"read-only-storage\" | \"uniform\" | \"storage\" {\r\n        return this._bufferType;\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "time",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public time: number;"
                },
                {
                  "objectType": "property",
                  "name": "items",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public get items(): any { return this.group.unstackedItems; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "itemNames",
                  "type": "string[]",
                  "visibility": "public",
                  "rawText": "public get itemNames(): string[] { return this.group.itemNames; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "nbComponent",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get nbComponent(): number { return this.group.arrayStride; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "nbUniforms",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get nbUniforms(): number { return this.group.items.length; }",
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "_accessMode",
                  "type": "\"read\" | \"read_write\"",
                  "visibility": "protected",
                  "rawText": "protected _accessMode:\"read\" | \"read_write\";"
                },
                {
                  "objectType": "property",
                  "name": "_bufferType",
                  "type": "\"read-only-storage\" | \"storage\" | \"uniform\"",
                  "visibility": "protected",
                  "rawText": "protected _bufferType: \"read-only-storage\" | \"storage\" | \"uniform\";"
                },
                {
                  "objectType": "property",
                  "name": "_usage",
                  "type": "number",
                  "visibility": "protected",
                  "rawText": "protected _usage: number;"
                },
                {
                  "objectType": "property",
                  "name": "debug",
                  "type": "string",
                  "visibility": "protected",
                  "rawText": "protected debug: string;"
                },
                {
                  "objectType": "property",
                  "name": "shaderVisibility",
                  "type": "GPUShaderStageFlags",
                  "visibility": "protected",
                  "rawText": "protected shaderVisibility: GPUShaderStageFlags;"
                },
                {
                  "objectType": "property",
                  "name": "pipelineType",
                  "type": "\"render\" | \"compute\" | \"compute_mixed\"",
                  "visibility": "protected",
                  "rawText": "protected pipelineType: \"compute\" | \"render\" | \"compute_mixed\";"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "UniformBuffer",
                  "params": [
                    {
                      "name": "propertyNames",
                      "type": "string[]"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public clone(propertyNames?: string[]): UniformBuffer {\r\n        //if propertyNames exists, it will clone only these properties and copy the others\r\n        //if propertyNames is undefined, it will clone every properties \r\n\r\n        const items = { ...this.group.unstackedItems };\r\n\r\n        if (propertyNames) {\r\n            for (let z in items) {\r\n                if (propertyNames.indexOf(z) !== -1) items[z] = items[z].clone();\r\n            }\r\n        } else {\r\n            for (let z in items) items[z] = items[z].clone();\r\n        }\r\n\r\n\r\n\r\n        //console.log(this.descriptor, this.shaderVisibility)\r\n        const buffer = new UniformBuffer(items, this.descriptor);\r\n        buffer.cloned = true;\r\n\r\n        (buffer as any).name = (this as any).name;\r\n        return buffer;\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "add",
                  "returnType": "Uniformable",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    },
                    {
                      "name": "data",
                      "type": "PrimitiveType"
                    },
                    {
                      "name": "useLocalVariable",
                      "type": "boolean"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public add(name: string, data: PrimitiveType, useLocalVariable: boolean = false): Uniformable {\r\n        return this.group.add(name, data, useLocalVariable);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "remove",
                  "returnType": "Uniformable",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public remove(name: string): Uniformable {\r\n        return this.group.remove(name);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public update(): void {\r\n\r\n\r\n        //if (!this._data) this._data = new Float32Array(new ArrayBuffer(this.byteSize))\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        \r\n        this.group.update(this.gpuResource);\r\n        this.mustBeTransfered = false;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createStruct",
                  "returnType": "{ struct: string; localVariables: string; }",
                  "params": [
                    {
                      "name": "uniformName",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createStruct(uniformName: string): { struct: string, localVariables: string } {\r\n\r\n\r\n        //console.warn(\"RESOURCE NAME = \", this.group.name)\r\n\r\n        const o = this.group.getStruct(uniformName);\r\n\r\n\r\n\r\n        return o;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "uniformName",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(uniformName: string, bindingId: number, groupId: number = 0): string {\r\n\r\n        const structName = uniformName.substring(0, 1).toUpperCase() + uniformName.slice(1);\r\n        const varName = uniformName.substring(0, 1).toLowerCase() + uniformName.slice(1);\r\n\r\n        if (this.bufferType === \"uniform\") return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<uniform> \" + varName + \":\" + structName + \";\\n\";\r\n        else {\r\n            //before 08/11/2024-------\r\n            //return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<storage, read> \" + varName + \":\" + structName + \";\\n\";\r\n\r\n            //update 08/11/2024:\r\n            return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<storage, \"+this._accessMode+\"> \" + varName + \":\" + structName + \";\\n\";\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getUniformById",
                  "returnType": "Uniformable",
                  "params": [
                    {
                      "name": "id",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public getUniformById(id: number) { return this.group.items[id]; }"
                },
                {
                  "objectType": "method",
                  "name": "getUniformByName",
                  "returnType": "Uniformable",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public getUniformByName(name: string) { return this.group.getElementByName(name); }"
                },
                {
                  "objectType": "method",
                  "name": "createGpuResource",
                  "returnType": "any",
                  "visibility": "public",
                  "rawText": "public createGpuResource(): any {\r\n\r\n\r\n\r\n        if (!this.gpuResource) {\r\n\r\n            //console.time(\"createGpuUniformBuffer\")\r\n\r\n            this.group.updateStartIdFromParentToChildren();\r\n\r\n            const size = this.group.arrayStride * Float32Array.BYTES_PER_ELEMENT;\r\n            let usage: GPUBufferUsageFlags = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST  ;\r\n\r\n            if (this.bufferType === \"read-only-storage\" || this.bufferType === \"storage\") usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC\r\n\r\n            //console.log(\"uniformBuffer createGpuResource size = \", size, this.group.arrayStride);\r\n            this.gpuResource = XGPU.device.createBuffer({\r\n\r\n                size,\r\n                usage,\r\n\r\n            })\r\n\r\n            this.update();\r\n\r\n            //console.timeEnd(\"createGpuUniformBuffer\")\r\n            //console.log(this.gpuResource)\r\n\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getItemsAsArray",
                  "returnType": "any[]",
                  "visibility": "public",
                  "rawText": "public getItemsAsArray(): any[] {\r\n        const result = [];\r\n        for (let i = 0; i < this.itemNames.length; i++) result[i] = this.items[this.itemNames[i]];\r\n        return result;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "destroyGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public destroyGpuResource() {\r\n        if (this.time && new Date().getTime() - this.time < 100 && XGPU.loseDeviceRecently) {\r\n            if (this.gpuResource) {\r\n                this.group.updateStack();\r\n                return;\r\n            }\r\n        }\r\n        this.time = new Date().getTime();\r\n\r\n        if (this.gpuResource) {\r\n            this.group.updateStack();\r\n            this.group.forceUpdate();\r\n            this.gpuResource.destroy();\r\n        }\r\n\r\n        //this.group.destroy();\r\n        this.gpuResource = null;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupLayoutEntry",
                  "returnType": "{ binding: number; visibility: number; buffer: { type: string; }; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, buffer: { type: string } } {\r\n\r\n        let type: string = \"uniform\";\r\n        if (this.bufferType) type = this.bufferType;\r\n        //console.log(\"bufferType = \", this.bufferType);\r\n\r\n        //console.log(\"createBindGroupLayoutEntry \", this.descriptor.visibility)\r\n        //console.log(\"UniformBuffer.createBindGroupLayoutEntry \", this.shaderVisibility, this.debug, this.cloned)\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: this.descriptor.visibility,\r\n            buffer: {\r\n                type,\r\n            },\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupEntry",
                  "returnType": "{ binding: number; resource: { buffer: GPUBuffer; }; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupEntry(bindingId: number): { binding: number, resource: { buffer: GPUBuffer } } {\r\n        //console.log(\"UniformBuffer.createBindgroupEntry \", this.items);\r\n        if (!this.gpuResource) this.createGpuResource();\r\n\r\n\r\n\r\n        return {\r\n            binding: bindingId,\r\n            resource: {\r\n                buffer: this.gpuResource\r\n            }\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setPipelineType",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "pipelineType",
                      "type": "\"render\" | \"compute\" | \"compute_mixed\""
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n\r\n        /*\r\n        if (this.group.arrayStride * Float32Array.BYTES_PER_ELEMENT < 65536 && this.pipelineType == \"render\") return \"uniform\";\r\n        return \"read-only-storage\";\r\n        */\r\n        /*\r\n        let usage: GPUBufferUsageFlags = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;\r\n\r\n        if (this.bufferType === \"read-only-storage\") usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST\r\n        */\r\n\r\n        this.pipelineType = pipelineType;\r\n\r\n\r\n\r\n\r\n        //console.warn(\"setPipelineType \", pipelineType)\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n        if (pipelineType === \"compute\" || pipelineType === \"compute_mixed\") {\r\n            if(!this._bufferType) this._bufferType = \"storage\";\r\n            if(!this._accessMode) this._accessMode = \"read_write\";\r\n\r\n            if(this._accessMode){\r\n                if(this._accessMode == \"read\"){\r\n                    this._bufferType = \"read-only-storage\";\r\n                }else{\r\n                    this._bufferType = \"storage\";\r\n                }\r\n            }else{\r\n                this._bufferType = \"storage\";\r\n                this._accessMode = \"read_write\";\r\n            }\r\n\r\n\r\n            this.descriptor.visibility = GPUShaderStage.COMPUTE;\r\n        } else {\r\n            if (this.group.arrayStride * Float32Array.BYTES_PER_ELEMENT < 65536) this._bufferType = \"uniform\";\r\n            else this._bufferType = \"storage\";\r\n            this._accessMode = \"read\";\r\n            this.descriptor.visibility = this.shaderVisibility = GPUShaderStage.FRAGMENT | GPUShaderStage.VERTEX;\r\n        }\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "items",
                  "type": "any"
                },
                {
                  "name": "descriptor",
                  "type": "{ useLocalVariable?: boolean; visibility?: GPUShaderStageFlags; accessMode?: \"read\" | \"read_write\"; }"
                }
              ],
              "rawText": "constructor(items: any, descriptor?: {\r\n        useLocalVariable?: boolean,\r\n        visibility?: GPUShaderStageFlags,\r\n        accessMode?:\"read\"|\"read_write\",\r\n       \r\n    }) {\r\n\r\n        super();\r\n       \r\n        this.descriptor = descriptor ? { ...descriptor } : {};\r\n        this.group = new UniformGroup(items, this.descriptor.useLocalVariable,true);\r\n        this.group.uniformBuffer = this;\r\n\r\n        if(descriptor.accessMode) this._accessMode = descriptor.accessMode;\r\n        \r\n    }"
            },
            "rawText": "export class UniformBuffer extends StageableBuffer implements IShaderResource {\r\n\r\n   \r\n\r\n    public gpuResource: GPUBuffer;\r\n    public descriptor: UniformBufferDescriptor;\r\n\r\n\r\n\r\n\r\n\r\n    public group: UniformGroup;\r\n\r\n\r\n    public get mustBeTransfered(): boolean { return this.group.mustBeTransfered; }\r\n    public set mustBeTransfered(b: boolean) {\r\n        this.group.mustBeTransfered = b;\r\n    }\r\n\r\n\r\n    constructor(items: any, descriptor?: {\r\n        useLocalVariable?: boolean,\r\n        visibility?: GPUShaderStageFlags,\r\n        accessMode?:\"read\"|\"read_write\",\r\n       \r\n    }) {\r\n\r\n        super();\r\n       \r\n        this.descriptor = descriptor ? { ...descriptor } : {};\r\n        this.group = new UniformGroup(items, this.descriptor.useLocalVariable,true);\r\n        this.group.uniformBuffer = this;\r\n\r\n        if(descriptor.accessMode) this._accessMode = descriptor.accessMode;\r\n        \r\n    }\r\n\r\n    public cloned: boolean = false;\r\n    public clone(propertyNames?: string[]): UniformBuffer {\r\n        //if propertyNames exists, it will clone only these properties and copy the others\r\n        //if propertyNames is undefined, it will clone every properties \r\n\r\n        const items = { ...this.group.unstackedItems };\r\n\r\n        if (propertyNames) {\r\n            for (let z in items) {\r\n                if (propertyNames.indexOf(z) !== -1) items[z] = items[z].clone();\r\n            }\r\n        } else {\r\n            for (let z in items) items[z] = items[z].clone();\r\n        }\r\n\r\n\r\n\r\n        //console.log(this.descriptor, this.shaderVisibility)\r\n        const buffer = new UniformBuffer(items, this.descriptor);\r\n        buffer.cloned = true;\r\n\r\n        (buffer as any).name = (this as any).name;\r\n        return buffer;\r\n\r\n    }\r\n\r\n\r\n    public add(name: string, data: PrimitiveType, useLocalVariable: boolean = false): Uniformable {\r\n        return this.group.add(name, data, useLocalVariable);\r\n    }\r\n\r\n    public remove(name: string): Uniformable {\r\n        return this.group.remove(name);\r\n    }\r\n\r\n\r\n\r\n\r\n    public update(): void {\r\n\r\n\r\n        //if (!this._data) this._data = new Float32Array(new ArrayBuffer(this.byteSize))\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        \r\n        this.group.update(this.gpuResource);\r\n        this.mustBeTransfered = false;\r\n    }\r\n\r\n    public createStruct(uniformName: string): { struct: string, localVariables: string } {\r\n\r\n\r\n        //console.warn(\"RESOURCE NAME = \", this.group.name)\r\n\r\n        const o = this.group.getStruct(uniformName);\r\n\r\n\r\n\r\n        return o;\r\n    }\r\n\r\n    public createDeclaration(uniformName: string, bindingId: number, groupId: number = 0): string {\r\n\r\n        const structName = uniformName.substring(0, 1).toUpperCase() + uniformName.slice(1);\r\n        const varName = uniformName.substring(0, 1).toLowerCase() + uniformName.slice(1);\r\n\r\n        if (this.bufferType === \"uniform\") return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<uniform> \" + varName + \":\" + structName + \";\\n\";\r\n        else {\r\n            //before 08/11/2024-------\r\n            //return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<storage, read> \" + varName + \":\" + structName + \";\\n\";\r\n\r\n            //update 08/11/2024:\r\n            return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<storage, \"+this._accessMode+\"> \" + varName + \":\" + structName + \";\\n\";\r\n        }\r\n    }\r\n\r\n    public getUniformById(id: number) { return this.group.items[id]; }\r\n    public getUniformByName(name: string) { return this.group.getElementByName(name); }\r\n\r\n    //------------------------------\r\n\r\n    protected _accessMode:\"read\" | \"read_write\";\r\n    public get accessMode():\"read\" | \"read_write\"{return this._accessMode;}\r\n\r\n    protected _bufferType: \"read-only-storage\" | \"storage\" | \"uniform\";\r\n    public get bufferType(): \"read-only-storage\" | \"uniform\" | \"storage\" {\r\n        return this._bufferType;\r\n    }\r\n\r\n    public createGpuResource(): any {\r\n\r\n\r\n\r\n        if (!this.gpuResource) {\r\n\r\n            //console.time(\"createGpuUniformBuffer\")\r\n\r\n            this.group.updateStartIdFromParentToChildren();\r\n\r\n            const size = this.group.arrayStride * Float32Array.BYTES_PER_ELEMENT;\r\n            let usage: GPUBufferUsageFlags = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST  ;\r\n\r\n            if (this.bufferType === \"read-only-storage\" || this.bufferType === \"storage\") usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC\r\n\r\n            //console.log(\"uniformBuffer createGpuResource size = \", size, this.group.arrayStride);\r\n            this.gpuResource = XGPU.device.createBuffer({\r\n\r\n                size,\r\n                usage,\r\n\r\n            })\r\n\r\n            this.update();\r\n\r\n            //console.timeEnd(\"createGpuUniformBuffer\")\r\n            //console.log(this.gpuResource)\r\n\r\n        }\r\n    }\r\n\r\n    public getItemsAsArray(): any[] {\r\n        const result = [];\r\n        for (let i = 0; i < this.itemNames.length; i++) result[i] = this.items[this.itemNames[i]];\r\n        return result;\r\n    }\r\n\r\n\r\n    public time: number;\r\n    public destroyGpuResource() {\r\n        if (this.time && new Date().getTime() - this.time < 100 && XGPU.loseDeviceRecently) {\r\n            if (this.gpuResource) {\r\n                this.group.updateStack();\r\n                return;\r\n            }\r\n        }\r\n        this.time = new Date().getTime();\r\n\r\n        if (this.gpuResource) {\r\n            this.group.updateStack();\r\n            this.group.forceUpdate();\r\n            this.gpuResource.destroy();\r\n        }\r\n\r\n        //this.group.destroy();\r\n        this.gpuResource = null;\r\n    }\r\n\r\n\r\n    public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, buffer: { type: string } } {\r\n\r\n        let type: string = \"uniform\";\r\n        if (this.bufferType) type = this.bufferType;\r\n        //console.log(\"bufferType = \", this.bufferType);\r\n\r\n        //console.log(\"createBindGroupLayoutEntry \", this.descriptor.visibility)\r\n        //console.log(\"UniformBuffer.createBindGroupLayoutEntry \", this.shaderVisibility, this.debug, this.cloned)\r\n\r\n        return {\r\n            binding: bindingId,\r\n            visibility: this.descriptor.visibility,\r\n            buffer: {\r\n                type,\r\n            },\r\n        }\r\n    }\r\n\r\n\r\n    public createBindGroupEntry(bindingId: number): { binding: number, resource: { buffer: GPUBuffer } } {\r\n        //console.log(\"UniformBuffer.createBindgroupEntry \", this.items);\r\n        if (!this.gpuResource) this.createGpuResource();\r\n\r\n\r\n\r\n        return {\r\n            binding: bindingId,\r\n            resource: {\r\n                buffer: this.gpuResource\r\n            }\r\n        }\r\n    }\r\n\r\n    public get items(): any { return this.group.unstackedItems; }\r\n    public get itemNames(): string[] { return this.group.itemNames; }\r\n    public get nbComponent(): number { return this.group.arrayStride; }\r\n    public get nbUniforms(): number { return this.group.items.length; }\r\n\r\n    //public get bufferType(): string { return \"uniform\"; }\r\n\r\n\r\n\r\n    protected _usage: number;\r\n\r\n    protected debug: string;\r\n    protected shaderVisibility: GPUShaderStageFlags;\r\n    protected pipelineType: \"compute\" | \"render\" | \"compute_mixed\";\r\n    public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n\r\n        /*\r\n        if (this.group.arrayStride * Float32Array.BYTES_PER_ELEMENT < 65536 && this.pipelineType == \"render\") return \"uniform\";\r\n        return \"read-only-storage\";\r\n        */\r\n        /*\r\n        let usage: GPUBufferUsageFlags = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;\r\n\r\n        if (this.bufferType === \"read-only-storage\") usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST\r\n        */\r\n\r\n        this.pipelineType = pipelineType;\r\n\r\n\r\n\r\n\r\n        //console.warn(\"setPipelineType \", pipelineType)\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n        if (pipelineType === \"compute\" || pipelineType === \"compute_mixed\") {\r\n            if(!this._bufferType) this._bufferType = \"storage\";\r\n            if(!this._accessMode) this._accessMode = \"read_write\";\r\n\r\n            if(this._accessMode){\r\n                if(this._accessMode == \"read\"){\r\n                    this._bufferType = \"read-only-storage\";\r\n                }else{\r\n                    this._bufferType = \"storage\";\r\n                }\r\n            }else{\r\n                this._bufferType = \"storage\";\r\n                this._accessMode = \"read_write\";\r\n            }\r\n\r\n\r\n            this.descriptor.visibility = GPUShaderStage.COMPUTE;\r\n        } else {\r\n            if (this.group.arrayStride * Float32Array.BYTES_PER_ELEMENT < 65536) this._bufferType = \"uniform\";\r\n            else this._bufferType = \"storage\";\r\n            this._accessMode = \"read\";\r\n            this.descriptor.visibility = this.shaderVisibility = GPUShaderStage.FRAGMENT | GPUShaderStage.VERTEX;\r\n        }\r\n    }\r\n\r\n\r\n   \r\n}"
          }
        ],
        "UniformGroup": [
          {
            "objectType": "type",
            "name": "Uniformable",
            "type": "Uniformable",
            "rawText": "export type Uniformable = PrimitiveFloatUniform | PrimitiveIntUniform | PrimitiveUintUniform | UniformGroup | UniformGroupArray;"
          },
          {
            "objectType": "class",
            "name": "UniformGroup",
            "filePath": "xGPU.shader.resources.UniformGroup",
            "extends": [
              "EventDispatcher"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "unstackedItems",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public unstackedItems: any = {};"
                },
                {
                  "objectType": "property",
                  "name": "items",
                  "type": "Uniformable[]",
                  "visibility": "public",
                  "rawText": "public items: Uniformable[];"
                },
                {
                  "objectType": "property",
                  "name": "itemNames",
                  "type": "string[]",
                  "visibility": "public",
                  "rawText": "public itemNames: string[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "arrayStride",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public arrayStride: number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "startId",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public startId: number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "globalStartId",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public globalStartId:number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "createVariableInsideMain",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public createVariableInsideMain: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "mustBeTransfered",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public mustBeTransfered:boolean = true;"
                },
                {
                  "objectType": "property",
                  "name": "wgsl",
                  "type": "{ struct: string; localVariables: string; }",
                  "visibility": "public",
                  "rawText": "public wgsl: { struct: string, localVariables: string };"
                },
                {
                  "objectType": "property",
                  "name": "wgslStructNames",
                  "type": "string[]",
                  "visibility": "public",
                  "rawText": "public wgslStructNames: string[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "datas",
                  "type": "ArrayBuffer",
                  "visibility": "public",
                  "rawText": "public datas: ArrayBuffer;"
                },
                {
                  "objectType": "property",
                  "name": "dataView",
                  "type": "DataView",
                  "visibility": "public",
                  "rawText": "public dataView: DataView;"
                },
                {
                  "objectType": "property",
                  "name": "uniformBuffer",
                  "type": "UniformBuffer",
                  "visibility": "public",
                  "rawText": "public get uniformBuffer(): UniformBuffer { return this.buffer }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "name",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public get name(): string { return this._name; }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "type",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public get type(): any {\r\n        return {\r\n            nbComponent: this.arrayStride,\r\n            isUniformGroup: true,\r\n            isArray: false\r\n        }\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "transfertWholeBuffer",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public transfertWholeBuffer:boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "existingStrucName",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public existingStrucName:string = undefined;"
                },
                {
                  "objectType": "property",
                  "name": "definition",
                  "type": "{ type: string; values: ArrayBuffer; items: any; name: string; }",
                  "visibility": "public",
                  "rawText": "public get definition():{type:string,values:ArrayBuffer,items:any,name:string}{\r\n\r\n        const items = {};\r\n        for(let i=0;i<this.items.length;i++){\r\n            items[this.itemNames[i]] = this.items[i].definition;\r\n        }\r\n\r\n        return {type:\"UniformGroup\",values:this.datas,items,name:this.name}\r\n    }",
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "mustDispatchChangeEvent",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected mustDispatchChangeEvent:boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "_name",
                  "type": "string",
                  "visibility": "protected",
                  "rawText": "protected _name: string;"
                },
                {
                  "objectType": "property",
                  "name": "buffer",
                  "type": "UniformBuffer",
                  "visibility": "protected",
                  "rawText": "protected buffer: UniformBuffer = null;"
                },
                {
                  "objectType": "property",
                  "name": "usedAsUniformBuffer",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected usedAsUniformBuffer:boolean;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "set",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "datas",
                      "type": "ArrayBuffer"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public set(datas: ArrayBuffer) { //to follow the structure of an ArrayBuffer like other uniforms\r\n        this.datas = datas;\r\n        this.dataView = new DataView(datas, 0, datas.byteLength);\r\n        this.updateItemFromDataView(this.dataView,0);\r\n        this.mustBeTransfered = true;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "destroy",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public destroy() {\r\n        console.warn(\"uniformGroup.destroy\")\r\n        this.unstackedItems = {};\r\n        this.items = [];\r\n        this.itemNames = [];\r\n        this.arrayStride = 0;\r\n        this.startId = 0;\r\n        this.mustBeTransfered = true;\r\n        this.datas = null;\r\n        this.buffer = null;\r\n        this.wgsl = null;\r\n        this._name = null;\r\n        this.uniformBuffer = null;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "UniformGroup",
                  "params": [
                    {
                      "name": "propertyNames",
                      "type": "string[]"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public clone(propertyNames?: string[]): UniformGroup {\r\n        //if propertyNames exists, it will clone only these properties and copy the others\r\n        //if propertyNames is undefined, it will clone every properties \r\n\r\n        const items = { ...this.unstackedItems };\r\n        if (propertyNames) {\r\n            for (let i = 0; i < propertyNames.length; i++) {\r\n                items[propertyNames[i]] = items[propertyNames[i]].clone();\r\n            }\r\n        } else {\r\n            for (let z in items) {\r\n                items[z] = items[z].clone();\r\n            }\r\n        }\r\n\r\n        const group = new UniformGroup(items);\r\n        group.name = this.name;\r\n\r\n        return group;\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "remove",
                  "returnType": "Uniformable",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public remove(name: string): Uniformable {\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            if (this.items[i].name === name) {\r\n                const o = this.items.splice(i, 1)[0];\r\n                this.itemNames.splice(this.itemNames.indexOf(name), 1);\r\n\r\n                return o\r\n            }\r\n        }\r\n        return null;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "add",
                  "returnType": "Uniformable",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    },
                    {
                      "name": "data",
                      "type": "Uniformable"
                    },
                    {
                      "name": "useLocalVariable",
                      "type": "boolean"
                    },
                    {
                      "name": "stackItems",
                      "type": "boolean"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public add(name: string, data: Uniformable, useLocalVariable: boolean = false, stackItems: boolean = true): Uniformable {\r\n\r\n       \r\n       \r\n        data.uniformBuffer = this.uniformBuffer;\r\n        data.name = name;\r\n        data.mustBeTransfered = true;\r\n\r\n        if ((this.uniformBuffer && this.uniformBuffer.descriptor.useLocalVariable) || useLocalVariable) {\r\n            data.createVariableInsideMain = true;\r\n        }\r\n\r\n        if(this.usedAsUniformBuffer == false || data instanceof UniformGroup || data instanceof UniformGroupArray || data instanceof Vec4Array){\r\n           \r\n            data.addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n        \r\n\r\n        const alreadyDefined: boolean = !!this.unstackedItems[name];\r\n        this.unstackedItems[name] = data;\r\n\r\n        if (alreadyDefined) {\r\n            for (let i = 0; i < this.items.length; i++) {\r\n                if (this.items[i].name === name) {\r\n                    this.items[i] = data;\r\n                    break;\r\n                }\r\n            }\r\n        } else {\r\n            this.itemNames.push(name);\r\n        }\r\n\r\n        if (stackItems) this.items = this.stackItems(this.unstackedItems);\r\n\r\n        if (this.wgsl) this.wgsl = this.getStruct(this.name);\r\n\r\n        if (this.uniformBuffer) this.uniformBuffer.mustBeTransfered = true;\r\n\r\n        return data;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getElementByName",
                  "returnType": "Uniformable",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public getElementByName(name: string): Uniformable {\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            if (this.items[i].name === name) {\r\n                //console.log(\"=>>>>>>> \", name)\r\n                return this.items[i];\r\n            }\r\n        }\r\n        return null;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createVariable",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "uniformBufferName",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createVariable(uniformBufferName: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n        const varName: string = this.getVarName(this.name);\r\n        return \"   var \" + varName + \":\" + this.getStructName(this.name) + \" = \" + this.getVarName(uniformBufferName) + \".\" + varName + \";\\n\"\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "updateStack",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public updateStack() {\r\n\r\n        this.items = this.stackItems(this.items);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "forceUpdate",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public forceUpdate(): void {\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            if (this.items[i] instanceof UniformGroup || this.items[i] instanceof UniformGroupArray) (this.items[i] as any).forceUpdate()\r\n            this.items[i].mustBeTransfered = true;\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setDatas",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "item",
                      "type": "PrimitiveType"
                    },
                    {
                      "name": "dataView",
                      "type": "DataView"
                    },
                    {
                      "name": "offset",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setDatas(item: PrimitiveType, dataView: DataView = null, offset: number = 0) {\r\n\r\n        if (!dataView) dataView = this.dataView;\r\n        const startId = item.startId + offset;\r\n        const type: GPUType = item.type;\r\n        const primitive: \"f32\" | \"i32\" | \"u32\" | \"f16\" = type.primitive;\r\n\r\n        //console.log(\"setDatas = \",item.name,startId,type.nbValues)\r\n\r\n        switch (primitive) {\r\n            case \"f32\":\r\n                for (let i = 0; i < type.nbValues; i++) dataView.setFloat32((startId + i) * 4, item[i], true);\r\n                break;\r\n            case \"i32\":\r\n                for (let i = 0; i < type.nbValues; i++) dataView.setInt32((startId + i) * 4, item[i], true);\r\n                break;\r\n            case \"u32\":\r\n                for (let i = 0; i < type.nbValues; i++) dataView.setUint32((startId + i) * 4, item[i], true);\r\n                break;\r\n        }\r\n        if(this.usedAsUniformBuffer == false && item.type.isArray == false){\r\n            item.mustBeTransfered = false;\r\n        }\r\n       \r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "updateItemFromDataView",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "dataView",
                      "type": "DataView"
                    },
                    {
                      "name": "offset",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public updateItemFromDataView(dataView:DataView,offset:number){\r\n\r\n        let item: Uniformable;\r\n        \r\n        for (let i = 0; i < this.items.length; i++) {\r\n            item = this.items[i];\r\n           \r\n            if (item instanceof UniformGroup || item instanceof UniformGroupArray) {\r\n                //console.log(\"call  (item as UniformGroup).copyIntoDataView\");\r\n                (item as UniformGroup).updateItemFromDataView(dataView, offset + item.startId);\r\n            } else {\r\n\r\n                const startId = item.startId + offset;\r\n                const type: GPUType = item.type;\r\n                const primitive: \"f32\" | \"i32\" | \"u32\" | \"f16\" = type.primitive;\r\n                const nb = type.nbValues;\r\n                if(primitive == \"f32\"){\r\n                    for(let i=0;i<nb;i++) item[i] = dataView.getFloat32((startId+i)*4,true);\r\n\r\n                }else if(primitive == \"i32\"){\r\n                    for(let i=0;i<nb;i++) item[i] = dataView.getInt32((startId+i)*4,true);\r\n\r\n                }else if(primitive == \"u32\"){\r\n                    for(let i=0;i<nb;i++) item[i] = dataView.getUint32((startId+i)*4,true);\r\n                }\r\n                item.mustBeTransfered = true;\r\n            }\r\n                //console.log(item.name,this.usedAsUniformBuffer)\r\n\r\n               \r\n               \r\n        }\r\n\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "copyIntoDataView",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "dataView",
                      "type": "DataView"
                    },
                    {
                      "name": "offset",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public copyIntoDataView(dataView: DataView, offset: number) {\r\n\r\n        let item: Uniformable;\r\n        let mustTransfer = false;\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            item = this.items[i];\r\n            //console.log(\"UG.copyIntoDataView item = \",item.name,item.mustBeTransfered)\r\n            if(item.mustBeTransfered){\r\n                mustTransfer = true;\r\n                //console.log(\"MBT => \",item.name)\r\n                if (item instanceof UniformGroup || item instanceof UniformGroupArray) {\r\n                    //console.log(\"call  (item as UniformGroup).copyIntoDataView\");\r\n                    (item as UniformGroup).copyIntoDataView(dataView, offset + item.startId);\r\n                } else {\r\n                    //console.log(\"call setDatas\")\r\n                    this.setDatas(item, dataView, offset)\r\n                }\r\n                //console.log(item.name,this.usedAsUniformBuffer)\r\n\r\n                if(this.usedAsUniformBuffer == false){\r\n                    item.mustBeTransfered = false;\r\n                }\r\n                //\r\n            }\r\n        }\r\n\r\n        //console.log(\"CIDV \",mustTransfer,this.usedAsUniformBuffer)\r\n        this.mustBeTransfered = mustTransfer;\r\n        if( mustTransfer){\r\n            this.dispatchEvent(UniformGroup.ON_CHANGE);\r\n        }\r\n        \r\n\r\n\r\n        //console.log(\"dataView = \",new Float32Array(dataView.buffer));\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "Promise<void>",
                  "params": [
                    {
                      "name": "gpuResource",
                      "type": "GPUBuffer"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public async update(gpuResource: GPUBuffer){//}, fromUniformBuffer: boolean = false) {\r\n\r\n       \r\n        let mustBeTransfered = false;\r\n        \r\n        let item: Uniformable;\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            item = this.items[i];\r\n           \r\n            if (!item.type.isUniformGroup) (item as any).update(); \r\n            else item.update(gpuResource);\r\n            \r\n\r\n\r\n            if ( item.mustBeTransfered) {\r\n                //console.log(\"item MBT = \",item.name)\r\n                mustBeTransfered = true;\r\n                if (!(item instanceof UniformGroup || item instanceof UniformGroupArray )) {\r\n\r\n                      \r\n                        this.setDatas(item)\r\n                        item.mustBeTransfered = false;\r\n\r\n                        if(this.transfertWholeBuffer == false || item.type.isArray){\r\n                            \r\n                            if(this.transfertWholeBuffer == false){\r\n                                XGPU.device.queue.writeBuffer(\r\n                                    gpuResource,\r\n                                    item.globalStartId * Float32Array.BYTES_PER_ELEMENT,\r\n                                    //item.startId * Float32Array.BYTES_PER_ELEMENT,\r\n                                    item.buffer,\r\n                                    item.byteOffset,\r\n                                    item.byteLength\r\n                                )\r\n\r\n                            }\r\n\r\n                        }\r\n\r\n\r\n                    \r\n\r\n                    \r\n                    \r\n                    //item.mustBeTransfered = false;\r\n\r\n                }else{\r\n                    \r\n                    item.copyIntoDataView(this.dataView,item.startId)\r\n                    \r\n                }\r\n\r\n                \r\n\r\n            }\r\n            \r\n        }\r\n\r\n       \r\n       \r\n\r\n        if(/*this.usedAsUniformBuffer &&*/ this.transfertWholeBuffer){\r\n\r\n           if(mustBeTransfered){\r\n                //console.log(\"AAAAAAAAAAAAAAAAAA \",this.mustBeTransfered,new Float32Array(this.dataView.buffer));\r\n                XGPU.device.queue.writeBuffer(\r\n                    gpuResource,\r\n                    0,\r\n                    this.datas,\r\n                    0,\r\n                    this.arrayStride * 4\r\n                )\r\n            }\r\n        }\r\n       \r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getStruct",
                  "returnType": "{ struct: string; localVariables: string; }",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public getStruct(name: string): { struct: string, localVariables: string } {\r\n\r\n        this.name = name;\r\n\r\n\r\n        let struct = \"struct \" + this.name + \" {\\n\";\r\n        let item: Uniformable;\r\n        let localVariables = \"\";\r\n        let otherStructs = \"\";\r\n\r\n        let primitiveStructs = \"\";\r\n        let o: { struct: string, localVariables: string }\r\n\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            item = this.items[i];\r\n\r\n\r\n\r\n            if (item instanceof UniformGroup || item instanceof UniformGroupArray) {\r\n                if (item instanceof UniformGroup) {\r\n                    if (!item.wgsl) {\r\n                        //console.log(\"#1 NAME = \", item.name, otherStructs)\r\n                        o = item.getStruct(item.name);\r\n                        localVariables += o.localVariables + \"\\n\";\r\n                        item.wgslStructNames.push(item.name);\r\n                    }\r\n                    if (otherStructs.indexOf(item.wgsl.struct) === -1) {\r\n                        //console.log(\"OHTER : \", otherStructs, item.wgsl.struct)\r\n                        otherStructs = item.wgsl.struct + otherStructs;\r\n                    }\r\n                    struct += \"    \" + this.getVarName(item.name) + \":\" + item.name + \",\\n\"\r\n                    localVariables += item.createVariable(this.name);\r\n\r\n\r\n\r\n                } else {\r\n                    name = item.name;\r\n                    \r\n                    if (!(item.groups[0] as UniformGroup).wgsl) {\r\n                        //console.log(\"#2 NAME = \", name)\r\n                        o = (item.groups[0] as UniformGroup).getStruct(item.name);\r\n                        localVariables += o.localVariables;\r\n                    }\r\n\r\n                    if (otherStructs.indexOf((item.groups[0] as UniformGroup).wgsl.struct) === -1) {\r\n                        otherStructs = (item.groups[0] as UniformGroup).wgsl.struct + otherStructs;\r\n                    }\r\n\r\n                    struct += \"@size(\"+item.length * item.groups[0].arrayStride * 4 +\")    \" + name + \":array<\" + this.getStructName(name) + \",\" + item.length + \">,\\n\"\r\n                    localVariables += item.createVariable(this.name);\r\n                }\r\n\r\n\r\n\r\n            } else {\r\n                let o = item as PrimitiveType;\r\n\r\n\r\n                if (o.propertyNames) {\r\n                    let s = o.createStruct();\r\n\r\n                    if (primitiveStructs.indexOf(s) === -1 && otherStructs.indexOf(s) === -1 && struct.indexOf(s) === -1) {\r\n                        primitiveStructs += s + \"\\n\";\r\n                    }\r\n                    \r\n                    struct += \"     @size(16) \" + o.name + \":\" + o.className + \",\\n\";\r\n                    //struct += \"     @size(16) \" + o.name + \":\" + o.constructor.name + \",\\n\";\r\n\r\n                } else {\r\n\r\n\r\n                    if (o.type.isArray) {\r\n\r\n                        if (o.type.isArrayOfMatrixs) {\r\n\r\n                            let col = o.type.matrixColumns;\r\n                            let row = 4;\r\n                            if (o.type.matrixRows === 2) row = 2;\r\n\r\n                            struct += \"    @size(\" + (o.type.arrayLength * col * row * 4) + \") \" + o.name + \":\" + o.type.dataType + \",\\n\";\r\n                        } else {\r\n\r\n                            struct += \"    @size(\" + (o.type.arrayLength * 16) + \") \" + o.name + \":\" + o.type.dataType + \",\\n\";\r\n                        }\r\n\r\n                    } else {\r\n                        struct += \"    \" + o.name + \":\" + o.type.dataType + \",\\n\";\r\n                    }\r\n\r\n                }\r\n\r\n\r\n                if (o.createVariableInsideMain) localVariables += o.createVariable(this.getVarName(this.name));\r\n            }\r\n        }\r\n        struct += \"}\\n\\n\";\r\n\r\n\r\n        struct = primitiveStructs + otherStructs + struct;\r\n\r\n\r\n\r\n\r\n        this.wgsl = {\r\n            struct,\r\n            localVariables\r\n        };\r\n\r\n        \r\n        return this.wgsl;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "stackItems",
                  "returnType": "Uniformable[]",
                  "params": [
                    {
                      "name": "items",
                      "type": "any"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public stackItems(items: any): Uniformable[] {\r\n\r\n        //console.warn(\"stackItems\")\r\n        //console.time(\"STACK ITEMS\")\r\n\r\n\r\n        //----- we sort the items by arraystride to start with bigger values / complex structure ----\r\n        /*\r\n        let itemList = [];\r\n        let item:any;\r\n        let uniformGroupArrays = [];\r\n        let uniformGroups = [];\r\n        let vecArrays = [];\r\n        let matrixArrays = [];\r\n        let matrixs = [];\r\n        let primitives = [];\r\n\r\n        for(let z in items){\r\n            item = items[z];\r\n            item.name = z;\r\n            if(item instanceof UniformGroupArray) uniformGroupArrays.push(item);\r\n            else if(item instanceof UniformGroup) uniformGroups.push(item);\r\n            else if(item.type.isArrayOfMatrixs) matrixArrays.push(item);\r\n            else if(item.type.isArray) vecArrays.push(item);\r\n            else if(item.type.isMatrix) matrixs.push(item);\r\n            else primitives.push(item);\r\n        } \r\n\r\n        const sortGroup = (a,b)=>{\r\n            if(a.arrayStride > b.arrayStride) return -1;\r\n            if(a.arrayStride < b.arrayStride) return 1;\r\n            return 0;\r\n        }\r\n\r\n        uniformGroupArrays = uniformGroupArrays.sort(sortGroup);\r\n        uniformGroups = uniformGroups.sort(sortGroup);\r\n\r\n        const sortArray = (a,b)=>{\r\n            const lenA = a.type.isArrayOfMatrixs ? a.type.matrixRows * 4 * a.type.arrayLength : a.type.arrayLength * 4;\r\n            const lenB = b.type.isArrayOfMatrixs ? b.type.matrixRows * 4 * b.type.arrayLength : b.type.arrayLength * 4;\r\n\r\n            if(lenA > lenB) return -1;\r\n            if(lenA < lenB) return 1;\r\n            return 0;\r\n        }\r\n\r\n        vecArrays = vecArrays.sort(sortArray);\r\n        matrixArrays = matrixArrays.sort(sortArray);\r\n\r\n        \r\n        primitives = primitives.sort((a,b)=>{\r\n            if(a.type.nbComponent > b.type.nbComponent) return -1;\r\n            if(a.type.nbComponent < b.type.nbComponent) return 1;\r\n            return 0;\r\n        })\r\n\r\n\r\n        itemList = uniformGroupArrays.concat(uniformGroups);\r\n        itemList = itemList.concat(matrixArrays);\r\n        itemList = itemList.concat(vecArrays);\r\n        itemList = itemList.concat(matrixs);\r\n        itemList = itemList.concat(primitives);\r\n        */\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n        const result: any[] = []\r\n\r\n        let bound = 1;\r\n\r\n        var floats: any[] = [];\r\n        var vec2s: any[] = [];\r\n        var vec3s: any[] = [];\r\n\r\n\r\n        let v: any, type: any, nbComponent;\r\n        let offset = 0;\r\n\r\n\r\n\r\n        //for(let i=0;i<itemList.length;i++){\r\n        for (let z in items) {\r\n\r\n            //v = itemList[i];\r\n            v = items[z];\r\n            v.name = z;\r\n            type = v.type;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n            if (v instanceof UniformGroupArray) {\r\n\r\n                v.startId = offset;\r\n                offset += v.arrayStride;\r\n                //console.log(v.name+\" =======>>>> \",v.arrayStride)\r\n                result.push(v);\r\n\r\n            } else {\r\n\r\n                if (type.isArray) {\r\n\r\n                    v.startId = offset;\r\n\r\n                    if (type.isArrayOfMatrixs) {\r\n                        offset += type.matrixRows * 4 * type.arrayLength;\r\n                    } else {\r\n                        offset += 4 * type.arrayLength;\r\n                    }\r\n                    bound = 4;\r\n                    result.push(v);\r\n\r\n\r\n                } else if (type.isMatrix) {\r\n                    v.startId = offset;\r\n\r\n                    let col = type.matrixColumns;\r\n                    let row = 4;\r\n                    if (type.matrixRows === 2) row = 2;\r\n                    offset += col * row;\r\n                    bound = row;\r\n                    result.push(v);\r\n\r\n                } else if (type.isUniformGroup) {\r\n                    \r\n                    if (type.nbComponent >= 4) {\r\n                        bound = 4;\r\n                        v.startId = offset;\r\n                        offset += Math.ceil(type.nbComponent / 4) * 4;\r\n                        \r\n                        result.push(v);\r\n                    }\r\n                   \r\n\r\n                } else if ((v as PrimitiveType).propertyNames) { //if it's a customClass the extends a PrimitiveType and use a struct\r\n                    bound = 4;\r\n                    v.startId = offset;\r\n                    offset += 4;\r\n                    result.push(v);\r\n\r\n                } else {\r\n\r\n\r\n\r\n                    nbComponent = type.nbValues;\r\n\r\n                    if (nbComponent === 1) floats.push(v);\r\n                    else if (nbComponent === 2) {\r\n                        if (bound < 2) bound = 2;\r\n                        vec2s.push(v);\r\n                    } else if (nbComponent === 3) {\r\n                        bound = 4;\r\n                        vec3s.push(v);\r\n                    } else if (nbComponent >= 4) {\r\n                        bound = 4;\r\n                        v.startId = offset;\r\n                        offset += nbComponent;\r\n                        result.push(v);\r\n                    }\r\n\r\n                }\r\n\r\n            }\r\n\r\n        }\r\n\r\n\r\n\r\n        //------------------------\r\n\r\n\r\n        const addVec3 = () => {\r\n            v = vec3s.shift();\r\n            v.startId = offset;\r\n            offset += 3;\r\n            result.push(v);\r\n            if (floats.length) {\r\n                const f = floats.shift();\r\n                f.startId = offset;\r\n                result.push(f);\r\n            }\r\n            offset++\r\n        }\r\n\r\n        let nb = vec3s.length;\r\n        for (let i = 0; i < nb; i++) addVec3();\r\n\r\n        //--------------------------\r\n\r\n        nb = vec2s.length;\r\n        for (let i = 0; i < nb; i++) {\r\n            v = vec2s.shift();\r\n            v.startId = offset;\r\n            offset += 2;\r\n            result.push(v);\r\n        }\r\n\r\n        //--------------------------\r\n\r\n        nb = floats.length;\r\n\r\n        //console.log(\"floats.length = \",nb)\r\n        for (let i = 0; i < nb; i++) {\r\n            v = floats.shift();\r\n            v.startId = offset;\r\n            //console.log(\"v = \",v)\r\n            //console.log(v.name, v.startId * 4)\r\n            offset++;\r\n            result.push(v);\r\n        }\r\n\r\n        //--------------------------\r\n        \r\n\r\n        //BEFORE 07/11/2024:\r\n        if (offset % bound !== 0) {\r\n            offset += bound - (offset % bound);\r\n        }\r\n        \r\n       //console.log(\"offset \",offset)\r\n        //----AJOUT LE 07/11/2024------\r\n        if(offset % 4 != 0){\r\n            const n = 4 - offset % 4;\r\n\r\n           if(!this.usedAsUniformBuffer){\r\n                for(let i=0;i<n;i++){\r\n                    const float = new Float(0);\r\n                    float.startId = offset;\r\n                    float.name = \"padding_\"+i;\r\n                    result.push(float)\r\n                    this.itemNames.push(float.name)\r\n                }\r\n           }\r\n            \r\n            offset += n;\r\n        }\r\n       \r\n        //--------------------------\r\n        \r\n\r\n        //console.log(\"uniformGroup \",result,offset,bound);\r\n        this.arrayStride = offset ;\r\n\r\n\r\n\r\n\r\n\r\n        this.datas = new ArrayBuffer(offset * 4);\r\n\r\n        \r\n\r\n        this.dataView = new DataView(this.datas, 0, this.datas.byteLength);\r\n        this.items = result;\r\n        this.copyIntoDataView(this.dataView, 0);\r\n\r\n        //console.timeEnd(\"STACK ITEMS\")\r\n        return result\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "updateStartIdFromParentToChildren",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n        \r\n        let item:Uniformable;\r\n        for(let i=0;i<this.items.length;i++){\r\n            item = this.items[i];\r\n            item.globalStartId = this.globalStartId + item.startId;\r\n            if(item instanceof UniformGroup || item instanceof UniformGroupArray || item.type.isArray){\r\n                item.updateStartIdFromParentToChildren();\r\n            }\r\n        }\r\n    }"
                }
              ],
              "protected": [
                {
                  "objectType": "method",
                  "name": "getStructName",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "protected",
                  "rawText": "protected getStructName(name: string) {\r\n        if (!name) return null;\r\n        return name[0].toUpperCase() + name.slice(1);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getVarName",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "protected",
                  "rawText": "protected getVarName(name: string) {\r\n        if (!name) return null;\r\n        return name[0].toLowerCase() + name.slice(1);\r\n    }"
                }
              ]
            },
            "statics": {
              "properties": {
                "public": [
                  {
                    "objectType": "property",
                    "name": "ON_CHANGE",
                    "type": "string",
                    "visibility": "public",
                    "rawText": "public static ON_CHANGE:string = \"ON_CHANGE\";"
                  },
                  {
                    "objectType": "property",
                    "name": "ON_CHANGED",
                    "type": "string",
                    "visibility": "public",
                    "rawText": "public static ON_CHANGED:string = \"ON_CHANGED\";"
                  }
                ]
              }
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "items",
                  "type": "any"
                },
                {
                  "name": "useLocalVariable",
                  "type": "boolean"
                },
                {
                  "name": "usedAsUniformBuffer",
                  "type": "boolean"
                }
              ],
              "rawText": "constructor(items: any, useLocalVariable?: boolean , usedAsUniformBuffer:boolean=false) {\r\n        super();\r\n\r\n        this.usedAsUniformBuffer = usedAsUniformBuffer;\r\n        this.createVariableInsideMain = !!useLocalVariable;\r\n\r\n        let o: any;\r\n        for (let z in items) {\r\n            o = items[z];\r\n           \r\n            if (o instanceof PrimitiveFloatUniform ||\r\n                o instanceof PrimitiveIntUniform ||\r\n                o instanceof PrimitiveUintUniform ||\r\n                o instanceof UniformGroup ||\r\n                o instanceof UniformGroupArray) {\r\n            } else {\r\n                throw new Error(\"UniformGroup accept only PrimitiveFloatUniform, PrimitiveIntUniform, PrimitiveUintUniform, UniformGroup and UniformGroupArray\")\r\n            }\r\n\r\n\r\n\r\n            this.add(z, o, this.createVariableInsideMain, false)\r\n        }\r\n\r\n        this.items = this.stackItems(items);\r\n    }"
            },
            "rawText": "export class UniformGroup extends EventDispatcher{\r\n\r\n    public static ON_CHANGE:string = \"ON_CHANGE\";\r\n    public static ON_CHANGED:string = \"ON_CHANGED\";\r\n\r\n    public unstackedItems: any = {};\r\n    public items: Uniformable[];\r\n    public itemNames: string[] = [];\r\n    public arrayStride: number = 0;\r\n    public startId: number = 0;\r\n    public globalStartId:number = 0;\r\n    public createVariableInsideMain: boolean = false;\r\n    \r\n    public mustBeTransfered:boolean = true;\r\n    protected mustDispatchChangeEvent:boolean = false;\r\n    /*\r\n    protected _mustBeTransfered: boolean = true;\r\n    public get mustBeTransfered():boolean{return this._mustBeTransfered};\r\n    public set mustBeTransfered(b:boolean){\r\n        if(b != this._mustBeTransfered){\r\n            console.warn(b)\r\n            if(b) this.dispatchEvent(UniformGroup.ON_CHANGE);\r\n            else this.dispatchEvent(UniformGroup.ON_CHANGED);\r\n            this._mustBeTransfered = b;\r\n        }\r\n    }*/\r\n\r\n    protected _name: string;\r\n    public wgsl: { struct: string, localVariables: string };\r\n\r\n    public wgslStructNames: string[] = []; /*an uniformGroup can be used multiple times, not necessarily in an array so we must \r\n                                       so we must store the name we use when we build the 'struct' in order to write a 'struct' \r\n                                       for every properties while being sure we don't have two sames structs*/\r\n\r\n\r\n    public datas: ArrayBuffer;\r\n    public dataView: DataView;\r\n\r\n    //private debug:boolean = false;\r\n    public set(datas: ArrayBuffer) { //to follow the structure of an ArrayBuffer like other uniforms\r\n        this.datas = datas;\r\n        this.dataView = new DataView(datas, 0, datas.byteLength);\r\n        this.updateItemFromDataView(this.dataView,0);\r\n        this.mustBeTransfered = true;\r\n    }   \r\n\r\n\r\n\r\n\r\n    protected buffer: UniformBuffer = null;\r\n    public get uniformBuffer(): UniformBuffer { return this.buffer };\r\n    public set uniformBuffer(buffer: UniformBuffer) {\r\n        this.buffer = buffer;\r\n        if (buffer) {\r\n            buffer.mustBeTransfered = true;\r\n        }\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            (this.items[i] as any).uniformBuffer = buffer;\r\n        }\r\n    }\r\n\r\n    public destroy() {\r\n        console.warn(\"uniformGroup.destroy\")\r\n        this.unstackedItems = {};\r\n        this.items = [];\r\n        this.itemNames = [];\r\n        this.arrayStride = 0;\r\n        this.startId = 0;\r\n        this.mustBeTransfered = true;\r\n        this.datas = null;\r\n        this.buffer = null;\r\n        this.wgsl = null;\r\n        this._name = null;\r\n        this.uniformBuffer = null;\r\n    }\r\n\r\n    protected usedAsUniformBuffer:boolean;\r\n\r\n    constructor(items: any, useLocalVariable?: boolean , usedAsUniformBuffer:boolean=false) {\r\n        super();\r\n\r\n        this.usedAsUniformBuffer = usedAsUniformBuffer;\r\n        this.createVariableInsideMain = !!useLocalVariable;\r\n\r\n        let o: any;\r\n        for (let z in items) {\r\n            o = items[z];\r\n           \r\n            if (o instanceof PrimitiveFloatUniform ||\r\n                o instanceof PrimitiveIntUniform ||\r\n                o instanceof PrimitiveUintUniform ||\r\n                o instanceof UniformGroup ||\r\n                o instanceof UniformGroupArray) {\r\n            } else {\r\n                throw new Error(\"UniformGroup accept only PrimitiveFloatUniform, PrimitiveIntUniform, PrimitiveUintUniform, UniformGroup and UniformGroupArray\")\r\n            }\r\n\r\n\r\n\r\n            this.add(z, o, this.createVariableInsideMain, false)\r\n        }\r\n\r\n        this.items = this.stackItems(items);\r\n    }\r\n\r\n\r\n    public get name(): string { return this._name; }\r\n    public set name(s: string) {\r\n        this._name = this.getStructName(s);\r\n    }\r\n\r\n    public clone(propertyNames?: string[]): UniformGroup {\r\n        //if propertyNames exists, it will clone only these properties and copy the others\r\n        //if propertyNames is undefined, it will clone every properties \r\n\r\n        const items = { ...this.unstackedItems };\r\n        if (propertyNames) {\r\n            for (let i = 0; i < propertyNames.length; i++) {\r\n                items[propertyNames[i]] = items[propertyNames[i]].clone();\r\n            }\r\n        } else {\r\n            for (let z in items) {\r\n                items[z] = items[z].clone();\r\n            }\r\n        }\r\n\r\n        const group = new UniformGroup(items);\r\n        group.name = this.name;\r\n\r\n        return group;\r\n\r\n    }\r\n\r\n    public remove(name: string): Uniformable {\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            if (this.items[i].name === name) {\r\n                const o = this.items.splice(i, 1)[0];\r\n                this.itemNames.splice(this.itemNames.indexOf(name), 1);\r\n\r\n                return o\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n\r\n\r\n\r\n    public add(name: string, data: Uniformable, useLocalVariable: boolean = false, stackItems: boolean = true): Uniformable {\r\n\r\n       \r\n       \r\n        data.uniformBuffer = this.uniformBuffer;\r\n        data.name = name;\r\n        data.mustBeTransfered = true;\r\n\r\n        if ((this.uniformBuffer && this.uniformBuffer.descriptor.useLocalVariable) || useLocalVariable) {\r\n            data.createVariableInsideMain = true;\r\n        }\r\n\r\n        if(this.usedAsUniformBuffer == false || data instanceof UniformGroup || data instanceof UniformGroupArray || data instanceof Vec4Array){\r\n           \r\n            data.addEventListener(\"ON_CHANGE\",()=>{\r\n                this.mustBeTransfered = true;\r\n                this.dispatchEvent(\"ON_CHANGE\");\r\n            })\r\n        }\r\n        \r\n\r\n        const alreadyDefined: boolean = !!this.unstackedItems[name];\r\n        this.unstackedItems[name] = data;\r\n\r\n        if (alreadyDefined) {\r\n            for (let i = 0; i < this.items.length; i++) {\r\n                if (this.items[i].name === name) {\r\n                    this.items[i] = data;\r\n                    break;\r\n                }\r\n            }\r\n        } else {\r\n            this.itemNames.push(name);\r\n        }\r\n\r\n        if (stackItems) this.items = this.stackItems(this.unstackedItems);\r\n\r\n        if (this.wgsl) this.wgsl = this.getStruct(this.name);\r\n\r\n        if (this.uniformBuffer) this.uniformBuffer.mustBeTransfered = true;\r\n\r\n        return data;\r\n    }\r\n\r\n    public getElementByName(name: string): Uniformable {\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            if (this.items[i].name === name) {\r\n                //console.log(\"=>>>>>>> \", name)\r\n                return this.items[i];\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n\r\n\r\n\r\n    protected getStructName(name: string) {\r\n        if (!name) return null;\r\n        return name[0].toUpperCase() + name.slice(1);\r\n    }\r\n    protected getVarName(name: string) {\r\n        if (!name) return null;\r\n        return name[0].toLowerCase() + name.slice(1);\r\n    }\r\n\r\n\r\n    public createVariable(uniformBufferName: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n        const varName: string = this.getVarName(this.name);\r\n        return \"   var \" + varName + \":\" + this.getStructName(this.name) + \" = \" + this.getVarName(uniformBufferName) + \".\" + varName + \";\\n\"\r\n    }\r\n\r\n\r\n    public updateStack() {\r\n\r\n        this.items = this.stackItems(this.items);\r\n    }\r\n\r\n    public forceUpdate(): void {\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            if (this.items[i] instanceof UniformGroup || this.items[i] instanceof UniformGroupArray) (this.items[i] as any).forceUpdate()\r\n            this.items[i].mustBeTransfered = true;\r\n        }\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\n    public get type(): any {\r\n        return {\r\n            nbComponent: this.arrayStride,\r\n            isUniformGroup: true,\r\n            isArray: false\r\n        }\r\n    }\r\n\r\n    public setDatas(item: PrimitiveType, dataView: DataView = null, offset: number = 0) {\r\n\r\n        if (!dataView) dataView = this.dataView;\r\n        const startId = item.startId + offset;\r\n        const type: GPUType = item.type;\r\n        const primitive: \"f32\" | \"i32\" | \"u32\" | \"f16\" = type.primitive;\r\n\r\n        //console.log(\"setDatas = \",item.name,startId,type.nbValues)\r\n\r\n        switch (primitive) {\r\n            case \"f32\":\r\n                for (let i = 0; i < type.nbValues; i++) dataView.setFloat32((startId + i) * 4, item[i], true);\r\n                break;\r\n            case \"i32\":\r\n                for (let i = 0; i < type.nbValues; i++) dataView.setInt32((startId + i) * 4, item[i], true);\r\n                break;\r\n            case \"u32\":\r\n                for (let i = 0; i < type.nbValues; i++) dataView.setUint32((startId + i) * 4, item[i], true);\r\n                break;\r\n        }\r\n        if(this.usedAsUniformBuffer == false && item.type.isArray == false){\r\n            item.mustBeTransfered = false;\r\n        }\r\n       \r\n    }\r\n\r\n\r\n    public updateItemFromDataView(dataView:DataView,offset:number){\r\n\r\n        let item: Uniformable;\r\n        \r\n        for (let i = 0; i < this.items.length; i++) {\r\n            item = this.items[i];\r\n           \r\n            if (item instanceof UniformGroup || item instanceof UniformGroupArray) {\r\n                //console.log(\"call  (item as UniformGroup).copyIntoDataView\");\r\n                (item as UniformGroup).updateItemFromDataView(dataView, offset + item.startId);\r\n            } else {\r\n\r\n                const startId = item.startId + offset;\r\n                const type: GPUType = item.type;\r\n                const primitive: \"f32\" | \"i32\" | \"u32\" | \"f16\" = type.primitive;\r\n                const nb = type.nbValues;\r\n                if(primitive == \"f32\"){\r\n                    for(let i=0;i<nb;i++) item[i] = dataView.getFloat32((startId+i)*4,true);\r\n\r\n                }else if(primitive == \"i32\"){\r\n                    for(let i=0;i<nb;i++) item[i] = dataView.getInt32((startId+i)*4,true);\r\n\r\n                }else if(primitive == \"u32\"){\r\n                    for(let i=0;i<nb;i++) item[i] = dataView.getUint32((startId+i)*4,true);\r\n                }\r\n                item.mustBeTransfered = true;\r\n            }\r\n                //console.log(item.name,this.usedAsUniformBuffer)\r\n\r\n               \r\n               \r\n        }\r\n\r\n\r\n    }\r\n\r\n    public copyIntoDataView(dataView: DataView, offset: number) {\r\n\r\n        let item: Uniformable;\r\n        let mustTransfer = false;\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            item = this.items[i];\r\n            //console.log(\"UG.copyIntoDataView item = \",item.name,item.mustBeTransfered)\r\n            if(item.mustBeTransfered){\r\n                mustTransfer = true;\r\n                //console.log(\"MBT => \",item.name)\r\n                if (item instanceof UniformGroup || item instanceof UniformGroupArray) {\r\n                    //console.log(\"call  (item as UniformGroup).copyIntoDataView\");\r\n                    (item as UniformGroup).copyIntoDataView(dataView, offset + item.startId);\r\n                } else {\r\n                    //console.log(\"call setDatas\")\r\n                    this.setDatas(item, dataView, offset)\r\n                }\r\n                //console.log(item.name,this.usedAsUniformBuffer)\r\n\r\n                if(this.usedAsUniformBuffer == false){\r\n                    item.mustBeTransfered = false;\r\n                }\r\n                //\r\n            }\r\n        }\r\n\r\n        //console.log(\"CIDV \",mustTransfer,this.usedAsUniformBuffer)\r\n        this.mustBeTransfered = mustTransfer;\r\n        if( mustTransfer){\r\n            this.dispatchEvent(UniformGroup.ON_CHANGE);\r\n        }\r\n        \r\n\r\n\r\n        //console.log(\"dataView = \",new Float32Array(dataView.buffer));\r\n    }\r\n\r\n   \r\n    public transfertWholeBuffer:boolean = false; \r\n\r\n    public async update(gpuResource: GPUBuffer){//}, fromUniformBuffer: boolean = false) {\r\n\r\n       \r\n        let mustBeTransfered = false;\r\n        \r\n        let item: Uniformable;\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            item = this.items[i];\r\n           \r\n            if (!item.type.isUniformGroup) (item as any).update(); \r\n            else item.update(gpuResource);\r\n            \r\n\r\n\r\n            if ( item.mustBeTransfered) {\r\n                //console.log(\"item MBT = \",item.name)\r\n                mustBeTransfered = true;\r\n                if (!(item instanceof UniformGroup || item instanceof UniformGroupArray )) {\r\n\r\n                      \r\n                        this.setDatas(item)\r\n                        item.mustBeTransfered = false;\r\n\r\n                        if(this.transfertWholeBuffer == false || item.type.isArray){\r\n                            \r\n                            if(this.transfertWholeBuffer == false){\r\n                                XGPU.device.queue.writeBuffer(\r\n                                    gpuResource,\r\n                                    item.globalStartId * Float32Array.BYTES_PER_ELEMENT,\r\n                                    //item.startId * Float32Array.BYTES_PER_ELEMENT,\r\n                                    item.buffer,\r\n                                    item.byteOffset,\r\n                                    item.byteLength\r\n                                )\r\n\r\n                            }\r\n\r\n                        }\r\n\r\n\r\n                    \r\n\r\n                    \r\n                    \r\n                    //item.mustBeTransfered = false;\r\n\r\n                }else{\r\n                    \r\n                    item.copyIntoDataView(this.dataView,item.startId)\r\n                    \r\n                }\r\n\r\n                \r\n\r\n            }\r\n            \r\n        }\r\n\r\n       \r\n       \r\n\r\n        if(/*this.usedAsUniformBuffer &&*/ this.transfertWholeBuffer){\r\n\r\n           if(mustBeTransfered){\r\n                //console.log(\"AAAAAAAAAAAAAAAAAA \",this.mustBeTransfered,new Float32Array(this.dataView.buffer));\r\n                XGPU.device.queue.writeBuffer(\r\n                    gpuResource,\r\n                    0,\r\n                    this.datas,\r\n                    0,\r\n                    this.arrayStride * 4\r\n                )\r\n            }\r\n        }\r\n       \r\n    }\r\n\r\n\r\n\r\n\r\n\r\n    public existingStrucName:string = undefined;\r\n\r\n    public getStruct(name: string): { struct: string, localVariables: string } {\r\n\r\n        this.name = name;\r\n\r\n\r\n        let struct = \"struct \" + this.name + \" {\\n\";\r\n        let item: Uniformable;\r\n        let localVariables = \"\";\r\n        let otherStructs = \"\";\r\n\r\n        let primitiveStructs = \"\";\r\n        let o: { struct: string, localVariables: string }\r\n\r\n        for (let i = 0; i < this.items.length; i++) {\r\n            item = this.items[i];\r\n\r\n\r\n\r\n            if (item instanceof UniformGroup || item instanceof UniformGroupArray) {\r\n                if (item instanceof UniformGroup) {\r\n                    if (!item.wgsl) {\r\n                        //console.log(\"#1 NAME = \", item.name, otherStructs)\r\n                        o = item.getStruct(item.name);\r\n                        localVariables += o.localVariables + \"\\n\";\r\n                        item.wgslStructNames.push(item.name);\r\n                    }\r\n                    if (otherStructs.indexOf(item.wgsl.struct) === -1) {\r\n                        //console.log(\"OHTER : \", otherStructs, item.wgsl.struct)\r\n                        otherStructs = item.wgsl.struct + otherStructs;\r\n                    }\r\n                    struct += \"    \" + this.getVarName(item.name) + \":\" + item.name + \",\\n\"\r\n                    localVariables += item.createVariable(this.name);\r\n\r\n\r\n\r\n                } else {\r\n                    name = item.name;\r\n                    \r\n                    if (!(item.groups[0] as UniformGroup).wgsl) {\r\n                        //console.log(\"#2 NAME = \", name)\r\n                        o = (item.groups[0] as UniformGroup).getStruct(item.name);\r\n                        localVariables += o.localVariables;\r\n                    }\r\n\r\n                    if (otherStructs.indexOf((item.groups[0] as UniformGroup).wgsl.struct) === -1) {\r\n                        otherStructs = (item.groups[0] as UniformGroup).wgsl.struct + otherStructs;\r\n                    }\r\n\r\n                    struct += \"@size(\"+item.length * item.groups[0].arrayStride * 4 +\")    \" + name + \":array<\" + this.getStructName(name) + \",\" + item.length + \">,\\n\"\r\n                    localVariables += item.createVariable(this.name);\r\n                }\r\n\r\n\r\n\r\n            } else {\r\n                let o = item as PrimitiveType;\r\n\r\n\r\n                if (o.propertyNames) {\r\n                    let s = o.createStruct();\r\n\r\n                    if (primitiveStructs.indexOf(s) === -1 && otherStructs.indexOf(s) === -1 && struct.indexOf(s) === -1) {\r\n                        primitiveStructs += s + \"\\n\";\r\n                    }\r\n                    \r\n                    struct += \"     @size(16) \" + o.name + \":\" + o.className + \",\\n\";\r\n                    //struct += \"     @size(16) \" + o.name + \":\" + o.constructor.name + \",\\n\";\r\n\r\n                } else {\r\n\r\n\r\n                    if (o.type.isArray) {\r\n\r\n                        if (o.type.isArrayOfMatrixs) {\r\n\r\n                            let col = o.type.matrixColumns;\r\n                            let row = 4;\r\n                            if (o.type.matrixRows === 2) row = 2;\r\n\r\n                            struct += \"    @size(\" + (o.type.arrayLength * col * row * 4) + \") \" + o.name + \":\" + o.type.dataType + \",\\n\";\r\n                        } else {\r\n\r\n                            struct += \"    @size(\" + (o.type.arrayLength * 16) + \") \" + o.name + \":\" + o.type.dataType + \",\\n\";\r\n                        }\r\n\r\n                    } else {\r\n                        struct += \"    \" + o.name + \":\" + o.type.dataType + \",\\n\";\r\n                    }\r\n\r\n                }\r\n\r\n\r\n                if (o.createVariableInsideMain) localVariables += o.createVariable(this.getVarName(this.name));\r\n            }\r\n        }\r\n        struct += \"}\\n\\n\";\r\n\r\n\r\n        struct = primitiveStructs + otherStructs + struct;\r\n\r\n\r\n\r\n\r\n        this.wgsl = {\r\n            struct,\r\n            localVariables\r\n        };\r\n\r\n        \r\n        return this.wgsl;\r\n    }\r\n\r\n\r\n\r\n\r\n    public stackItems(items: any): Uniformable[] {\r\n\r\n        //console.warn(\"stackItems\")\r\n        //console.time(\"STACK ITEMS\")\r\n\r\n\r\n        //----- we sort the items by arraystride to start with bigger values / complex structure ----\r\n        /*\r\n        let itemList = [];\r\n        let item:any;\r\n        let uniformGroupArrays = [];\r\n        let uniformGroups = [];\r\n        let vecArrays = [];\r\n        let matrixArrays = [];\r\n        let matrixs = [];\r\n        let primitives = [];\r\n\r\n        for(let z in items){\r\n            item = items[z];\r\n            item.name = z;\r\n            if(item instanceof UniformGroupArray) uniformGroupArrays.push(item);\r\n            else if(item instanceof UniformGroup) uniformGroups.push(item);\r\n            else if(item.type.isArrayOfMatrixs) matrixArrays.push(item);\r\n            else if(item.type.isArray) vecArrays.push(item);\r\n            else if(item.type.isMatrix) matrixs.push(item);\r\n            else primitives.push(item);\r\n        } \r\n\r\n        const sortGroup = (a,b)=>{\r\n            if(a.arrayStride > b.arrayStride) return -1;\r\n            if(a.arrayStride < b.arrayStride) return 1;\r\n            return 0;\r\n        }\r\n\r\n        uniformGroupArrays = uniformGroupArrays.sort(sortGroup);\r\n        uniformGroups = uniformGroups.sort(sortGroup);\r\n\r\n        const sortArray = (a,b)=>{\r\n            const lenA = a.type.isArrayOfMatrixs ? a.type.matrixRows * 4 * a.type.arrayLength : a.type.arrayLength * 4;\r\n            const lenB = b.type.isArrayOfMatrixs ? b.type.matrixRows * 4 * b.type.arrayLength : b.type.arrayLength * 4;\r\n\r\n            if(lenA > lenB) return -1;\r\n            if(lenA < lenB) return 1;\r\n            return 0;\r\n        }\r\n\r\n        vecArrays = vecArrays.sort(sortArray);\r\n        matrixArrays = matrixArrays.sort(sortArray);\r\n\r\n        \r\n        primitives = primitives.sort((a,b)=>{\r\n            if(a.type.nbComponent > b.type.nbComponent) return -1;\r\n            if(a.type.nbComponent < b.type.nbComponent) return 1;\r\n            return 0;\r\n        })\r\n\r\n\r\n        itemList = uniformGroupArrays.concat(uniformGroups);\r\n        itemList = itemList.concat(matrixArrays);\r\n        itemList = itemList.concat(vecArrays);\r\n        itemList = itemList.concat(matrixs);\r\n        itemList = itemList.concat(primitives);\r\n        */\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n        const result: any[] = []\r\n\r\n        let bound = 1;\r\n\r\n        var floats: any[] = [];\r\n        var vec2s: any[] = [];\r\n        var vec3s: any[] = [];\r\n\r\n\r\n        let v: any, type: any, nbComponent;\r\n        let offset = 0;\r\n\r\n\r\n\r\n        //for(let i=0;i<itemList.length;i++){\r\n        for (let z in items) {\r\n\r\n            //v = itemList[i];\r\n            v = items[z];\r\n            v.name = z;\r\n            type = v.type;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n            if (v instanceof UniformGroupArray) {\r\n\r\n                v.startId = offset;\r\n                offset += v.arrayStride;\r\n                //console.log(v.name+\" =======>>>> \",v.arrayStride)\r\n                result.push(v);\r\n\r\n            } else {\r\n\r\n                if (type.isArray) {\r\n\r\n                    v.startId = offset;\r\n\r\n                    if (type.isArrayOfMatrixs) {\r\n                        offset += type.matrixRows * 4 * type.arrayLength;\r\n                    } else {\r\n                        offset += 4 * type.arrayLength;\r\n                    }\r\n                    bound = 4;\r\n                    result.push(v);\r\n\r\n\r\n                } else if (type.isMatrix) {\r\n                    v.startId = offset;\r\n\r\n                    let col = type.matrixColumns;\r\n                    let row = 4;\r\n                    if (type.matrixRows === 2) row = 2;\r\n                    offset += col * row;\r\n                    bound = row;\r\n                    result.push(v);\r\n\r\n                } else if (type.isUniformGroup) {\r\n                    \r\n                    if (type.nbComponent >= 4) {\r\n                        bound = 4;\r\n                        v.startId = offset;\r\n                        offset += Math.ceil(type.nbComponent / 4) * 4;\r\n                        \r\n                        result.push(v);\r\n                    }\r\n                   \r\n\r\n                } else if ((v as PrimitiveType).propertyNames) { //if it's a customClass the extends a PrimitiveType and use a struct\r\n                    bound = 4;\r\n                    v.startId = offset;\r\n                    offset += 4;\r\n                    result.push(v);\r\n\r\n                } else {\r\n\r\n\r\n\r\n                    nbComponent = type.nbValues;\r\n\r\n                    if (nbComponent === 1) floats.push(v);\r\n                    else if (nbComponent === 2) {\r\n                        if (bound < 2) bound = 2;\r\n                        vec2s.push(v);\r\n                    } else if (nbComponent === 3) {\r\n                        bound = 4;\r\n                        vec3s.push(v);\r\n                    } else if (nbComponent >= 4) {\r\n                        bound = 4;\r\n                        v.startId = offset;\r\n                        offset += nbComponent;\r\n                        result.push(v);\r\n                    }\r\n\r\n                }\r\n\r\n            }\r\n\r\n        }\r\n\r\n\r\n\r\n        //------------------------\r\n\r\n\r\n        const addVec3 = () => {\r\n            v = vec3s.shift();\r\n            v.startId = offset;\r\n            offset += 3;\r\n            result.push(v);\r\n            if (floats.length) {\r\n                const f = floats.shift();\r\n                f.startId = offset;\r\n                result.push(f);\r\n            }\r\n            offset++\r\n        }\r\n\r\n        let nb = vec3s.length;\r\n        for (let i = 0; i < nb; i++) addVec3();\r\n\r\n        //--------------------------\r\n\r\n        nb = vec2s.length;\r\n        for (let i = 0; i < nb; i++) {\r\n            v = vec2s.shift();\r\n            v.startId = offset;\r\n            offset += 2;\r\n            result.push(v);\r\n        }\r\n\r\n        //--------------------------\r\n\r\n        nb = floats.length;\r\n\r\n        //console.log(\"floats.length = \",nb)\r\n        for (let i = 0; i < nb; i++) {\r\n            v = floats.shift();\r\n            v.startId = offset;\r\n            //console.log(\"v = \",v)\r\n            //console.log(v.name, v.startId * 4)\r\n            offset++;\r\n            result.push(v);\r\n        }\r\n\r\n        //--------------------------\r\n        \r\n\r\n        //BEFORE 07/11/2024:\r\n        if (offset % bound !== 0) {\r\n            offset += bound - (offset % bound);\r\n        }\r\n        \r\n       //console.log(\"offset \",offset)\r\n        //----AJOUT LE 07/11/2024------\r\n        if(offset % 4 != 0){\r\n            const n = 4 - offset % 4;\r\n\r\n           if(!this.usedAsUniformBuffer){\r\n                for(let i=0;i<n;i++){\r\n                    const float = new Float(0);\r\n                    float.startId = offset;\r\n                    float.name = \"padding_\"+i;\r\n                    result.push(float)\r\n                    this.itemNames.push(float.name)\r\n                }\r\n           }\r\n            \r\n            offset += n;\r\n        }\r\n       \r\n        //--------------------------\r\n        \r\n\r\n        //console.log(\"uniformGroup \",result,offset,bound);\r\n        this.arrayStride = offset ;\r\n\r\n\r\n\r\n\r\n\r\n        this.datas = new ArrayBuffer(offset * 4);\r\n\r\n        \r\n\r\n        this.dataView = new DataView(this.datas, 0, this.datas.byteLength);\r\n        this.items = result;\r\n        this.copyIntoDataView(this.dataView, 0);\r\n\r\n        //console.timeEnd(\"STACK ITEMS\")\r\n        return result\r\n\r\n    }\r\n\r\n    \r\n\r\n    public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n        \r\n        let item:Uniformable;\r\n        for(let i=0;i<this.items.length;i++){\r\n            item = this.items[i];\r\n            item.globalStartId = this.globalStartId + item.startId;\r\n            if(item instanceof UniformGroup || item instanceof UniformGroupArray || item.type.isArray){\r\n                item.updateStartIdFromParentToChildren();\r\n            }\r\n        }\r\n    }\r\n\r\n    public get definition():{type:string,values:ArrayBuffer,items:any,name:string}{\r\n\r\n        const items = {};\r\n        for(let i=0;i<this.items.length;i++){\r\n            items[this.itemNames[i]] = this.items[i].definition;\r\n        }\r\n\r\n        return {type:\"UniformGroup\",values:this.datas,items,name:this.name}\r\n    }\r\n\r\n    /*\r\n    protected createTypedArrayBuffer(result: any) {\r\n\r\n        let datas: Float32Array | Int32Array | Uint32Array;\r\n        if (this.primitiveType === \"f32\") datas = new Float32Array(this.arrayStride);\r\n        else if (this.primitiveType === \"i32\") datas = new Int32Array(this.arrayStride);\r\n        else if (this.primitiveType === \"u32\") datas = new Uint32Array(this.arrayStride);\r\n\r\n        //console.log(\"uniform type = \", this._primitiveType)\r\n\r\n        let o: any;\r\n        for (let i = 0; i < result.length; i++) {\r\n            o = result[i];\r\n            if (o instanceof UniformGroup || o instanceof UniformGroupArray) {\r\n                if (o instanceof UniformGroup) {\r\n                    datas.set(o.datas as Float32Array | Int32Array | Uint32Array, o.startId);\r\n                } else {\r\n                    let start = o.startId;\r\n                    for (let j = 0; j < o.length; j++) {\r\n                        datas.set(o.groups[j].datas as Float32Array | Int32Array | Uint32Array, start);\r\n                        start += o.groups[j].arrayStride;\r\n                    }\r\n                }\r\n            } else {\r\n                datas.set(o, o.startId)\r\n            }\r\n        }\r\n\r\n        this.datas = datas;\r\n\r\n    }\r\n    */\r\n}"
          }
        ],
        "UniformGroupArray": [
          {
            "objectType": "class",
            "name": "UniformGroupArray",
            "filePath": "xGPU.shader.resources.UniformGroupArray",
            "extends": [
              "EventDispatcher"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "groups",
                  "type": "UniformGroup[]",
                  "visibility": "public",
                  "rawText": "public groups: UniformGroup[];"
                },
                {
                  "objectType": "property",
                  "name": "startId",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public startId: number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "globalStartId",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public globalStartId:number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "createVariableInsideMain",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public createVariableInsideMain: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "name",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public name: string;"
                },
                {
                  "objectType": "property",
                  "name": "mustBeTransfered",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public mustBeTransfered:boolean = true;"
                },
                {
                  "objectType": "property",
                  "name": "uniformBuffer",
                  "type": "UniformBuffer",
                  "visibility": "public",
                  "rawText": "public get uniformBuffer(): UniformBuffer { return this.buffer }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "type",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public get type(): any { return { nbComponent: this.arrayStride, isUniformGroup: true, isArray: true } }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "length",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get length(): number { return this.groups.length }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "arrayStride",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get arrayStride(): number { \r\n\r\n        let stride = this.groups[0].arrayStride * this.groups.length ;\r\n        /*\r\n        if(stride % 4 != 0){\r\n            stride += 4 - stride % 4;\r\n        }\r\n        */\r\n        //console.log(\"STRIDE = \",stride);\r\n\r\n        return stride;\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "isArray",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public get isArray(): boolean { return true; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "isUniformGroup",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public get isUniformGroup(): boolean { return true; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "definition",
                  "type": "{ type: string; groups: any[]; name: string; }",
                  "visibility": "public",
                  "rawText": "public get definition():{type:string,groups:any[],name:string}{\r\n\r\n        const groups = [];\r\n        for(let i=0;i<this.groups.length;i++){\r\n            groups[i] = this.groups[i].definition;\r\n        }\r\n\r\n        return {type:\"UniformGroupArray\",groups,name:this.name}\r\n    }",
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "mustDispatchChangeEvent",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected mustDispatchChangeEvent:boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "buffer",
                  "type": "UniformBuffer",
                  "visibility": "protected",
                  "rawText": "protected buffer: UniformBuffer = null;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "updateStartIdFromParentToChildren",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n        \r\n        for(let i=0;i<this.groups.length;i++){\r\n            this.groups[i].globalStartId = this.globalStartId + this.groups[i].startId;\r\n            this.groups[i].updateStartIdFromParentToChildren();\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "UniformGroupArray",
                  "visibility": "public",
                  "rawText": "public clone(): UniformGroupArray {\r\n        const t = [...this.groups];\r\n        for (let i = 0; i < t.length; i++) {\r\n            t[i] = t[i].clone();\r\n        }\r\n\r\n        const group = new UniformGroupArray(t, this.createVariableInsideMain);\r\n        group.startId = this.startId;\r\n        group.name = this.name;\r\n        return group;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "copyIntoDataView",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "dataView",
                      "type": "DataView"
                    },
                    {
                      "name": "offset",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public copyIntoDataView(dataView: DataView, offset: number) {\r\n        //console.log(\"groupArray copy into dataview\")\r\n        let group: UniformGroup;\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            if(group.mustBeTransfered){\r\n                group.copyIntoDataView(dataView, offset);\r\n                //console.log(\"groupArray \",i,offset,new Float32Array(dataView.buffer))\r\n                group.mustBeTransfered = false;\r\n            }\r\n            //\r\n            \r\n            offset += group.arrayStride;\r\n        }\r\n        this.mustBeTransfered = false;\r\n        //console.log(\"====> \",Array.from(new Float32Array(dataView.buffer)))\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createVariable",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "uniformBufferName",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createVariable(uniformBufferName: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n        const varName: string = this.getVarName(this.name);\r\n        return \"   var \" + varName + \":array<\" + this.getStructName(this.name) + \",\" + this.length + \"> = \" + this.getVarName(uniformBufferName) + \".\" + varName + \";\\n\"\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "gpuResource",
                      "type": "GPUBuffer"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public update(gpuResource: GPUBuffer){\r\n        \r\n        //console.warn(\"uniformGroupArray.update\")\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].update(gpuResource);\r\n        }\r\n        \r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "forceUpdate",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public forceUpdate(): void {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].forceUpdate()\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getElementById",
                  "returnType": "UniformGroup",
                  "params": [
                    {
                      "name": "id",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public getElementById(id: number): UniformGroup { return this.groups[id] }"
                }
              ],
              "protected": [
                {
                  "objectType": "method",
                  "name": "getStructName",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "protected",
                  "rawText": "protected getStructName(name: string) {\r\n        if (!name) return null;\r\n        return name[0].toUpperCase() + name.slice(1);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getVarName",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "protected",
                  "rawText": "protected getVarName(name: string) {\r\n        if (!name) return null;\r\n        return name[0].toLowerCase() + name.slice(1);\r\n    }"
                }
              ]
            },
            "statics": {
              "properties": {
                "public": [
                  {
                    "objectType": "property",
                    "name": "ON_CHANGE",
                    "type": "string",
                    "visibility": "public",
                    "rawText": "public static ON_CHANGE:string = \"ON_CHANGE\";"
                  },
                  {
                    "objectType": "property",
                    "name": "ON_CHANGED",
                    "type": "string",
                    "visibility": "public",
                    "rawText": "public static ON_CHANGED:string = \"ON_CHANGED\";"
                  }
                ]
              }
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "groups",
                  "type": "UniformGroup[]"
                },
                {
                  "name": "createLocalVariable",
                  "type": "boolean"
                }
              ],
              "rawText": "constructor(groups: UniformGroup[], createLocalVariable: boolean = false) {\r\n        \r\n        super();\r\n\r\n        this.groups = groups;\r\n\r\n\r\n        //----- AJOUT LE 07/11/2024 --------\r\n        let offset = 0;\r\n        groups.forEach((g)=>{\r\n            g.startId = offset;\r\n            g.startId = offset;\r\n            offset += g.arrayStride;\r\n            \r\n            \r\n            g.addEventListener(UniformGroup.ON_CHANGE,()=>{\r\n               \r\n                this.mustBeTransfered = true;\r\n                this.dispatchEvent(UniformGroupArray.ON_CHANGE)\r\n            })\r\n            \r\n        })\r\n        //----------------------------------\r\n\r\n        this.createVariableInsideMain = createLocalVariable;\r\n    }"
            },
            "rawText": "export class UniformGroupArray extends EventDispatcher {\r\n\r\n    public static ON_CHANGE:string = \"ON_CHANGE\";\r\n    public static ON_CHANGED:string = \"ON_CHANGED\";\r\n\r\n\r\n    public groups: UniformGroup[];\r\n\r\n    public startId: number = 0;\r\n    public globalStartId:number = 0;\r\n    \r\n    public createVariableInsideMain: boolean = false;\r\n    public name: string;\r\n\r\n    public mustBeTransfered:boolean = true;\r\n    protected mustDispatchChangeEvent:boolean = false;\r\n   \r\n\r\n    protected buffer: UniformBuffer = null;\r\n    public get uniformBuffer(): UniformBuffer { return this.buffer };\r\n    public set uniformBuffer(buffer: UniformBuffer) {\r\n        this.buffer = buffer;\r\n        if (buffer) buffer.mustBeTransfered = true;\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].uniformBuffer = buffer;\r\n        }\r\n    }\r\n\r\n    constructor(groups: UniformGroup[], createLocalVariable: boolean = false) {\r\n        \r\n        super();\r\n\r\n        this.groups = groups;\r\n\r\n\r\n        //----- AJOUT LE 07/11/2024 --------\r\n        let offset = 0;\r\n        groups.forEach((g)=>{\r\n            g.startId = offset;\r\n            g.startId = offset;\r\n            offset += g.arrayStride;\r\n            \r\n            \r\n            g.addEventListener(UniformGroup.ON_CHANGE,()=>{\r\n               \r\n                this.mustBeTransfered = true;\r\n                this.dispatchEvent(UniformGroupArray.ON_CHANGE)\r\n            })\r\n            \r\n        })\r\n        //----------------------------------\r\n\r\n        this.createVariableInsideMain = createLocalVariable;\r\n    }\r\n\r\n    public updateStartIdFromParentToChildren(){\r\n        //used to update the startId of elements contained in an array\r\n        //|=> by default, the startId is related to the parent, but the parent may have a parent too so we must update every startId\r\n        \r\n        for(let i=0;i<this.groups.length;i++){\r\n            this.groups[i].globalStartId = this.globalStartId + this.groups[i].startId;\r\n            this.groups[i].updateStartIdFromParentToChildren();\r\n        }\r\n    }\r\n\r\n    public clone(): UniformGroupArray {\r\n        const t = [...this.groups];\r\n        for (let i = 0; i < t.length; i++) {\r\n            t[i] = t[i].clone();\r\n        }\r\n\r\n        const group = new UniformGroupArray(t, this.createVariableInsideMain);\r\n        group.startId = this.startId;\r\n        group.name = this.name;\r\n        return group;\r\n    }\r\n\r\n    public get type(): any { return { nbComponent: this.arrayStride, isUniformGroup: true, isArray: true } }\r\n\r\n    public copyIntoDataView(dataView: DataView, offset: number) {\r\n        //console.log(\"groupArray copy into dataview\")\r\n        let group: UniformGroup;\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            group = this.groups[i];\r\n            if(group.mustBeTransfered){\r\n                group.copyIntoDataView(dataView, offset);\r\n                //console.log(\"groupArray \",i,offset,new Float32Array(dataView.buffer))\r\n                group.mustBeTransfered = false;\r\n            }\r\n            //\r\n            \r\n            offset += group.arrayStride;\r\n        }\r\n        this.mustBeTransfered = false;\r\n        //console.log(\"====> \",Array.from(new Float32Array(dataView.buffer)))\r\n    }\r\n\r\n\r\n    protected getStructName(name: string) {\r\n        if (!name) return null;\r\n        return name[0].toUpperCase() + name.slice(1);\r\n    }\r\n    protected getVarName(name: string) {\r\n        if (!name) return null;\r\n        return name[0].toLowerCase() + name.slice(1);\r\n    }\r\n\r\n    public createVariable(uniformBufferName: string): string {\r\n        if (!this.createVariableInsideMain) return \"\";\r\n        const varName: string = this.getVarName(this.name);\r\n        return \"   var \" + varName + \":array<\" + this.getStructName(this.name) + \",\" + this.length + \"> = \" + this.getVarName(uniformBufferName) + \".\" + varName + \";\\n\"\r\n    }\r\n\r\n    \r\n\r\n    public update(gpuResource: GPUBuffer){\r\n        \r\n        //console.warn(\"uniformGroupArray.update\")\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].update(gpuResource);\r\n        }\r\n        \r\n    }\r\n\r\n    public forceUpdate(): void {\r\n        for (let i = 0; i < this.groups.length; i++) {\r\n            this.groups[i].forceUpdate()\r\n        }\r\n    }\r\n\r\n    public getElementById(id: number): UniformGroup { return this.groups[id] };\r\n\r\n    public get length(): number { return this.groups.length };\r\n    public get arrayStride(): number { \r\n\r\n        let stride = this.groups[0].arrayStride * this.groups.length ;\r\n        /*\r\n        if(stride % 4 != 0){\r\n            stride += 4 - stride % 4;\r\n        }\r\n        */\r\n        //console.log(\"STRIDE = \",stride);\r\n\r\n        return stride;\r\n    }\r\n    public get isArray(): boolean { return true; }\r\n    public get isUniformGroup(): boolean { return true; }\r\n\r\n\r\n    public get definition():{type:string,groups:any[],name:string}{\r\n\r\n        const groups = [];\r\n        for(let i=0;i<this.groups.length;i++){\r\n            groups[i] = this.groups[i].definition;\r\n        }\r\n\r\n        return {type:\"UniformGroupArray\",groups,name:this.name}\r\n    }\r\n}"
          }
        ],
        "VertexAttribute": [
          {
            "objectType": "class",
            "name": "VertexAttribute",
            "filePath": "xGPU.shader.resources.VertexAttribute",
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "dataOffset",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public dataOffset: number;"
                },
                {
                  "objectType": "property",
                  "name": "mustBeTransfered",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public mustBeTransfered: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "vertexBuffer",
                  "type": "VertexBuffer",
                  "visibility": "public",
                  "rawText": "public get vertexBuffer(): VertexBuffer { return this._vertexBuffer; }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "datas",
                  "type": "number[] | number[][]",
                  "visibility": "public",
                  "rawText": "public get datas(): number[][] | number[] { return this._data }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "useByVertexData",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public get useByVertexData(): boolean { return typeof this._data[0] != \"number\" }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "format",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public get format(): string { return this._dataType }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "type",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public get type(): string {//---------------------------\r\n        //this function will be used in HighLevelParser. \r\n        //It mimic the existing structure using VertexAttribute.Float instead of FloatBuffer\r\n        return this._dataType;\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "bytePerElement",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get bytePerElement(): number { return this.vertexType.bytes }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "varType",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public get varType(): string { return this.vertexType.varType }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "name",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public get name(): string { return this._name; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "nbComponent",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get nbComponent(): number { return this.nbValues; }",
                  "get": true
                }
              ],
              "private": [
                {
                  "objectType": "property",
                  "name": "_name",
                  "type": "string",
                  "visibility": "private",
                  "rawText": "private _name: string;"
                },
                {
                  "objectType": "property",
                  "name": "_dataType",
                  "type": "string",
                  "visibility": "private",
                  "rawText": "private _dataType: string;"
                },
                {
                  "objectType": "property",
                  "name": "nbValues",
                  "type": "number",
                  "visibility": "private",
                  "rawText": "private nbValues: number;"
                },
                {
                  "objectType": "property",
                  "name": "vertexType",
                  "type": "{ name: string; nbComponent: number; bytes: number; varType: string; }",
                  "visibility": "private",
                  "rawText": "private vertexType: { name: string, nbComponent: number, bytes: number, varType: string };"
                },
                {
                  "objectType": "property",
                  "name": "_data",
                  "type": "number[] | number[][]",
                  "visibility": "private",
                  "rawText": "private _data: number[][] | number[];"
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "_vertexBuffer",
                  "type": "VertexBuffer",
                  "visibility": "protected",
                  "rawText": "protected _vertexBuffer: VertexBuffer;"
                },
                {
                  "objectType": "property",
                  "name": "waitingVertexBuffer",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected waitingVertexBuffer: boolean = false;"
                }
              ]
            },
            "methods": {
              "private": [
                {
                  "objectType": "method",
                  "name": "renameVertexDataType",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "type",
                      "type": "string"
                    }
                  ],
                  "visibility": "private",
                  "rawText": "private renameVertexDataType(type: string): string {\r\n        switch (type) {\r\n            case \"float\":\r\n                return \"float32\";\r\n            case \"vec2\":\r\n                return \"float32x2\";\r\n            case \"vec3\":\r\n                return \"float32x3\";\r\n            case \"vec4\":\r\n                return \"float32x4\";\r\n\r\n            case \"int\":\r\n                return \"sint32\";\r\n            case \"ivec2\":\r\n                return \"sint32x2\";\r\n            case \"ivec3\":\r\n                return \"sint32x3\";\r\n            case \"ivec4\":\r\n                return \"sint32x4\";\r\n\r\n\r\n            case \"uint\":\r\n                return \"uint32\";\r\n            case \"uvec2\":\r\n                return \"uint32x2\";\r\n            case \"uvec3\":\r\n                return \"uint32x3\";\r\n            case \"uvec4\":\r\n                return \"uint32x4\";\r\n\r\n        }\r\n        return type;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getVertexDataType",
                  "returnType": "{ name: string; nbComponent: number; bytes: number; varType: string; }",
                  "params": [
                    {
                      "name": "dataType",
                      "type": "string"
                    }
                  ],
                  "visibility": "private",
                  "rawText": "private getVertexDataType(dataType: string): { name: string, nbComponent: number, bytes: number, varType: string } {\r\n\r\n        switch (dataType) {\r\n\r\n            case \"u32\":\r\n                return { name: \"uint32\", nbComponent: 1, bytes: 4, varType: \"u32\" };\r\n            case \"vec2<u32>\":\r\n                return { name: \"uint32x2\", nbComponent: 2, bytes: 8, varType: \"vec2<u32>\" };\r\n            case \"vec3<u32>\":\r\n                return { name: \"uint32x3\", nbComponent: 3, bytes: 12, varType: \"vec3<u32>\" };\r\n            case \"vec4<u32>\":\r\n                return { name: \"uint32x4\", nbComponent: 4, bytes: 16, varType: \"vec4<u32>\" };\r\n\r\n            case \"i32\":\r\n                return { name: \"sint32\", nbComponent: 1, bytes: 4, varType: \"i32\" };\r\n            case \"vec2<i32>\":\r\n                return { name: \"sint32x2\", nbComponent: 2, bytes: 8, varType: \"vec2<i32>\" };\r\n            case \"vec3<i32>\":\r\n                return { name: \"sint32x3\", nbComponent: 3, bytes: 12, varType: \"vec3<i32>\" };\r\n            case \"vec4<i32>\":\r\n                return { name: \"sint32x4\", nbComponent: 4, bytes: 16, varType: \"vec4<i32>\" };\r\n\r\n            case \"f32\":\r\n                return { name: \"float32\", nbComponent: 1, bytes: 4, varType: \"f32\" };\r\n            case \"vec2<f32>\":\r\n                return { name: \"float32x2\", nbComponent: 2, bytes: 8, varType: \"vec2<f32>\" };\r\n            case \"vec3<f32>\":\r\n                return { name: \"float32x3\", nbComponent: 3, bytes: 12, varType: \"vec3<f32>\" };\r\n            case \"vec4<f32>\":\r\n                return { name: \"float32x4\", nbComponent: 4, bytes: 16, varType: \"vec4<f32>\" };\r\n\r\n\r\n            case \"vec2<f16>\":\r\n                return { name: \"float16x2\", nbComponent: 2, bytes: 4, varType: \"vec2<f16>\" };\r\n            case \"vec4<f16>\":\r\n                return { name: \"float16x4\", nbComponent: 4, bytes: 8, varType: \"vec4<f16>\" };\r\n\r\n            default:\r\n                throw new Error(\"GPUVertexAttribute.getVertexDataType error : dataInfo doesn't represent a correct VertexAttribute data-type\")\r\n\r\n        }\r\n\r\n\r\n    }"
                }
              ]
            },
            "statics": {
              "properties": {
                "public": [
                  {
                    "objectType": "property",
                    "name": "types",
                    "type": "any",
                    "visibility": "public",
                    "rawText": "public static get types(): any {\r\n        return {\r\n            \"uint8x2\": { nbComponent: 2, bytes: 2, varType: \"vec2<u32>\" },\r\n            \"uint8x4\": { nbComponent: 4, bytes: 4, varType: \"vec4<u32>\" },\r\n            \"sint8x2\": { nbComponent: 2, bytes: 2, varType: \"vec2<i32>\" },\r\n            \"sint8x4\": { nbComponent: 4, bytes: 4, varType: \"vec4<i32>\" },\r\n\r\n            \"unorm8x2\": { nbComponent: 2, bytes: 2, varType: \"vec2<f32>\" },\r\n            \"unorm8x4\": { nbComponent: 4, bytes: 4, varType: \"vec4<f32>\" },\r\n\r\n            \"snorm8x2\": { nbComponent: 2, bytes: 2, varType: \"vec2<f32>\" },\r\n            \"snorm8x4\": { nbComponent: 4, bytes: 4, varType: \"vec4<f32>\" },\r\n\r\n            \"uint16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<u32>\" },\r\n            \"uint16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<u32>\" },\r\n\r\n            \"sint16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<i32>\" },\r\n            \"sint16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<i32>\" },\r\n\r\n            \"unorm16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<f32>\" },\r\n            \"unorm16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<f32>\" },\r\n\r\n            \"snorm16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<f32>\" },\r\n            \"snorm16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<f32>\" },\r\n\r\n            \"float16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<f16>\" },\r\n            \"float16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<f16>\" },\r\n\r\n            \"float32\": { nbComponent: 1, bytes: 4, varType: \"f32\" },\r\n            \"float32x2\": { nbComponent: 2, bytes: 8, varType: \"vec2<f32>\" },\r\n            \"float32x3\": { nbComponent: 3, bytes: 12, varType: \"vec3<f32>\" },\r\n            \"float32x4\": { nbComponent: 4, bytes: 16, varType: \"vec4<f32>\" },\r\n\r\n            \"uint32\": { nbComponent: 1, bytes: 4, varType: \"u32\" },\r\n            \"uint32x2\": { nbComponent: 2, bytes: 8, varType: \"vec2<u32>\" },\r\n            \"uint32x3\": { nbComponent: 3, bytes: 12, varType: \"vec3<u32>\" },\r\n            \"uint32x4\": { nbComponent: 4, bytes: 16, varType: \"vec4<u32>\" },\r\n\r\n            \"sint32\": { nbComponent: 1, bytes: 4, varType: \"i32\" },\r\n            \"sint32x2\": { nbComponent: 2, bytes: 8, varType: \"vec2<i32>\" },\r\n            \"sint32x3\": { nbComponent: 3, bytes: 12, varType: \"vec3<i32>\" },\r\n            \"sint32x4\": { nbComponent: 4, bytes: 16, varType: \"vec4<i32>\" },\r\n        }\r\n    }",
                    "get": true
                  }
                ]
              },
              "methods": {
                "public": [
                  {
                    "objectType": "method",
                    "name": "Float",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static Float(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        //console.log(\"offset = \", datas, offset)\r\n        return { type: \"float32\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "Vec2",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static Vec2(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"float32x2\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "Vec3",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static Vec3(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"float32x3\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "Vec4",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static Vec4(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"float32x4\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "Int",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static Int(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"sint32\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "IVec2",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static IVec2(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"sint32x2\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "IVec3",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static IVec3(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"sint32x3\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "IVec4",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static IVec4(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"sint32x4\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "Uint",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static Uint(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"uint32\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "UVec2",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static UVec2(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"uint32x2\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "UVec3",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static UVec3(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"uint32x3\", offset, datas }\r\n    }"
                  },
                  {
                    "objectType": "method",
                    "name": "UVec4",
                    "returnType": "{ type: string; offset: number; datas: number | number[] | number[][]; }",
                    "params": [
                      {
                        "name": "datas",
                        "type": "number | number[] | number[][]"
                      },
                      {
                        "name": "offset",
                        "type": "number"
                      }
                    ],
                    "visibility": "public",
                    "rawText": "public static UVec4(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas && !offset) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"uint32x4\", offset, datas }\r\n    }"
                  }
                ]
              }
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "name",
                  "type": "string"
                },
                {
                  "name": "dataType",
                  "type": "string"
                },
                {
                  "name": "offset",
                  "type": "number"
                }
              ],
              "rawText": "constructor(name: string, dataType: string, offset?: number) {\r\n\r\n        dataType = this.renameVertexDataType(dataType);\r\n\r\n        this._name = name;\r\n        this._dataType = dataType;\r\n        this.dataOffset = offset;\r\n\r\n        if (VertexAttribute.types[dataType]) {\r\n            this.vertexType = VertexAttribute.types[dataType];\r\n            this.nbValues = this.vertexType.nbComponent;\r\n        } else {\r\n\r\n            const infos = new GPUType(dataType);\r\n            this.nbValues = infos.nbValues;\r\n            this.vertexType = this.getVertexDataType(infos.dataType)\r\n        }\r\n    }"
            },
            "rawText": "export class VertexAttribute {\r\n\r\n\r\n\r\n    public static Float(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        //console.log(\"offset = \", datas, offset)\r\n        return { type: \"float32\", offset, datas }\r\n    }\r\n    public static Vec2(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"float32x2\", offset, datas }\r\n    }\r\n    public static Vec3(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"float32x3\", offset, datas }\r\n    }\r\n    public static Vec4(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"float32x4\", offset, datas }\r\n    }\r\n\r\n    public static Int(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"sint32\", offset, datas }\r\n    }\r\n    public static IVec2(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"sint32x2\", offset, datas }\r\n    }\r\n    public static IVec3(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"sint32x3\", offset, datas }\r\n    }\r\n    public static IVec4(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"sint32x4\", offset, datas }\r\n    }\r\n\r\n    public static Uint(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"uint32\", offset, datas }\r\n    }\r\n    public static UVec2(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"uint32x2\", offset, datas }\r\n    }\r\n    public static UVec3(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"uint32x3\", offset, datas }\r\n    }\r\n    public static UVec4(datas?: number[][] | number[] | number, offset?: number) {\r\n        if (datas && !offset) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n        return { type: \"uint32x4\", offset, datas }\r\n    }\r\n\r\n\r\n\r\n    public static get types(): any {\r\n        return {\r\n            \"uint8x2\": { nbComponent: 2, bytes: 2, varType: \"vec2<u32>\" },\r\n            \"uint8x4\": { nbComponent: 4, bytes: 4, varType: \"vec4<u32>\" },\r\n            \"sint8x2\": { nbComponent: 2, bytes: 2, varType: \"vec2<i32>\" },\r\n            \"sint8x4\": { nbComponent: 4, bytes: 4, varType: \"vec4<i32>\" },\r\n\r\n            \"unorm8x2\": { nbComponent: 2, bytes: 2, varType: \"vec2<f32>\" },\r\n            \"unorm8x4\": { nbComponent: 4, bytes: 4, varType: \"vec4<f32>\" },\r\n\r\n            \"snorm8x2\": { nbComponent: 2, bytes: 2, varType: \"vec2<f32>\" },\r\n            \"snorm8x4\": { nbComponent: 4, bytes: 4, varType: \"vec4<f32>\" },\r\n\r\n            \"uint16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<u32>\" },\r\n            \"uint16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<u32>\" },\r\n\r\n            \"sint16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<i32>\" },\r\n            \"sint16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<i32>\" },\r\n\r\n            \"unorm16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<f32>\" },\r\n            \"unorm16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<f32>\" },\r\n\r\n            \"snorm16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<f32>\" },\r\n            \"snorm16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<f32>\" },\r\n\r\n            \"float16x2\": { nbComponent: 2, bytes: 4, varType: \"vec2<f16>\" },\r\n            \"float16x4\": { nbComponent: 4, bytes: 8, varType: \"vec4<f16>\" },\r\n\r\n            \"float32\": { nbComponent: 1, bytes: 4, varType: \"f32\" },\r\n            \"float32x2\": { nbComponent: 2, bytes: 8, varType: \"vec2<f32>\" },\r\n            \"float32x3\": { nbComponent: 3, bytes: 12, varType: \"vec3<f32>\" },\r\n            \"float32x4\": { nbComponent: 4, bytes: 16, varType: \"vec4<f32>\" },\r\n\r\n            \"uint32\": { nbComponent: 1, bytes: 4, varType: \"u32\" },\r\n            \"uint32x2\": { nbComponent: 2, bytes: 8, varType: \"vec2<u32>\" },\r\n            \"uint32x3\": { nbComponent: 3, bytes: 12, varType: \"vec3<u32>\" },\r\n            \"uint32x4\": { nbComponent: 4, bytes: 16, varType: \"vec4<u32>\" },\r\n\r\n            \"sint32\": { nbComponent: 1, bytes: 4, varType: \"i32\" },\r\n            \"sint32x2\": { nbComponent: 2, bytes: 8, varType: \"vec2<i32>\" },\r\n            \"sint32x3\": { nbComponent: 3, bytes: 12, varType: \"vec3<i32>\" },\r\n            \"sint32x4\": { nbComponent: 4, bytes: 16, varType: \"vec4<i32>\" },\r\n        }\r\n    }\r\n\r\n\r\n    private _name: string;\r\n    private _dataType: string;\r\n    private nbValues: number;\r\n    private vertexType: { name: string, nbComponent: number, bytes: number, varType: string };\r\n\r\n    private _data: number[][] | number[];\r\n    public dataOffset: number;\r\n    public mustBeTransfered: boolean = false;\r\n\r\n    protected _vertexBuffer: VertexBuffer;\r\n\r\n\r\n\r\n\r\n\r\n\r\n    constructor(name: string, dataType: string, offset?: number) {\r\n\r\n        dataType = this.renameVertexDataType(dataType);\r\n\r\n        this._name = name;\r\n        this._dataType = dataType;\r\n        this.dataOffset = offset;\r\n\r\n        if (VertexAttribute.types[dataType]) {\r\n            this.vertexType = VertexAttribute.types[dataType];\r\n            this.nbValues = this.vertexType.nbComponent;\r\n        } else {\r\n\r\n            const infos = new GPUType(dataType);\r\n            this.nbValues = infos.nbValues;\r\n            this.vertexType = this.getVertexDataType(infos.dataType)\r\n        }\r\n    }\r\n\r\n\r\n    protected waitingVertexBuffer: boolean = false;\r\n    public get vertexBuffer(): VertexBuffer { return this._vertexBuffer; }\r\n    public set vertexBuffer(vb: VertexBuffer) {\r\n        this._vertexBuffer = vb;\r\n        if (this.waitingVertexBuffer) {\r\n            this.waitingVertexBuffer = true;\r\n            this.vertexBuffer.attributeChanged = true;\r\n        }\r\n    }\r\n\r\n\r\n\r\n    public get datas(): number[][] | number[] { return this._data }\r\n    public set datas(n: number[][] | number[]) {\r\n        if (this._data != n) {\r\n            this._data = n;\r\n            if (this.vertexBuffer) this.vertexBuffer.attributeChanged = true;\r\n            else this.waitingVertexBuffer = true;\r\n            this.mustBeTransfered = true;\r\n        }\r\n    }\r\n\r\n\r\n    public get useByVertexData(): boolean { return typeof this._data[0] != \"number\" }\r\n\r\n    public get format(): string { return this._dataType }\r\n\r\n    public get type(): string {//---------------------------\r\n        //this function will be used in HighLevelParser. \r\n        //It mimic the existing structure using VertexAttribute.Float instead of FloatBuffer\r\n        return this._dataType;\r\n    }//---------------------------------------------------\r\n\r\n    public get bytePerElement(): number { return this.vertexType.bytes }\r\n    public get varType(): string { return this.vertexType.varType }\r\n    public get name(): string { return this._name; }\r\n    public get nbComponent(): number { return this.nbValues; }\r\n\r\n\r\n    private renameVertexDataType(type: string): string {\r\n        switch (type) {\r\n            case \"float\":\r\n                return \"float32\";\r\n            case \"vec2\":\r\n                return \"float32x2\";\r\n            case \"vec3\":\r\n                return \"float32x3\";\r\n            case \"vec4\":\r\n                return \"float32x4\";\r\n\r\n            case \"int\":\r\n                return \"sint32\";\r\n            case \"ivec2\":\r\n                return \"sint32x2\";\r\n            case \"ivec3\":\r\n                return \"sint32x3\";\r\n            case \"ivec4\":\r\n                return \"sint32x4\";\r\n\r\n\r\n            case \"uint\":\r\n                return \"uint32\";\r\n            case \"uvec2\":\r\n                return \"uint32x2\";\r\n            case \"uvec3\":\r\n                return \"uint32x3\";\r\n            case \"uvec4\":\r\n                return \"uint32x4\";\r\n\r\n        }\r\n        return type;\r\n    }\r\n\r\n\r\n    private getVertexDataType(dataType: string): { name: string, nbComponent: number, bytes: number, varType: string } {\r\n\r\n        switch (dataType) {\r\n\r\n            case \"u32\":\r\n                return { name: \"uint32\", nbComponent: 1, bytes: 4, varType: \"u32\" };\r\n            case \"vec2<u32>\":\r\n                return { name: \"uint32x2\", nbComponent: 2, bytes: 8, varType: \"vec2<u32>\" };\r\n            case \"vec3<u32>\":\r\n                return { name: \"uint32x3\", nbComponent: 3, bytes: 12, varType: \"vec3<u32>\" };\r\n            case \"vec4<u32>\":\r\n                return { name: \"uint32x4\", nbComponent: 4, bytes: 16, varType: \"vec4<u32>\" };\r\n\r\n            case \"i32\":\r\n                return { name: \"sint32\", nbComponent: 1, bytes: 4, varType: \"i32\" };\r\n            case \"vec2<i32>\":\r\n                return { name: \"sint32x2\", nbComponent: 2, bytes: 8, varType: \"vec2<i32>\" };\r\n            case \"vec3<i32>\":\r\n                return { name: \"sint32x3\", nbComponent: 3, bytes: 12, varType: \"vec3<i32>\" };\r\n            case \"vec4<i32>\":\r\n                return { name: \"sint32x4\", nbComponent: 4, bytes: 16, varType: \"vec4<i32>\" };\r\n\r\n            case \"f32\":\r\n                return { name: \"float32\", nbComponent: 1, bytes: 4, varType: \"f32\" };\r\n            case \"vec2<f32>\":\r\n                return { name: \"float32x2\", nbComponent: 2, bytes: 8, varType: \"vec2<f32>\" };\r\n            case \"vec3<f32>\":\r\n                return { name: \"float32x3\", nbComponent: 3, bytes: 12, varType: \"vec3<f32>\" };\r\n            case \"vec4<f32>\":\r\n                return { name: \"float32x4\", nbComponent: 4, bytes: 16, varType: \"vec4<f32>\" };\r\n\r\n\r\n            case \"vec2<f16>\":\r\n                return { name: \"float16x2\", nbComponent: 2, bytes: 4, varType: \"vec2<f16>\" };\r\n            case \"vec4<f16>\":\r\n                return { name: \"float16x4\", nbComponent: 4, bytes: 8, varType: \"vec4<f16>\" };\r\n\r\n            default:\r\n                throw new Error(\"GPUVertexAttribute.getVertexDataType error : dataInfo doesn't represent a correct VertexAttribute data-type\")\r\n\r\n        }\r\n\r\n\r\n    }\r\n\r\n}"
          }
        ],
        "VertexBuffer": [
          {
            "objectType": "type",
            "name": "VertexBufferDescriptor",
            "type": "VertexBufferDescriptor",
            "rawText": "export type VertexBufferDescriptor = {\r\n    stepMode?: \"vertex\" | \"instance\",\r\n    accessMode?: \"read\" | \"read_write\",\r\n    usage?: GPUBufferUsageFlags,\r\n    datas?: Float32Array | Int32Array | Uint32Array | Uint16Array,\r\n}"
          },
          {
            "objectType": "class",
            "name": "VertexBuffer",
            "filePath": "xGPU.shader.resources.VertexBuffer",
            "extends": [
              "StageableBuffer",
              "EventDispatcher"
            ],
            "implements": [
              "IShaderResource"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "bufferId",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public bufferId: number"
                },
                {
                  "objectType": "property",
                  "name": "io",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public io: number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "resourceIO",
                  "type": "VertexBufferIO",
                  "visibility": "public",
                  "rawText": "public resourceIO: VertexBufferIO = null;"
                },
                {
                  "objectType": "property",
                  "name": "mustBeTransfered",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public mustBeTransfered: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "vertexArrays",
                  "type": "VertexAttribute[]",
                  "visibility": "public",
                  "rawText": "public vertexArrays: VertexAttribute[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "attributes",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public attributes: any = {};"
                },
                {
                  "objectType": "property",
                  "name": "gpuResource",
                  "type": "GPUBuffer",
                  "visibility": "public",
                  "rawText": "public gpuResource: GPUBuffer;"
                },
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "VertexBufferDescriptor",
                  "visibility": "public",
                  "rawText": "public descriptor: VertexBufferDescriptor;"
                },
                {
                  "objectType": "property",
                  "name": "nbComponentData",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public nbComponentData: number;"
                },
                {
                  "objectType": "property",
                  "name": "attributeChanged",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public attributeChanged: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "buffer",
                  "type": "GPUBuffer",
                  "visibility": "public",
                  "rawText": "public get buffer(): GPUBuffer {\r\n        if (this.gpuBufferIOs) {\r\n\r\n            const buf: any = this.gpuBufferIOs[this.gpuBufferIO_index++ % 2]\r\n            return buf;\r\n        }\r\n\r\n        return this.gpuResource;\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "stepMode",
                  "type": "\"vertex\" | \"instance\"",
                  "visibility": "public",
                  "rawText": "public get stepMode(): \"vertex\" | \"instance\" { return this.descriptor.stepMode }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "length",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get length(): number { return this.vertexArrays.length; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "nbComponent",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get nbComponent(): number { return this._nbComponent; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "nbVertex",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get nbVertex(): number {\r\n        if (!this.datas) return 0;\r\n        if (this.nbComponentData) return this.datas.length / this.nbComponentData;\r\n        return this.datas.length / this._nbComponent\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "datas",
                  "type": "Float32Array | Int32Array | Uint32Array | Uint16Array",
                  "visibility": "public",
                  "rawText": "public get datas(): Float32Array | Int32Array | Uint32Array | Uint16Array { return this._datas; }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "attributeDescriptor",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public get attributeDescriptor(): any {\r\n        const result = {};\r\n        let o;\r\n        for (let name in this.attributes) {\r\n            o = this.attributes[name] as VertexAttribute;\r\n            result[name] = {\r\n                type: o.format,\r\n                offset: o.dataOffset\r\n            }\r\n        }\r\n        return result;\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "debug",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public debug:boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "arrayStride",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public arrayStride: number;"
                },
                {
                  "objectType": "property",
                  "name": "lowLevelBuffer",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public lowLevelBuffer:boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "bufferSize",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get bufferSize(): number { return this._bufferSize; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "time",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public time: number;"
                }
              ],
              "private": [
                {
                  "objectType": "property",
                  "name": "_nbComponent",
                  "type": "number",
                  "visibility": "private",
                  "rawText": "private _nbComponent: number = 0;"
                },
                {
                  "objectType": "property",
                  "name": "_datas",
                  "type": "Float32Array | Int32Array | Uint32Array | Uint16Array",
                  "visibility": "private",
                  "rawText": "private _datas: Float32Array | Int32Array | Uint32Array | Uint16Array;"
                },
                {
                  "objectType": "property",
                  "name": "_byteCount",
                  "type": "number",
                  "visibility": "private",
                  "rawText": "private _byteCount: number = 0;"
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "gpuBufferIOs",
                  "type": "GPUBuffer[]",
                  "visibility": "protected",
                  "rawText": "protected gpuBufferIOs: GPUBuffer[];"
                },
                {
                  "objectType": "property",
                  "name": "gpuBufferIO_index",
                  "type": "number",
                  "visibility": "protected",
                  "rawText": "protected gpuBufferIO_index: number = 1;"
                },
                {
                  "objectType": "property",
                  "name": "pipelineType",
                  "type": "\"render\" | \"compute\" | \"compute_mixed\"",
                  "visibility": "protected",
                  "rawText": "protected pipelineType: \"compute\" | \"render\" | \"compute_mixed\";"
                },
                {
                  "objectType": "property",
                  "name": "layout",
                  "type": "any",
                  "visibility": "protected",
                  "rawText": "protected layout: any;"
                },
                {
                  "objectType": "property",
                  "name": "_bufferSize",
                  "type": "number",
                  "visibility": "protected",
                  "rawText": "protected _bufferSize: number;"
                },
                {
                  "objectType": "property",
                  "name": "deviceId",
                  "type": "number",
                  "visibility": "protected",
                  "rawText": "protected deviceId: number;"
                },
                {
                  "objectType": "property",
                  "name": "destroyed",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected destroyed: boolean = true;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "VertexBuffer",
                  "visibility": "public",
                  "rawText": "public clone(): VertexBuffer {\r\n        const vb = new VertexBuffer(this.attributeDescriptor, this.descriptor);\r\n        vb.bufferId = this.bufferId;\r\n        let datas: Float32Array | Int32Array | Uint32Array;\r\n        if (this.datas instanceof Float32Array) datas = new Float32Array(this.datas.length);\r\n        else if (this.datas instanceof Int32Array) datas = new Int32Array(this.datas.length);\r\n        else if (this.datas instanceof Uint32Array) datas = new Uint32Array(this.datas.length);\r\n\r\n\r\n        //const data = new Float32Array(this.datas.length);\r\n        datas.set(this.datas);\r\n        vb.datas = datas;\r\n\r\n        //console.log(\"clone\")\r\n\r\n        return vb;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "initBufferIO",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "buffers",
                      "type": "GPUBuffer[]"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public initBufferIO(buffers: GPUBuffer[]) {\r\n        this.gpuBufferIOs = buffers;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getCurrentBuffer",
                  "returnType": "GPUBuffer",
                  "visibility": "public",
                  "rawText": "public getCurrentBuffer() {\r\n\r\n        if (this.gpuBufferIOs) return this.gpuBufferIOs[(this.gpuBufferIO_index + 1) % 2]\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        return this.gpuResource;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setComplexDatas",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "datas",
                      "type": "Float32Array | Int32Array | Uint32Array"
                    },
                    {
                      "name": "nbComponentTotal",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setComplexDatas(datas: Float32Array | Int32Array | Uint32Array, nbComponentTotal: number) {\r\n        this._nbComponent = nbComponentTotal;\r\n        this.datas = datas;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createArray",
                  "returnType": "VertexAttribute",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    },
                    {
                      "name": "dataType",
                      "type": "string"
                    },
                    {
                      "name": "offset",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createArray(name: string, dataType: string, offset?: number): VertexAttribute {\r\n\r\n        if (this.attributes[name] && this.attributes[name].vertexBuffer) {\r\n\r\n            return this.attributes[name];\r\n        }\r\n\r\n\r\n        let v: VertexAttribute = this.attributes[name];\r\n\r\n        //console.warn(\"createArray \", name, dataType, offset, this.attributes[name]);\r\n\r\n        if (!v) v = this.attributes[name] = new VertexAttribute(name, dataType, offset);\r\n        v.vertexBuffer = this;\r\n\r\n        const nbCompo = v.nbComponent;\r\n        const _offset = v.dataOffset === undefined ? 0 : v.dataOffset;\r\n        this._nbComponent += nbCompo;\r\n\r\n        //console.log(\"v.dataOffset = \", name, v.dataOffset)\r\n\r\n        if (v.dataOffset === undefined) this._byteCount += nbCompo * new GPUType(v.varType).byteValue;\r\n        else this._byteCount = Math.max(this._byteCount, (_offset + v.nbComponent) * new GPUType(v.varType).byteValue);\r\n\r\n        this.vertexArrays.push(v);\r\n        return v;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getAttributeByName",
                  "returnType": "VertexAttribute",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public getAttributeByName(name: string): VertexAttribute {\r\n        return this.attributes[name];\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "vertexBufferName",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    },
                    {
                      "name": "isInput",
                      "type": "boolean"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(vertexBufferName: string, bindingId: number, groupId: number = 0, isInput: boolean = true): string {\r\n        //console.warn(\"VB.createDeclaration \", vertexBufferName, isInput)\r\n        if (isInput) { }\r\n\r\n\r\n        this.stackAttributes();\r\n\r\n        let structName = vertexBufferName.substring(0, 1).toUpperCase() + vertexBufferName.slice(1);\r\n        const varName = vertexBufferName.substring(0, 1).toLowerCase() + vertexBufferName.slice(1);\r\n\r\n        //console.log(\"XGPU||| structName = \",structName);\r\n\r\n        let result = \"\";\r\n        let type = \"storage, read\";\r\n        let structType = \"array<\" + structName + \">\"\r\n        if (this.descriptor.accessMode == \"read\"){ //this.io === 1 || this.io === 0) {\r\n\r\n            result += \"struct \" + structName + \"{\\n\";\r\n            let a: VertexAttribute;\r\n            for (let i = 0; i < this.vertexArrays.length; i++) {\r\n                a = this.vertexArrays[i];\r\n                result += \"   \" + a.name + \":\" + a.varType + \",\\n\";\r\n            }\r\n            result += \"}\\n\\n\";\r\n            structType = \"array<\" + structName + \">\"\r\n        } else {\r\n            type = \"storage, read_write\"\r\n            if(this.io == 2){\r\n                //remove the '_out' \r\n                structName = structName.slice(0, structName.length - 4);\r\n            }else{\r\n\r\n                result += \"struct \" + structName + \"{\\n\";\r\n                let a: VertexAttribute;\r\n                for (let i = 0; i < this.vertexArrays.length; i++) {\r\n                    a = this.vertexArrays[i];\r\n                    result += \"   \" + a.name + \":\" + a.varType + \",\\n\";\r\n                }\r\n                result += \"}\\n\\n\";\r\n                structType = \"array<\" + structName + \">\"\r\n\r\n\r\n            }\r\n           \r\n            structType = \"array<\" + structName + \">\"\r\n        }\r\n\r\n        result += \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<\" + type + \"> \" + varName + \":\" + structType + \";\\n\";\r\n\r\n        return result;\r\n\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupLayoutEntry",
                  "returnType": "any",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupLayoutEntry(bindingId: number): any {\r\n        \r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.COMPUTE,\r\n            buffer: {\r\n                type: this.descriptor.accessMode === \"read\" ? \"read-only-storage\" : \"storage\"\r\n            },\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupEntry",
                  "returnType": "any",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupEntry(bindingId: number): any {\r\n\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        //console.log(\"VertexBuffer.createBindgroupEntry size = \", this.datas.byteLength)\r\n        let size = 0;\r\n        if (this.datas) size = this.datas.byteLength;\r\n        if(this.lowLevelBuffer) size = this._bufferSize;\r\n        return {\r\n            binding: bindingId,\r\n            resource: {\r\n                buffer: this.gpuResource,\r\n                offset: 0,\r\n                size\r\n            }\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setPipelineType",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "pipelineType",
                      "type": "\"render\" | \"compute\" | \"compute_mixed\""
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (this.pipelineType || pipelineType == \"compute\" && this.lowLevelBuffer == true) return;\r\n        \r\n        this.pipelineType = pipelineType ;\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n\r\n        if (pipelineType === \"render\") {\r\n            if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read\";\r\n            if (!this.descriptor.usage) this.descriptor.usage = GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST;\r\n\r\n        } else if (pipelineType === \"compute_mixed\") {\r\n           \r\n            if (this.io === 1 || this.io === 0) { //VertexBufferIO output , usable in a renderPipeline\r\n                if (!this.descriptor.usage) this.descriptor.usage = GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\r\n                if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read\";\r\n            } else if (this.io === 2) { //VertexBufferIO input\r\n                if (!this.descriptor.usage) this.descriptor.usage = GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\r\n                if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read_write\";\r\n            }\r\n\r\n        } else if (pipelineType === \"compute\") {\r\n            if (this.io === 1 || this.io == 0) { //VertexBufferIO output || VertexBuffer in computeShader\r\n                if (!this.descriptor.usage) this.descriptor.usage = GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\r\n                if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read\";\r\n            } else if (this.io === 2) { //VertexBufferIO input\r\n                if (!this.descriptor.usage) this.descriptor.usage =  GPUBufferUsage.VERTEX |GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\r\n                if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read_write\";\r\n            }\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createStruct",
                  "returnType": "ShaderStruct",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createStruct(name: string): ShaderStruct {\r\n\r\n        const structName = name.substring(0, 1).toUpperCase() + name.slice(1);\r\n        const properties: { name: string, type: string, builtin?: string }[] = [];\r\n        let a: VertexAttribute;\r\n        for (let i = 0; i < this.vertexArrays.length; i++) {\r\n            a = this.vertexArrays[i];\r\n            properties[i] = { name: a.name, type: a.varType, builtin: \"\" };\r\n        }\r\n\r\n        return new ShaderStruct(structName, properties)\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "stackAttributes",
                  "returnType": "{ stepMode: \"vertex\" | \"instance\"; arrayStride: number; attributes: any[]; }",
                  "params": [
                    {
                      "name": "builtinOffset",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public stackAttributes(builtinOffset: number = 0) {\r\n\r\n        //console.log(\"---------- STACK ATTRIBUTES ------------\");\r\n        //console.log(this.descriptor.stepMode)\r\n        const result: VertexAttribute[] = []\r\n\r\n        let bound = 1;\r\n\r\n        var floats: VertexAttribute[] = [];\r\n        var vec2s: VertexAttribute[] = [];\r\n        var vec3s: VertexAttribute[] = [];\r\n\r\n        let v;\r\n        let offset = 0;\r\n        for (let i = 0; i < this.vertexArrays.length; i++) {\r\n            v = this.vertexArrays[i];\r\n            if (v.nbComponent === 1) floats.push(v);\r\n            else if (v.nbComponent === 2) {\r\n                if (bound < 2) bound = 2;\r\n                vec2s.push(v);\r\n            } else if (v.nbComponent === 3) {\r\n                bound = 4;\r\n                vec3s.push(v);\r\n            } else if (v.nbComponent === 4) {\r\n                bound = 4;\r\n                v.dataOffset = offset;\r\n                offset += 4;\r\n                result.push(v);\r\n            }\r\n        }\r\n\r\n\r\n        //------------------------\r\n\r\n\r\n        const addVec3 = () => {\r\n            v = vec3s.shift();\r\n            v.dataOffset = offset;\r\n            offset += 3;\r\n            result.push(v);\r\n            if (floats.length) {\r\n                const f = floats.shift();\r\n                f.dataOffset = offset;\r\n                result.push(f);\r\n            }\r\n            offset++\r\n        }\r\n\r\n        let nb = vec3s.length;\r\n        for (let i = 0; i < nb; i++) addVec3();\r\n\r\n        //--------------------------\r\n\r\n        nb = vec2s.length;\r\n        for (let i = 0; i < nb; i++) {\r\n            v = vec2s.shift();\r\n            v.dataOffset = offset;\r\n            offset += 2;\r\n            result.push(v);\r\n        }\r\n\r\n        //--------------------------\r\n\r\n        nb = floats.length;\r\n        for (let i = 0; i < nb; i++) {\r\n            v = floats.shift();\r\n            v.dataOffset = offset;\r\n            offset++;\r\n            result.push(v);\r\n        }\r\n\r\n        //--------------------------\r\n\r\n        if (offset % bound !== 0) {\r\n            offset += bound - (offset % bound);\r\n        }\r\n\r\n        //--------------------------\r\n        this.vertexArrays = result;\r\n\r\n        const attributes = [];\r\n        for (let i = 0; i < result.length; i++) {\r\n            attributes[i] = {\r\n                shaderLocation: builtinOffset + i,\r\n                offset: result[i].dataOffset * Float32Array.BYTES_PER_ELEMENT,\r\n                format: this.vertexArrays[i].format\r\n            }\r\n        }\r\n\r\n        //-----------------\r\n        this.arrayStride = offset;\r\n\r\n        //console.log(\"this.arrayStride = \", offset);\r\n        //console.log(this.descriptor.stepMode)\r\n\r\n        const res =  {\r\n            stepMode: this.descriptor.stepMode,\r\n            arrayStride: Float32Array.BYTES_PER_ELEMENT * this.arrayStride,\r\n            attributes\r\n        }\r\n\r\n        //console.log(\"res = \",res)\r\n        return res\r\n\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "addVertexInstance",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "instanceId",
                      "type": "number"
                    },
                    {
                      "name": "o",
                      "type": "any"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public addVertexInstance(instanceId: number, o: any) {\r\n        const start = instanceId * this.arrayStride;\r\n        const datas = this._datas;\r\n        let attribute: VertexAttribute;\r\n        for (let z in o) {\r\n            attribute = this.getAttributeByName(z);\r\n            if (attribute) {\r\n                datas[start + attribute.dataOffset] = o[z];\r\n            }\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createVertexBufferLayout",
                  "returnType": "any",
                  "params": [
                    {
                      "name": "builtinOffset",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createVertexBufferLayout(builtinOffset: number = 0): any {\r\n\r\n\r\n        //console.log(this.io, this.descriptor.stepMode)\r\n        if (this.gpuBufferIOs) {\r\n            //console.log(\"GPUBufferIOs = \",this.gpuBufferIOs)\r\n            return this.stackAttributes(builtinOffset);\r\n        }\r\n\r\n\r\n\r\n        let nb = this._nbComponent;\r\n        if (this.nbComponentData) nb = this.nbComponentData;\r\n\r\n        const obj = {\r\n            stepMode: this.descriptor.stepMode,\r\n            arrayStride: Float32Array.BYTES_PER_ELEMENT * nb,\r\n            attributes: []\r\n        }\r\n\r\n        let componentId = 0;\r\n        let offset: number;\r\n        for (let i = 0; i < this.vertexArrays.length; i++) {\r\n            offset = componentId;\r\n            if (this.vertexArrays[i].dataOffset !== undefined) offset = componentId = this.vertexArrays[i].dataOffset;\r\n            obj.attributes[i] = {\r\n                shaderLocation: builtinOffset + i,\r\n                offset: offset * Float32Array.BYTES_PER_ELEMENT,\r\n                format: this.vertexArrays[i].format\r\n            }\r\n\r\n            componentId += this.vertexArrays[i].nbComponent;\r\n        }\r\n        //console.log(\"vb layout = \", obj)\r\n        obj.arrayStride = Math.max(this._byteCount, nb * Float32Array.BYTES_PER_ELEMENT);\r\n        this.layout = obj;\r\n        return obj;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createLowLevelBuffer",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "bufferSize",
                      "type": "number"
                    },
                    {
                      "name": "accessMode",
                      "type": "\"read\" | \"read_write\""
                    },
                    {
                      "name": "usage",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createLowLevelBuffer(bufferSize:number,accessMode:\"read\"|\"read_write\" = \"read\" ,usage:number = GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST){\r\n        this.lowLevelBuffer = true;\r\n\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n       \r\n        this.descriptor.usage = usage;\r\n        this.descriptor.accessMode = accessMode;\r\n        this.deviceId = XGPU.deviceId;\r\n\r\n        this._bufferSize = bufferSize;\r\n        this.gpuResource = XGPU.device.createBuffer({\r\n            size: bufferSize,\r\n            usage: this.descriptor.usage,\r\n            mappedAtCreation: false,\r\n        })\r\n\r\n       \r\n       \r\n\r\n        this.destroyed = false;\r\n        this.mustBeTransfered = true;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "resizeLowLevelBuffer",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "byteLength",
                      "type": "number"
                    },
                    {
                      "name": "copyPreviousDataWithin",
                      "type": "boolean"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public resizeLowLevelBuffer(byteLength:number,copyPreviousDataWithin:boolean=false):void{\r\n\r\n        if(!this.lowLevelBuffer) return ;\r\n\r\n        const oldBuffer = this.gpuResource;\r\n\r\n        this._bufferSize = byteLength;\r\n        this.gpuResource = XGPU.device.createBuffer({\r\n            size: byteLength,\r\n            usage: this.descriptor.usage,\r\n            mappedAtCreation: false,\r\n        })\r\n\r\n\r\n        if(copyPreviousDataWithin){\r\n            \r\n            const command = XGPU.device.createCommandEncoder();\r\n            command.copyBufferToBuffer(oldBuffer,0,this.gpuResource,0,oldBuffer.size);\r\n            const end = command.finish();\r\n        \r\n            XGPU.device.queue.submit([end]);\r\n            XGPU.device.queue.onSubmittedWorkDone().then(()=>{\r\n                //console.log(\"DESTROY BUFFER\")\r\n                oldBuffer.destroy();\r\n            })\r\n        \r\n        }else{\r\n            \r\n            oldBuffer.destroy();\r\n            \r\n        }\r\n            \r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "updateLowLevelBuffer",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "buffer",
                      "type": "ArrayBuffer"
                    },
                    {
                      "name": "bufferOffset",
                      "type": "number"
                    },
                    {
                      "name": "dataOffset",
                      "type": "number"
                    },
                    {
                      "name": "size",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public updateLowLevelBuffer(buffer:ArrayBuffer,bufferOffset:number,dataOffset?:number,size?:number){\r\n        //console.log({dataOffset,size,buffer})\r\n\r\n       \r\n            if(size == undefined) size = buffer.byteLength;\r\n            if(dataOffset == undefined) dataOffset = 0;\r\n\r\n            if(!this.gpuResource) throw new Error(\"you must create a GPUBuffer using VertexBuffer.createGPUResource(bufferSize)\");\r\n            //if(bufferOffset + size > this._bufferSize) throw new Error(\"incorrect gpu buffer length, max length = \"+this._bufferSize+\" vs \"+(bufferOffset + size));\r\n            \r\n            \r\n            if(dataOffset + size > buffer.byteLength) throw new Error(\"incorrect datas length\")\r\n\r\n            XGPU.device.queue.writeBuffer(this.gpuResource, bufferOffset, buffer,dataOffset,size)\r\n      \r\n\r\n\r\n     }"
                },
                {
                  "objectType": "method",
                  "name": "createGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public createGpuResource() {\r\n        if(this.lowLevelBuffer) return;\r\n        if (this.attributeChanged) this.updateAttributes();\r\n        if (!this.datas || this.gpuBufferIOs) return;\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n\r\n        const bufferSize = this.datas.byteLength;\r\n        //console.warn(\"VB.createGPUResource \", this.io, this.pipelineType, XGPU.debugUsage(this.descriptor.usage))\r\n        this.deviceId = XGPU.deviceId;\r\n        this._bufferSize = bufferSize;\r\n        this.gpuResource = XGPU.device.createBuffer({\r\n            size: bufferSize,\r\n            usage: this.descriptor.usage,\r\n            mappedAtCreation: false,\r\n        })\r\n        this.destroyed = false;\r\n        this.mustBeTransfered = true;\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "destroyGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public destroyGpuResource() {\r\n        if (this.destroyed) return;\r\n\r\n\r\n        if (this.time && new Date().getTime() - this.time < 100 && XGPU.loseDeviceRecently) {\r\n            return;\r\n        }\r\n        this.time = new Date().getTime();\r\n\r\n        if (this.io && XGPU.loseDeviceRecently) {\r\n\r\n            if (this.io === 1) {\r\n\r\n\r\n                const vbio = this.resourceIO;\r\n                const vbs = vbio.buffers;\r\n\r\n               \r\n               \r\n                this.setPipelineType(this.pipelineType)\r\n                const currentDatas = vbio.currentDatas ? vbio.currentDatas : vbs[0]._datas;\r\n\r\n                if (vbs[0]._datas instanceof Float32Array) vbs[0]._datas = vbs[1]._datas = new Float32Array(currentDatas);\r\n                else if (vbs[0]._datas instanceof Int32Array) vbs[0]._datas = vbs[1]._datas = new Int32Array(currentDatas);\r\n                else if (vbs[0]._datas instanceof Uint32Array) vbs[0]._datas = vbs[1]._datas = new Uint32Array(currentDatas);\r\n\r\n                //vbs[0]._datas = \r\n                let temp = vbs[0].gpuBufferIOs;\r\n                vbs[0].gpuBufferIOs = null;\r\n                vbs[0].createGpuResource();\r\n                vbs[0].gpuBufferIOs = temp;\r\n\r\n                temp = vbs[1].gpuBufferIOs;\r\n                vbs[1].gpuBufferIOs = null;\r\n                vbs[1].createGpuResource();\r\n                vbs[1].gpuBufferIOs = temp;\r\n\r\n                vbs[0].gpuBufferIOs[0] = vbs[0].gpuResource;\r\n                vbs[0].gpuBufferIOs[1] = vbs[1].gpuResource;\r\n\r\n\r\n            }\r\n            return\r\n\r\n        }\r\n        this.destroyed = true;\r\n        if (this.resourceIO) {\r\n            this.resourceIO.destroy();\r\n            this.resourceIO = null;\r\n        }\r\n        if (this.gpuResource) {\r\n            this.gpuResource.destroy();\r\n            this.gpuResource = null;\r\n        }\r\n\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "updateBuffer",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public updateBuffer(): void {\r\n        if(this.lowLevelBuffer) return;\r\n        if (!this.datas) return;\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        if (this.datas.byteLength != this._bufferSize) this.createGpuResource();\r\n\r\n        XGPU.device.queue.writeBuffer(this.gpuResource, 0, this.datas.buffer)\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getVertexArrayById",
                  "returnType": "VertexAttribute",
                  "params": [
                    {
                      "name": "id",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public getVertexArrayById(id: number): VertexAttribute { return this.vertexArrays[id]; }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "boolean",
                  "visibility": "public",
                  "rawText": "public update(): boolean {\r\n        if(this.lowLevelBuffer) return true;\r\n        if (this.vertexArrays.length === 0) return false;\r\n        if (this.attributeChanged) this.updateAttributes();\r\n\r\n        if (this.mustBeTransfered) {\r\n            this.mustBeTransfered = false;\r\n            this.updateBuffer();\r\n        }\r\n\r\n        return true;\r\n    }"
                }
              ],
              "protected": [
                {
                  "objectType": "method",
                  "name": "updateAttributes",
                  "returnType": "void",
                  "visibility": "protected",
                  "rawText": "protected updateAttributes() {\r\n\r\n        let attribute: VertexAttribute;\r\n        attribute = this.vertexArrays[0];\r\n        const nbAttributes = this.vertexArrays.length;\r\n\r\n        let offset: number = 0;\r\n\r\n        if (this.vertexArrays[0] && this.vertexArrays[0].useByVertexData) {\r\n\r\n\r\n            const nbVertex = attribute.datas.length;\r\n            if (!this._datas) this._datas = new Float32Array(nbVertex * this.nbComponent)\r\n\r\n            for (let i = 0; i < nbVertex; i++) {\r\n                for (let j = 0; j < nbAttributes; j++) {\r\n                    attribute = this.vertexArrays[j];\r\n                    if (attribute.mustBeTransfered) {\r\n                        //console.log(nbVertex, nbAttributes, offset, attribute)\r\n                        this._datas.set((attribute.datas as number[][])[i], offset);\r\n\r\n                    }\r\n                    offset += attribute.nbComponent;\r\n                }\r\n            }\r\n        } else {\r\n\r\n            const nbVertex = attribute.datas.length / attribute.nbComponent;\r\n            if (!this._datas) this._datas = new Float32Array(nbVertex * this.nbComponent)\r\n\r\n\r\n            for (let j = 0; j < nbAttributes; j++) {\r\n                attribute = this.vertexArrays[j];\r\n                if (attribute.mustBeTransfered) {\r\n\r\n                    this._datas.set(attribute.datas as number[], offset);\r\n                }\r\n                offset += attribute.nbComponent;\r\n\r\n            }\r\n\r\n        }\r\n\r\n\r\n\r\n\r\n        for (let j = 0; j < nbAttributes; j++) this.vertexArrays[j].mustBeTransfered = false;\r\n\r\n        this.attributeChanged = false;\r\n        this.mustBeTransfered = true;\r\n\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "attributes",
                  "type": "any"
                },
                {
                  "name": "descriptor",
                  "type": "{ stepMode?: \"vertex\" | \"instance\"; accessMode?: \"read\" | \"read_write\"; usage?: GPUBufferUsageFlags; datas?: Float32Array | Int32Array | Uint32Array | Uint16Array; gpuUpdateMode?: \"auto\" | \"manual\"; }"
                }
              ],
              "rawText": "constructor(attributes: any, descriptor?: {\r\n        stepMode?: \"vertex\" | \"instance\",\r\n        accessMode?: \"read\" | \"read_write\",\r\n        usage?: GPUBufferUsageFlags,\r\n        datas?: Float32Array | Int32Array | Uint32Array | Uint16Array,\r\n        gpuUpdateMode?:\"auto\"|\"manual\"\r\n    }) {\r\n\r\n        super();\r\n        //console.warn(\"VERTEX BUFFER 2\", attributes)\r\n\r\n        if (!descriptor) descriptor = {};\r\n        else descriptor = { ...descriptor };\r\n\r\n        if (!descriptor.stepMode) descriptor.stepMode = \"vertex\";\r\n       \r\n        this.descriptor = descriptor;\r\n\r\n        const items: any = attributes;\r\n        let buffer, offset, datas;\r\n        let attribute: VertexAttribute;\r\n        let nbComponent:number = 0;\r\n        for (let name in items) {\r\n            buffer = items[name];\r\n            offset = buffer.offset;\r\n            datas = buffer.datas;\r\n            nbComponent += buffer.nbComponent;\r\n            //console.log(\"=> \", name, offset,buffer.nbComponent)\r\n\r\n            if (!this.attributes[name]) {\r\n                attribute = this.createArray(name, buffer.type, offset);\r\n                //console.log(name, offset)\r\n                if (datas) attribute.datas = datas;\r\n            } else {\r\n                //console.log(this.attributes[name])\r\n            }\r\n\r\n        }\r\n        if (descriptor.datas) this.datas = descriptor.datas;\r\n\r\n\r\n        if(descriptor.gpuUpdateMode == \"manual\"){\r\n           \r\n            const accessMode = descriptor.accessMode ? descriptor.accessMode : \"read\";\r\n\r\n            if(!descriptor.usage){\r\n                throw new Error(\"VertexBuffer constructor : you must set the property 'usage' in the descriptor if 'gpuUpdateMode' is set to 'manual' \")\r\n            }\r\n\r\n            const usage = descriptor.usage;\r\n            this.createLowLevelBuffer(nbComponent * 4,accessMode,usage);\r\n        }\r\n\r\n    }"
            },
            "rawText": "export class VertexBuffer extends StageableBuffer implements IShaderResource {\r\n\r\n    public bufferId: number //the id used in renderPass.setVertexBuffer\r\n\r\n    public io: number = 0;\r\n    public resourceIO: VertexBufferIO = null;\r\n    public mustBeTransfered: boolean = false;\r\n    public vertexArrays: VertexAttribute[] = [];\r\n    public attributes: any = {};\r\n    public gpuResource: GPUBuffer;\r\n    public descriptor: VertexBufferDescriptor;\r\n\r\n\r\n\r\n    private _nbComponent: number = 0;\r\n\r\n    private _datas: Float32Array | Int32Array | Uint32Array | Uint16Array;\r\n    public nbComponentData: number;\r\n    public attributeChanged: boolean = false;\r\n\r\n\r\n\r\n\r\n    constructor(attributes: any, descriptor?: {\r\n        stepMode?: \"vertex\" | \"instance\",\r\n        accessMode?: \"read\" | \"read_write\",\r\n        usage?: GPUBufferUsageFlags,\r\n        datas?: Float32Array | Int32Array | Uint32Array | Uint16Array,\r\n        gpuUpdateMode?:\"auto\"|\"manual\"\r\n    }) {\r\n\r\n        super();\r\n        //console.warn(\"VERTEX BUFFER 2\", attributes)\r\n\r\n        if (!descriptor) descriptor = {};\r\n        else descriptor = { ...descriptor };\r\n\r\n        if (!descriptor.stepMode) descriptor.stepMode = \"vertex\";\r\n       \r\n        this.descriptor = descriptor;\r\n\r\n        const items: any = attributes;\r\n        let buffer, offset, datas;\r\n        let attribute: VertexAttribute;\r\n        let nbComponent:number = 0;\r\n        for (let name in items) {\r\n            buffer = items[name];\r\n            offset = buffer.offset;\r\n            datas = buffer.datas;\r\n            nbComponent += buffer.nbComponent;\r\n            //console.log(\"=> \", name, offset,buffer.nbComponent)\r\n\r\n            if (!this.attributes[name]) {\r\n                attribute = this.createArray(name, buffer.type, offset);\r\n                //console.log(name, offset)\r\n                if (datas) attribute.datas = datas;\r\n            } else {\r\n                //console.log(this.attributes[name])\r\n            }\r\n\r\n        }\r\n        if (descriptor.datas) this.datas = descriptor.datas;\r\n\r\n\r\n        if(descriptor.gpuUpdateMode == \"manual\"){\r\n           \r\n            const accessMode = descriptor.accessMode ? descriptor.accessMode : \"read\";\r\n\r\n            if(!descriptor.usage){\r\n                throw new Error(\"VertexBuffer constructor : you must set the property 'usage' in the descriptor if 'gpuUpdateMode' is set to 'manual' \")\r\n            }\r\n\r\n            const usage = descriptor.usage;\r\n            this.createLowLevelBuffer(nbComponent * 4,accessMode,usage);\r\n        }\r\n\r\n    }\r\n\r\n    /*\r\n    public pushDatas(datas: Float32Array | Int32Array | Uint32Array | Uint16Array) {\r\n        this.mustBeTransfered = true;\r\n\r\n        if (!extraBufferSize) extraBufferSize = 1000;\r\n\r\n        //if (this.datas) console.log(this.datas.length + \" VS \" + (offset + len))\r\n\r\n        if (!this._datas || this._datas.length < offset + len) {\r\n\r\n\r\n           \r\n\r\n\r\n            if (!this._datas) {\r\n                this._datas = datas;\r\n                this.createGpuResource();\r\n            } else if ((offset + len) - this._datas.length >= extraBufferSize) {\r\n                this._datas = datas;\r\n                this.createGpuResource();\r\n            } else {\r\n\r\n                //console.log(\"B\")\r\n\r\n                if (indices instanceof Uint16Array) this._datas = new Uint16Array(this._datas.length + extraBufferSize);\r\n                else this._datas = new Uint32Array(this._datas.length + extraBufferSize);\r\n                this._datas.set(indices);\r\n                this.createGpuResource();\r\n            }\r\n        } else {\r\n            //console.log(\"A \", indices.slice(offset, offset + len))\r\n            if (offset && len) this._datas.set(indices.slice(offset, offset + len), offset)\r\n            else this._datas.set(indices);\r\n        }\r\n\r\n        this.update();\r\n    }\r\n    */\r\n\r\n\r\n    public clone(): VertexBuffer {\r\n        const vb = new VertexBuffer(this.attributeDescriptor, this.descriptor);\r\n        vb.bufferId = this.bufferId;\r\n        let datas: Float32Array | Int32Array | Uint32Array;\r\n        if (this.datas instanceof Float32Array) datas = new Float32Array(this.datas.length);\r\n        else if (this.datas instanceof Int32Array) datas = new Int32Array(this.datas.length);\r\n        else if (this.datas instanceof Uint32Array) datas = new Uint32Array(this.datas.length);\r\n\r\n\r\n        //const data = new Float32Array(this.datas.length);\r\n        datas.set(this.datas);\r\n        vb.datas = datas;\r\n\r\n        //console.log(\"clone\")\r\n\r\n        return vb;\r\n    }\r\n\r\n\r\n    protected gpuBufferIOs: GPUBuffer[];\r\n    protected gpuBufferIO_index: number = 1;\r\n\r\n    public initBufferIO(buffers: GPUBuffer[]) {\r\n        this.gpuBufferIOs = buffers;\r\n    }\r\n\r\n\r\n    public get buffer(): GPUBuffer {\r\n        if (this.gpuBufferIOs) {\r\n\r\n            const buf: any = this.gpuBufferIOs[this.gpuBufferIO_index++ % 2]\r\n            return buf;\r\n        }\r\n\r\n        return this.gpuResource;\r\n    }\r\n\r\n    public getCurrentBuffer() {\r\n\r\n        if (this.gpuBufferIOs) return this.gpuBufferIOs[(this.gpuBufferIO_index + 1) % 2]\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        return this.gpuResource;\r\n    }\r\n\r\n    public get stepMode(): \"vertex\" | \"instance\" { return this.descriptor.stepMode }\r\n\r\n    public get length(): number { return this.vertexArrays.length; }\r\n    public get nbComponent(): number { return this._nbComponent; }\r\n    public get nbVertex(): number {\r\n        if (!this.datas) return 0;\r\n        if (this.nbComponentData) return this.datas.length / this.nbComponentData;\r\n        return this.datas.length / this._nbComponent\r\n    }\r\n\r\n\r\n    public get datas(): Float32Array | Int32Array | Uint32Array | Uint16Array { return this._datas; }\r\n    public set datas(f: Float32Array | Int32Array | Uint32Array | Uint16Array) {\r\n        this._datas = f;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n\r\n    public setComplexDatas(datas: Float32Array | Int32Array | Uint32Array, nbComponentTotal: number) {\r\n        this._nbComponent = nbComponentTotal;\r\n        this.datas = datas;\r\n    }\r\n\r\n    public get attributeDescriptor(): any {\r\n        const result = {};\r\n        let o;\r\n        for (let name in this.attributes) {\r\n            o = this.attributes[name] as VertexAttribute;\r\n            result[name] = {\r\n                type: o.format,\r\n                offset: o.dataOffset\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    private _byteCount: number = 0;\r\n    public createArray(name: string, dataType: string, offset?: number): VertexAttribute {\r\n\r\n        if (this.attributes[name] && this.attributes[name].vertexBuffer) {\r\n\r\n            return this.attributes[name];\r\n        }\r\n\r\n\r\n        let v: VertexAttribute = this.attributes[name];\r\n\r\n        //console.warn(\"createArray \", name, dataType, offset, this.attributes[name]);\r\n\r\n        if (!v) v = this.attributes[name] = new VertexAttribute(name, dataType, offset);\r\n        v.vertexBuffer = this;\r\n\r\n        const nbCompo = v.nbComponent;\r\n        const _offset = v.dataOffset === undefined ? 0 : v.dataOffset;\r\n        this._nbComponent += nbCompo;\r\n\r\n        //console.log(\"v.dataOffset = \", name, v.dataOffset)\r\n\r\n        if (v.dataOffset === undefined) this._byteCount += nbCompo * new GPUType(v.varType).byteValue;\r\n        else this._byteCount = Math.max(this._byteCount, (_offset + v.nbComponent) * new GPUType(v.varType).byteValue);\r\n\r\n        this.vertexArrays.push(v);\r\n        return v;\r\n    }\r\n\r\n    public getAttributeByName(name: string): VertexAttribute {\r\n        return this.attributes[name];\r\n    }\r\n\r\n    //----------------------------- USED WITH COMPUTE PIPELINE ----------------------------------------\r\n\r\n    public createDeclaration(vertexBufferName: string, bindingId: number, groupId: number = 0, isInput: boolean = true): string {\r\n        //console.warn(\"VB.createDeclaration \", vertexBufferName, isInput)\r\n        if (isInput) { }\r\n\r\n\r\n        this.stackAttributes();\r\n\r\n        let structName = vertexBufferName.substring(0, 1).toUpperCase() + vertexBufferName.slice(1);\r\n        const varName = vertexBufferName.substring(0, 1).toLowerCase() + vertexBufferName.slice(1);\r\n\r\n        //console.log(\"XGPU||| structName = \",structName);\r\n\r\n        let result = \"\";\r\n        let type = \"storage, read\";\r\n        let structType = \"array<\" + structName + \">\"\r\n        if (this.descriptor.accessMode == \"read\"){ //this.io === 1 || this.io === 0) {\r\n\r\n            result += \"struct \" + structName + \"{\\n\";\r\n            let a: VertexAttribute;\r\n            for (let i = 0; i < this.vertexArrays.length; i++) {\r\n                a = this.vertexArrays[i];\r\n                result += \"   \" + a.name + \":\" + a.varType + \",\\n\";\r\n            }\r\n            result += \"}\\n\\n\";\r\n            structType = \"array<\" + structName + \">\"\r\n        } else {\r\n            type = \"storage, read_write\"\r\n            if(this.io == 2){\r\n                //remove the '_out' \r\n                structName = structName.slice(0, structName.length - 4);\r\n            }else{\r\n\r\n                result += \"struct \" + structName + \"{\\n\";\r\n                let a: VertexAttribute;\r\n                for (let i = 0; i < this.vertexArrays.length; i++) {\r\n                    a = this.vertexArrays[i];\r\n                    result += \"   \" + a.name + \":\" + a.varType + \",\\n\";\r\n                }\r\n                result += \"}\\n\\n\";\r\n                structType = \"array<\" + structName + \">\"\r\n\r\n\r\n            }\r\n           \r\n            structType = \"array<\" + structName + \">\"\r\n        }\r\n\r\n        result += \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<\" + type + \"> \" + varName + \":\" + structType + \";\\n\";\r\n\r\n        return result;\r\n\r\n\r\n    }\r\n    public debug:boolean = false;\r\n\r\n    public createBindGroupLayoutEntry(bindingId: number): any {\r\n        \r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.COMPUTE,\r\n            buffer: {\r\n                type: this.descriptor.accessMode === \"read\" ? \"read-only-storage\" : \"storage\"\r\n            },\r\n        }\r\n    }\r\n\r\n    public createBindGroupEntry(bindingId: number): any {\r\n\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        //console.log(\"VertexBuffer.createBindgroupEntry size = \", this.datas.byteLength)\r\n        let size = 0;\r\n        if (this.datas) size = this.datas.byteLength;\r\n        if(this.lowLevelBuffer) size = this._bufferSize;\r\n        return {\r\n            binding: bindingId,\r\n            resource: {\r\n                buffer: this.gpuResource,\r\n                offset: 0,\r\n                size\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n    protected pipelineType: \"compute\" | \"render\" | \"compute_mixed\";\r\n\r\n    public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (this.pipelineType || pipelineType == \"compute\" && this.lowLevelBuffer == true) return;\r\n        \r\n        this.pipelineType = pipelineType ;\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n\r\n        if (pipelineType === \"render\") {\r\n            if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read\";\r\n            if (!this.descriptor.usage) this.descriptor.usage = GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST;\r\n\r\n        } else if (pipelineType === \"compute_mixed\") {\r\n           \r\n            if (this.io === 1 || this.io === 0) { //VertexBufferIO output , usable in a renderPipeline\r\n                if (!this.descriptor.usage) this.descriptor.usage = GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\r\n                if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read\";\r\n            } else if (this.io === 2) { //VertexBufferIO input\r\n                if (!this.descriptor.usage) this.descriptor.usage = GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\r\n                if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read_write\";\r\n            }\r\n\r\n        } else if (pipelineType === \"compute\") {\r\n            if (this.io === 1 || this.io == 0) { //VertexBufferIO output || VertexBuffer in computeShader\r\n                if (!this.descriptor.usage) this.descriptor.usage = GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\r\n                if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read\";\r\n            } else if (this.io === 2) { //VertexBufferIO input\r\n                if (!this.descriptor.usage) this.descriptor.usage =  GPUBufferUsage.VERTEX |GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\r\n                if (!this.descriptor.accessMode) this.descriptor.accessMode = \"read_write\";\r\n            }\r\n        }\r\n    }\r\n\r\n    //------------------------------------------------------------------------------------------------------\r\n\r\n    public createStruct(name: string): ShaderStruct {\r\n\r\n        const structName = name.substring(0, 1).toUpperCase() + name.slice(1);\r\n        const properties: { name: string, type: string, builtin?: string }[] = [];\r\n        let a: VertexAttribute;\r\n        for (let i = 0; i < this.vertexArrays.length; i++) {\r\n            a = this.vertexArrays[i];\r\n            properties[i] = { name: a.name, type: a.varType, builtin: \"\" };\r\n        }\r\n\r\n        return new ShaderStruct(structName, properties)\r\n    }\r\n\r\n\r\n\r\n    public arrayStride: number;\r\n    public stackAttributes(builtinOffset: number = 0) {\r\n\r\n        //console.log(\"---------- STACK ATTRIBUTES ------------\");\r\n        //console.log(this.descriptor.stepMode)\r\n        const result: VertexAttribute[] = []\r\n\r\n        let bound = 1;\r\n\r\n        var floats: VertexAttribute[] = [];\r\n        var vec2s: VertexAttribute[] = [];\r\n        var vec3s: VertexAttribute[] = [];\r\n\r\n        let v;\r\n        let offset = 0;\r\n        for (let i = 0; i < this.vertexArrays.length; i++) {\r\n            v = this.vertexArrays[i];\r\n            if (v.nbComponent === 1) floats.push(v);\r\n            else if (v.nbComponent === 2) {\r\n                if (bound < 2) bound = 2;\r\n                vec2s.push(v);\r\n            } else if (v.nbComponent === 3) {\r\n                bound = 4;\r\n                vec3s.push(v);\r\n            } else if (v.nbComponent === 4) {\r\n                bound = 4;\r\n                v.dataOffset = offset;\r\n                offset += 4;\r\n                result.push(v);\r\n            }\r\n        }\r\n\r\n\r\n        //------------------------\r\n\r\n\r\n        const addVec3 = () => {\r\n            v = vec3s.shift();\r\n            v.dataOffset = offset;\r\n            offset += 3;\r\n            result.push(v);\r\n            if (floats.length) {\r\n                const f = floats.shift();\r\n                f.dataOffset = offset;\r\n                result.push(f);\r\n            }\r\n            offset++\r\n        }\r\n\r\n        let nb = vec3s.length;\r\n        for (let i = 0; i < nb; i++) addVec3();\r\n\r\n        //--------------------------\r\n\r\n        nb = vec2s.length;\r\n        for (let i = 0; i < nb; i++) {\r\n            v = vec2s.shift();\r\n            v.dataOffset = offset;\r\n            offset += 2;\r\n            result.push(v);\r\n        }\r\n\r\n        //--------------------------\r\n\r\n        nb = floats.length;\r\n        for (let i = 0; i < nb; i++) {\r\n            v = floats.shift();\r\n            v.dataOffset = offset;\r\n            offset++;\r\n            result.push(v);\r\n        }\r\n\r\n        //--------------------------\r\n\r\n        if (offset % bound !== 0) {\r\n            offset += bound - (offset % bound);\r\n        }\r\n\r\n        //--------------------------\r\n        this.vertexArrays = result;\r\n\r\n        const attributes = [];\r\n        for (let i = 0; i < result.length; i++) {\r\n            attributes[i] = {\r\n                shaderLocation: builtinOffset + i,\r\n                offset: result[i].dataOffset * Float32Array.BYTES_PER_ELEMENT,\r\n                format: this.vertexArrays[i].format\r\n            }\r\n        }\r\n\r\n        //-----------------\r\n        this.arrayStride = offset;\r\n\r\n        //console.log(\"this.arrayStride = \", offset);\r\n        //console.log(this.descriptor.stepMode)\r\n\r\n        const res =  {\r\n            stepMode: this.descriptor.stepMode,\r\n            arrayStride: Float32Array.BYTES_PER_ELEMENT * this.arrayStride,\r\n            attributes\r\n        }\r\n\r\n        //console.log(\"res = \",res)\r\n        return res\r\n\r\n\r\n    }\r\n\r\n\r\n    public addVertexInstance(instanceId: number, o: any) {\r\n        const start = instanceId * this.arrayStride;\r\n        const datas = this._datas;\r\n        let attribute: VertexAttribute;\r\n        for (let z in o) {\r\n            attribute = this.getAttributeByName(z);\r\n            if (attribute) {\r\n                datas[start + attribute.dataOffset] = o[z];\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n    protected layout: any;\r\n\r\n    public createVertexBufferLayout(builtinOffset: number = 0): any {\r\n\r\n\r\n        //console.log(this.io, this.descriptor.stepMode)\r\n        if (this.gpuBufferIOs) {\r\n            //console.log(\"GPUBufferIOs = \",this.gpuBufferIOs)\r\n            return this.stackAttributes(builtinOffset);\r\n        }\r\n\r\n\r\n\r\n        let nb = this._nbComponent;\r\n        if (this.nbComponentData) nb = this.nbComponentData;\r\n\r\n        const obj = {\r\n            stepMode: this.descriptor.stepMode,\r\n            arrayStride: Float32Array.BYTES_PER_ELEMENT * nb,\r\n            attributes: []\r\n        }\r\n\r\n        let componentId = 0;\r\n        let offset: number;\r\n        for (let i = 0; i < this.vertexArrays.length; i++) {\r\n            offset = componentId;\r\n            if (this.vertexArrays[i].dataOffset !== undefined) offset = componentId = this.vertexArrays[i].dataOffset;\r\n            obj.attributes[i] = {\r\n                shaderLocation: builtinOffset + i,\r\n                offset: offset * Float32Array.BYTES_PER_ELEMENT,\r\n                format: this.vertexArrays[i].format\r\n            }\r\n\r\n            componentId += this.vertexArrays[i].nbComponent;\r\n        }\r\n        //console.log(\"vb layout = \", obj)\r\n        obj.arrayStride = Math.max(this._byteCount, nb * Float32Array.BYTES_PER_ELEMENT);\r\n        this.layout = obj;\r\n        return obj;\r\n    }\r\n\r\n\r\n    public lowLevelBuffer:boolean = false;\r\n    public createLowLevelBuffer(bufferSize:number,accessMode:\"read\"|\"read_write\" = \"read\" ,usage:number = GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST){\r\n        this.lowLevelBuffer = true;\r\n\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n       \r\n        this.descriptor.usage = usage;\r\n        this.descriptor.accessMode = accessMode;\r\n        this.deviceId = XGPU.deviceId;\r\n\r\n        this._bufferSize = bufferSize;\r\n        this.gpuResource = XGPU.device.createBuffer({\r\n            size: bufferSize,\r\n            usage: this.descriptor.usage,\r\n            mappedAtCreation: false,\r\n        })\r\n\r\n       \r\n       \r\n\r\n        this.destroyed = false;\r\n        this.mustBeTransfered = true;\r\n    }\r\n\r\n   \r\n    public resizeLowLevelBuffer(byteLength:number,copyPreviousDataWithin:boolean=false):void{\r\n\r\n        if(!this.lowLevelBuffer) return ;\r\n\r\n        const oldBuffer = this.gpuResource;\r\n\r\n        this._bufferSize = byteLength;\r\n        this.gpuResource = XGPU.device.createBuffer({\r\n            size: byteLength,\r\n            usage: this.descriptor.usage,\r\n            mappedAtCreation: false,\r\n        })\r\n\r\n\r\n        if(copyPreviousDataWithin){\r\n            \r\n            const command = XGPU.device.createCommandEncoder();\r\n            command.copyBufferToBuffer(oldBuffer,0,this.gpuResource,0,oldBuffer.size);\r\n            const end = command.finish();\r\n        \r\n            XGPU.device.queue.submit([end]);\r\n            XGPU.device.queue.onSubmittedWorkDone().then(()=>{\r\n                //console.log(\"DESTROY BUFFER\")\r\n                oldBuffer.destroy();\r\n            })\r\n        \r\n        }else{\r\n            \r\n            oldBuffer.destroy();\r\n            \r\n        }\r\n            \r\n    }\r\n\r\n    public updateLowLevelBuffer(buffer:ArrayBuffer,bufferOffset:number,dataOffset?:number,size?:number){\r\n        //console.log({dataOffset,size,buffer})\r\n\r\n       \r\n            if(size == undefined) size = buffer.byteLength;\r\n            if(dataOffset == undefined) dataOffset = 0;\r\n\r\n            if(!this.gpuResource) throw new Error(\"you must create a GPUBuffer using VertexBuffer.createGPUResource(bufferSize)\");\r\n            //if(bufferOffset + size > this._bufferSize) throw new Error(\"incorrect gpu buffer length, max length = \"+this._bufferSize+\" vs \"+(bufferOffset + size));\r\n            \r\n            \r\n            if(dataOffset + size > buffer.byteLength) throw new Error(\"incorrect datas length\")\r\n\r\n            XGPU.device.queue.writeBuffer(this.gpuResource, bufferOffset, buffer,dataOffset,size)\r\n      \r\n\r\n\r\n     }\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n    protected _bufferSize: number;\r\n    protected deviceId: number;\r\n    public get bufferSize(): number { return this._bufferSize; }\r\n    public createGpuResource() {\r\n        if(this.lowLevelBuffer) return;\r\n        if (this.attributeChanged) this.updateAttributes();\r\n        if (!this.datas || this.gpuBufferIOs) return;\r\n        if (this.gpuResource) this.gpuResource.destroy();\r\n\r\n        const bufferSize = this.datas.byteLength;\r\n        //console.warn(\"VB.createGPUResource \", this.io, this.pipelineType, XGPU.debugUsage(this.descriptor.usage))\r\n        this.deviceId = XGPU.deviceId;\r\n        this._bufferSize = bufferSize;\r\n        this.gpuResource = XGPU.device.createBuffer({\r\n            size: bufferSize,\r\n            usage: this.descriptor.usage,\r\n            mappedAtCreation: false,\r\n        })\r\n        this.destroyed = false;\r\n        this.mustBeTransfered = true;\r\n\r\n    }\r\n\r\n    public time: number;\r\n    protected destroyed: boolean = true;\r\n    public destroyGpuResource() {\r\n        if (this.destroyed) return;\r\n\r\n\r\n        if (this.time && new Date().getTime() - this.time < 100 && XGPU.loseDeviceRecently) {\r\n            return;\r\n        }\r\n        this.time = new Date().getTime();\r\n\r\n        if (this.io && XGPU.loseDeviceRecently) {\r\n\r\n            if (this.io === 1) {\r\n\r\n\r\n                const vbio = this.resourceIO;\r\n                const vbs = vbio.buffers;\r\n\r\n               \r\n               \r\n                this.setPipelineType(this.pipelineType)\r\n                const currentDatas = vbio.currentDatas ? vbio.currentDatas : vbs[0]._datas;\r\n\r\n                if (vbs[0]._datas instanceof Float32Array) vbs[0]._datas = vbs[1]._datas = new Float32Array(currentDatas);\r\n                else if (vbs[0]._datas instanceof Int32Array) vbs[0]._datas = vbs[1]._datas = new Int32Array(currentDatas);\r\n                else if (vbs[0]._datas instanceof Uint32Array) vbs[0]._datas = vbs[1]._datas = new Uint32Array(currentDatas);\r\n\r\n                //vbs[0]._datas = \r\n                let temp = vbs[0].gpuBufferIOs;\r\n                vbs[0].gpuBufferIOs = null;\r\n                vbs[0].createGpuResource();\r\n                vbs[0].gpuBufferIOs = temp;\r\n\r\n                temp = vbs[1].gpuBufferIOs;\r\n                vbs[1].gpuBufferIOs = null;\r\n                vbs[1].createGpuResource();\r\n                vbs[1].gpuBufferIOs = temp;\r\n\r\n                vbs[0].gpuBufferIOs[0] = vbs[0].gpuResource;\r\n                vbs[0].gpuBufferIOs[1] = vbs[1].gpuResource;\r\n\r\n\r\n            }\r\n            return\r\n\r\n        }\r\n        this.destroyed = true;\r\n        if (this.resourceIO) {\r\n            this.resourceIO.destroy();\r\n            this.resourceIO = null;\r\n        }\r\n        if (this.gpuResource) {\r\n            this.gpuResource.destroy();\r\n            this.gpuResource = null;\r\n        }\r\n\r\n\r\n    }\r\n\r\n    \r\n\r\n    public updateBuffer(): void {\r\n        if(this.lowLevelBuffer) return;\r\n        if (!this.datas) return;\r\n        if (!this.gpuResource) this.createGpuResource();\r\n        if (this.datas.byteLength != this._bufferSize) this.createGpuResource();\r\n\r\n        XGPU.device.queue.writeBuffer(this.gpuResource, 0, this.datas.buffer)\r\n\r\n    }\r\n\r\n    public getVertexArrayById(id: number): VertexAttribute { return this.vertexArrays[id]; }\r\n\r\n\r\n    protected updateAttributes() {\r\n\r\n        let attribute: VertexAttribute;\r\n        attribute = this.vertexArrays[0];\r\n        const nbAttributes = this.vertexArrays.length;\r\n\r\n        let offset: number = 0;\r\n\r\n        if (this.vertexArrays[0] && this.vertexArrays[0].useByVertexData) {\r\n\r\n\r\n            const nbVertex = attribute.datas.length;\r\n            if (!this._datas) this._datas = new Float32Array(nbVertex * this.nbComponent)\r\n\r\n            for (let i = 0; i < nbVertex; i++) {\r\n                for (let j = 0; j < nbAttributes; j++) {\r\n                    attribute = this.vertexArrays[j];\r\n                    if (attribute.mustBeTransfered) {\r\n                        //console.log(nbVertex, nbAttributes, offset, attribute)\r\n                        this._datas.set((attribute.datas as number[][])[i], offset);\r\n\r\n                    }\r\n                    offset += attribute.nbComponent;\r\n                }\r\n            }\r\n        } else {\r\n\r\n            const nbVertex = attribute.datas.length / attribute.nbComponent;\r\n            if (!this._datas) this._datas = new Float32Array(nbVertex * this.nbComponent)\r\n\r\n\r\n            for (let j = 0; j < nbAttributes; j++) {\r\n                attribute = this.vertexArrays[j];\r\n                if (attribute.mustBeTransfered) {\r\n\r\n                    this._datas.set(attribute.datas as number[], offset);\r\n                }\r\n                offset += attribute.nbComponent;\r\n\r\n            }\r\n\r\n        }\r\n\r\n\r\n\r\n\r\n        for (let j = 0; j < nbAttributes; j++) this.vertexArrays[j].mustBeTransfered = false;\r\n\r\n        this.attributeChanged = false;\r\n        this.mustBeTransfered = true;\r\n\r\n    }\r\n\r\n\r\n    public update(): boolean {\r\n        if(this.lowLevelBuffer) return true;\r\n        if (this.vertexArrays.length === 0) return false;\r\n        if (this.attributeChanged) this.updateAttributes();\r\n\r\n        if (this.mustBeTransfered) {\r\n            this.mustBeTransfered = false;\r\n            this.updateBuffer();\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n}"
          }
        ],
        "VertexBufferIO": [
          {
            "objectType": "class",
            "name": "VertexBufferIO",
            "filePath": "xGPU.shader.resources.VertexBufferIO",
            "extends": [
              "StageableBuffer",
              "EventDispatcher"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "buffers",
                  "type": "VertexBuffer[]",
                  "visibility": "public",
                  "rawText": "public buffers: VertexBuffer[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public descriptor: any;"
                },
                {
                  "objectType": "property",
                  "name": "input",
                  "type": "VertexBuffer",
                  "visibility": "public",
                  "rawText": "public get input(): VertexBuffer { return this.buffers[0] }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "output",
                  "type": "VertexBuffer",
                  "visibility": "public",
                  "rawText": "public get output(): VertexBuffer { return this.buffers[1] }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "currentDatas",
                  "type": "ArrayBuffer",
                  "visibility": "public",
                  "rawText": "public currentDatas: ArrayBuffer;"
                },
                {
                  "objectType": "property",
                  "name": "dataStructureChanged",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public dataStructureChanged: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "nextDatas",
                  "type": "Float32Array | Int32Array | Uint32Array",
                  "visibility": "public",
                  "rawText": "public nextDatas: Float32Array | Int32Array | Uint32Array"
                },
                {
                  "objectType": "property",
                  "name": "datas",
                  "type": "Float32Array | Int32Array | Uint32Array",
                  "visibility": "public",
                  "rawText": "public set datas(v: Float32Array | Int32Array | Uint32Array) {\r\n        this.buffers[0].datas = v;\r\n        this.buffers[1].datas = v;\r\n\r\n    }",
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "attributeDescriptor",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public get attributeDescriptor(): any {\r\n        if (!this.attributeDesc) this.attributeDesc = this.buffers[0].attributeDescriptor;\r\n        return this.attributeDesc;\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "bufferSize",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get bufferSize(): number { return this.buffers[0].buffer.size; }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "nbVertex",
                  "type": "number",
                  "visibility": "public",
                  "rawText": "public get nbVertex(): number { return this.buffers[0].nbVertex }",
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "deviceId",
                  "type": "number",
                  "visibility": "protected",
                  "rawText": "protected deviceId: number;"
                },
                {
                  "objectType": "property",
                  "name": "view",
                  "type": "any",
                  "visibility": "protected",
                  "rawText": "protected view: any;"
                },
                {
                  "objectType": "property",
                  "name": "attributeDesc",
                  "type": "any",
                  "visibility": "protected",
                  "rawText": "protected attributeDesc: any;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "destroy",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public destroy() {\r\n        if (this.stagingBuffer) this.stagingBuffer.destroy();\r\n        this.buffers[0].destroyGpuResource();\r\n        this.buffers[1].destroyGpuResource();\r\n        this.buffers = undefined;\r\n        this.onOutputData = undefined;\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getOutputData",
                  "returnType": "Promise<any>",
                  "visibility": "public",
                  "rawText": "public async getOutputData() {\r\n\r\n\r\n        this.rebuildAfterDeviceLost()\r\n\r\n\r\n        //------------------------------------------\r\n        // getting this value change the reference of the GPUBuffer and create the \"ping pong\"\r\n        // That's why it must be the first line, before the exceptions\r\n\r\n        const buffer = this.buffers[0].buffer;\r\n        //-------------------------------------------\r\n\r\n        //console.log(\"getOutputData \", this.onOutputData, this.canCallMapAsync)\r\n\r\n        if (!this.onOutputData) return null;\r\n\r\n\r\n\r\n        if (!this.canCallMapAsync) return;\r\n\r\n        this.canCallMapAsync = false;\r\n\r\n\r\n\r\n        if (!this.stagingBuffer) this.stagingBuffer = XGPU.createStagingBuffer(this.bufferSize);\r\n        const copyEncoder = XGPU.device.createCommandEncoder();\r\n        const stage = this.stagingBuffer;\r\n\r\n        copyEncoder.copyBufferToBuffer(buffer, 0, stage, 0, stage.size);\r\n\r\n        XGPU.device.queue.submit([copyEncoder.finish()]);\r\n\r\n\r\n        await this.stagingBuffer.mapAsync(GPUMapMode.READ, 0, stage.size)\r\n        this.canCallMapAsync = true;\r\n\r\n        const copyArray = stage.getMappedRange(0, stage.size);\r\n        const data = copyArray.slice(0);\r\n        stage.unmap();\r\n\r\n        this.currentDatas = data;\r\n\r\n        this.onOutputData(data);\r\n\r\n\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "VertexBufferIO",
                  "visibility": "public",
                  "rawText": "public clone(): VertexBufferIO {\r\n        return new VertexBufferIO(this.buffers[0].attributeDescriptor, this.descriptor);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(name: string, bindingId: number, groupId: number): string {\r\n        const structName = name.substring(0, 1).toUpperCase() + name.slice(1);\r\n        const varName = name.substring(0, 1).toLowerCase() + name.slice(1);\r\n\r\n        let result = \"\";\r\n        result += \"struct \" + structName + \"{\\n\";\r\n        let a: VertexAttribute;\r\n        for (let i = 0; i < this.buffers[0].vertexArrays.length; i++) {\r\n            a = this.buffers[0].vertexArrays[i];\r\n            result += \"   \" + a.name + \":\" + a.varType + \",\\n\";\r\n        }\r\n        result += \"}\\n\\n\";\r\n\r\n        result += \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<storage, read> \" + varName + \":array<\" + structName + \">;\\n\";//\"_Array;\\n\";\r\n        result += \"@binding(\" + (bindingId + 1) + \") @group(\" + groupId + \") var<storage, read_write> \" + varName + \"_out:array<\" + structName + \">;\\n\";// + \"_Array;\\n\";\r\n        return result + \"\\n\";\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createVertexInstances",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "nbInstance",
                      "type": "number"
                    },
                    {
                      "name": "createInstance",
                      "type": "(instanceId: number) => any"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createVertexInstances(nbInstance: number, createInstance: (instanceId: number) => any) {\r\n\r\n        if (undefined == this.buffers[0].arrayStride) {\r\n            this.buffers[0].stackAttributes();\r\n        }\r\n\r\n\r\n\r\n\r\n        const attributes = this.buffers[0].attributes;\r\n        const arrayStride = this.buffers[0].arrayStride;\r\n\r\n\r\n        let type: any;\r\n        for (let z in attributes) {\r\n            type = attributes[z].format;\r\n            break;\r\n        }\r\n\r\n        let datas;\r\n\r\n        if (type === \"float32\" || type === \"float32x2\" || type === \"float32x3\" || type === \"float32x4\") datas = new Float32Array(arrayStride * nbInstance);\r\n        else if (type == \"sint32\" || type == \"sint32x2\" || type == \"sint32x3\" || type == \"sint32x4\") datas = new Int32Array(arrayStride * nbInstance);\r\n        else if (type == \"uint32\" || type == \"uint32x2\" || type == \"uint32x3\" || type == \"uint32x4\") datas = new Uint32Array(arrayStride * nbInstance);\r\n\r\n\r\n\r\n        let o: any;\r\n        let start;\r\n        let attribute;\r\n        for (let i = 0; i < nbInstance; i++) {\r\n            start = arrayStride * i;\r\n            o = createInstance(i);\r\n\r\n            for (let z in o) {\r\n                attribute = attributes[z];\r\n                if (attribute) {\r\n                    datas.set(o[z], start + attribute.dataOffset);\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        this.datas = datas;\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getVertexInstances",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "datas",
                      "type": "Float32Array"
                    },
                    {
                      "name": "onGetInstance",
                      "type": "(o: any) => void"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public getVertexInstances(datas: Float32Array, onGetInstance: (o: any) => void) {\r\n        const arrayStride = this.buffers[0].arrayStride ? this.buffers[0].arrayStride : this.buffers[1].arrayStride;\r\n        const attributes = this.buffers[0].attributes;\r\n\r\n        if (!this.view) {\r\n            this.view = {};\r\n            for (let z in attributes) {\r\n                const a = attributes[z];\r\n                let val;\r\n                if (a.nbComponent === 1) val = { x: 0, ___offset: a.dataOffset };//new Float();\r\n                else if (a.nbComponent === 2) val = { x: 0, y: 0, ___offset: a.dataOffset };//new Vec2();\r\n                else if (a.nbComponent === 3) val = { x: 0, y: 0, z: 0, ___offset: a.dataOffset };//new Vec3();\r\n                else if (a.nbComponent === 4) val = { x: 0, y: 0, z: 0, w: 0, ___offset: a.dataOffset };//new Vec4();\r\n                this.view[z] = val;\r\n            }\r\n        }\r\n\r\n\r\n        const view: any = this.view;\r\n\r\n\r\n\r\n        const nb = this.buffers[0].datas.length / arrayStride;\r\n        let start: number, s: number, nbCompo;\r\n        let v: any;\r\n\r\n        for (let i = 0; i < nb; i++) {\r\n            start = i * arrayStride;\r\n\r\n            for (let z in attributes) {\r\n                nbCompo = attributes[z].nbComponent;\r\n                s = start + attributes[z].dataOffset;\r\n                v = view[z];\r\n                v.x = datas[s];\r\n                if (nbCompo >= 2) {\r\n                    v.y = datas[s + 1];\r\n                    if (nbCompo >= 3) {\r\n                        v.z = datas[s + 2];\r\n                        if (nbCompo == 4) v.w = datas[s + 3];\r\n                    }\r\n                }\r\n            }\r\n            onGetInstance(view);\r\n        }\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public update() {\r\n\r\n        this.rebuildAfterDeviceLost()\r\n\r\n\r\n        this.buffers[0].update();\r\n        this.buffers[1].update();\r\n    }"
                }
              ],
              "private": [
                {
                  "objectType": "method",
                  "name": "rebuildAfterDeviceLost",
                  "returnType": "void",
                  "visibility": "private",
                  "rawText": "private rebuildAfterDeviceLost() {\r\n        if (this.deviceId != XGPU.deviceId) {\r\n            //console.log(\"VertexBufferIO. REBUILD AFTER LOST\")\r\n            this.deviceId = XGPU.deviceId;\r\n            this.canCallMapAsync = true;\r\n            this.stagingBuffer = null;\r\n            this.currentDatas = this.buffers[0].datas\r\n        }\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "attributes",
                  "type": "any"
                },
                {
                  "name": "descriptor",
                  "type": "any"
                }
              ],
              "rawText": "constructor(attributes: any, descriptor?: any) {\r\n\r\n        super();\r\n\r\n        if (!descriptor) descriptor = {};\r\n        else descriptor = { ...descriptor };\r\n\r\n        this.descriptor = descriptor;\r\n        if (!descriptor.stepMode) descriptor.stepMode = \"instance\";\r\n        //console.log(descriptor.stepMode)\r\n\r\n        this.deviceId = XGPU.deviceId;\r\n        this.buffers[0] = new VertexBuffer(attributes, descriptor);\r\n        this.buffers[1] = new VertexBuffer(attributes, descriptor);\r\n\r\n        this.buffers[0].io = 1;\r\n        this.buffers[1].io = 2;\r\n\r\n        this.buffers[0].resourceIO = this;\r\n        this.buffers[1].resourceIO = this;\r\n\r\n    }"
            },
            "rawText": "export class VertexBufferIO extends StageableBuffer {\r\n\r\n    public buffers: VertexBuffer[] = [];\r\n    public descriptor: any;\r\n    //public onOutputData: (data: ArrayBuffer) => void;\r\n\r\n    //protected stagingBuffer: GPUBuffer;\r\n    //protected canCallMapAsync: boolean = true;\r\n\r\n    protected deviceId: number;\r\n\r\n    constructor(attributes: any, descriptor?: any) {\r\n\r\n        super();\r\n\r\n        if (!descriptor) descriptor = {};\r\n        else descriptor = { ...descriptor };\r\n\r\n        this.descriptor = descriptor;\r\n        if (!descriptor.stepMode) descriptor.stepMode = \"instance\";\r\n        //console.log(descriptor.stepMode)\r\n\r\n        this.deviceId = XGPU.deviceId;\r\n        this.buffers[0] = new VertexBuffer(attributes, descriptor);\r\n        this.buffers[1] = new VertexBuffer(attributes, descriptor);\r\n\r\n        this.buffers[0].io = 1;\r\n        this.buffers[1].io = 2;\r\n\r\n        this.buffers[0].resourceIO = this;\r\n        this.buffers[1].resourceIO = this;\r\n\r\n    }\r\n\r\n    public get input(): VertexBuffer { return this.buffers[0] }\r\n    public get output(): VertexBuffer { return this.buffers[1] }\r\n\r\n\r\n    public destroy() {\r\n        if (this.stagingBuffer) this.stagingBuffer.destroy();\r\n        this.buffers[0].destroyGpuResource();\r\n        this.buffers[1].destroyGpuResource();\r\n        this.buffers = undefined;\r\n        this.onOutputData = undefined;\r\n\r\n    }\r\n\r\n\r\n    private rebuildAfterDeviceLost() {\r\n        if (this.deviceId != XGPU.deviceId) {\r\n            //console.log(\"VertexBufferIO. REBUILD AFTER LOST\")\r\n            this.deviceId = XGPU.deviceId;\r\n            this.canCallMapAsync = true;\r\n            this.stagingBuffer = null;\r\n            this.currentDatas = this.buffers[0].datas\r\n        }\r\n    }\r\n\r\n\r\n\r\n    public currentDatas: ArrayBuffer;\r\n\r\n\r\n\r\n    public async getOutputData() {\r\n\r\n\r\n        this.rebuildAfterDeviceLost()\r\n\r\n\r\n        //------------------------------------------\r\n        // getting this value change the reference of the GPUBuffer and create the \"ping pong\"\r\n        // That's why it must be the first line, before the exceptions\r\n\r\n        const buffer = this.buffers[0].buffer;\r\n        //-------------------------------------------\r\n\r\n        //console.log(\"getOutputData \", this.onOutputData, this.canCallMapAsync)\r\n\r\n        if (!this.onOutputData) return null;\r\n\r\n\r\n\r\n        if (!this.canCallMapAsync) return;\r\n\r\n        this.canCallMapAsync = false;\r\n\r\n\r\n\r\n        if (!this.stagingBuffer) this.stagingBuffer = XGPU.createStagingBuffer(this.bufferSize);\r\n        const copyEncoder = XGPU.device.createCommandEncoder();\r\n        const stage = this.stagingBuffer;\r\n\r\n        copyEncoder.copyBufferToBuffer(buffer, 0, stage, 0, stage.size);\r\n\r\n        XGPU.device.queue.submit([copyEncoder.finish()]);\r\n\r\n\r\n        await this.stagingBuffer.mapAsync(GPUMapMode.READ, 0, stage.size)\r\n        this.canCallMapAsync = true;\r\n\r\n        const copyArray = stage.getMappedRange(0, stage.size);\r\n        const data = copyArray.slice(0);\r\n        stage.unmap();\r\n\r\n        this.currentDatas = data;\r\n\r\n        this.onOutputData(data);\r\n\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n    public clone(): VertexBufferIO {\r\n        return new VertexBufferIO(this.buffers[0].attributeDescriptor, this.descriptor);\r\n    }\r\n\r\n    public createDeclaration(name: string, bindingId: number, groupId: number): string {\r\n        const structName = name.substring(0, 1).toUpperCase() + name.slice(1);\r\n        const varName = name.substring(0, 1).toLowerCase() + name.slice(1);\r\n\r\n        let result = \"\";\r\n        result += \"struct \" + structName + \"{\\n\";\r\n        let a: VertexAttribute;\r\n        for (let i = 0; i < this.buffers[0].vertexArrays.length; i++) {\r\n            a = this.buffers[0].vertexArrays[i];\r\n            result += \"   \" + a.name + \":\" + a.varType + \",\\n\";\r\n        }\r\n        result += \"}\\n\\n\";\r\n\r\n        result += \"@binding(\" + bindingId + \") @group(\" + groupId + \") var<storage, read> \" + varName + \":array<\" + structName + \">;\\n\";//\"_Array;\\n\";\r\n        result += \"@binding(\" + (bindingId + 1) + \") @group(\" + groupId + \") var<storage, read_write> \" + varName + \"_out:array<\" + structName + \">;\\n\";// + \"_Array;\\n\";\r\n        return result + \"\\n\";\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n    public createVertexInstances(nbInstance: number, createInstance: (instanceId: number) => any) {\r\n\r\n        if (undefined == this.buffers[0].arrayStride) {\r\n            this.buffers[0].stackAttributes();\r\n        }\r\n\r\n\r\n\r\n\r\n        const attributes = this.buffers[0].attributes;\r\n        const arrayStride = this.buffers[0].arrayStride;\r\n\r\n\r\n        let type: any;\r\n        for (let z in attributes) {\r\n            type = attributes[z].format;\r\n            break;\r\n        }\r\n\r\n        let datas;\r\n\r\n        if (type === \"float32\" || type === \"float32x2\" || type === \"float32x3\" || type === \"float32x4\") datas = new Float32Array(arrayStride * nbInstance);\r\n        else if (type == \"sint32\" || type == \"sint32x2\" || type == \"sint32x3\" || type == \"sint32x4\") datas = new Int32Array(arrayStride * nbInstance);\r\n        else if (type == \"uint32\" || type == \"uint32x2\" || type == \"uint32x3\" || type == \"uint32x4\") datas = new Uint32Array(arrayStride * nbInstance);\r\n\r\n\r\n\r\n        let o: any;\r\n        let start;\r\n        let attribute;\r\n        for (let i = 0; i < nbInstance; i++) {\r\n            start = arrayStride * i;\r\n            o = createInstance(i);\r\n\r\n            for (let z in o) {\r\n                attribute = attributes[z];\r\n                if (attribute) {\r\n                    datas.set(o[z], start + attribute.dataOffset);\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        this.datas = datas;\r\n\r\n    }\r\n\r\n\r\n    protected view: any;\r\n    public getVertexInstances(datas: Float32Array, onGetInstance: (o: any) => void) {\r\n        const arrayStride = this.buffers[0].arrayStride ? this.buffers[0].arrayStride : this.buffers[1].arrayStride;\r\n        const attributes = this.buffers[0].attributes;\r\n\r\n        if (!this.view) {\r\n            this.view = {};\r\n            for (let z in attributes) {\r\n                const a = attributes[z];\r\n                let val;\r\n                if (a.nbComponent === 1) val = { x: 0, ___offset: a.dataOffset };//new Float();\r\n                else if (a.nbComponent === 2) val = { x: 0, y: 0, ___offset: a.dataOffset };//new Vec2();\r\n                else if (a.nbComponent === 3) val = { x: 0, y: 0, z: 0, ___offset: a.dataOffset };//new Vec3();\r\n                else if (a.nbComponent === 4) val = { x: 0, y: 0, z: 0, w: 0, ___offset: a.dataOffset };//new Vec4();\r\n                this.view[z] = val;\r\n            }\r\n        }\r\n\r\n\r\n        const view: any = this.view;\r\n\r\n\r\n\r\n        const nb = this.buffers[0].datas.length / arrayStride;\r\n        let start: number, s: number, nbCompo;\r\n        let v: any;\r\n\r\n        for (let i = 0; i < nb; i++) {\r\n            start = i * arrayStride;\r\n\r\n            for (let z in attributes) {\r\n                nbCompo = attributes[z].nbComponent;\r\n                s = start + attributes[z].dataOffset;\r\n                v = view[z];\r\n                v.x = datas[s];\r\n                if (nbCompo >= 2) {\r\n                    v.y = datas[s + 1];\r\n                    if (nbCompo >= 3) {\r\n                        v.z = datas[s + 2];\r\n                        if (nbCompo == 4) v.w = datas[s + 3];\r\n                    }\r\n                }\r\n            }\r\n            onGetInstance(view);\r\n        }\r\n\r\n    }\r\n\r\n    public dataStructureChanged: boolean = false;\r\n    public nextDatas: Float32Array | Int32Array | Uint32Array\r\n\r\n    public set datas(v: Float32Array | Int32Array | Uint32Array) {\r\n        this.buffers[0].datas = v;\r\n        this.buffers[1].datas = v;\r\n\r\n    }\r\n\r\n    protected attributeDesc: any;\r\n    public get attributeDescriptor(): any {\r\n        if (!this.attributeDesc) this.attributeDesc = this.buffers[0].attributeDescriptor;\r\n        return this.attributeDesc;\r\n    }\r\n\r\n\r\n\r\n\r\n    public update() {\r\n\r\n        this.rebuildAfterDeviceLost()\r\n\r\n\r\n        this.buffers[0].update();\r\n        this.buffers[1].update();\r\n    }\r\n\r\n    public get bufferSize(): number { return this.buffers[0].buffer.size; }\r\n\r\n    public get nbVertex(): number { return this.buffers[0].nbVertex }\r\n\r\n\r\n}"
          }
        ],
        "VideoTexture": [
          {
            "objectType": "type",
            "name": "VideoTextureDescriptor",
            "type": "VideoTextureDescriptor",
            "rawText": "export type VideoTextureDescriptor = {\r\n    source?: HTMLVideoElement,\r\n    format?: GPUTextureFormat,\r\n    usage?: GPUTextureUsageFlags,\r\n    size?: GPUExtent3D,\r\n    mipLevelCount?: GPUIntegerCoordinate,\r\n    sampleCount?: GPUSize32,\r\n    dimension?: GPUTextureDimension,\r\n    viewFormats?: GPUTextureFormat[],\r\n    defaultViewDescriptor?: any\r\n}"
          },
          {
            "objectType": "class",
            "name": "VideoTexture",
            "filePath": "xGPU.shader.resources.VideoTexture",
            "implements": [
              "IShaderResource"
            ],
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "mustBeTransfered",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public mustBeTransfered: boolean = true;"
                },
                {
                  "objectType": "property",
                  "name": "descriptor",
                  "type": "VideoTextureDescriptor",
                  "visibility": "public",
                  "rawText": "public descriptor: VideoTextureDescriptor;"
                },
                {
                  "objectType": "property",
                  "name": "useWebcodec",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public useWebcodec: boolean = false;"
                },
                {
                  "objectType": "property",
                  "name": "gpuResource",
                  "type": "HTMLVideoElement",
                  "visibility": "public",
                  "rawText": "public gpuResource: HTMLVideoElement"
                },
                {
                  "objectType": "property",
                  "name": "source",
                  "type": "HTMLVideoElement",
                  "visibility": "public",
                  "rawText": "public set source(video: HTMLVideoElement) {\r\n        this.gpuResource = video;\r\n        this.descriptor.source = video;\r\n        this.descriptor.size = [video.width, video.height];\r\n\r\n        let nbError: number = 0;\r\n        const frame = () => {\r\n            if (!this.gpuResource) return;\r\n            if (XGPU.device && this.deviceId === XGPU.deviceId) {\r\n                this.bindgroups.forEach(b => b.build());\r\n                nbError = 0;\r\n            } else {\r\n                nbError++;\r\n            }\r\n\r\n            if (nbError < 30) {\r\n                //i keep the video updating during 30 frame after device loss\r\n                //because we don't know if we lost the device voluntarily (if we change the page ) \r\n                //or because the device was lost for an external reason (in this case, the video must continue to update)\r\n                video.requestVideoFrameCallback(frame);\r\n            } else {\r\n                video.src = undefined;\r\n                //console.log(\"KILL VIDEO\")\r\n            }\r\n        }\r\n\r\n        video.requestVideoFrameCallback(frame)\r\n    }",
                  "set": true
                }
              ],
              "private": [
                {
                  "objectType": "property",
                  "name": "videoFrame",
                  "type": "any",
                  "visibility": "private",
                  "rawText": "private videoFrame: any;"
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "bindgroups",
                  "type": "Bindgroup[]",
                  "visibility": "protected",
                  "rawText": "protected bindgroups: Bindgroup[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "deviceId",
                  "type": "number",
                  "visibility": "protected",
                  "rawText": "protected deviceId: number;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "addBindgroup",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "bindgroup",
                      "type": "Bindgroup"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public addBindgroup(bindgroup: Bindgroup) {\r\n        if (this.bindgroups.indexOf(bindgroup) === -1) {\r\n            this.bindgroups.push(bindgroup);\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "VideoTexture",
                  "visibility": "public",
                  "rawText": "public clone(): VideoTexture {\r\n        return new VideoTexture(this.descriptor);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "varName",
                      "type": "string"
                    },
                    {
                      "name": "bindingId",
                      "type": "number"
                    },
                    {
                      "name": "groupId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_external;\\n\";\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupLayoutEntry",
                  "returnType": "{ binding: number; visibility: number; externalTexture: GPUExternalTextureBindingLayout; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, externalTexture: GPUExternalTextureBindingLayout } {\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT,\r\n            externalTexture: {},\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public createGpuResource() {\r\n        /*\r\n        no code here : \r\n        The HtmlVideoElement is used as gpyResource \r\n        */\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "update",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public update(): void {\r\n        /*\r\n        np code here :\r\n        the video update itself automaticly\r\n        */\r\n        this.deviceId = XGPU.deviceId;\r\n\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "destroyGpuResource",
                  "returnType": "void",
                  "visibility": "public",
                  "rawText": "public destroyGpuResource() {\r\n\r\n        //console.log(\"destroyGpuResource deviceLost = \")\r\n        /*\r\n        if (this.gpuResource ) {\r\n            this.gpuResource.src = undefined;\r\n            this.gpuResource = null;\r\n        }*/\r\n        if (this.videoFrame) {\r\n            this.videoFrame.close();\r\n            this.videoFrame = null;\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createBindGroupEntry",
                  "returnType": "{ binding: number; resource: GPUExternalTexture; }",
                  "params": [
                    {
                      "name": "bindingId",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUExternalTexture } {\r\n\r\n        if (this.useWebcodec) {\r\n            if (this.videoFrame) this.videoFrame.close();\r\n            this.videoFrame = new window[\"VideoFrame\"](this.gpuResource)\r\n        }\r\n\r\n\r\n        if (!this.gpuResource) throw new Error(\"gpuResource cannot be null. You must provide a HTMLVideoElement\")\r\n        return {\r\n            binding: bindingId,\r\n            resource: XGPU.device.importExternalTexture({\r\n                source: this.useWebcodec ? this.videoFrame as any : this.gpuResource\r\n            })\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "setPipelineType",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "pipelineType",
                      "type": "\"render\" | \"compute\" | \"compute_mixed\""
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType) { }\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "descriptor",
                  "type": "{ source?: HTMLVideoElement; format?: GPUTextureFormat; usage?: GPUTextureUsageFlags; size?: GPUExtent3D; mipLevelCount?: GPUIntegerCoordinate; sampleCount?: GPUSize32; dimension?: GPUTextureDimension; viewFormats?: GPUTextureFormat[]; defaultViewDescriptor?: any; }"
                }
              ],
              "rawText": "constructor(descriptor: {\r\n        source?: HTMLVideoElement,\r\n        format?: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        size?: GPUExtent3D,\r\n        mipLevelCount?: GPUIntegerCoordinate,\r\n        sampleCount?: GPUSize32,\r\n        dimension?: GPUTextureDimension,\r\n        viewFormats?: GPUTextureFormat[],\r\n        defaultViewDescriptor?: any,\r\n\r\n    }) {\r\n\r\n        if (undefined === descriptor.format) descriptor.format = \"rgba8unorm\";\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (undefined === descriptor.mipLevelCount) descriptor.mipLevelCount = 1;\r\n        if (undefined === descriptor.sampleCount) descriptor.sampleCount = 1;\r\n        if (undefined === descriptor.dimension) descriptor.dimension = \"2d\";\r\n        if (undefined === descriptor.viewFormats) descriptor.viewFormats = [];\r\n\r\n        this.descriptor = descriptor;\r\n\r\n        if (descriptor.source) this.source = descriptor.source;\r\n    }"
            },
            "rawText": "export class VideoTexture implements IShaderResource {\r\n\r\n    public mustBeTransfered: boolean = true;\r\n    public descriptor: VideoTextureDescriptor;\r\n    public useWebcodec: boolean = false; //still in beta \r\n\r\n    public gpuResource: HTMLVideoElement\r\n\r\n    /*\r\n    bindgroups: an array of bindgroup that contains the VideoTexture \r\n    => I need it to call its \"build\" function onVideoFrameCallback\r\n    => a videoTexture can be contained in multiple bindgroups, that's why it's an array\r\n    */\r\n    protected bindgroups: Bindgroup[] = [];\r\n    public addBindgroup(bindgroup: Bindgroup) {\r\n        if (this.bindgroups.indexOf(bindgroup) === -1) {\r\n            this.bindgroups.push(bindgroup);\r\n        }\r\n    }\r\n\r\n    constructor(descriptor: {\r\n        source?: HTMLVideoElement,\r\n        format?: GPUTextureFormat,\r\n        usage?: GPUTextureUsageFlags,\r\n        size?: GPUExtent3D,\r\n        mipLevelCount?: GPUIntegerCoordinate,\r\n        sampleCount?: GPUSize32,\r\n        dimension?: GPUTextureDimension,\r\n        viewFormats?: GPUTextureFormat[],\r\n        defaultViewDescriptor?: any,\r\n\r\n    }) {\r\n\r\n        if (undefined === descriptor.format) descriptor.format = \"rgba8unorm\";\r\n        if (undefined === descriptor.usage) descriptor.usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\r\n        if (undefined === descriptor.mipLevelCount) descriptor.mipLevelCount = 1;\r\n        if (undefined === descriptor.sampleCount) descriptor.sampleCount = 1;\r\n        if (undefined === descriptor.dimension) descriptor.dimension = \"2d\";\r\n        if (undefined === descriptor.viewFormats) descriptor.viewFormats = [];\r\n\r\n        this.descriptor = descriptor;\r\n\r\n        if (descriptor.source) this.source = descriptor.source;\r\n    }\r\n\r\n    public clone(): VideoTexture {\r\n        return new VideoTexture(this.descriptor);\r\n    }\r\n\r\n\r\n    public set source(video: HTMLVideoElement) {\r\n        this.gpuResource = video;\r\n        this.descriptor.source = video;\r\n        this.descriptor.size = [video.width, video.height];\r\n\r\n        let nbError: number = 0;\r\n        const frame = () => {\r\n            if (!this.gpuResource) return;\r\n            if (XGPU.device && this.deviceId === XGPU.deviceId) {\r\n                this.bindgroups.forEach(b => b.build());\r\n                nbError = 0;\r\n            } else {\r\n                nbError++;\r\n            }\r\n\r\n            if (nbError < 30) {\r\n                //i keep the video updating during 30 frame after device loss\r\n                //because we don't know if we lost the device voluntarily (if we change the page ) \r\n                //or because the device was lost for an external reason (in this case, the video must continue to update)\r\n                video.requestVideoFrameCallback(frame);\r\n            } else {\r\n                video.src = undefined;\r\n                //console.log(\"KILL VIDEO\")\r\n            }\r\n        }\r\n\r\n        video.requestVideoFrameCallback(frame)\r\n    }\r\n\r\n\r\n\r\n\r\n    public createDeclaration(varName: string, bindingId: number, groupId: number = 0): string {\r\n        return \"@binding(\" + bindingId + \") @group(\" + groupId + \") var \" + varName + \":texture_external;\\n\";\r\n    }\r\n\r\n\r\n    public createBindGroupLayoutEntry(bindingId: number): { binding: number, visibility: number, externalTexture: GPUExternalTextureBindingLayout } {\r\n        return {\r\n            binding: bindingId,\r\n            visibility: GPUShaderStage.FRAGMENT,\r\n            externalTexture: {},\r\n        }\r\n    }\r\n\r\n    public createGpuResource() {\r\n        /*\r\n        no code here : \r\n        The HtmlVideoElement is used as gpyResource \r\n        */\r\n    }\r\n    public update(): void {\r\n        /*\r\n        np code here :\r\n        the video update itself automaticly\r\n        */\r\n        this.deviceId = XGPU.deviceId;\r\n\r\n    }\r\n\r\n    protected deviceId: number;\r\n    public destroyGpuResource() {\r\n\r\n        //console.log(\"destroyGpuResource deviceLost = \")\r\n        /*\r\n        if (this.gpuResource ) {\r\n            this.gpuResource.src = undefined;\r\n            this.gpuResource = null;\r\n        }*/\r\n        if (this.videoFrame) {\r\n            this.videoFrame.close();\r\n            this.videoFrame = null;\r\n        }\r\n    }\r\n\r\n    private videoFrame: any;\r\n\r\n    public createBindGroupEntry(bindingId: number): { binding: number, resource: GPUExternalTexture } {\r\n\r\n        if (this.useWebcodec) {\r\n            if (this.videoFrame) this.videoFrame.close();\r\n            this.videoFrame = new window[\"VideoFrame\"](this.gpuResource)\r\n        }\r\n\r\n\r\n        if (!this.gpuResource) throw new Error(\"gpuResource cannot be null. You must provide a HTMLVideoElement\")\r\n        return {\r\n            binding: bindingId,\r\n            resource: XGPU.device.importExternalTexture({\r\n                source: this.useWebcodec ? this.videoFrame as any : this.gpuResource\r\n            })\r\n        }\r\n    }\r\n\r\n    public setPipelineType(pipelineType: \"compute\" | \"render\" | \"compute_mixed\") {\r\n        if (pipelineType) { }\r\n        //use to handle particular cases in descriptor relative to the nature of pipeline\r\n    }\r\n\r\n}"
          }
        ],
        "attributes": {
          "FloatBuffer": [
            {
              "objectType": "class",
              "name": "FloatBuffer",
              "filePath": "xGPU.shader.resources.attributes.FloatBuffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"float32\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }"
              },
              "rawText": "export class FloatBuffer extends VertexAttribute {\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"float32\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }\r\n}"
            }
          ],
          "IVec2Buffer": [
            {
              "objectType": "class",
              "name": "IVec2Buffer",
              "filePath": "xGPU.shader.resources.attributes.IVec2Buffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"sint32x2\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }"
              },
              "rawText": "export class IVec2Buffer extends VertexAttribute {\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"sint32x2\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }\r\n}"
            }
          ],
          "IVec3Buffer": [
            {
              "objectType": "class",
              "name": "IVec3Buffer",
              "filePath": "xGPU.shader.resources.attributes.IVec3Buffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"sint32x3\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }"
              },
              "rawText": "export class IVec3Buffer extends VertexAttribute {\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"sint32x3\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }\r\n}"
            }
          ],
          "IVec4Buffer": [
            {
              "objectType": "class",
              "name": "IVec4Buffer",
              "filePath": "xGPU.shader.resources.attributes.IVec4Buffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"sint32x4\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }"
              },
              "rawText": "export class IVec4Buffer extends VertexAttribute {\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"sint32x4\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }\r\n}"
            }
          ],
          "IntBuffer": [
            {
              "objectType": "class",
              "name": "IntBuffer",
              "filePath": "xGPU.shader.resources.attributes.IntBuffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"sint32\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }"
              },
              "rawText": "export class IntBuffer extends VertexAttribute {\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"sint32\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }\r\n}"
            }
          ],
          "UVec2Buffer": [
            {
              "objectType": "class",
              "name": "UVec2Buffer",
              "filePath": "xGPU.shader.resources.attributes.UVec2Buffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"uint32x2\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }"
              },
              "rawText": "export class UVec2Buffer extends VertexAttribute {\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"uint32x2\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }\r\n}"
            }
          ],
          "UVec3Buffer": [
            {
              "objectType": "class",
              "name": "UVec3Buffer",
              "filePath": "xGPU.shader.resources.attributes.UVec3Buffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"uint32x3\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }"
              },
              "rawText": "export class UVec3Buffer extends VertexAttribute {\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"uint32x3\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }\r\n}"
            }
          ],
          "UVec4Buffer": [
            {
              "objectType": "class",
              "name": "UVec4Buffer",
              "filePath": "xGPU.shader.resources.attributes.UVec4Buffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"uint32x4\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }"
              },
              "rawText": "export class UVec4Buffer extends VertexAttribute {\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"uint32x4\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }\r\n}"
            }
          ],
          "UintBuffer": [
            {
              "objectType": "class",
              "name": "UintBuffer",
              "filePath": "xGPU.shader.resources.attributes.UintBuffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"uint32\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }"
              },
              "rawText": "export class UintBuffer extends VertexAttribute {\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"uint32\", offset)\r\n        if (typeof (datas) != \"number\") this.datas = datas;\r\n    }\r\n}"
            }
          ],
          "Vec2Buffer": [
            {
              "objectType": "class",
              "name": "Vec2Buffer",
              "filePath": "xGPU.shader.resources.attributes.Vec2Buffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        //console.log(\"Vec2Buffer \", offset)\r\n\r\n        super(\"\", \"float32x2\", offset)\r\n        //console.log(\"Vec2Buffer.dataOffset = \", this.dataOffset)\r\n        if (typeof (datas) != \"number\") {\r\n            this.datas = datas;\r\n        }\r\n\r\n    }"
              },
              "rawText": "export class Vec2Buffer extends VertexAttribute {\r\n\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        //console.log(\"Vec2Buffer \", offset)\r\n\r\n        super(\"\", \"float32x2\", offset)\r\n        //console.log(\"Vec2Buffer.dataOffset = \", this.dataOffset)\r\n        if (typeof (datas) != \"number\") {\r\n            this.datas = datas;\r\n        }\r\n\r\n    }\r\n\r\n\r\n}"
            }
          ],
          "Vec3Buffer": [
            {
              "objectType": "class",
              "name": "Vec3Buffer",
              "filePath": "xGPU.shader.resources.attributes.Vec3Buffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"float32x3\", offset)\r\n\r\n        if (typeof (datas) != \"number\") {\r\n            this.datas = datas;\r\n        }\r\n\r\n    }"
              },
              "rawText": "export class Vec3Buffer extends VertexAttribute {\r\n\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"float32x3\", offset)\r\n\r\n        if (typeof (datas) != \"number\") {\r\n            this.datas = datas;\r\n        }\r\n\r\n    }\r\n\r\n\r\n}"
            }
          ],
          "Vec4Buffer": [
            {
              "objectType": "class",
              "name": "Vec4Buffer",
              "filePath": "xGPU.shader.resources.attributes.Vec4Buffer",
              "extends": [
                "VertexAttribute"
              ],
              "constructor": {
                "objectType": "constructor",
                "name": "constructor",
                "params": [
                  {
                    "name": "datas",
                    "type": "number | number[] | number[][]"
                  },
                  {
                    "name": "offset",
                    "type": "number"
                  }
                ],
                "rawText": "constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"float32x4\", offset)\r\n\r\n        if (typeof (datas) != \"number\") {\r\n            this.datas = datas;\r\n        }\r\n\r\n    }"
              },
              "rawText": "export class Vec4Buffer extends VertexAttribute {\r\n\r\n\r\n    constructor(datas?: number[][] | number[] | number, offset?: number) {\r\n\r\n        if (datas != undefined && offset === undefined) {\r\n            if (typeof datas === \"number\") {\r\n                offset = datas;\r\n                datas = undefined;\r\n            }\r\n        }\r\n\r\n        super(\"\", \"float32x4\", offset)\r\n\r\n        if (typeof (datas) != \"number\") {\r\n            this.datas = datas;\r\n        }\r\n\r\n    }\r\n\r\n\r\n}"
            }
          ]
        }
      },
      "shaderParts": {
        "ShaderNode": [
          {
            "objectType": "class",
            "name": "ShaderNode",
            "filePath": "xGPU.shader.shaderParts.ShaderNode",
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "enabled",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public enabled: boolean = true;"
                },
                {
                  "objectType": "property",
                  "name": "executeSubNodeAfterCode",
                  "type": "boolean",
                  "visibility": "public",
                  "rawText": "public executeSubNodeAfterCode: boolean = true;"
                },
                {
                  "objectType": "property",
                  "name": "nodeByName",
                  "type": "{ [key: string]: ShaderNode; }",
                  "visibility": "public",
                  "rawText": "public get nodeByName():{[key:string]:ShaderNode}{\r\n        return this._nodeByName;\r\n    }",
                  "get": true
                },
                {
                  "objectType": "property",
                  "name": "text",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public get text(): string { return this._text }",
                  "get": true,
                  "set": true
                },
                {
                  "objectType": "property",
                  "name": "value",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public get value(): string {\r\n\r\n        let result = \"\";\r\n\r\n        if (this.executeSubNodeAfterCode) {\r\n\r\n            result += this.text + \"\\n\";\r\n        }\r\n        if (this.subNodes) {\r\n            for (let i = 0; i < this.subNodes.length; i++) {\r\n                result += this.subNodes[i].value + \"\\n\";\r\n            }\r\n        }\r\n\r\n        if (!this.executeSubNodeAfterCode) result += this.text + \"\\n\";\r\n\r\n\r\n        //console.log(this.text + \" vs \" + result)\r\n        return result;\r\n    }",
                  "get": true
                }
              ],
              "private": [
                {
                  "objectType": "property",
                  "name": "_text",
                  "type": "string",
                  "visibility": "private",
                  "rawText": "private _text: string;"
                },
                {
                  "objectType": "property",
                  "name": "insideMainFunction",
                  "type": "boolean",
                  "visibility": "private",
                  "rawText": "private insideMainFunction: boolean;"
                },
                {
                  "objectType": "property",
                  "name": "_nodeByName",
                  "type": "{ [key: string]: ShaderNode; }",
                  "visibility": "private",
                  "rawText": "private _nodeByName:{[key:string]:ShaderNode} = {};"
                },
                {
                  "objectType": "property",
                  "name": "subNodes",
                  "type": "ShaderNode[]",
                  "visibility": "private",
                  "rawText": "private subNodes: ShaderNode[];"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "replaceValues",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "values",
                      "type": "{ old: string; new: string; }[]"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public replaceValues(values: { old: string, new: string }[]) {\r\n        for (let i = 0; i < values.length; i++) {\r\n            this.replaceKeyWord(values[i].old, values[i].new);\r\n            //this._text = this._text.replace(values[i].old, values[i].new);\r\n        }\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "replaceKeyWord",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "wordToReplace",
                      "type": "string"
                    },
                    {
                      "name": "replacement",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public replaceKeyWord(wordToReplace: string, replacement: string) {\r\n        const regex = new RegExp(`(?<=[^\\\\w.])\\\\b${wordToReplace}\\\\b`, 'g');\r\n        this._text = this._text.replace(regex, replacement);\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "createNode",
                  "returnType": "ShaderNode",
                  "params": [
                    {
                      "name": "code",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public createNode(code: string = \"\"): ShaderNode {\r\n        const node = new ShaderNode(code);\r\n        if (!this.subNodes) this.subNodes = [];\r\n        this.subNodes.push(node);\r\n        return node;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "addNode",
                  "returnType": "ShaderNode",
                  "params": [
                    {
                      "name": "nodeName",
                      "type": "string"
                    },
                    {
                      "name": "code",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public addNode(nodeName:string,code:string=\"\"):ShaderNode{\r\n        const node = this.createNode(code);\r\n        this._nodeByName[nodeName] = node;\r\n        return node;\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "code",
                  "type": "string"
                },
                {
                  "name": "insideMainFunction",
                  "type": "boolean"
                }
              ],
              "rawText": "constructor(code: string = \"\", insideMainFunction: boolean = false) {\r\n        this.text = code;\r\n        this.insideMainFunction = insideMainFunction;\r\n    }"
            },
            "rawText": "export class ShaderNode {\r\n\r\n    public enabled: boolean = true;\r\n    public executeSubNodeAfterCode: boolean = true;\r\n\r\n\r\n    private _text: string;\r\n    private insideMainFunction: boolean;\r\n\r\n    private _nodeByName:{[key:string]:ShaderNode} = {};\r\n    public get nodeByName():{[key:string]:ShaderNode}{\r\n        return this._nodeByName;\r\n    }\r\n\r\n\r\n    private subNodes: ShaderNode[];\r\n\r\n    constructor(code: string = \"\", insideMainFunction: boolean = false) {\r\n        this.text = code;\r\n        this.insideMainFunction = insideMainFunction;\r\n    }\r\n\r\n\r\n    public get text(): string { return this._text }\r\n    public set text(s: string) {\r\n        \r\n        //--------- remove useless tabulations while keeping tabs structure -------\r\n\r\n        const lines = s.split(\"\\n\");\r\n        let line;\r\n        let nbTabMin = 99999999;\r\n\r\n        if (lines.length > 1) {\r\n            for (let i = 0; i < lines.length; i++) {\r\n                line = lines[i];\r\n                for (let j = 0; j < line.length; j++) {\r\n                    if (line[j] === \"\\n\") continue;\r\n                    if (line[j] !== \" \") {\r\n                        if (nbTabMin > j) nbTabMin = j;\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            if (this.insideMainFunction && nbTabMin >= 3) nbTabMin -= 3;\r\n            for (let i = 0; i < lines.length; i++) {\r\n                lines[i] = lines[i].slice(nbTabMin);\r\n            }\r\n\r\n            s = lines.join(\"\\n\");\r\n        }\r\n        //-----------------------------------------------------------------------\r\n\r\n        this._text = s;\r\n    }\r\n\r\n    public replaceValues(values: { old: string, new: string }[]) {\r\n        for (let i = 0; i < values.length; i++) {\r\n            this.replaceKeyWord(values[i].old, values[i].new);\r\n            //this._text = this._text.replace(values[i].old, values[i].new);\r\n        }\r\n    }\r\n\r\n    public replaceKeyWord(wordToReplace: string, replacement: string) {\r\n        const regex = new RegExp(`(?<=[^\\\\w.])\\\\b${wordToReplace}\\\\b`, 'g');\r\n        this._text = this._text.replace(regex, replacement);\r\n    }\r\n\r\n\r\n\r\n    public get value(): string {\r\n\r\n        let result = \"\";\r\n\r\n        if (this.executeSubNodeAfterCode) {\r\n\r\n            result += this.text + \"\\n\";\r\n        }\r\n        if (this.subNodes) {\r\n            for (let i = 0; i < this.subNodes.length; i++) {\r\n                result += this.subNodes[i].value + \"\\n\";\r\n            }\r\n        }\r\n\r\n        if (!this.executeSubNodeAfterCode) result += this.text + \"\\n\";\r\n\r\n\r\n        //console.log(this.text + \" vs \" + result)\r\n        return result;\r\n    }\r\n\r\n    public createNode(code: string = \"\"): ShaderNode {\r\n        const node = new ShaderNode(code);\r\n        if (!this.subNodes) this.subNodes = [];\r\n        this.subNodes.push(node);\r\n        return node;\r\n    }\r\n\r\n    public addNode(nodeName:string,code:string=\"\"):ShaderNode{\r\n        const node = this.createNode(code);\r\n        this._nodeByName[nodeName] = node;\r\n        return node;\r\n    }\r\n\r\n\r\n\r\n}"
          }
        ],
        "ShaderStage": [
          {
            "objectType": "class",
            "name": "ShaderStage",
            "filePath": "xGPU.shader.shaderParts.ShaderStage",
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "inputs",
                  "type": "{ name: string; type: any; builtin?: string; }[]",
                  "visibility": "public",
                  "rawText": "public inputs: { name: string, type: any, builtin?: string }[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "outputs",
                  "type": "{ name: string; type: any; builtin?: string; }[]",
                  "visibility": "public",
                  "rawText": "public outputs: { name: string, type: any, builtin?: string }[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "export",
                  "type": "{ name: string; type: any; }[]",
                  "visibility": "public",
                  "rawText": "public export: { name: string, type: any }[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "require",
                  "type": "{ name: string; type: any; }[]",
                  "visibility": "public",
                  "rawText": "public require: { name: string, type: any }[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "pipelineConstants",
                  "type": "any",
                  "visibility": "public",
                  "rawText": "public pipelineConstants: any = {};"
                },
                {
                  "objectType": "property",
                  "name": "constants",
                  "type": "ShaderNode",
                  "visibility": "public",
                  "rawText": "public constants: ShaderNode;"
                },
                {
                  "objectType": "property",
                  "name": "main",
                  "type": "ShaderNode",
                  "visibility": "public",
                  "rawText": "public main: ShaderNode;"
                },
                {
                  "objectType": "property",
                  "name": "shaderType",
                  "type": "\"compute\" | \"vertex\" | \"fragment\"",
                  "visibility": "public",
                  "rawText": "public shaderType: \"vertex\" | \"fragment\" | \"compute\";"
                },
                {
                  "objectType": "property",
                  "name": "debugLogs",
                  "type": "{ label: string; val: string; }[]",
                  "visibility": "public",
                  "rawText": "public debugLogs: { label: string, val: string }[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "debugRenders",
                  "type": "{ label: string; val: string; color: string; }[]",
                  "visibility": "public",
                  "rawText": "public debugRenders: { label: string, val: string, color: string }[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "shaderInfos",
                  "type": "{ code: string; output: ShaderStruct; }",
                  "visibility": "public",
                  "rawText": "public get shaderInfos(): { code: string, output: ShaderStruct } { return this._shaderInfos; }",
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "_shaderInfos",
                  "type": "{ code: string; output: ShaderStruct; }",
                  "visibility": "protected",
                  "rawText": "protected _shaderInfos: { code: string, output: ShaderStruct };"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "addOutputVariable",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    },
                    {
                      "name": "shaderType",
                      "type": "{ type: string; }"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public addOutputVariable(name: string, shaderType: { type: string }) {\r\n        this.outputs.push({ name, type: shaderType.type })\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "addInputVariable",
                  "returnType": "void",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    },
                    {
                      "name": "shaderTypeOrBuiltIn",
                      "type": "{ type: string; builtin?: string; }"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public addInputVariable(name: string, shaderTypeOrBuiltIn: { type: string, builtin?: string }) {\r\n        this.outputs.push({ name, type: shaderTypeOrBuiltIn.type, builtin: shaderTypeOrBuiltIn.builtin })\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "build",
                  "returnType": "{ code: string; output: ShaderStruct; }",
                  "params": [
                    {
                      "name": "shaderPipeline",
                      "type": "any"
                    },
                    {
                      "name": "input",
                      "type": "ShaderStruct"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public build(shaderPipeline: any, input: ShaderStruct): { code: string, output: ShaderStruct } {\r\n        //must be overrided;\r\n        if (!shaderPipeline || !input) {\r\n\r\n        };\r\n\r\n        if (this._shaderInfos) return this._shaderInfos;\r\n        this._shaderInfos = { code: \"\", output: null }\r\n        return this._shaderInfos;\r\n    }"
                }
              ],
              "protected": [
                {
                  "objectType": "method",
                  "name": "unwrapVariableInMainFunction",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "shaderVariables",
                      "type": "string"
                    }
                  ],
                  "visibility": "protected",
                  "rawText": "protected unwrapVariableInMainFunction(shaderVariables: string) {\r\n        const variables: string[] = shaderVariables.split(\"\\n\");\r\n        let s: string;\r\n        let objs = [];\r\n        for (let i = 0; i < variables.length; i++) {\r\n            variables[i] = s = variables[i].split(\"\\t\").join(\"\").trim().slice(4);\r\n            if (!s.length) continue;\r\n            let t = s.split(\" = \");\r\n            let varName = t[0].split(\":\")[0];\r\n            let otherName = t[1].slice(0, t[1].length - 1);\r\n            objs.push({\r\n                varName,\r\n                otherName\r\n            })\r\n        }\r\n\r\n\r\n        const searchAndReplace = (shaderCode: string, wordToReplace: string, replacement: string) => {\r\n            const regex = new RegExp(`(?<=[^\\\\w.])\\\\b${wordToReplace}\\\\b`, 'g');\r\n            return shaderCode.replace(regex, replacement);\r\n        }\r\n\r\n        let shader = this.main.value + \"\";\r\n\r\n        for (let i = 0; i < objs.length; i++) {\r\n            shader = searchAndReplace(shader, objs[i].varName, objs[i].otherName);\r\n        }\r\n\r\n        return shader;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "unwrapVariableInWGSL",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "shaderVariables",
                      "type": "string"
                    },
                    {
                      "name": "wgsl",
                      "type": "string"
                    }
                  ],
                  "visibility": "protected",
                  "rawText": "protected unwrapVariableInWGSL(shaderVariables: string, wgsl: string) {\r\n        const variables: string[] = shaderVariables.split(\"\\n\");\r\n        let s: string;\r\n        let objs = [];\r\n        for (let i = 0; i < variables.length; i++) {\r\n            variables[i] = s = variables[i].split(\"\\t\").join(\"\").trim().slice(4);\r\n            if (!s.length) continue;\r\n            let t = s.split(\" = \");\r\n            let varName = t[0].split(\":\")[0];\r\n            let otherName = t[1].slice(0, t[1].length - 1);\r\n            objs.push({\r\n                varName,\r\n                otherName\r\n            })\r\n        }\r\n\r\n\r\n        const searchAndReplace = (shaderCode: string, wordToReplace: string, replacement: string) => {\r\n            const regex = new RegExp(`(?<=[^\\\\w.])\\\\b${wordToReplace}\\\\b`, 'g');\r\n            return shaderCode.replace(regex, replacement);\r\n        }\r\n\r\n\r\n        for (let i = 0; i < objs.length; i++) {\r\n            wgsl = searchAndReplace(wgsl, objs[i].varName, objs[i].otherName);\r\n        }\r\n\r\n        return wgsl;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "formatWGSLCode",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "code",
                      "type": "string"
                    }
                  ],
                  "visibility": "protected",
                  "rawText": "protected formatWGSLCode(code: string): string {\r\n\r\n\r\n\r\n\r\n        const res:string[] = code.split(\"\\n\");\r\n            let count:number = 0;\r\n\r\n            let tabs:string[] = [];\r\n            for(let i=0;i<16;i++){\r\n                if(i==0) tabs[i] = \"\";\r\n                else tabs[i] = tabs[i-1]+\"\\t\";\r\n            }\r\n            \r\n            const res2:string[]= [];\r\n            var s:string;\r\n            var empty = true;\r\n            for(let i=0;i<res.length;i++){\r\n                s = res[i].trim();\r\n                if(s.includes(\"}\")) count--;\r\n\r\n                if(s != \"\" || !empty){\r\n                    empty = s == \"\";\r\n                    res2.push(tabs[count] + s);\r\n                }\r\n                \r\n                if(res[i].includes(\"{\")) count++; \r\n            }\r\n\r\n           return res2.join(\"\\n\");\r\n\r\n       \r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "shaderType",
                  "type": "\"compute\" | \"vertex\" | \"fragment\""
                }
              ],
              "rawText": "constructor(shaderType: \"vertex\" | \"fragment\" | \"compute\") {\r\n        \r\n        this.shaderType = shaderType;\r\n        this.constants = new ShaderNode();\r\n        this.main = new ShaderNode(\"\", true);\r\n\r\n    }"
            },
            "rawText": "export class ShaderStage  {\r\n\r\n    \r\n\r\n    public inputs: { name: string, type: any, builtin?: string }[] = [];\r\n    public outputs: { name: string, type: any, builtin?: string }[] = [];\r\n    public export: { name: string, type: any }[] = [];\r\n    public require: { name: string, type: any }[] = [];\r\n\r\n    public pipelineConstants: any = {};\r\n    public constants: ShaderNode;\r\n    public main: ShaderNode;\r\n\r\n    public shaderType: \"vertex\" | \"fragment\" | \"compute\";\r\n\r\n    constructor(shaderType: \"vertex\" | \"fragment\" | \"compute\") {\r\n        \r\n        this.shaderType = shaderType;\r\n        this.constants = new ShaderNode();\r\n        this.main = new ShaderNode(\"\", true);\r\n\r\n    }\r\n\r\n\r\n    public debugLogs: { label: string, val: string }[] = [];\r\n    public debugRenders: { label: string, val: string, color: string }[] = [];\r\n    /*\r\n    public extractDebugInfo(shaderCode: string): string {\r\n        const { code, debugLogs, debugRenders } = ShaderStage.extractDebugInfo(shaderCode);\r\n        this.debugLogs = debugLogs;\r\n        this.debugRenders = debugRenders;\r\n        return code;\r\n    }\r\n\r\n    public static extractDebugInfo(code: string): {\r\n        code: string,\r\n        debugLogs: any[],\r\n        debugRenders: any[]\r\n    } {\r\n\r\n        const result: any = {};\r\n        result.debugLogs = [];\r\n        result.debugRenders = [];\r\n\r\n        const cut = (s: string) => {\r\n            let id;\r\n            for (let i = s.length - 1; i > -1; i--) {\r\n                if (s[i] === \",\") {\r\n                    id = i;\r\n                    break;\r\n                }\r\n            }\r\n\r\n            return {\r\n                label: s.slice(0, id),\r\n                val: s.slice(id + 1)\r\n            }\r\n\r\n        }\r\n\r\n        const extractDebug = (line: string) => {\r\n            let s: string = line.split(\"XGPU.debug(\")[1].split(\");\")[0];\r\n\r\n            //const { label, val } = cut(s);\r\n            //console.log(\"A = \", label);\r\n            //console.log(\"B = \", val);\r\n            result.debugLogs.push(cut(s));\r\n        }\r\n        const extractDebugRender = (line: string) => {\r\n            //XGPU.renderDebug(\"testC : \",output.position,vec4(0.0,0.0,1.0,1.0));\r\n            let s: string = line.split(\"XGPU.renderDebug(\")[1].split(\");\")[0];\r\n            let t = s.split(\",vec4\")\r\n            let color = \"vec4\" + t[1];\r\n            s = t[0];\r\n\r\n            //const { label, val } = cut(s);\r\n            //console.log(\"A = \", label);\r\n            //console.log(\"B = \", val);\r\n            //console.log(\"C = \", color);\r\n\r\n            result.debugRenders.push({\r\n                ...cut(s),\r\n                color\r\n            })\r\n\r\n        }\r\n\r\n\r\n        const lines: string[] = code.split(\"\\n\");\r\n        const newLines: string[] = [];\r\n        for (let i = 0; i < lines.length; i++) {\r\n            if (lines[i].includes(\"XGPU.debug\")) {\r\n                extractDebug(lines[i])\r\n            } else if (lines[i].includes(\"XGPU.renderDebug\")) {\r\n                extractDebugRender(lines[i]);\r\n            } else {\r\n                newLines.push(lines[i]);\r\n            }\r\n        }\r\n\r\n        result.code = newLines.join(\"\\n\");\r\n\r\n        return result;\r\n\r\n\r\n    }*/\r\n\r\n    protected unwrapVariableInMainFunction(shaderVariables: string) {\r\n        const variables: string[] = shaderVariables.split(\"\\n\");\r\n        let s: string;\r\n        let objs = [];\r\n        for (let i = 0; i < variables.length; i++) {\r\n            variables[i] = s = variables[i].split(\"\\t\").join(\"\").trim().slice(4);\r\n            if (!s.length) continue;\r\n            let t = s.split(\" = \");\r\n            let varName = t[0].split(\":\")[0];\r\n            let otherName = t[1].slice(0, t[1].length - 1);\r\n            objs.push({\r\n                varName,\r\n                otherName\r\n            })\r\n        }\r\n\r\n\r\n        const searchAndReplace = (shaderCode: string, wordToReplace: string, replacement: string) => {\r\n            const regex = new RegExp(`(?<=[^\\\\w.])\\\\b${wordToReplace}\\\\b`, 'g');\r\n            return shaderCode.replace(regex, replacement);\r\n        }\r\n\r\n        let shader = this.main.value + \"\";\r\n\r\n        for (let i = 0; i < objs.length; i++) {\r\n            shader = searchAndReplace(shader, objs[i].varName, objs[i].otherName);\r\n        }\r\n\r\n        return shader;\r\n    }\r\n\r\n    protected unwrapVariableInWGSL(shaderVariables: string, wgsl: string) {\r\n        const variables: string[] = shaderVariables.split(\"\\n\");\r\n        let s: string;\r\n        let objs = [];\r\n        for (let i = 0; i < variables.length; i++) {\r\n            variables[i] = s = variables[i].split(\"\\t\").join(\"\").trim().slice(4);\r\n            if (!s.length) continue;\r\n            let t = s.split(\" = \");\r\n            let varName = t[0].split(\":\")[0];\r\n            let otherName = t[1].slice(0, t[1].length - 1);\r\n            objs.push({\r\n                varName,\r\n                otherName\r\n            })\r\n        }\r\n\r\n\r\n        const searchAndReplace = (shaderCode: string, wordToReplace: string, replacement: string) => {\r\n            const regex = new RegExp(`(?<=[^\\\\w.])\\\\b${wordToReplace}\\\\b`, 'g');\r\n            return shaderCode.replace(regex, replacement);\r\n        }\r\n\r\n\r\n        for (let i = 0; i < objs.length; i++) {\r\n            wgsl = searchAndReplace(wgsl, objs[i].varName, objs[i].otherName);\r\n        }\r\n\r\n        return wgsl;\r\n    }\r\n\r\n\r\n\r\n\r\n    public addOutputVariable(name: string, shaderType: { type: string }) {\r\n        this.outputs.push({ name, type: shaderType.type })\r\n    }\r\n    public addInputVariable(name: string, shaderTypeOrBuiltIn: { type: string, builtin?: string }) {\r\n        this.outputs.push({ name, type: shaderTypeOrBuiltIn.type, builtin: shaderTypeOrBuiltIn.builtin })\r\n    }\r\n\r\n    protected formatWGSLCode(code: string): string {\r\n\r\n\r\n\r\n\r\n        const res:string[] = code.split(\"\\n\");\r\n            let count:number = 0;\r\n\r\n            let tabs:string[] = [];\r\n            for(let i=0;i<16;i++){\r\n                if(i==0) tabs[i] = \"\";\r\n                else tabs[i] = tabs[i-1]+\"\\t\";\r\n            }\r\n            \r\n            const res2:string[]= [];\r\n            var s:string;\r\n            var empty = true;\r\n            for(let i=0;i<res.length;i++){\r\n                s = res[i].trim();\r\n                if(s.includes(\"}\")) count--;\r\n\r\n                if(s != \"\" || !empty){\r\n                    empty = s == \"\";\r\n                    res2.push(tabs[count] + s);\r\n                }\r\n                \r\n                if(res[i].includes(\"{\")) count++; \r\n            }\r\n\r\n           return res2.join(\"\\n\");\r\n\r\n       \r\n    }\r\n\r\n\r\n\r\n    public get shaderInfos(): { code: string, output: ShaderStruct } { return this._shaderInfos; }\r\n    protected _shaderInfos: { code: string, output: ShaderStruct };\r\n    public build(shaderPipeline: any, input: ShaderStruct): { code: string, output: ShaderStruct } {\r\n        //must be overrided;\r\n        if (!shaderPipeline || !input) {\r\n\r\n        };\r\n\r\n        if (this._shaderInfos) return this._shaderInfos;\r\n        this._shaderInfos = { code: \"\", output: null }\r\n        return this._shaderInfos;\r\n    }\r\n\r\n\r\n   \r\n}"
          }
        ],
        "ShaderStruct": [
          {
            "objectType": "class",
            "name": "ShaderStruct",
            "filePath": "xGPU.shader.shaderParts.ShaderStruct",
            "properties": {
              "public": [
                {
                  "objectType": "property",
                  "name": "name",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public name: string;"
                },
                {
                  "objectType": "property",
                  "name": "struct",
                  "type": "string",
                  "visibility": "public",
                  "rawText": "public get struct(): string {\r\n        let result = \"struct \" + this.name + \" {\\n\";\r\n        let o;\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n\r\n            if (this.isShaderIO) {\r\n                if (i > 0) o.builtin = \"@location(\" + (i - 1) + \")\";\r\n                //console.log(o.name + \" , i = \", i, \" location = \", o.builtin, \" -- \", o.builtin.length)\r\n                result += \"   \" + o.builtin + \" \" + o.name + \":\" + o.type + \",\\n\";\r\n            } else {\r\n                if (undefined !== o.size) result += \"    \" + \"@size(\" + o.size + \") @align(16) \" + o.name + \":\" + o.type + \",\\n\";\r\n                else result += \"   \" + \" \" + o.name + \":\" + o.type + \",\\n\";\r\n            }\r\n        }\r\n        result += \"}\\n\\n\";\r\n\r\n        /*\r\n        const varName = this.name.substring(0, 1).toLowerCase() + this.name.slice(1);\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n            if (o.obj) result += o.obj.createVariable(varName) + \"\\n\";\r\n        }\r\n        */\r\n        return result;\r\n    }",
                  "get": true
                }
              ],
              "protected": [
                {
                  "objectType": "property",
                  "name": "properties",
                  "type": "{ name: string; type: string; builtin?: string; }[]",
                  "visibility": "protected",
                  "rawText": "protected properties: { name: string, type: string, builtin?: string }[] = [];"
                },
                {
                  "objectType": "property",
                  "name": "isShaderIO",
                  "type": "boolean",
                  "visibility": "protected",
                  "rawText": "protected isShaderIO: boolean = false;"
                }
              ]
            },
            "methods": {
              "public": [
                {
                  "objectType": "method",
                  "name": "clone",
                  "returnType": "ShaderStruct",
                  "params": [
                    {
                      "name": "name",
                      "type": "string"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public clone(name?: string): ShaderStruct {\r\n        let n: string = name ? name : this.name;\r\n        return new ShaderStruct(n, [...this.properties])\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "addProperty",
                  "returnType": "ShaderStruct",
                  "params": [
                    {
                      "name": "o",
                      "type": "{ name: string; type: string; builtin?: string; offset?: number; size?: number; obj?: any; }"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public addProperty(o: { name: string, type: string, builtin?: string, offset?: number, size?: number, obj?: any }): ShaderStruct {\r\n\r\n        //console.warn(\"addProperty \", o)\r\n\r\n        if (!o.builtin) o.builtin = \"\";\r\n        this.properties.push(o as { name: string, type: string, builtin: string, offset })\r\n        return this;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getComputeVariableDeclaration",
                  "returnType": "string",
                  "params": [
                    {
                      "name": "offset",
                      "type": "number"
                    }
                  ],
                  "visibility": "public",
                  "rawText": "public getComputeVariableDeclaration(offset: number = 0): string {\r\n        let o;\r\n        let result: string = \"\";\r\n        let k = 0;\r\n\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n\r\n            if (o.type.createDeclaration) {//if o.type has a type PipelineResource\r\n\r\n                if (o.type instanceof VertexBuffer) {\r\n                    o.type.name = o.name;\r\n                    result += o.type.createDeclaration((offset + k++), 0, !o.isOutput);\r\n                } else {\r\n                    result += o.type.createDeclaration(offset + k++);\r\n                    if (o.type.createStruct) result += o.type.createStruct().struct;\r\n                }\r\n            }\r\n        }\r\n        return result;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getFunctionParams",
                  "returnType": "string",
                  "visibility": "public",
                  "rawText": "public getFunctionParams(): string {\r\n        let result = \"\";\r\n        let o;\r\n        //console.log(\"getFunctionParams \", this.properties)\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n            result += o.builtin + \" \" + o.name + \":\" + o.type;\r\n            if (i != this.properties.length - 1) result += \", \";\r\n            if (i != this.properties.length - 1) result += \" \";\r\n        }\r\n\r\n        return result;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getComputeFunctionParams",
                  "returnType": "string",
                  "visibility": "public",
                  "rawText": "public getComputeFunctionParams(): string {\r\n        let result = \"\";\r\n        let o;\r\n        let k = 0;\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n            if (!o.type.createDeclaration) {\r\n                if (k++ !== 0) result += \", \";\r\n                result += o.builtin + \" \" + o.name + \":\" + o.type;\r\n\r\n\r\n            }\r\n\r\n        }\r\n\r\n        return result;\r\n    }"
                },
                {
                  "objectType": "method",
                  "name": "getInputFromOutput",
                  "returnType": "ShaderStruct",
                  "visibility": "public",
                  "rawText": "public getInputFromOutput(): ShaderStruct {\r\n        if (this.name != \"Output\") return null;\r\n        return new ShaderStruct(\"Input\", this.properties.slice(1))\r\n\r\n    }"
                }
              ]
            },
            "constructor": {
              "objectType": "constructor",
              "name": "constructor",
              "params": [
                {
                  "name": "name",
                  "type": "string"
                },
                {
                  "name": "properties",
                  "type": "{ name: string; type: string; builtin?: string; }[]"
                }
              ],
              "rawText": "constructor(name: string, properties?: ({ name: string, type: string, builtin?: string })[]) {\r\n\r\n        if (name === \"Input\" || name === \"Output\") {\r\n            this.isShaderIO = true;\r\n        }\r\n        //console.log(name + \" => isShaderIO = \", this.isShaderIO)\r\n\r\n        this.name = name;\r\n        if (properties) {\r\n            for (let i = 0; i < properties.length; i++) {\r\n                if (!properties[i].builtin) properties[i].builtin = \"\";\r\n            }\r\n            this.properties = properties;\r\n        }\r\n\r\n    }"
            },
            "rawText": "export class ShaderStruct {\r\n\r\n    protected properties: { name: string, type: string, builtin?: string }[] = [];\r\n    protected isShaderIO: boolean = false;\r\n    public name: string;\r\n\r\n    constructor(name: string, properties?: ({ name: string, type: string, builtin?: string })[]) {\r\n\r\n        if (name === \"Input\" || name === \"Output\") {\r\n            this.isShaderIO = true;\r\n        }\r\n        //console.log(name + \" => isShaderIO = \", this.isShaderIO)\r\n\r\n        this.name = name;\r\n        if (properties) {\r\n            for (let i = 0; i < properties.length; i++) {\r\n                if (!properties[i].builtin) properties[i].builtin = \"\";\r\n            }\r\n            this.properties = properties;\r\n        }\r\n\r\n    }\r\n\r\n    public clone(name?: string): ShaderStruct {\r\n        let n: string = name ? name : this.name;\r\n        return new ShaderStruct(n, [...this.properties])\r\n    }\r\n\r\n    public addProperty(o: { name: string, type: string, builtin?: string, offset?: number, size?: number, obj?: any }): ShaderStruct {\r\n\r\n        //console.warn(\"addProperty \", o)\r\n\r\n        if (!o.builtin) o.builtin = \"\";\r\n        this.properties.push(o as { name: string, type: string, builtin: string, offset })\r\n        return this;\r\n    }\r\n\r\n    public getComputeVariableDeclaration(offset: number = 0): string {\r\n        let o;\r\n        let result: string = \"\";\r\n        let k = 0;\r\n\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n\r\n            if (o.type.createDeclaration) {//if o.type has a type PipelineResource\r\n\r\n                if (o.type instanceof VertexBuffer) {\r\n                    o.type.name = o.name;\r\n                    result += o.type.createDeclaration((offset + k++), 0, !o.isOutput);\r\n                } else {\r\n                    result += o.type.createDeclaration(offset + k++);\r\n                    if (o.type.createStruct) result += o.type.createStruct().struct;\r\n                }\r\n            }\r\n        }\r\n        return result;\r\n    }\r\n\r\n    public getFunctionParams(): string {\r\n        let result = \"\";\r\n        let o;\r\n        //console.log(\"getFunctionParams \", this.properties)\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n            result += o.builtin + \" \" + o.name + \":\" + o.type;\r\n            if (i != this.properties.length - 1) result += \", \";\r\n            if (i != this.properties.length - 1) result += \" \";\r\n        }\r\n\r\n        return result;\r\n    }\r\n\r\n    public getComputeFunctionParams(): string {\r\n        let result = \"\";\r\n        let o;\r\n        let k = 0;\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n            if (!o.type.createDeclaration) {\r\n                if (k++ !== 0) result += \", \";\r\n                result += o.builtin + \" \" + o.name + \":\" + o.type;\r\n\r\n\r\n            }\r\n\r\n        }\r\n\r\n        return result;\r\n    }\r\n\r\n    public getInputFromOutput(): ShaderStruct {\r\n        if (this.name != \"Output\") return null;\r\n        return new ShaderStruct(\"Input\", this.properties.slice(1))\r\n\r\n    }\r\n\r\n    public get struct(): string {\r\n        let result = \"struct \" + this.name + \" {\\n\";\r\n        let o;\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n\r\n            if (this.isShaderIO) {\r\n                if (i > 0) o.builtin = \"@location(\" + (i - 1) + \")\";\r\n                //console.log(o.name + \" , i = \", i, \" location = \", o.builtin, \" -- \", o.builtin.length)\r\n                result += \"   \" + o.builtin + \" \" + o.name + \":\" + o.type + \",\\n\";\r\n            } else {\r\n                if (undefined !== o.size) result += \"    \" + \"@size(\" + o.size + \") @align(16) \" + o.name + \":\" + o.type + \",\\n\";\r\n                else result += \"   \" + \" \" + o.name + \":\" + o.type + \",\\n\";\r\n            }\r\n        }\r\n        result += \"}\\n\\n\";\r\n\r\n        /*\r\n        const varName = this.name.substring(0, 1).toLowerCase() + this.name.slice(1);\r\n        for (let i = 0; i < this.properties.length; i++) {\r\n            o = this.properties[i];\r\n            if (o.obj) result += o.obj.createVariable(varName) + \"\\n\";\r\n        }\r\n        */\r\n        return result;\r\n    }\r\n}"
          }
        ]
      }
    }
  }
}