From 8e0bf7dee455b4d39a823ee4e349dd33eac58a66 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Feb 2025 22:01:31 +0800 Subject: [PATCH 001/214] vertexFormatMap --- src/caches/getNGPURenderPipeline.ts | 7 +- src/types/VertexFormat.ts | 106 +--------------------------- 2 files changed, 4 insertions(+), 109 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 0690da6..1d88d9e 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { getBlendConstantColor, IBlendState, IDepthStencilState, IFragmentState, IIndicesDataTypes, IPrimitiveState, IRenderPipeline, IStencilFaceState, IVertexAttributes, IVertexState, IWriteMask } from "@feng3d/render-api"; +import { getBlendConstantColor, IBlendState, IDepthStencilState, IFragmentState, IIndicesDataTypes, IPrimitiveState, IRenderPipeline, IStencilFaceState, IVertexAttributes, IVertexState, IWriteMask, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -10,7 +10,6 @@ import { NGPUFragmentState } from "../internal/NGPUFragmentState"; import { NGPURenderPipeline } from "../internal/NGPURenderPipeline"; import { NGPUVertexBuffer } from "../internal/NGPUVertexBuffer"; import { NGPUVertexState } from "../internal/NGPUVertexState"; -import { gpuVertexFormatMap, WGSLVertexType } from "../types/VertexFormat"; import { ChainMap } from "../utils/ChainMap"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; @@ -309,11 +308,11 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: IVertexAttributes) // const wgslType = getWGSLType(v.type); // let possibleFormats = wgslVertexTypeMap[wgslType].possibleFormats; // console.assert(possibleFormats.indexOf(format) !== -1, `顶点${attributeName} 提供的数据格式 ${format} 与着色器中类型 ${wgslType} 不匹配!`); - console.assert(data.constructor.name === gpuVertexFormatMap[format].typedArrayConstructor.name, + console.assert(data.constructor.name === vertexFormatMap[format].typedArrayConstructor.name, `顶点${attributeName} 提供的数据类型 ${data.constructor.name} 与格式 ${format} 不匹配!请使用 ${data.constructor.name} 来组织数据或者更改数据格式。`); // 如果 偏移值大于 单个顶点尺寸,则该值被放入 IGPUVertexBuffer.offset。 - const vertexByteSize = gpuVertexFormatMap[format].byteSize; + const vertexByteSize = vertexFormatMap[format].byteSize; // if (!arrayStride) { diff --git a/src/types/VertexFormat.ts b/src/types/VertexFormat.ts index ff021eb..4faa9f6 100644 --- a/src/types/VertexFormat.ts +++ b/src/types/VertexFormat.ts @@ -1,109 +1,5 @@ -/** - * 有类型数组构造器。 - */ -export type TypedArrayConstructor = Int8ArrayConstructor | Uint8ArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Float32ArrayConstructor; - -/** - * GPU顶点数据类型 - */ -export type GPUVertexDataType = - | "unsigned int" - | "signed int" - | "unsigned normalized" - | "signed normalized" - | "float" - ; - -/** - * 顶点数据在WGSL中的类型。 - */ -export type WGSLVertexType = - | "vec2" - | "vec4" - | "vec2" - | "vec4" - | "vec2" - | "vec4" - | "vec2" - | "vec4" - | "f32" - | "vec3" - | "u32" - | "vec3" - | "i32" - | "vec3" - ; +import { WGSLVertexType } from "@feng3d/render-api"; -/** - * GPU顶点格式对应的信息 - */ -export type GPUVertexFormatValue = { - /** - * 数据类型。 - */ - dataType: GPUVertexDataType, - - /** - * 部件数量。 - */ - components: 1 | 2 | 3 | 4, - - /** - * 所占字节尺寸。 - */ - byteSize: 2 | 4 | 8 | 12 | 16, - - /** - * 在着色器中对应类型。 - */ - wgslType: WGSLVertexType, - - /** - * 对应类型数组构造器。 - */ - typedArrayConstructor: TypedArrayConstructor, -}; - -/** - * 顶点格式对应信息映射 - * - * 以 {@link GPUVertexFormat} 为键值。 - * - * @see https://www.orillusion.com/zh/webgpu.html#vertex-formats - */ -export const gpuVertexFormatMap: Record = { - uint8x2: { dataType: "unsigned int", components: 2, byteSize: 2, wgslType: "vec2", typedArrayConstructor: Uint8Array }, - uint8x4: { dataType: "unsigned int", components: 4, byteSize: 4, wgslType: "vec4", typedArrayConstructor: Uint8Array }, - sint8x2: { dataType: "signed int", components: 2, byteSize: 2, wgslType: "vec2", typedArrayConstructor: Int8Array }, - sint8x4: { dataType: "signed int", components: 4, byteSize: 4, wgslType: "vec4", typedArrayConstructor: Int8Array }, - unorm8x2: { dataType: "unsigned normalized", components: 2, byteSize: 2, wgslType: "vec2", typedArrayConstructor: Uint8Array }, - unorm8x4: { dataType: "unsigned normalized", components: 4, byteSize: 4, wgslType: "vec4", typedArrayConstructor: Uint8Array }, - snorm8x2: { dataType: "signed normalized", components: 2, byteSize: 2, wgslType: "vec2", typedArrayConstructor: Int8Array }, - snorm8x4: { dataType: "signed normalized", components: 4, byteSize: 4, wgslType: "vec4", typedArrayConstructor: Int8Array }, - uint16x2: { dataType: "unsigned int", components: 2, byteSize: 4, wgslType: "vec2", typedArrayConstructor: Uint16Array }, - uint16x4: { dataType: "unsigned int", components: 4, byteSize: 8, wgslType: "vec4", typedArrayConstructor: Uint16Array }, - sint16x2: { dataType: "signed int", components: 2, byteSize: 4, wgslType: "vec2", typedArrayConstructor: Int16Array }, - sint16x4: { dataType: "signed int", components: 4, byteSize: 8, wgslType: "vec4", typedArrayConstructor: Int16Array }, - unorm16x2: { dataType: "unsigned normalized", components: 2, byteSize: 4, wgslType: "vec2", typedArrayConstructor: Uint16Array }, - unorm16x4: { dataType: "unsigned normalized", components: 4, byteSize: 8, wgslType: "vec4", typedArrayConstructor: Uint16Array }, - snorm16x2: { dataType: "signed normalized", components: 2, byteSize: 4, wgslType: "vec2", typedArrayConstructor: Int16Array }, - snorm16x4: { dataType: "signed normalized", components: 4, byteSize: 8, wgslType: "vec4", typedArrayConstructor: Int16Array }, - float16x2: { dataType: "float", components: 2, byteSize: 4, wgslType: "vec2", typedArrayConstructor: undefined }, // 没有找到与之对应的 typedArrayConstructor - float16x4: { dataType: "float", components: 4, byteSize: 8, wgslType: "vec4", typedArrayConstructor: undefined }, // 没有找到与之对应的 typedArrayConstructor - float32: { dataType: "float", components: 1, byteSize: 4, wgslType: "f32", typedArrayConstructor: Float32Array }, - float32x2: { dataType: "float", components: 2, byteSize: 8, wgslType: "vec2", typedArrayConstructor: Float32Array }, - float32x3: { dataType: "float", components: 3, byteSize: 12, wgslType: "vec3", typedArrayConstructor: Float32Array }, - float32x4: { dataType: "float", components: 4, byteSize: 16, wgslType: "vec4", typedArrayConstructor: Float32Array }, - uint32: { dataType: "unsigned int", components: 1, byteSize: 4, wgslType: "u32", typedArrayConstructor: Uint32Array }, - uint32x2: { dataType: "unsigned int", components: 2, byteSize: 8, wgslType: "vec2", typedArrayConstructor: Uint32Array }, - uint32x3: { dataType: "unsigned int", components: 3, byteSize: 12, wgslType: "vec3", typedArrayConstructor: Uint32Array }, - uint32x4: { dataType: "unsigned int", components: 4, byteSize: 16, wgslType: "vec4", typedArrayConstructor: Uint32Array }, - sint32: { dataType: "signed int", components: 1, byteSize: 4, wgslType: "i32", typedArrayConstructor: Int32Array }, - sint32x2: { dataType: "signed int", components: 2, byteSize: 8, wgslType: "vec2", typedArrayConstructor: Int32Array }, - sint32x3: { dataType: "signed int", components: 3, byteSize: 12, wgslType: "vec3", typedArrayConstructor: Int32Array }, - sint32x4: { dataType: "signed int", components: 4, byteSize: 16, wgslType: "vec4", typedArrayConstructor: Int32Array }, - "unorm10-10-10-2": { dataType: "unsigned normalized", components: 4, byteSize: 4, wgslType: "vec4", typedArrayConstructor: Int32Array }, -}; /** * WGSL着色器中顶点类型对应的GPU顶点数据格式。 -- Gitee From 7bb80a06f7295b31bc73e178ea37fa2d76b08629 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Feb 2025 22:59:59 +0800 Subject: [PATCH 002/214] IRenderObject.draw: IDrawVertex | IDrawIndexed --- .../src/webgpu/RenderObjectChanges/index.ts | 4 ++-- examples/src/webgpu/a-buffer/index.ts | 6 +++--- examples/src/webgpu/animometer/index.ts | 2 +- examples/src/webgpu/bitonicSort/utils.ts | 2 +- examples/src/webgpu/blending/index.ts | 4 ++-- examples/src/webgpu/cameras/index.ts | 2 +- examples/src/webgpu/computeBoids/index.ts | 2 +- examples/src/webgpu/cornell/rasterizer.ts | 2 +- examples/src/webgpu/cubemap/index.ts | 2 +- examples/src/webgpu/deferredRendering/index.ts | 6 +++--- examples/src/webgpu/fractalCube/index.ts | 2 +- examples/src/webgpu/gameOfLife/index.ts | 2 +- examples/src/webgpu/helloTriangle/index.ts | 4 ++-- examples/src/webgpu/helloTriangleMSAA/index.ts | 2 +- examples/src/webgpu/imageBlur/index.ts | 2 +- examples/src/webgpu/instancedCube/index.ts | 2 +- examples/src/webgpu/multipleCanvases/index.ts | 2 +- examples/src/webgpu/normalMap/index.ts | 2 +- examples/src/webgpu/occlusionQuery/index.ts | 2 +- examples/src/webgpu/particles/index.ts | 2 +- examples/src/webgpu/points/index.ts | 2 +- examples/src/webgpu/renderBundles/index.ts | 2 +- examples/src/webgpu/resizeCanvas/index.ts | 2 +- .../src/webgpu/resizeObserverHDDPI/index.ts | 2 +- examples/src/webgpu/reversedZ/index.ts | 10 +++++----- examples/src/webgpu/rotatingCube/index.ts | 2 +- examples/src/webgpu/samplerParameters/index.ts | 10 +++++----- examples/src/webgpu/shadowMapping/index.ts | 4 ++-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 18 ++++++++---------- examples/src/webgpu/skinnedMesh/index.ts | 2 +- examples/src/webgpu/textRenderingMsdf/index.ts | 2 +- .../src/webgpu/textRenderingMsdf/msdfText.ts | 2 +- examples/src/webgpu/texturedCube/index.ts | 2 +- examples/src/webgpu/timestampQuery/index.ts | 2 +- examples/src/webgpu/transparentCanvas/index.ts | 2 +- examples/src/webgpu/twoCubes/index.ts | 2 +- examples/src/webgpu/videoUploading/index.ts | 2 +- .../webgpu/volumeRenderingTexture3D/index.ts | 2 +- examples/src/webgpu/wireframe/index.ts | 4 ++-- examples/src/webgpu/worker/worker.ts | 2 +- src/runs/RunWebGPU.ts | 14 +++++++++----- 41 files changed, 73 insertions(+), 71 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index 2c9d14f..e7c5c63 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -33,8 +33,8 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 }, indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 - uniforms: { color: [1, 0, 0, 0] }, // Uniform 颜色值。 - drawIndexed: { indexCount: 3 }, // 绘制命令 + uniforms: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 + draw: { __type: "DrawIndexed", indexCount: 3 }, // 绘制命令 }; const submit: ISubmit = { // 一次GPU提交 diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index cc774ca..a8b19e6 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -290,7 +290,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uniforms: bindingResources, vertices, indices, - drawIndexed: { indexCount: mesh.triangles.length * 3, instanceCount: 8 }, + draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, }] }; passEncoders.push(opaquePassEncoder); @@ -326,7 +326,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, vertices, indices, - drawIndexed: { indexCount: mesh.triangles.length * 3, instanceCount: 8 }, + draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, } ], }; @@ -345,7 +345,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...bindingResources, sliceInfo: sliceInfoBuffer[slice] }, - drawVertex: { vertexCount: 6 }, + draw: { __type: "DrawVertex", vertexCount: 6 }, } ] }; diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index 1694cfa..f7fd66b 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -63,7 +63,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => color: { data: vertexBuffer, format: "float32x4", offset: vec4Size, arrayStride: 2 * vec4Size }, }, uniforms: {}, - drawVertex: { vertexCount: 3, instanceCount: 1 }, + draw: { __type: "DrawVertex", vertexCount: 3, instanceCount: 1 }, }; const uniformBytes = 5 * Float32Array.BYTES_PER_ELEMENT; diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index a9f4d09..d204917 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -59,7 +59,7 @@ export abstract class Base2DRendererClass renderObjects: [{ pipeline, uniforms: bindingResources, - drawVertex: { vertexCount: 6, instanceCount: 1 } + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1 } }], }; commandEncoder.passEncoders.push(passEncoder); diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index e23096c..263969c 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -506,13 +506,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const ro: IRenderObject = { pipeline: dstPipeline, uniforms: dstBindGroup, - drawVertex: { vertexCount: 6 }, + draw: { __type: "DrawVertex", vertexCount: 6 }, }; const ro1: IRenderObject = { pipeline: srcPipeline, uniforms: srcBindGroup, - drawVertex: { vertexCount: 6 }, + draw: { __type: "DrawVertex", vertexCount: 6 }, }; const renderObjects: IRenderPassObject[] = [ diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index 796f892..f804033 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -100,7 +100,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline, vertices, uniforms: bindingResources, - drawVertex: { vertexCount: cubeVertexCount }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }; const renderPassDescriptor: IRenderPassDescriptor = { diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index e380a98..7ede543 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -102,7 +102,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => a_particleVel: { data: particleBuffers[0], format: "float32x2", offset: 2 * 4, arrayStride: 4 * 4, stepMode: "instance" }, a_pos: { data: vertexBufferData, format: "float32x2" }, }, - drawVertex: { vertexCount: 3, instanceCount: numParticles } + draw: { __type: "DrawVertex", vertexCount: 3, instanceCount: numParticles } }; const renderObject1: IRenderObject = { diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index 99d6dad..0ad5109 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -85,7 +85,7 @@ export default class Rasterizer ...this.common.uniforms.bindGroup, ...this.bindGroup, }, - drawIndexed: { indexCount: this.scene.indexCount }, + draw: { __type: "DrawIndexed", indexCount: this.scene.indexCount }, }], }; } diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index bd1bf86..1329432 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -137,7 +137,7 @@ const init = async (canvas: HTMLCanvasElement) => mySampler: sampler, myTexture: { texture: cubemapTexture }, }, - drawVertex: { vertexCount: cubeVertexCount }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }; function frame() diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 5369240..bd08ea1 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -336,7 +336,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, vertices, indices: indexBuffer, - drawIndexed: { indexCount }, + draw: { __type: "DrawIndexed", indexCount }, }, ] }); @@ -363,7 +363,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uniforms: { ...gBufferTexturesBindGroup, }, - drawVertex: { vertexCount: 6 }, + draw: { __type: "DrawVertex", vertexCount: 6 }, }, ] }); @@ -377,7 +377,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...gBufferTexturesBindGroup, ...lightsBufferBindGroup, }, - drawVertex: { vertexCount: 6 }, + draw: { __type: "DrawVertex", vertexCount: 6 }, }, ] }); diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index f0ab182..9d5eb7d 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -94,7 +94,7 @@ const init = async (canvas: HTMLCanvasElement) => mySampler: sampler, myTexture: { texture: cubeTexture }, }, - drawVertex: { vertexCount: cubeVertexCount }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }; const copyTextureToTexture: ICopyTextureToTexture = { diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 7297020..ab73874 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -139,7 +139,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: renderPipeline, uniforms: uniformBindGroup, vertices: vertices1, - drawVertex: { vertexCount: 4, instanceCount: length }, + draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: length }, } ], } diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 808fa7c..1c6df8d 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -44,8 +44,8 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 }, indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 - uniforms: { color: [1, 0, 0, 0] }, // Uniform 颜色值。 - drawIndexed: { indexCount: 3 }, // 绘制命令 + uniforms: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 + draw: { __type: "DrawIndexed", indexCount: 3 }, // 绘制命令 }] }, ] diff --git a/examples/src/webgpu/helloTriangleMSAA/index.ts b/examples/src/webgpu/helloTriangleMSAA/index.ts index fa8ab80..de8b318 100644 --- a/examples/src/webgpu/helloTriangleMSAA/index.ts +++ b/examples/src/webgpu/helloTriangleMSAA/index.ts @@ -24,7 +24,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, - drawVertex: { vertexCount: 3 }, + draw: { __type: "DrawVertex", vertexCount: 3 }, }; function frame() diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 57c56fd..c1d748e 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -145,7 +145,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [{ pipeline: fullscreenQuadPipeline1, uniforms: showResultBindGroup1, - drawVertex: { vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, }], }; diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 9f22a3b..5897ef6 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -117,7 +117,7 @@ const init = async (canvas: HTMLCanvasElement) => modelViewProjectionMatrix: mvpMatricesData }, }, - drawVertex: { vertexCount: cubeVertexCount, instanceCount: numInstances } + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: numInstances } }; const data: ISubmit = { diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index e9578c3..ae39bc3 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -322,7 +322,7 @@ const init = async () => vertices: vertexAttributes, indices, uniforms: bindGroup, - drawIndexed: { indexCount: indices.length }, + draw: { __type: "DrawIndexed", indexCount: indices.length }, }], }); }); diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index 148b503..00b5aa8 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -332,7 +332,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, indices: box.indices, uniforms: bindingResourcesList[currentSurfaceBindGroup], - drawIndexed: { indexCount: box.indices.length }, + draw: { __type: "DrawIndexed", indexCount: box.indices.length }, }], }] }] diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index f96df9d..a896754 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -138,7 +138,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => bufferView: undefined, }, }, - drawIndexed: { indexCount: indices.length }, + draw: { __type: "DrawIndexed", indexCount: indices.length }, }; const renderObjects: IRenderObject[] = objectInfos.map((v) => diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index b6279e9..f0eb766 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -293,7 +293,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: renderPipeline, uniforms: { ...uniformBindGroup }, vertices: { ...particlesVertices, ...quadVertices }, - drawVertex: { vertexCount: 6, instanceCount: numParticles, firstVertex: 0, firstInstance: 0 }, + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: numParticles, firstVertex: 0, firstInstance: 0 }, }], } ); diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index fd37df3..7d204f9 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -201,7 +201,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline, vertices, uniforms: bindingResources, - drawVertex: { vertexCount: 6, instanceCount: kNumPoints }, + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, }] } ] diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 913623c..5e2c794 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -261,7 +261,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => uniforms: { ...frameBindGroup, ...renderable.bindGroup }, vertices: renderable.vertexAttributes, indices: renderable.indices, - drawIndexed: { indexCount: renderable.indexCount }, + draw: { __type: "DrawIndexed", indexCount: renderable.indexCount }, }; } diff --git a/examples/src/webgpu/resizeCanvas/index.ts b/examples/src/webgpu/resizeCanvas/index.ts index a5f4910..c20add7 100644 --- a/examples/src/webgpu/resizeCanvas/index.ts +++ b/examples/src/webgpu/resizeCanvas/index.ts @@ -22,7 +22,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, - drawVertex: { vertexCount: 3 }, + draw: { __type: "DrawVertex", vertexCount: 3 }, }; canvas.classList.add(styles.animatedCanvasSize); diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index 84c2699..b153026 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -106,7 +106,7 @@ return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); renderObjects: [{ pipeline, uniforms: bindGroup, - drawVertex: { vertexCount: 3 }, + draw: { __type: "DrawVertex", vertexCount: 3 }, }] }] }] diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 7004551..9451a5e 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -378,7 +378,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: colorPassPipelines[m], uniforms: { ...uniformBindGroups[m] }, vertices, - drawVertex: { vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, }] }); } @@ -400,7 +400,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, vertices, - drawVertex: { vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, }] }); precisionErrorPassEncoders.push({ @@ -417,7 +417,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: precisionPassPipelines[m], uniforms: { ...uniformBindGroups[m], ...depthTextureBindGroup }, vertices, - drawVertex: { vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, }] }); } @@ -439,7 +439,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, vertices, - drawVertex: { vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, }] }); depthBufferPassEncoders.push({ @@ -449,7 +449,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: textureQuadPassPipline, uniforms: { ...depthTextureBindGroup }, - drawVertex: { vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, }] }); } diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index bd2fff0..2bd26fa 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement) => uniforms: { uniforms, }, - drawVertex: { vertexCount: cubeVertexCount }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }; const aspect = canvas.width / canvas.height; diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index db9a6f9..4d43f89 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -323,7 +323,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: vpX, y: vpY, width: kViewportSize, height: kViewportSize, minDepth: 0, maxDepth: 1 }, pipeline: texturedSquarePipeline, uniforms: bindingResources0, - drawVertex: { vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } } ); } @@ -337,7 +337,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: kLastViewport, y: kLastViewport, width: 32, height: 32, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - drawVertex: { vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } } ); renderObjects.push( @@ -345,7 +345,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport, width: 16, height: 16, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - drawVertex: { vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } } ); renderObjects.push( @@ -353,7 +353,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 16, width: 8, height: 8, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - drawVertex: { vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } } ); renderObjects.push( @@ -361,7 +361,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 24, width: 4, height: 4, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - drawVertex: { vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } } ); diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 95c68d5..e608770 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -228,7 +228,7 @@ const init = async (canvas: HTMLCanvasElement) => }, vertices, indices: indexBuffer, - drawIndexed: { indexCount }, + draw: { __type: "DrawIndexed", indexCount }, }, ] }, @@ -243,7 +243,7 @@ const init = async (canvas: HTMLCanvasElement) => }, vertices, indices: indexBuffer, - drawIndexed: { indexCount }, + draw: { __type: "DrawIndexed", indexCount }, } ], } diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 304b90d..5ae43e8 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,8 +1,8 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { IBuffer, IDrawIndexed, IDrawVertex, IFragmentState, IPrimitiveState, IRenderObject, IRenderPipeline, IUniforms, IVertexAttributes, IVertexState } from "@feng3d/render-api"; -import { getIGPUBuffer, gpuVertexFormatMap } from "@feng3d/webgpu"; +import { IBuffer, IDraw, IFragmentState, IPrimitiveState, IRenderObject, IRenderPipeline, IUniforms, IVertexAttributes, IVertexState, vertexFormatMap } from "@feng3d/render-api"; +import { getIGPUBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models // Modified from Will Usher code found at this link https://www.willusher.io/graphics/2023/05/16/0-to-gltf-first-mesh @@ -369,7 +369,7 @@ export class GLTFPrimitive const vertexFormat: GPUVertexFormat = this.attributeMap[attr].vertexType; const attrString = attr.toLowerCase().replace(/_0$/, ""); - const Cls = gpuVertexFormatMap[vertexFormat].typedArrayConstructor; + const Cls = vertexFormatMap[vertexFormat].typedArrayConstructor; const data = new Cls(view.buffer, view.byteOffset, view.byteLength / Cls.BYTES_PER_ELEMENT); @@ -454,19 +454,18 @@ export class GLTFPrimitive render(renderObjects: IRenderObject[], bindingResources: IUniforms) { - let drawIndexed: IDrawIndexed; - let drawVertex: IDrawVertex; + let draw: IDraw; if (this.indices) { - drawIndexed = { indexCount: this.indices.length }; + draw = { __type: "DrawIndexed", indexCount: this.indices.length }; } else { const vertexAttribute = this.vertices[Object.keys(this.vertices)[0]]; - const vertexCount = vertexAttribute.data.byteLength / gpuVertexFormatMap[vertexAttribute.format].byteSize; + const vertexCount = vertexAttribute.data.byteLength / vertexFormatMap[vertexAttribute.format].byteSize; - drawVertex = { vertexCount }; + draw = { __type: "DrawVertex", vertexCount }; } const renderObject: IRenderObject = { @@ -475,8 +474,7 @@ export class GLTFPrimitive //if skin do something with bone bind group vertices: this.vertices, indices: this.indices, - drawVertex, - drawIndexed, + draw, }; renderObjects.push(renderObject); } diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index e48f69c..161835e 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -517,7 +517,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, vertices: skinnedGridVertexBuffers.vertices, indices: skinnedGridVertexBuffers.indices, - drawIndexed: { indexCount: gridIndices.length }, + draw: { __type: "DrawIndexed", indexCount: gridIndices.length }, }; // passEncoders.push({ diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index b3d6523..effe2e8 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -263,7 +263,7 @@ setBlendConstant().`, pipeline, uniforms: uniformBindGroup, vertices: verticesBuffer, - drawVertex: { vertexCount: cubeVertexCount, instanceCount: 1 }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: 1 }, }); textRenderer.render(renderObjects, ...text); diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index a84fb44..a541713 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -347,7 +347,7 @@ export class MsdfTextRenderer ...font.bindGroup, ...bindGroup, }, - drawVertex: { vertexCount: 4, instanceCount: measurements.printedCharCount }, + draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: measurements.printedCharCount }, } ], }; diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index f3132c5..fc60aa8 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -68,7 +68,7 @@ const init = async (canvas: HTMLCanvasElement) => mySampler: sampler, myTexture: { texture: cubeTexture }, }, - drawVertex: { vertexCount: cubeVertexCount }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }; const aspect = canvas.width / canvas.height; diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 7488827..4579b79 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -115,7 +115,7 @@ const init = async (canvas: HTMLCanvasElement) => uniforms: { uniforms, }, - drawVertex: { vertexCount: cubeVertexCount }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }; const submit: ISubmit = { diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index c8284a4..1512079 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -109,7 +109,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline, uniforms: uniformBindGroup, vertices: verticesBuffer, - drawVertex: { vertexCount: cubeVertexCount }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }] }] }] diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index 60dea74..d6c39d3 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -56,7 +56,7 @@ const init = async (canvas: HTMLCanvasElement) => uniforms: { uniforms, }, - drawVertex: { vertexCount: cubeVertexCount }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }; const uniforms1: IBufferBinding = { diff --git a/examples/src/webgpu/videoUploading/index.ts b/examples/src/webgpu/videoUploading/index.ts index aa46a83..d979336 100644 --- a/examples/src/webgpu/videoUploading/index.ts +++ b/examples/src/webgpu/videoUploading/index.ts @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement) => source: video, }, }, - drawVertex: { vertexCount: 6 }, + draw: { __type: "DrawVertex", vertexCount: 6 }, }; function frame() diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index b86fc57..1704e99 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -163,7 +163,7 @@ const init = async (canvas: HTMLCanvasElement) => renderObjects: [{ pipeline, uniforms: uniformBindGroup, - drawVertex: { vertexCount: 3 }, + draw: { __type: "DrawVertex", vertexCount: 3 }, }], }] }] diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index b0156f7..8b46c0c 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -331,7 +331,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => vertices: vertexAttributes, indices, uniforms: litBindGroup, - drawIndexed: { indexCount: indices.length }, + draw: { __type: "DrawIndexed", indexCount: indices.length }, }); } } @@ -351,7 +351,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push({ pipeline, uniforms: wireframeBindGroups[bindGroupNdx], - drawVertex: { vertexCount: indices.length * countMult }, + draw: { __type: "DrawVertex", vertexCount: indices.length * countMult }, }); }); } diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 4396556..3836d34 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -157,7 +157,7 @@ async function init(canvas: OffscreenCanvas) pipeline, uniforms: uniformBindGroup, vertices: verticesBuffer, - drawVertex: { vertexCount: cubeVertexCount } + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount } }] }] }] diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 9134abe..a8ae20d 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -26,7 +26,6 @@ import { GPUQueue_submit } from "../eventnames"; import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; import { getIGPUSetIndexBuffer } from "../internal/getIGPUSetIndexBuffer"; import { ChainMap } from "../utils/ChainMap"; -import { watcher } from "@feng3d/watcher"; export class RunWebGPU { @@ -300,7 +299,7 @@ export class RunWebGPU */ protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: IRenderObject) { - const { viewport, scissorRect, pipeline, vertices, indices, uniforms: bindingResources, drawVertex, drawIndexed } = renderObject; + const { viewport, scissorRect, pipeline, vertices, indices, uniforms: bindingResources, draw } = renderObject; const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; @@ -321,9 +320,14 @@ export class RunWebGPU this.runIndices(device, passEncoder, indices); - this.runDrawVertex(passEncoder, drawVertex); - - this.runDrawIndexed(passEncoder, drawIndexed); + if (draw.__type === 'DrawVertex') + { + this.runDrawVertex(passEncoder, draw); + } + else + { + this.runDrawIndexed(passEncoder, draw); + } } protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, vertices: IVertexAttributes, indices: IIndicesDataTypes) -- Gitee From 4eb6743e6716b43f3cb0a5752517d09d3593ae2b Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Feb 2025 23:01:53 +0800 Subject: [PATCH 003/214] gpuFragmentState && --- src/caches/getNGPURenderPipeline.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 1d88d9e..39de1d2 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -71,10 +71,10 @@ export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPas renderPipeline._version = ~~renderPipeline._version + 1; renderPipelineMap.delete([renderPipeline, renderPassFormat._key, vertices, indexFormat]); watcher.unwatch(vertexStateResult, "_version", onchanged); - watcher.unwatch(gpuFragmentState, "_version", onchanged); + gpuFragmentState && watcher.unwatch(gpuFragmentState, "_version", onchanged); } watcher.watch(vertexStateResult, "_version", onchanged); - watcher.watch(gpuFragmentState, "_version", onchanged); + gpuFragmentState && watcher.watch(gpuFragmentState, "_version", onchanged); return result; } -- Gitee From 716950c93a95bccbfef0f48b1f1d769d73c6d0d7 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Feb 2025 23:38:40 +0800 Subject: [PATCH 004/214] IRenderObject.geometry: IGeometry --- .../src/webgpu/RenderObjectChanges/index.ts | 10 +++-- examples/src/webgpu/a-buffer/index.ts | 20 ++++++---- examples/src/webgpu/animometer/index.ts | 12 +++--- examples/src/webgpu/bitonicSort/utils.ts | 4 +- examples/src/webgpu/blending/index.ts | 8 +++- examples/src/webgpu/cameras/index.ts | 6 ++- examples/src/webgpu/computeBoids/index.ts | 37 +++++++++++-------- examples/src/webgpu/cornell/rasterizer.ts | 8 ++-- examples/src/webgpu/cubemap/index.ts | 12 +++--- .../src/webgpu/deferredRendering/index.ts | 16 +++++--- examples/src/webgpu/fractalCube/index.ts | 10 +++-- examples/src/webgpu/gameOfLife/index.ts | 6 ++- examples/src/webgpu/helloTriangle/index.ts | 10 +++-- .../src/webgpu/helloTriangleMSAA/index.ts | 4 +- examples/src/webgpu/imageBlur/index.ts | 20 +++++----- examples/src/webgpu/instancedCube/index.ts | 10 +++-- examples/src/webgpu/multipleCanvases/index.ts | 12 +++--- examples/src/webgpu/normalMap/index.ts | 22 ++++++----- examples/src/webgpu/occlusionQuery/index.ts | 14 ++++--- examples/src/webgpu/particles/index.ts | 12 +++--- examples/src/webgpu/points/index.ts | 6 ++- examples/src/webgpu/renderBundles/index.ts | 16 ++++---- examples/src/webgpu/resizeCanvas/index.ts | 4 +- .../src/webgpu/resizeObserverHDDPI/index.ts | 4 +- examples/src/webgpu/reversedZ/index.ts | 28 +++++++++----- examples/src/webgpu/rotatingCube/index.ts | 10 +++-- .../src/webgpu/samplerParameters/index.ts | 20 +++++++--- examples/src/webgpu/shadowMapping/index.ts | 16 +++++--- examples/src/webgpu/skinnedMesh/glbUtils.ts | 8 ++-- examples/src/webgpu/skinnedMesh/index.ts | 8 ++-- .../src/webgpu/textRenderingMsdf/index.ts | 6 ++- .../src/webgpu/textRenderingMsdf/msdfText.ts | 4 +- examples/src/webgpu/texturedCube/index.ts | 12 +++--- examples/src/webgpu/timestampQuery/index.ts | 6 ++- .../src/webgpu/transparentCanvas/index.ts | 6 ++- examples/src/webgpu/twoCubes/index.ts | 12 +++--- examples/src/webgpu/videoUploading/index.ts | 4 +- .../webgpu/volumeRenderingTexture3D/index.ts | 4 +- examples/src/webgpu/wireframe/index.ts | 12 ++++-- examples/src/webgpu/worker/worker.ts | 6 ++- src/runs/RunWebGPU.ts | 4 +- src/utils/quitIfWebGPUNotAvailable.ts | 5 +++ 42 files changed, 287 insertions(+), 167 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index e7c5c63..786a4e6 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -29,12 +29,14 @@ const init = async (canvas: HTMLCanvasElement) => } ` }, }, - vertices: { - position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 + geometry:{ + vertices: { + position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 + }, + indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 + draw: { __type: "DrawIndexed", indexCount: 3 }, // 绘制命令 }, - indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 uniforms: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 - draw: { __type: "DrawIndexed", indexCount: 3 }, // 绘制命令 }; const submit: ISubmit = { // 一次GPU提交 diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index a8b19e6..1927c39 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -288,9 +288,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [{ pipeline: opaquePipeline, uniforms: bindingResources, - vertices, - indices, - draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, + geometry: { + vertices, + indices, + draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, + } }] }; passEncoders.push(opaquePassEncoder); @@ -324,9 +326,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...bindingResources, sliceInfo: sliceInfoBuffer[slice], }, - vertices, - indices, - draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, + geometry: { + vertices, + indices, + draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, + } } ], }; @@ -345,7 +349,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...bindingResources, sliceInfo: sliceInfoBuffer[slice] }, - draw: { __type: "DrawVertex", vertexCount: 6 }, + geometry: { + draw: { __type: "DrawVertex", vertexCount: 6 }, + } } ] }; diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index f7fd66b..3044b80 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -58,12 +58,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: IRenderObject = { pipeline, - vertices: { - position: { data: vertexBuffer, format: "float32x4", offset: 0, arrayStride: 2 * vec4Size }, - color: { data: vertexBuffer, format: "float32x4", offset: vec4Size, arrayStride: 2 * vec4Size }, - }, uniforms: {}, - draw: { __type: "DrawVertex", vertexCount: 3, instanceCount: 1 }, + geometry: { + vertices: { + position: { data: vertexBuffer, format: "float32x4", offset: 0, arrayStride: 2 * vec4Size }, + color: { data: vertexBuffer, format: "float32x4", offset: vec4Size, arrayStride: 2 * vec4Size }, + }, + draw: { __type: "DrawVertex", vertexCount: 3, instanceCount: 1 }, + }, }; const uniformBytes = 5 * Float32Array.BYTES_PER_ELEMENT; diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index d204917..c463807 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -59,7 +59,9 @@ export abstract class Base2DRendererClass renderObjects: [{ pipeline, uniforms: bindingResources, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1 } + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1 } + } }], }; commandEncoder.passEncoders.push(passEncoder); diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 263969c..e68a050 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -506,13 +506,17 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const ro: IRenderObject = { pipeline: dstPipeline, uniforms: dstBindGroup, - draw: { __type: "DrawVertex", vertexCount: 6 }, + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 6 }, + } }; const ro1: IRenderObject = { pipeline: srcPipeline, uniforms: srcBindGroup, - draw: { __type: "DrawVertex", vertexCount: 6 }, + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 6 }, + } }; const renderObjects: IRenderPassObject[] = [ diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index f804033..41c2e93 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -98,9 +98,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: IRenderObject = { pipeline, - vertices, uniforms: bindingResources, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + geometry:{ + vertices, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + } }; const renderPassDescriptor: IRenderPassDescriptor = { diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index 7ede543..de39953 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -97,27 +97,32 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullFace: "back", }, }, - vertices: { - a_particlePos: { data: particleBuffers[0], format: "float32x2", offset: 0, arrayStride: 4 * 4, stepMode: "instance" }, - a_particleVel: { data: particleBuffers[0], format: "float32x2", offset: 2 * 4, arrayStride: 4 * 4, stepMode: "instance" }, - a_pos: { data: vertexBufferData, format: "float32x2" }, - }, - draw: { __type: "DrawVertex", vertexCount: 3, instanceCount: numParticles } + geometry: { + vertices: { + a_particlePos: { data: particleBuffers[0], format: "float32x2", offset: 0, arrayStride: 4 * 4, stepMode: "instance" }, + a_particleVel: { data: particleBuffers[0], format: "float32x2", offset: 2 * 4, arrayStride: 4 * 4, stepMode: "instance" }, + a_pos: { data: vertexBufferData, format: "float32x2" }, + }, + draw: { __type: "DrawVertex", vertexCount: 3, instanceCount: numParticles } + } }; const renderObject1: IRenderObject = { ...renderObject, - vertices: { - ...renderObject.vertices, - a_particlePos: { - ...renderObject.vertices.a_particlePos, - data: particleBuffers[1], + geometry: { + ...renderObject.geometry, + vertices: { + ...renderObject.geometry.vertices, + a_particlePos: { + ...renderObject.geometry.vertices.a_particlePos, + data: particleBuffers[1], + }, + a_particleVel: { + ...renderObject.geometry.vertices.a_particleVel, + data: particleBuffers[1], + }, }, - a_particleVel: { - ...renderObject.vertices.a_particleVel, - data: particleBuffers[1], - }, - }, + } }; let t = 0; diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index 0ad5109..b146059 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -79,13 +79,15 @@ export default class Rasterizer descriptor: this.renderPassDescriptor, renderObjects: [{ pipeline: this.pipeline, - vertices: this.scene.vertexAttributes, - indices: this.scene.indices, uniforms: { ...this.common.uniforms.bindGroup, ...this.bindGroup, }, - draw: { __type: "DrawIndexed", indexCount: this.scene.indexCount }, + geometry: { + vertices: this.scene.vertexAttributes, + indices: this.scene.indices, + draw: { __type: "DrawIndexed", indexCount: this.scene.indexCount }, + }, }], }; } diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index 1329432..c21af1b 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -126,10 +126,6 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "none", }, }, - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, - }, uniforms: { uniforms: { modelViewProjectionMatrix: new Float32Array(16) @@ -137,7 +133,13 @@ const init = async (canvas: HTMLCanvasElement) => mySampler: sampler, myTexture: { texture: cubemapTexture }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + geometry: { + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + } }; function frame() diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index bd08ea1..3687892 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -334,9 +334,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uniforms: { ...sceneUniformBindGroup, }, - vertices, - indices: indexBuffer, - draw: { __type: "DrawIndexed", indexCount }, + geometry: { + vertices, + indices: indexBuffer, + draw: { __type: "DrawIndexed", indexCount }, + } }, ] }); @@ -363,7 +365,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uniforms: { ...gBufferTexturesBindGroup, }, - draw: { __type: "DrawVertex", vertexCount: 6 }, + geometry: { + draw: { __type: "DrawVertex", vertexCount: 6 }, + } }, ] }); @@ -377,7 +381,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...gBufferTexturesBindGroup, ...lightsBufferBindGroup, }, - draw: { __type: "DrawVertex", vertexCount: 6 }, + geometry: { + draw: { __type: "DrawVertex", vertexCount: 6 }, + }, }, ] }); diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 9d5eb7d..173042d 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -83,9 +83,12 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, }, - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + geometry: { + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }, uniforms: { uniforms: { @@ -94,7 +97,6 @@ const init = async (canvas: HTMLCanvasElement) => mySampler: sampler, myTexture: { texture: cubeTexture }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }; const copyTextureToTexture: ICopyTextureToTexture = { diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index ab73874..fe23423 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -138,8 +138,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { pipeline: renderPipeline, uniforms: uniformBindGroup, - vertices: vertices1, - draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: length }, + geometry:{ + vertices: vertices1, + draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: length }, + } } ], } diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 1c6df8d..9f69ea4 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -40,12 +40,14 @@ const init = async (canvas: HTMLCanvasElement) => } ` }, }, - vertices: { - position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 + geometry: { + vertices: { + position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 + }, + indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 + draw: { __type: "DrawIndexed", indexCount: 3 }, // 绘制命令 }, - indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 uniforms: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 - draw: { __type: "DrawIndexed", indexCount: 3 }, // 绘制命令 }] }, ] diff --git a/examples/src/webgpu/helloTriangleMSAA/index.ts b/examples/src/webgpu/helloTriangleMSAA/index.ts index de8b318..28be374 100644 --- a/examples/src/webgpu/helloTriangleMSAA/index.ts +++ b/examples/src/webgpu/helloTriangleMSAA/index.ts @@ -24,7 +24,9 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, - draw: { __type: "DrawVertex", vertexCount: 3 }, + geometry: { + draw: { __type: "DrawVertex", vertexCount: 3 }, + }, }; function frame() diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index c1d748e..44a3cf7 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -66,14 +66,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const blurParamsBuffer = new Uint8Array(8); - const computeConstants: IUniforms = { + const computeConstants: IUniforms = { samp: sampler, params: { bufferView: blurParamsBuffer, }, }; - const computeBindGroup0: IUniforms = { + const computeBindGroup0: IUniforms = { inputTex: { texture: cubeTexture1 }, outputTex: { texture: textures[0] }, flip: { @@ -81,7 +81,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; - const computeBindGroup1: IUniforms = { + const computeBindGroup1: IUniforms = { inputTex: { texture: textures[0] }, outputTex: { texture: textures[1] }, flip: { @@ -89,7 +89,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const computeBindGroup2: IUniforms = { + const computeBindGroup2: IUniforms = { inputTex: { texture: textures[1] }, outputTex: { texture: textures[0] }, flip: { @@ -97,7 +97,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const showResultBindGroup1: IUniforms = { + const showResultBindGroup1: IUniforms = { mySampler: sampler, myTexture: { texture: textures[1] }, }; @@ -145,7 +145,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [{ pipeline: fullscreenQuadPipeline1, uniforms: showResultBindGroup1, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, + geometry: { + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, + }, }], }; @@ -161,15 +163,15 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ] }; - const bindingResources0: IUniforms = { + const bindingResources0: IUniforms = { ...computeConstants, ...computeBindGroup0, }; - const bindingResources1: IUniforms = { + const bindingResources1: IUniforms = { ...computeConstants, ...computeBindGroup1, }; - const bindingResources2: IUniforms = { + const bindingResources2: IUniforms = { ...computeConstants, ...computeBindGroup2, }; diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 5897ef6..a5080dd 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -108,16 +108,18 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, }, - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + geometry: { + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: numInstances } }, uniforms: { uniforms: { modelViewProjectionMatrix: mvpMatricesData }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: numInstances } }; const data: ISubmit = { diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index ae39bc3..d027d8f 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -172,7 +172,7 @@ const init = async () => worldViewProjectionMatrixValue: Float32Array; worldMatrixValue: Float32Array; uniformValues: Float32Array; - bindGroup: IUniforms; + bindGroup: IUniforms; rotation: number; model: Model; renderPassDescriptor?: IRenderPassDescriptor @@ -224,7 +224,7 @@ const init = async () => colorValue.set(randColor()); // Make a bind group for this uniform - const bindGroup: IUniforms = { + const bindGroup: IUniforms = { uni: { bufferView: uniformValues, worldViewProjectionMatrix: undefined, @@ -319,10 +319,12 @@ const init = async () => descriptor: renderPassDescriptor, renderObjects: [{ pipeline, - vertices: vertexAttributes, - indices, uniforms: bindGroup, - draw: { __type: "DrawIndexed", indexCount: indices.length }, + geometry: { + vertices: vertexAttributes, + indices, + draw: { __type: "DrawIndexed", indexCount: indices.length }, + }, }], }); }); diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index 00b5aa8..4b0ef94 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -318,21 +318,23 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: renderPassDescriptor, renderObjects: [{ pipeline: texturedCubePipeline, + uniforms: bindingResourcesList[currentSurfaceBindGroup], // * position : float32x3 // * normal : float32x3 // * uv : float32x2 // * tangent : float32x3 // * bitangent : float32x3 - vertices: { - position: { data: box.vertices, offset: 0, format: "float32x3", arrayStride: box.vertexStride }, - normal: { data: box.vertices, offset: 12, format: "float32x3", arrayStride: box.vertexStride }, - uv: { data: box.vertices, offset: 24, format: "float32x2", arrayStride: box.vertexStride }, - vert_tan: { data: box.vertices, offset: 32, format: "float32x3", arrayStride: box.vertexStride }, - vert_bitan: { data: box.vertices, offset: 44, format: "float32x3", arrayStride: box.vertexStride }, - }, - indices: box.indices, - uniforms: bindingResourcesList[currentSurfaceBindGroup], - draw: { __type: "DrawIndexed", indexCount: box.indices.length }, + geometry: { + vertices: { + position: { data: box.vertices, offset: 0, format: "float32x3", arrayStride: box.vertexStride }, + normal: { data: box.vertices, offset: 12, format: "float32x3", arrayStride: box.vertexStride }, + uv: { data: box.vertices, offset: 24, format: "float32x2", arrayStride: box.vertexStride }, + vert_tan: { data: box.vertices, offset: 32, format: "float32x3", arrayStride: box.vertexStride }, + vert_bitan: { data: box.vertices, offset: 44, format: "float32x3", arrayStride: box.vertexStride }, + }, + indices: box.indices, + draw: { __type: "DrawIndexed", indexCount: box.indices.length }, + } }], }] }] diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index a896754..243c8bc 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -128,17 +128,19 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: IRenderObject = { pipeline, - vertices: { - position: { data: vertexBuf, offset: 0, arrayStride: 6 * 4, format: "float32x3" }, - normal: { data: vertexBuf, offset: 12, arrayStride: 6 * 4, format: "float32x3" }, + geometry: { + vertices: { + position: { data: vertexBuf, offset: 0, arrayStride: 6 * 4, format: "float32x3" }, + normal: { data: vertexBuf, offset: 12, arrayStride: 6 * 4, format: "float32x3" }, + }, + indices, + draw: { __type: "DrawIndexed", indexCount: indices.length }, }, - indices, uniforms: { uni: { bufferView: undefined, }, }, - draw: { __type: "DrawIndexed", indexCount: indices.length }, }; const renderObjects: IRenderObject[] = objectInfos.map((v) => @@ -156,7 +158,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); const occlusionQueryObjects: IGPUOcclusionQuery[] = renderObjects.map((ro) => - ({ __type: "OcclusionQuery", renderObjects: [ro] })); + ({ __type: "OcclusionQuery", renderObjects: [ro] })); const renderPass: IRenderPass = { descriptor: renderPassDescriptor, diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index f0eb766..205f235 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -75,7 +75,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => + 0; const uniformBuffer = new Uint8Array(uniformBufferSize); - const uniformBindGroup: IUniforms = { + const uniformBindGroup: IUniforms = { render_params: { bufferView: uniformBuffer, }, @@ -180,7 +180,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { const levelWidth = textureWidth >> level; const levelHeight = textureHeight >> level; - const probabilityMapBindGroup: IUniforms = { + const probabilityMapBindGroup: IUniforms = { ubo: { bufferView: probabilityMapUBOBuffer }, buf_in: { bufferView: level & 1 ? bufferA : bufferB }, buf_out: { bufferView: level & 1 ? bufferB : bufferA }, @@ -251,7 +251,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => code: simulateWGSL, }, }; - const computeBindGroup: IUniforms = { + const computeBindGroup: IUniforms = { sim_params: { bufferView: simulationUBOBuffer, }, @@ -292,8 +292,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [{ pipeline: renderPipeline, uniforms: { ...uniformBindGroup }, - vertices: { ...particlesVertices, ...quadVertices }, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: numParticles, firstVertex: 0, firstInstance: 0 }, + geometry: { + vertices: { ...particlesVertices, ...quadVertices }, + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: numParticles, firstVertex: 0, firstInstance: 0 }, + }, }], } ); diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 7d204f9..137c553 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -199,9 +199,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: renderPassDescriptor, renderObjects: [{ pipeline, - vertices, uniforms: bindingResources, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, + geometry: { + vertices, + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, + } }] } ] diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 5e2c794..45d8820 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -15,7 +15,7 @@ interface Renderable vertexAttributes: IVertexAttributes; indices: Uint16Array; indexCount: number; - bindGroup?: IUniforms; + bindGroup?: IUniforms; } const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => @@ -137,11 +137,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => function createSphereBindGroup1( texture: ITexture, transform: Float32Array - ): IUniforms + ): IUniforms { const uniformBuffer = new Float32Array(transform); - const bindGroup: IUniforms = { + const bindGroup: IUniforms = { modelMatrix: { bufferView: uniformBuffer, }, @@ -218,7 +218,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => ); const modelViewProjectionMatrix = mat4.create(); - const frameBindGroup: IUniforms = { + const frameBindGroup: IUniforms = { uniforms: { bufferView: uniformBuffer, }, @@ -259,9 +259,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => renderable.renderObject = { pipeline, uniforms: { ...frameBindGroup, ...renderable.bindGroup }, - vertices: renderable.vertexAttributes, - indices: renderable.indices, - draw: { __type: "DrawIndexed", indexCount: renderable.indexCount }, + geometry: { + vertices: renderable.vertexAttributes, + indices: renderable.indices, + draw: { __type: "DrawIndexed", indexCount: renderable.indexCount }, + } }; } diff --git a/examples/src/webgpu/resizeCanvas/index.ts b/examples/src/webgpu/resizeCanvas/index.ts index c20add7..7fc111f 100644 --- a/examples/src/webgpu/resizeCanvas/index.ts +++ b/examples/src/webgpu/resizeCanvas/index.ts @@ -22,7 +22,9 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, - draw: { __type: "DrawVertex", vertexCount: 3 }, + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 3 }, + } }; canvas.classList.add(styles.animatedCanvasSize); diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index b153026..72bf43c 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -106,7 +106,9 @@ return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); renderObjects: [{ pipeline, uniforms: bindGroup, - draw: { __type: "DrawVertex", vertexCount: 3 }, + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 3 }, + } }] }] }] diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 9451a5e..5e5d775 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -377,8 +377,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: colorPassPipelines[m], uniforms: { ...uniformBindGroups[m] }, - vertices, - draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + geometry:{ + vertices, + draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + } }] }); } @@ -399,8 +401,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, - vertices, - draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + geometry:{ + vertices, + draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + } }] }); precisionErrorPassEncoders.push({ @@ -416,8 +420,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: precisionPassPipelines[m], uniforms: { ...uniformBindGroups[m], ...depthTextureBindGroup }, - vertices, - draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + geometry:{ + vertices, + draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + } }] }); } @@ -438,8 +444,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, - vertices, - draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + geometry:{ + vertices, + draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + } }] }); depthBufferPassEncoders.push({ @@ -449,7 +457,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: textureQuadPassPipline, uniforms: { ...depthTextureBindGroup }, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, + } }] }); } diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index 2bd26fa..b0303fa 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -40,14 +40,16 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, }, - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + geometry:{ + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }, uniforms: { uniforms, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, }; const aspect = canvas.width / canvas.height; diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index 4d43f89..d27e6ba 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -323,7 +323,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: vpX, y: vpY, width: kViewportSize, height: kViewportSize, minDepth: 0, maxDepth: 1 }, pipeline: texturedSquarePipeline, uniforms: bindingResources0, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } + } } ); } @@ -337,7 +339,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: kLastViewport, y: kLastViewport, width: 32, height: 32, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } + } } ); renderObjects.push( @@ -345,7 +349,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport, width: 16, height: 16, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } + } } ); renderObjects.push( @@ -353,7 +359,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 16, width: 8, height: 8, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } + } } ); renderObjects.push( @@ -361,7 +369,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 24, width: 4, height: 4, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } + geometry:{ + draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } + } } ); diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index e608770..f7589bb 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -226,9 +226,11 @@ const init = async (canvas: HTMLCanvasElement) => ...sceneBindGroupForShadow, ...modelBindGroup, }, - vertices, - indices: indexBuffer, - draw: { __type: "DrawIndexed", indexCount }, + geometry: { + vertices, + indices: indexBuffer, + draw: { __type: "DrawIndexed", indexCount }, + } }, ] }, @@ -241,9 +243,11 @@ const init = async (canvas: HTMLCanvasElement) => ...sceneBindGroupForRender, ...modelBindGroup, }, - vertices, - indices: indexBuffer, - draw: { __type: "DrawIndexed", indexCount }, + geometry: { + vertices, + indices: indexBuffer, + draw: { __type: "DrawIndexed", indexCount }, + } } ], } diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 5ae43e8..aba02e3 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -472,9 +472,11 @@ export class GLTFPrimitive pipeline: this.renderPipeline, uniforms: bindingResources, //if skin do something with bone bind group - vertices: this.vertices, - indices: this.indices, - draw, + geometry: { + vertices: this.vertices, + indices: this.indices, + draw, + } }; renderObjects.push(renderObject); } diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 161835e..851567c 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -515,9 +515,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...generalUniformsBGCLuster, ...skinnedGridBoneBGCluster, }, - vertices: skinnedGridVertexBuffers.vertices, - indices: skinnedGridVertexBuffers.indices, - draw: { __type: "DrawIndexed", indexCount: gridIndices.length }, + geometry:{ + vertices: skinnedGridVertexBuffers.vertices, + indices: skinnedGridVertexBuffers.indices, + draw: { __type: "DrawIndexed", indexCount: gridIndices.length }, + } }; // passEncoders.push({ diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index effe2e8..0bdecc1 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -262,8 +262,10 @@ setBlendConstant().`, renderObjects.push({ pipeline, uniforms: uniformBindGroup, - vertices: verticesBuffer, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: 1 }, + geometry: { + vertices: verticesBuffer, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: 1 }, + } }); textRenderer.render(renderObjects, ...text); diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index a541713..8a44750 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -347,7 +347,9 @@ export class MsdfTextRenderer ...font.bindGroup, ...bindGroup, }, - draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: measurements.printedCharCount }, + geometry: { + draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: measurements.printedCharCount }, + } } ], }; diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index fc60aa8..8e52811 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -59,16 +59,18 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, }, - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, - }, uniforms: { uniforms, mySampler: sampler, myTexture: { texture: cubeTexture }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + geometry: { + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + } }; const aspect = canvas.width / canvas.height; diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 4579b79..9af488c 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -111,11 +111,13 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: IRenderObject = { pipeline, - vertices, uniforms: { uniforms, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + geometry: { + vertices, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + } }; const submit: ISubmit = { diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 1512079..d378312 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -108,8 +108,10 @@ const init = async (canvas: HTMLCanvasElement) => renderObjects: [{ pipeline, uniforms: uniformBindGroup, - vertices: verticesBuffer, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + geometry: { + vertices: verticesBuffer, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + } }] }] }] diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index d6c39d3..c3c8786 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -49,14 +49,16 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, }, - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, - }, uniforms: { uniforms, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + geometry: { + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + }, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + } }; const uniforms1: IBufferBinding = { diff --git a/examples/src/webgpu/videoUploading/index.ts b/examples/src/webgpu/videoUploading/index.ts index d979336..4399356 100644 --- a/examples/src/webgpu/videoUploading/index.ts +++ b/examples/src/webgpu/videoUploading/index.ts @@ -47,7 +47,9 @@ const init = async (canvas: HTMLCanvasElement) => source: video, }, }, - draw: { __type: "DrawVertex", vertexCount: 6 }, + geometry: { + draw: { __type: "DrawVertex", vertexCount: 6 }, + } }; function frame() diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index 1704e99..85a199b 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -163,7 +163,9 @@ const init = async (canvas: HTMLCanvasElement) => renderObjects: [{ pipeline, uniforms: uniformBindGroup, - draw: { __type: "DrawVertex", vertexCount: 3 }, + geometry: { + draw: { __type: "DrawVertex", vertexCount: 3 }, + } }], }] }] diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 8b46c0c..629f8ec 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -328,10 +328,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { renderObjects.push({ pipeline: litPipeline, - vertices: vertexAttributes, - indices, uniforms: litBindGroup, - draw: { __type: "DrawIndexed", indexCount: indices.length }, + geometry:{ + vertices: vertexAttributes, + indices, + draw: { __type: "DrawIndexed", indexCount: indices.length }, + } }); } } @@ -351,7 +353,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push({ pipeline, uniforms: wireframeBindGroups[bindGroupNdx], - draw: { __type: "DrawVertex", vertexCount: indices.length * countMult }, + geometry:{ + draw: { __type: "DrawVertex", vertexCount: indices.length * countMult }, + } }); }); } diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 3836d34..d28cc62 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -156,8 +156,10 @@ async function init(canvas: OffscreenCanvas) renderObjects: [{ pipeline, uniforms: uniformBindGroup, - vertices: verticesBuffer, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount } + geometry: { + vertices: verticesBuffer, + draw: { __type: "DrawVertex", vertexCount: cubeVertexCount } + } }] }] }] diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index a8ae20d..85b8b78 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -299,7 +299,7 @@ export class RunWebGPU */ protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: IRenderObject) { - const { viewport, scissorRect, pipeline, vertices, indices, uniforms: bindingResources, draw } = renderObject; + const { viewport, scissorRect, pipeline, uniforms: bindingResources, geometry } = renderObject; const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; @@ -312,6 +312,8 @@ export class RunWebGPU this.runScissorRect(passEncoder as GPURenderPassEncoder, renderPassFormat.attachmentSize, scissorRect); } + const { vertices, indices, draw } = geometry; + this.runRenderPipeline(device, passEncoder, renderPassFormat, pipeline, vertices, indices); this.runBindingResources(device, passEncoder, shader, bindingResources); diff --git a/src/utils/quitIfWebGPUNotAvailable.ts b/src/utils/quitIfWebGPUNotAvailable.ts index 30b2f9b..e84f63d 100644 --- a/src/utils/quitIfWebGPUNotAvailable.ts +++ b/src/utils/quitIfWebGPUNotAvailable.ts @@ -79,6 +79,11 @@ const fail = (() => // (show the first error, not the most recent error). if (!dialogBox.open) { + if (msg.indexOf("allow_unsafe_apis") > -1) + { + msg += "\n\n使用到了您的浏览器不支持的特性,请更换您的浏览器试试。"; + } + dialogText.textContent = msg; dialogBox.showModal(); } -- Gitee From 51f10cb805e5c07335526a2e9b3c5ff09fce67af Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 00:42:11 +0800 Subject: [PATCH 005/214] IGeometry.primitive?: IPrimitiveState --- examples/src/webgpu/a-buffer/index.ts | 18 +++++------ examples/src/webgpu/animometer/index.ts | 6 ++-- examples/src/webgpu/bitonicSort/utils.ts | 10 +++--- examples/src/webgpu/cameras/index.ts | 8 ++--- examples/src/webgpu/computeBoids/index.ts | 4 +-- examples/src/webgpu/cornell/rasterizer.ts | 6 ++-- examples/src/webgpu/cubemap/index.ts | 6 ++-- .../src/webgpu/deferredRendering/index.ts | 6 ++-- examples/src/webgpu/fractalCube/index.ts | 4 +-- examples/src/webgpu/gameOfLife/index.ts | 14 ++++----- examples/src/webgpu/instancedCube/index.ts | 4 +-- examples/src/webgpu/multipleCanvases/index.ts | 6 ++-- examples/src/webgpu/normalMap/index.ts | 4 +++ examples/src/webgpu/normalMap/utils.ts | 6 ---- examples/src/webgpu/occlusionQuery/index.ts | 8 ++--- examples/src/webgpu/particles/index.ts | 1 - examples/src/webgpu/renderBundles/index.ts | 13 ++++---- examples/src/webgpu/reversedZ/index.ts | 31 ++++++++++--------- examples/src/webgpu/rotatingCube/index.ts | 4 +-- examples/src/webgpu/shadowMapping/index.ts | 4 +-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 22 ++++++------- examples/src/webgpu/skinnedMesh/gridUtils.ts | 3 -- examples/src/webgpu/skinnedMesh/index.ts | 5 ++- .../src/webgpu/textRenderingMsdf/index.ts | 13 ++++---- .../src/webgpu/textRenderingMsdf/msdfText.ts | 6 ++-- examples/src/webgpu/texturedCube/index.ts | 6 ++-- examples/src/webgpu/timestampQuery/index.ts | 16 +++++----- .../src/webgpu/transparentCanvas/index.ts | 9 +++--- examples/src/webgpu/twoCubes/index.ts | 6 ++-- .../webgpu/volumeRenderingTexture3D/index.ts | 8 ++--- examples/src/webgpu/wireframe/index.ts | 29 +++++++++-------- examples/src/webgpu/worker/worker.ts | 16 +++++----- src/caches/getNGPURenderPipeline.ts | 12 +++---- src/runs/RunWebGPU.ts | 16 +++++----- 34 files changed, 163 insertions(+), 167 deletions(-) diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 1927c39..fe48910 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -63,9 +63,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: opaqueWGSL, }, - primitive: { - topology: "triangle-list", - }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -85,9 +82,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, ], }, - primitive: { - topology: "triangle-list", - }, label: "translucentPipeline", }; @@ -121,9 +115,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, ], }, - primitive: { - topology: "triangle-list", - }, label: "compositePipeline", }; @@ -289,6 +280,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: opaquePipeline, uniforms: bindingResources, geometry: { + primitive: { + topology: "triangle-list", + }, vertices, indices, draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, @@ -327,6 +321,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => sliceInfo: sliceInfoBuffer[slice], }, geometry: { + primitive: { + topology: "triangle-list", + }, vertices, indices, draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, @@ -350,6 +347,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => sliceInfo: sliceInfoBuffer[slice] }, geometry: { + primitive: { + topology: "triangle-list", + }, draw: { __type: "DrawVertex", vertexCount: 6 }, } } diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index 3044b80..00511fa 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -40,9 +40,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: animometerWGSL, }, - primitive: { - frontFace: "ccw", - } }; const pipeline: IRenderPipeline = { @@ -60,6 +57,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline, uniforms: {}, geometry: { + primitive: { + frontFace: "ccw", + }, vertices: { position: { data: vertexBuffer, format: "float32x4", offset: 0, arrayStride: 2 * vec4Size }, color: { data: vertexBuffer, format: "float32x4", offset: vec4Size, arrayStride: 2 * vec4Size }, diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index c463807..6b7c842 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -59,7 +59,11 @@ export abstract class Base2DRendererClass renderObjects: [{ pipeline, uniforms: bindingResources, - geometry:{ + geometry: { + primitive: { + topology: "triangle-list", + cullFace: "none", + }, draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1 } } }], @@ -80,10 +84,6 @@ export abstract class Base2DRendererClass fragment: { code, }, - primitive: { - topology: "triangle-list", - cullFace: "none", - }, }; return renderPipeline; diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index 41c2e93..cea4615 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -54,10 +54,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: cubeWGSL, }, - primitive: { - topology: "triangle-list", - cullFace: "back", - }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -100,6 +96,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline, uniforms: bindingResources, geometry:{ + primitive: { + topology: "triangle-list", + cullFace: "back", + }, vertices, draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, } diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index de39953..e2fe751 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -93,11 +93,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: IRenderObject = { pipeline: { vertex: { code: spriteWGSL }, fragment: { code: spriteWGSL }, + }, + geometry: { primitive: { cullFace: "back", }, - }, - geometry: { vertices: { a_particlePos: { data: particleBuffers[0], format: "float32x2", offset: 0, arrayStride: 4 * 4, stepMode: "instance" }, a_particleVel: { data: particleBuffers[0], format: "float32x2", offset: 2 * 4, arrayStride: 4 * 4, stepMode: "instance" }, diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index b146059..6bf211a 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -69,9 +69,6 @@ export default class Rasterizer fragment: { code: rasterizerWGSL + common.wgsl, }, - primitive: { - cullFace: "back", - }, }; // @@ -84,6 +81,9 @@ export default class Rasterizer ...this.bindGroup, }, geometry: { + primitive: { + cullFace: "back", + }, vertices: this.scene.vertexAttributes, indices: this.scene.indices, draw: { __type: "DrawIndexed", indexCount: this.scene.indexCount }, diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index c21af1b..2fd1f18 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -122,9 +122,6 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: IRenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleCubemapWGSL }, - primitive: { - cullFace: "none", - }, }, uniforms: { uniforms: { @@ -134,6 +131,9 @@ const init = async (canvas: HTMLCanvasElement) => myTexture: { texture: cubemapTexture }, }, geometry: { + primitive: { + cullFace: "none", + }, vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 3687892..525fc2f 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -81,7 +81,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: fragmentWriteGBuffers, }, - primitive, }; const gBuffersDebugViewPipeline: IRenderPipeline = { @@ -95,7 +94,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => canvasSizeHeight: canvas.height, }, }, - primitive, }; const deferredRenderPipeline: IRenderPipeline = { vertex: { @@ -104,7 +102,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: fragmentDeferredRendering, }, - primitive, }; const depthTexture: ITexture = { @@ -335,6 +332,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...sceneUniformBindGroup, }, geometry: { + primitive, vertices, indices: indexBuffer, draw: { __type: "DrawIndexed", indexCount }, @@ -366,6 +364,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...gBufferTexturesBindGroup, }, geometry: { + primitive, draw: { __type: "DrawVertex", vertexCount: 6 }, } }, @@ -382,6 +381,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...lightsBufferBindGroup, }, geometry: { + primitive, draw: { __type: "DrawVertex", vertexCount: 6 }, }, }, diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 173042d..0441c43 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -79,11 +79,11 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: IRenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleSelfWGSL }, + }, + geometry: { primitive: { cullFace: "back", }, - }, - geometry: { vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index fe23423..80df37f 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -74,22 +74,19 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cell: { data: buffer1, format: "uint32", stepMode: "instance" } }; - const bindGroup0: IUniforms = { + const bindGroup0: IUniforms = { size: { bufferView: sizeBuffer }, current: { bufferView: buffer0 }, next: { bufferView: buffer1 }, }; - const bindGroup1: IUniforms = { + const bindGroup1: IUniforms = { size: { bufferView: sizeBuffer }, current: { bufferView: buffer1 }, next: { bufferView: buffer0 }, }; const renderPipeline: IRenderPipeline = { - primitive: { - topology: "triangle-strip", - }, vertex: { code: vertWGSL, }, @@ -98,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const uniformBindGroup: IUniforms = { + const uniformBindGroup: IUniforms = { size: { bufferView: sizeBuffer, offset: 0, @@ -138,7 +135,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { pipeline: renderPipeline, uniforms: uniformBindGroup, - geometry:{ + geometry: { + primitive: { + topology: "triangle-strip", + }, vertices: vertices1, draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: length }, } diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index a5080dd..637b96b 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -104,11 +104,11 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: IRenderObject = { pipeline: { vertex: { code: instancedVertWGSL }, fragment: { code: vertexPositionColorWGSL }, + }, + geometry: { primitive: { cullFace: "back", }, - }, - geometry: { vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index d027d8f..0c2e63e 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -122,9 +122,6 @@ const init = async () => fragment: { ...module, }, - primitive: { - cullFace: "back", - }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -321,6 +318,9 @@ const init = async () => pipeline, uniforms: bindGroup, geometry: { + primitive: { + cullFace: "back", + }, vertices: vertexAttributes, indices, draw: { __type: "DrawIndexed", indexCount: indices.length }, diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index 4b0ef94..352269e 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -325,6 +325,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // * tangent : float32x3 // * bitangent : float32x3 geometry: { + primitive: { + topology: "triangle-list", + cullFace: "back", + }, vertices: { position: { data: box.vertices, offset: 0, format: "float32x3", arrayStride: box.vertexStride }, normal: { data: box.vertices, offset: 12, format: "float32x3", arrayStride: box.vertexStride }, diff --git a/examples/src/webgpu/normalMap/utils.ts b/examples/src/webgpu/normalMap/utils.ts index a75dd61..64dbc28 100644 --- a/examples/src/webgpu/normalMap/utils.ts +++ b/examples/src/webgpu/normalMap/utils.ts @@ -5,8 +5,6 @@ export const create3DRenderPipeline = ( vertexShader: string, fragmentShader: string, depthTest = false, - topology: GPUPrimitiveTopology = "triangle-list", - cullMode: GPUCullMode = "back" ) => { let depthStencil: IDepthStencilState; @@ -26,10 +24,6 @@ export const create3DRenderPipeline = ( fragment: { code: fragmentShader, }, - primitive: { - topology, - cullFace: cullMode, - }, depthStencil, }; diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 243c8bc..5bd1999 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -29,10 +29,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: solidColorLitWGSL, }, - primitive: { - topology: "triangle-list", - cullFace: "back", - }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -129,6 +125,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: IRenderObject = { pipeline, geometry: { + primitive: { + topology: "triangle-list", + cullFace: "back", + }, vertices: { position: { data: vertexBuf, offset: 0, arrayStride: 6 * 4, format: "float32x3" }, normal: { data: vertexBuf, offset: 12, arrayStride: 6 * 4, format: "float32x3" }, diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index 205f235..aec6f71 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -59,7 +59,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, ], }, - primitive: {}, depthStencil: { depthWriteEnabled: false, diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 45d8820..52ee5cd 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -48,13 +48,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => fragment: { code: meshWGSL, }, - primitive: { - // Backface culling since the sphere is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - cullFace: "back", - }, - // Enable depth testing so that the fragment closest to the camera // is rendered in front. }; @@ -260,6 +253,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => pipeline, uniforms: { ...frameBindGroup, ...renderable.bindGroup }, geometry: { + primitive: { + // Backface culling since the sphere is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullFace: "back", + }, vertices: renderable.vertexAttributes, indices: renderable.indices, draw: { __type: "DrawIndexed", indexCount: renderable.indexCount }, diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 5e5d775..c3a61eb 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -91,9 +91,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => vertex: { code: vertexDepthPrePassWGSL, }, - primitive: { - cullFace: "back", - }, }; // we need the depthCompare to fit the depth buffer mode we are using. @@ -123,9 +120,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: fragmentPrecisionErrorPassWGSL, }, - primitive: { - cullFace: "back", - }, }; const precisionPassPipelines: IRenderPipeline[] = []; @@ -152,9 +146,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: fragmentWGSL, }, - primitive: { - cullFace: "back", - }, }; // @@ -377,7 +368,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: colorPassPipelines[m], uniforms: { ...uniformBindGroups[m] }, - geometry:{ + geometry: { + primitive: { + cullFace: "back", + }, vertices, draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } @@ -401,7 +395,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, - geometry:{ + geometry: { + primitive: { + cullFace: "back", + }, vertices, draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } @@ -420,7 +417,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: precisionPassPipelines[m], uniforms: { ...uniformBindGroups[m], ...depthTextureBindGroup }, - geometry:{ + geometry: { + primitive: { + cullFace: "back", + }, vertices, draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } @@ -444,7 +444,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, - geometry:{ + geometry: { + primitive: { + cullFace: "back", + }, vertices, draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } @@ -457,7 +460,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: textureQuadPassPipline, uniforms: { ...depthTextureBindGroup }, - geometry:{ + geometry: { draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, } }] diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index b0303fa..3416a9f 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -36,11 +36,11 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: IRenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, + }, + geometry:{ primitive: { cullFace: "back", }, - }, - geometry:{ vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index f7589bb..ab5e8bd 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -62,7 +62,6 @@ const init = async (canvas: HTMLCanvasElement) => depthWriteEnabled: true, depthCompare: "less", }, - primitive, }; // Create a bind group layout which holds the scene uniforms and @@ -82,7 +81,6 @@ const init = async (canvas: HTMLCanvasElement) => depthWriteEnabled: true, depthCompare: "less", }, - primitive, }; const depthTexture: ITexture = { @@ -227,6 +225,7 @@ const init = async (canvas: HTMLCanvasElement) => ...modelBindGroup, }, geometry: { + primitive, vertices, indices: indexBuffer, draw: { __type: "DrawIndexed", indexCount }, @@ -244,6 +243,7 @@ const init = async (canvas: HTMLCanvasElement) => ...modelBindGroup, }, geometry: { + primitive, vertices, indices: indexBuffer, draw: { __type: "DrawIndexed", indexCount }, diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index aba02e3..0a46978 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -427,21 +427,10 @@ export class GLTFPrimitive // targets: [{ format: colorFormat }], }; - // Our loader only supports triangle lists and strips, so by default we set - // the primitive topology to triangle list, and check if it's instead a triangle strip - let primitive: IPrimitiveState = { topology: "triangle-list" }; - if (this.topology == GLTFRenderMode.TRIANGLE_STRIP) - { - primitive = { - topology: "triangle-strip", - }; - } - const rpDescript: IRenderPipeline = { label: `${label}.pipeline`, vertex: vertexState, fragment: fragmentState, - primitive, depthStencil: { // format: depthFormat, depthWriteEnabled: true, @@ -468,11 +457,22 @@ export class GLTFPrimitive draw = { __type: "DrawVertex", vertexCount }; } + // Our loader only supports triangle lists and strips, so by default we set + // the primitive topology to triangle list, and check if it's instead a triangle strip + let primitive: IPrimitiveState = { topology: "triangle-list" }; + if (this.topology == GLTFRenderMode.TRIANGLE_STRIP) + { + primitive = { + topology: "triangle-strip", + }; + } + const renderObject: IRenderObject = { pipeline: this.renderPipeline, uniforms: bindingResources, //if skin do something with bone bind group geometry: { + primitive, vertices: this.vertices, indices: this.indices, draw, diff --git a/examples/src/webgpu/skinnedMesh/gridUtils.ts b/examples/src/webgpu/skinnedMesh/gridUtils.ts index 7430adb..8546ed3 100644 --- a/examples/src/webgpu/skinnedMesh/gridUtils.ts +++ b/examples/src/webgpu/skinnedMesh/gridUtils.ts @@ -32,9 +32,6 @@ export const createSkinnedGridRenderPipeline = ( fragment: { code: fragmentShader, }, - primitive: { - topology: "line-list", - }, }; return pipeline; diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 851567c..1e7f775 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -515,7 +515,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...generalUniformsBGCLuster, ...skinnedGridBoneBGCluster, }, - geometry:{ + geometry: { + primitive: { + topology: "line-list", + }, vertices: skinnedGridVertexBuffers.vertices, indices: skinnedGridVertexBuffers.indices, draw: { __type: "DrawIndexed", indexCount: gridIndices.length }, diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index 0bdecc1..dd59664 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -148,13 +148,6 @@ setBlendConstant().`, fragment: { code: vertexPositionColorWGSL, }, - primitive: { - // Backface culling since the cube is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - cullFace: "back", - }, - // Enable depth testing so that the fragment closest to the camera // is rendered in front. depthStencil: { @@ -263,6 +256,12 @@ setBlendConstant().`, pipeline, uniforms: uniformBindGroup, geometry: { + primitive: { + // Backface culling since the cube is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullFace: "back", + }, vertices: verticesBuffer, draw: { __type: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: 1 }, } diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index 8a44750..e3fa9d8 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -189,9 +189,6 @@ export class MsdfTextRenderer }, ], }, - primitive: { - topology: "triangle-strip", - }, depthStencil: { depthWriteEnabled: false, depthCompare: "less", @@ -348,6 +345,9 @@ export class MsdfTextRenderer ...bindGroup, }, geometry: { + primitive: { + topology: "triangle-strip", + }, draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: measurements.printedCharCount }, } } diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index 8e52811..a2b2955 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -55,9 +55,6 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: IRenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleTextureMixColorWGSL }, - primitive: { - cullFace: "back", - }, }, uniforms: { uniforms, @@ -65,6 +62,9 @@ const init = async (canvas: HTMLCanvasElement) => myTexture: { texture: cubeTexture }, }, geometry: { + primitive: { + cullFace: "back", + }, vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 9af488c..42f1a55 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -68,14 +68,6 @@ const init = async (canvas: HTMLCanvasElement) => fragment: { code: fragmentWGSL, }, - primitive: { - topology: "triangle-list", - - // Backface culling since the cube is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - cullFace: "back", - }, // Enable depth testing so that the fragment closest to the camera // is rendered in front. @@ -115,6 +107,14 @@ const init = async (canvas: HTMLCanvasElement) => uniforms, }, geometry: { + primitive: { + topology: "triangle-list", + + // Backface culling since the cube is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullFace: "back", + }, vertices, draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, } diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index d378312..3391b19 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -37,11 +37,6 @@ const init = async (canvas: HTMLCanvasElement) => fragment: { code: vertexPositionColorWGSL, }, - primitive: { - topology: "triangle-list", - cullFace: "back", - }, - depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -109,6 +104,10 @@ const init = async (canvas: HTMLCanvasElement) => pipeline, uniforms: uniformBindGroup, geometry: { + primitive: { + topology: "triangle-list", + cullFace: "back", + }, vertices: verticesBuffer, draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, } diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index c3c8786..c269824 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -45,14 +45,14 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: IRenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, - primitive: { - cullFace: "back", - }, }, uniforms: { uniforms, }, geometry: { + primitive: { + cullFace: "back", + }, vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index 85a199b..4fff613 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -35,10 +35,6 @@ const init = async (canvas: HTMLCanvasElement) => fragment: { code: volumeWGSL, }, - primitive: { - topology: "triangle-list", - cullFace: "back", - }, }; const uniformBuffer = { @@ -164,6 +160,10 @@ const init = async (canvas: HTMLCanvasElement) => pipeline, uniforms: uniformBindGroup, geometry: { + primitive: { + topology: "triangle-list", + cullFace: "back", + }, draw: { __type: "DrawVertex", vertexCount: 3 }, } }], diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 629f8ec..225a527 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IPrimitiveState, IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, IVertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -58,9 +58,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: solidColorLitWGSL, }, - primitive: { - cullFace: "back", - }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -85,9 +82,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => code: wireframeWGSL, entryPoint: "fs", }, - primitive: { - topology: "line-list", - }, depthStencil: { depthWriteEnabled: true, depthCompare: "less-equal", @@ -118,9 +112,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, ], }, - primitive: { - topology: "triangle-list", - }, depthStencil: { depthWriteEnabled: true, depthCompare: "less-equal", @@ -329,7 +320,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push({ pipeline: litPipeline, uniforms: litBindGroup, - geometry:{ + geometry: { + primitive: { + cullFace: "back", + }, vertices: vertexAttributes, indices, draw: { __type: "DrawIndexed", indexCount: indices.length }, @@ -344,16 +338,21 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Note: If we're using the line-list based pipeline then we need to // multiply the vertex count by 2 since we need to emit 6 vertices // for each triangle (3 edges). - const [bindGroupNdx, countMult, pipeline] + const [bindGroupNdx, countMult, pipeline, primitive] = settings.barycentricCoordinatesBased - ? [1, 1, barycentricCoordinatesBasedWireframePipeline] - : [0, 2, wireframePipeline]; + ? [1, 1, barycentricCoordinatesBasedWireframePipeline, { + topology: "triangle-list", + } as IPrimitiveState] + : [0, 2, wireframePipeline, { + topology: "line-list", + } as IPrimitiveState]; objectInfos.forEach(({ wireframeBindGroups, model: { indices } }) => { renderObjects.push({ pipeline, uniforms: wireframeBindGroups[bindGroupNdx], - geometry:{ + geometry: { + primitive, draw: { __type: "DrawVertex", vertexCount: indices.length * countMult }, } }); diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index d28cc62..ac07d5a 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -85,14 +85,6 @@ async function init(canvas: OffscreenCanvas) fragment: { code: vertexPositionColorWGSL, }, - primitive: { - topology: "triangle-list", - - // Backface culling since the cube is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - cullFace: "back", - }, // Enable depth testing so that the fragment closest to the camera // is rendered in front. @@ -157,6 +149,14 @@ async function init(canvas: OffscreenCanvas) pipeline, uniforms: uniformBindGroup, geometry: { + primitive: { + topology: "triangle-list", + + // Backface culling since the cube is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullFace: "back", + }, vertices: verticesBuffer, draw: { __type: "DrawVertex", vertexCount: cubeVertexCount } } diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 39de1d2..6aa50e5 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -21,14 +21,14 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPassFormat: IGPURenderPassFormat, vertices: IVertexAttributes, indices: IIndicesDataTypes) +export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPassFormat: IGPURenderPassFormat, primitive: IPrimitiveState, vertices: IVertexAttributes, indices: IIndicesDataTypes) { const indexFormat = indices ? getIGPUSetIndexBuffer(indices).indexFormat : undefined; - let result = renderPipelineMap.get([renderPipeline, renderPassFormat._key, vertices, indexFormat]); + let result = renderPipelineMap.get([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); if (result) return result; - const { label, primitive } = renderPipeline; + const { label } = renderPipeline; const gpuPrimitive = getGPUPrimitiveState(primitive, indexFormat); @@ -62,14 +62,14 @@ export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPas }; result = { _version: 0, pipeline, vertexBuffers: vertexStateResult.vertexBuffers }; - renderPipelineMap.set([renderPipeline, renderPassFormat._key, vertices, indexFormat], result); + renderPipelineMap.set([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat], result); // 监听管线变化 const onchanged = () => { result._version++; renderPipeline._version = ~~renderPipeline._version + 1; - renderPipelineMap.delete([renderPipeline, renderPassFormat._key, vertices, indexFormat]); + renderPipelineMap.delete([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); watcher.unwatch(vertexStateResult, "_version", onchanged); gpuFragmentState && watcher.unwatch(gpuFragmentState, "_version", onchanged); } @@ -80,7 +80,7 @@ export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPas } const renderPipelineMap = new ChainMap< - [IRenderPipeline, string, IVertexAttributes, GPUIndexFormat], + [IRenderPipeline, string, IPrimitiveState, IVertexAttributes, GPUIndexFormat], { /** * GPU渲染管线描述。 diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 85b8b78..589672b 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { ICommandEncoder, ICopyBufferToBuffer, ICopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IRenderObject, IRenderPass, IRenderPassObject, IRenderPipeline, IScissorRect, ISubmit, IUniforms, IVertexAttributes, IViewport } from "@feng3d/render-api"; +import { ICommandEncoder, ICopyBufferToBuffer, ICopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IPrimitiveState, IRenderObject, IRenderPass, IRenderPassObject, IRenderPipeline, IScissorRect, ISubmit, IUniforms, IVertexAttributes, IViewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -312,13 +312,13 @@ export class RunWebGPU this.runScissorRect(passEncoder as GPURenderPassEncoder, renderPassFormat.attachmentSize, scissorRect); } - const { vertices, indices, draw } = geometry; + const { primitive, vertices, indices, draw } = geometry; - this.runRenderPipeline(device, passEncoder, renderPassFormat, pipeline, vertices, indices); + this.runRenderPipeline(device, passEncoder, renderPassFormat, pipeline, primitive, vertices, indices); this.runBindingResources(device, passEncoder, shader, bindingResources); - this.runVertices(device, passEncoder, renderPassFormat, pipeline, vertices, indices); + this.runVertices(device, passEncoder, renderPassFormat, pipeline, primitive, vertices, indices); this.runIndices(device, passEncoder, indices); @@ -332,10 +332,10 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, vertices: IVertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, primitive: IPrimitiveState, vertices: IVertexAttributes, indices: IIndicesDataTypes) { // - const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, vertices, indices); + const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); const nPipeline = renderPipelineResult.pipeline; @@ -429,9 +429,9 @@ export class RunWebGPU }); } - protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, vertices: IVertexAttributes, indices: IIndicesDataTypes) + protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, primitive: IPrimitiveState, vertices: IVertexAttributes, indices: IIndicesDataTypes) { - const renderPipeline = getNGPURenderPipeline(pipeline, renderPassFormat, vertices, indices); + const renderPipeline = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); // renderPipeline.vertexBuffers?.forEach((vertexBuffer, index) => -- Gitee From 1efa4b11591ac45a3d066c53daaa45aac59b1ff2 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 01:22:27 +0800 Subject: [PATCH 006/214] Geometry --- examples/src/webgpu/a-buffer/index.ts | 4 ++-- examples/src/webgpu/cameras/index.ts | 4 ++-- examples/src/webgpu/computeBoids/index.ts | 1 + examples/src/webgpu/cornell/scene.ts | 6 +++--- examples/src/webgpu/deferredRendering/index.ts | 4 ++-- examples/src/webgpu/gameOfLife/index.ts | 10 +++++----- examples/src/webgpu/multipleCanvases/index.ts | 6 +++--- examples/src/webgpu/particles/index.ts | 6 +++--- examples/src/webgpu/points/index.ts | 4 ++-- examples/src/webgpu/renderBundles/index.ts | 6 +++--- examples/src/webgpu/reversedZ/index.ts | 4 ++-- examples/src/webgpu/shadowMapping/index.ts | 4 ++-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 6 +++--- examples/src/webgpu/skinnedMesh/gridUtils.ts | 4 ++-- examples/src/webgpu/textRenderingMsdf/index.ts | 4 ++-- examples/src/webgpu/timestampQuery/index.ts | 4 ++-- examples/src/webgpu/transparentCanvas/index.ts | 4 ++-- examples/src/webgpu/wireframe/index.ts | 8 ++++---- examples/src/webgpu/worker/worker.ts | 5 +++-- src/caches/getNGPURenderPipeline.ts | 14 +++++++------- src/data/IGPUPrimitiveState.ts | 8 +++++--- src/runs/RunWebGPU.ts | 6 +++--- 22 files changed, 63 insertions(+), 59 deletions(-) diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index fe48910..c0e68e0 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, IPassEncoder, IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, ITextureView, IVertexAttributes } from "@feng3d/render-api"; +import { IBufferBinding, IPassEncoder, IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, ITextureView, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -35,7 +35,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // Create the model vertex buffer - const vertices: IVertexAttributes = { + const vertices: VertexAttributes = { position: { data: new Float32Array(mesh.positions.flat()), format: "float32x3", arrayStride: 12 } }; // Create the model index buffer diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index cea4615..a4a3919 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -5,7 +5,7 @@ import { ArcballCamera, WASDCamera } from "./camera"; import cubeWGSL from "./cube.wgsl"; import { createInputHandler } from "./input"; -import { IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -42,7 +42,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); // Create a vertex buffer from the cube data. - const vertices: IVertexAttributes = { + const vertices: VertexAttributes = { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index e2fe751..adcae5b 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -111,6 +111,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...renderObject, geometry: { ...renderObject.geometry, + draw: renderObject.geometry.draw, vertices: { ...renderObject.geometry.vertices, a_particlePos: { diff --git a/examples/src/webgpu/cornell/scene.ts b/examples/src/webgpu/cornell/scene.ts index 96bc1cf..cd445c7 100644 --- a/examples/src/webgpu/cornell/scene.ts +++ b/examples/src/webgpu/cornell/scene.ts @@ -1,4 +1,4 @@ -import { IVertexAttributes } from "@feng3d/render-api"; +import { VertexAttributes } from "@feng3d/render-api"; import { Vec3, vec3 } from "wgpu-matrix"; function reciprocal(v: Vec3) @@ -130,7 +130,7 @@ export default class Scene readonly vertexCount: number; readonly indexCount: number; readonly vertices: Float32Array; - readonly vertexAttributes: IVertexAttributes; + readonly vertexAttributes: VertexAttributes; readonly indices: Uint16Array; readonly quadBuffer: Float32Array; readonly quads = [ @@ -280,7 +280,7 @@ export default class Scene const vertices = vertexData; - const vertexAttributes: IVertexAttributes = { + const vertexAttributes: VertexAttributes = { position: { data: vertices, format: "float32x4", offset: 0 * 4, arrayStride: vertexStride }, uv: { data: vertices, format: "float32x3", offset: 4 * 4, arrayStride: vertexStride }, emissive: { data: vertices, format: "float32x3", offset: 7 * 4, arrayStride: vertexStride }, diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 525fc2f..77c7ec8 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -10,7 +10,7 @@ import lightUpdate from "./lightUpdate.wgsl"; import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; -import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, ITextureView, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, ITextureView, IUniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const kMaxNumLights = 1024; @@ -36,7 +36,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => vertexBuffer.set(mesh.uvs[i], kVertexStride * i + 6); } - const vertices: IVertexAttributes = { + const vertices: VertexAttributes = { position: { data: vertexBuffer, format: "float32x3", offset: 0, arrayStride: Float32Array.BYTES_PER_ELEMENT * 8 }, normal: { data: vertexBuffer, format: "float32x3", offset: Float32Array.BYTES_PER_ELEMENT * 3, arrayStride: Float32Array.BYTES_PER_ELEMENT * 8 }, uv: { data: vertexBuffer, format: "float32x2", offset: Float32Array.BYTES_PER_ELEMENT * 6, arrayStride: Float32Array.BYTES_PER_ELEMENT * 8 }, diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 80df37f..6f6b6ce 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -4,7 +4,7 @@ import computeWGSL from "./compute.wgsl"; import fragWGSL from "./frag.wgsl"; import vertWGSL from "./vert.wgsl"; -import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -23,7 +23,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const squareVertices = new Uint32Array([0, 0, 0, 1, 1, 0, 1, 1]); - const verticesSquareBuffer: IVertexAttributes = { + const verticesSquareBuffer: VertexAttributes = { pos: { data: squareVertices, format: "uint32x2" } }; @@ -40,9 +40,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => let wholeTime = 0; let loopTimes = 0; let buffer0: Uint32Array; - let verticesBuffer0: IVertexAttributes; + let verticesBuffer0: VertexAttributes; let buffer1: Uint32Array; - let verticesBuffer1: IVertexAttributes; + let verticesBuffer1: VertexAttributes; let render: () => void; function resetGameData() { @@ -114,7 +114,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const passEncodersArray: (IGPUComputePass | IRenderPass)[][] = []; for (let i = 0; i < 2; i++) { - const vertices1: IVertexAttributes = {}; + const vertices1: VertexAttributes = {}; Object.assign(vertices1, i ? verticesBuffer1 : verticesBuffer0, verticesSquareBuffer); passEncodersArray[i] = [ diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index 0c2e63e..a36ca03 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,4 +1,4 @@ -import { IPassEncoder, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IPassEncoder, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; @@ -23,14 +23,14 @@ function createBufferWithData( type Model = { vertices: Float32Array; indices: Uint32Array; - vertexAttributes: IVertexAttributes, + vertexAttributes: VertexAttributes, }; function createVertexAndIndexBuffer( { vertices, indices }: { vertices: Float32Array; indices: Uint32Array } ): Model { - const vertexAttributes: IVertexAttributes = { + const vertexAttributes: VertexAttributes = { position: { data: vertices, format: "float32x3", offset: 0, arrayStride: 6 * 4 }, normal: { data: vertices, format: "float32x3", offset: 3 * 4, arrayStride: 6 * 4 }, }; diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index aec6f71..33a3ef8 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -7,7 +7,7 @@ import particleWGSL from "./particle.wgsl"; import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; -import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const numParticles = 50000; @@ -31,7 +31,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const particlesBuffer = new Float32Array(numParticles * particleInstanceByteSize / 4); - const particlesVertices: IVertexAttributes = { + const particlesVertices: VertexAttributes = { position: { data: particlesBuffer, format: "float32x3", offset: particlePositionOffset, arrayStride: particleInstanceByteSize, stepMode: "instance" }, color: { data: particlesBuffer, format: "float32x4", offset: particleColorOffset, arrayStride: particleInstanceByteSize, stepMode: "instance" }, }; @@ -103,7 +103,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ]; const quadVertexBuffer = new Float32Array(vertexData); - const quadVertices: IVertexAttributes = { + const quadVertices: VertexAttributes = { quad_pos: { data: quadVertexBuffer, format: "float32x2" } }; diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 137c553..56741f2 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -1,4 +1,4 @@ -import { IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; @@ -103,7 +103,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); const kNumPoints = vertexData.length / 3; - const vertices: IVertexAttributes = { + const vertices: VertexAttributes = { position: { data: vertexData, format: "float32x3", arrayStride: 12, stepMode: "instance" }, }; diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 52ee5cd..16e9f36 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPass, IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISampler, ISubmit, ITexture, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderObject, IRenderPass, IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISampler, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, IGPURenderBundle, WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -12,7 +12,7 @@ import meshWGSL from "./mesh.wgsl"; interface Renderable { renderObject?: IRenderObject; - vertexAttributes: IVertexAttributes; + vertexAttributes: VertexAttributes; indices: Uint16Array; indexCount: number; bindGroup?: IUniforms; @@ -112,7 +112,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => // Create a vertex buffer from the sphere data. const vertices = sphereMesh.vertices; - const vertexAttributes: IVertexAttributes = { + const vertexAttributes: VertexAttributes = { position: { data: vertices, format: "float32x3", offset: SphereLayout.positionsOffset, arrayStride: SphereLayout.vertexStride }, normal: { data: vertices, format: "float32x3", offset: SphereLayout.normalOffset, arrayStride: SphereLayout.vertexStride }, uv: { data: vertices, format: "float32x2", offset: SphereLayout.uvOffset, arrayStride: SphereLayout.vertexStride }, diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index c3a61eb..dd90a10 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -10,7 +10,7 @@ import vertexDepthPrePassWGSL from "./vertexDepthPrePass.wgsl"; import vertexPrecisionErrorPassWGSL from "./vertexPrecisionErrorPass.wgsl"; import vertexTextureQuadWGSL from "./vertexTextureQuad.wgsl"; -import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; // Two planes close to each other for depth precision test @@ -78,7 +78,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); - const vertices: IVertexAttributes = { + const vertices: VertexAttributes = { position: { data: geometryVertexArray, format: "float32x4", offset: geometryPositionOffset, arrayStride: geometryVertexSize }, color: { data: geometryVertexArray, format: "float32x4", offset: geometryColorOffset, arrayStride: geometryVertexSize }, }; diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index ab5e8bd..1585869 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -6,7 +6,7 @@ import fragmentWGSL from "./fragment.wgsl"; import vertexWGSL from "./vertex.wgsl"; import vertexShadowWGSL from "./vertexShadow.wgsl"; -import { IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; import { WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; const shadowDepthTextureSize = 1024; @@ -28,7 +28,7 @@ const init = async (canvas: HTMLCanvasElement) => vertexBuffer.set(mesh.normals[i], 6 * i + 3); } - const vertices: IVertexAttributes = { + const vertices: VertexAttributes = { position: { data: vertexBuffer, format: "float32x3", offset: 0, arrayStride: Float32Array.BYTES_PER_ELEMENT * 6 }, normal: { data: vertexBuffer, format: "float32x3", offset: Float32Array.BYTES_PER_ELEMENT * 3, arrayStride: Float32Array.BYTES_PER_ELEMENT * 6 }, }; diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 0a46978..15ecbac 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { IBuffer, IDraw, IFragmentState, IPrimitiveState, IRenderObject, IRenderPipeline, IUniforms, IVertexAttributes, IVertexState, vertexFormatMap } from "@feng3d/render-api"; +import { IBuffer, IDraw, IFragmentState, PrimitiveState, IRenderObject, IRenderPipeline, IUniforms, VertexAttributes, IVertexState, vertexFormatMap } from "@feng3d/render-api"; import { getIGPUBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -345,7 +345,7 @@ export class GLTFPrimitive renderPipeline: IRenderPipeline; private attributeMap: AttributeMapInterface; private attributes: string[] = []; - vertices: IVertexAttributes; + vertices: VertexAttributes; indices: Uint16Array | Uint32Array; constructor( topology: GLTFRenderMode, @@ -459,7 +459,7 @@ export class GLTFPrimitive // Our loader only supports triangle lists and strips, so by default we set // the primitive topology to triangle list, and check if it's instead a triangle strip - let primitive: IPrimitiveState = { topology: "triangle-list" }; + let primitive: PrimitiveState = { topology: "triangle-list" }; if (this.topology == GLTFRenderMode.TRIANGLE_STRIP) { primitive = { diff --git a/examples/src/webgpu/skinnedMesh/gridUtils.ts b/examples/src/webgpu/skinnedMesh/gridUtils.ts index 8546ed3..8acbba5 100644 --- a/examples/src/webgpu/skinnedMesh/gridUtils.ts +++ b/examples/src/webgpu/skinnedMesh/gridUtils.ts @@ -1,4 +1,4 @@ -import { IRenderPipeline, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPipeline, VertexAttributes } from "@feng3d/render-api"; import { gridIndices, gridJoints, gridVertices, gridWeights } from "./gridData"; @@ -7,7 +7,7 @@ export const createSkinnedGridBuffers = () => { // Utility function that creates GPUBuffers from data - const vertices: IVertexAttributes = { + const vertices: VertexAttributes = { vert_pos: { data: gridVertices, format: "float32x2" }, joints: { data: gridJoints, format: "uint32x4" }, weights: { data: gridWeights, format: "float32x4" }, diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index dd59664..35d6195 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISubmit, ITexture, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import basicVertWGSL from "../../shaders/basic.vert.wgsl"; @@ -136,7 +136,7 @@ setBlendConstant().`, ]; // Create a vertex buffer from the cube data. - const verticesBuffer: IVertexAttributes = { + const verticesBuffer: VertexAttributes = { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 42f1a55..ddb97d5 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -54,7 +54,7 @@ const init = async (canvas: HTMLCanvasElement) => const perfDisplay = document.querySelector("#info pre"); // Create a vertex buffer from the cube data. - const vertices: IVertexAttributes = { + const vertices: VertexAttributes = { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 3391b19..3c95e1f 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { IRenderPassDescriptor, IRenderPipeline, ITexture, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPassDescriptor, IRenderPipeline, ITexture, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -25,7 +25,7 @@ const init = async (canvas: HTMLCanvasElement) => }; // Create a vertex buffer from the cube data. - const verticesBuffer: IVertexAttributes = { + const verticesBuffer: VertexAttributes = { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 225a527..6fbcbeb 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -1,4 +1,4 @@ -import { IPrimitiveState, IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, PrimitiveState, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -30,7 +30,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => type Model = { vertices: Float32Array; indices: Uint32Array; - vertexAttributes: IVertexAttributes + vertexAttributes: VertexAttributes }; const models = Object.values(modelData).map((v) => @@ -342,10 +342,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => = settings.barycentricCoordinatesBased ? [1, 1, barycentricCoordinatesBasedWireframePipeline, { topology: "triangle-list", - } as IPrimitiveState] + } as PrimitiveState] : [0, 2, wireframePipeline, { topology: "line-list", - } as IPrimitiveState]; + } as PrimitiveState]; objectInfos.forEach(({ wireframeBindGroups, model: { indices } }) => { renderObjects.push({ diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index ac07d5a..015315d 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { IRenderPassDescriptor, IRenderPipeline, ISubmit, IVertexAttributes } from "@feng3d/render-api"; +import { IRenderPassDescriptor, IRenderPipeline, ISubmit, VertexAttributes } from "@feng3d/render-api"; import { getOffscreenCanvasId, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -73,7 +73,7 @@ async function init(canvas: OffscreenCanvas) const context: IGPUCanvasContext = { canvasId: getOffscreenCanvasId(canvas) }; // Create a vertex buffer from the cube data. - const verticesBuffer: IVertexAttributes = { + const verticesBuffer: VertexAttributes = { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; @@ -156,6 +156,7 @@ async function init(canvas: OffscreenCanvas) // Faces pointing away from the camera will be occluded by faces // pointing toward the camera. cullFace: "back", + frontFace: "ccw", }, vertices: verticesBuffer, draw: { __type: "DrawVertex", vertexCount: cubeVertexCount } diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 6aa50e5..9b509aa 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { getBlendConstantColor, IBlendState, IDepthStencilState, IFragmentState, IIndicesDataTypes, IPrimitiveState, IRenderPipeline, IStencilFaceState, IVertexAttributes, IVertexState, IWriteMask, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; +import { getBlendConstantColor, IBlendState, IDepthStencilState, IFragmentState, IIndicesDataTypes, IRenderPipeline, IStencilFaceState, VertexAttributes, IVertexState, IWriteMask, PrimitiveState, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -21,7 +21,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPassFormat: IGPURenderPassFormat, primitive: IPrimitiveState, vertices: IVertexAttributes, indices: IIndicesDataTypes) +export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPassFormat: IGPURenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const indexFormat = indices ? getIGPUSetIndexBuffer(indices).indexFormat : undefined; @@ -80,7 +80,7 @@ export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPas } const renderPipelineMap = new ChainMap< - [IRenderPipeline, string, IPrimitiveState, IVertexAttributes, GPUIndexFormat], + [IRenderPipeline, string, PrimitiveState, VertexAttributes, GPUIndexFormat], { /** * GPU渲染管线描述。 @@ -131,7 +131,7 @@ function getStencilReference(depthStencil?: IDepthStencilState) return stencilReference; } -function getGPUPrimitiveState(primitive?: IPrimitiveState, indexFormat?: GPUIndexFormat) +function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndexFormat) { let stripIndexFormat: GPUIndexFormat; if (primitive?.topology === "triangle-strip" || primitive?.topology === "line-strip") @@ -217,7 +217,7 @@ function getGPUStencilFaceState(stencilFaceState?: IStencilFaceState) * @param vertices 顶点数据。 * @returns 完整的顶点阶段描述与顶点缓冲区列表。 */ -function getNGPUVertexState(vertexState: IVertexState, vertices: IVertexAttributes) +function getNGPUVertexState(vertexState: IVertexState, vertices: VertexAttributes) { let result = vertexStateMap.get([vertexState, vertices]); if (result) return result; @@ -264,7 +264,7 @@ function getNGPUVertexState(vertexState: IVertexState, vertices: IVertexAttribut return result; } -const vertexStateMap = new ChainMap<[IVertexState, IVertexAttributes], { +const vertexStateMap = new ChainMap<[IVertexState, VertexAttributes], { gpuVertexState: NGPUVertexState; vertexBuffers: NGPUVertexBuffer[]; /** @@ -280,7 +280,7 @@ const vertexStateMap = new ChainMap<[IVertexState, IVertexAttributes], { * @param vertices 顶点数据。 * @returns 顶点缓冲区布局数组以及顶点缓冲区数组。 */ -function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: IVertexAttributes) +function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) { const vertexBufferLayouts: GPUVertexBufferLayout[] = []; diff --git a/src/data/IGPUPrimitiveState.ts b/src/data/IGPUPrimitiveState.ts index 7be3993..6c556e0 100644 --- a/src/data/IGPUPrimitiveState.ts +++ b/src/data/IGPUPrimitiveState.ts @@ -1,4 +1,4 @@ -import { IPrimitiveState } from "@feng3d/render-api"; +import { PrimitiveState } from "@feng3d/render-api"; declare module "@feng3d/render-api" { @@ -7,12 +7,14 @@ declare module "@feng3d/render-api" * * `stripIndexFormat` 将由引擎自动设置。 */ - export interface IPrimitiveState + export interface PrimitiveState { /** * If true, indicates that depth clipping is disabled. * Requires the {@link GPUFeatureName#"depth-clip-control"} feature to be enabled. */ - readonly unclippedDepth?: boolean; + unclippedDepth?: boolean; } + } +PrimitiveState.prototype.unclippedDepth = false; diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 589672b..beb0acf 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { ICommandEncoder, ICopyBufferToBuffer, ICopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IPrimitiveState, IRenderObject, IRenderPass, IRenderPassObject, IRenderPipeline, IScissorRect, ISubmit, IUniforms, IVertexAttributes, IViewport } from "@feng3d/render-api"; +import { ICommandEncoder, ICopyBufferToBuffer, ICopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IRenderObject, IRenderPass, IRenderPassObject, IRenderPipeline, IScissorRect, ISubmit, IUniforms, VertexAttributes, IViewport, PrimitiveState } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -332,7 +332,7 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, primitive: IPrimitiveState, vertices: IVertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { // const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); @@ -429,7 +429,7 @@ export class RunWebGPU }); } - protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, primitive: IPrimitiveState, vertices: IVertexAttributes, indices: IIndicesDataTypes) + protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const renderPipeline = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); -- Gitee From 3d59fd789d5602d41cff5381a4e8ee116e4f4846 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 01:30:21 +0800 Subject: [PATCH 007/214] BlendComponent BlendState Buffer --- examples/src/webgpu/bitonicSort/index.ts | 6 +++--- examples/src/webgpu/blending/index.ts | 6 +++--- examples/src/webgpu/skinnedMesh/glbUtils.ts | 6 +++--- src/WebGPU.ts | 4 ++-- src/caches/getGPUBuffer.ts | 8 ++++---- src/caches/getIGPUBuffer.ts | 6 +++--- src/caches/getNGPURenderPipeline.ts | 4 ++-- src/data/IGPUBuffer.ts | 4 ++-- src/data/IGPURenderPipeline.ts | 2 +- src/internal/IGPUIndexBuffer.ts | 4 ++-- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 20ff191..b6d02f5 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,4 +1,4 @@ -import { IBuffer, IBufferBinding, ICommandEncoder, IRenderPassDescriptor, ISubmit, IUniforms } from "@feng3d/render-api"; +import { Buffer, IBufferBinding, ICommandEncoder, IRenderPassDescriptor, ISubmit, IUniforms } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -262,7 +262,7 @@ async function init( const elementsOutputBuffer: IBufferBinding = { bufferView: new Uint8Array(elementsBufferSize) }; - const elementsStagingBuffer: IBuffer = { + const elementsStagingBuffer: Buffer = { size: elementsBufferSize, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, }; @@ -272,7 +272,7 @@ async function init( const atomicSwapsOutputBuffer: IBufferBinding = { bufferView: new Uint32Array(1) }; - const atomicSwapsStagingBuffer: IBuffer = { + const atomicSwapsStagingBuffer: Buffer = { size: Uint32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, }; diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index e68a050..8c17250 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import texturedQuadWGSL from "./texturedQuad.wgsl"; -import { IBlendComponent, IRenderObject, IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISampler, ISubmit, ITexture, ITextureView, IUniforms } from "@feng3d/render-api"; +import { BlendComponent, IRenderObject, IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISampler, ISubmit, ITexture, ITextureView, IUniforms } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -324,13 +324,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const kPresets = keysOf(presets); type Preset = (typeof kPresets)[number]; - const color: IBlendComponent = { + const color: BlendComponent = { operation: "add", srcFactor: "one", dstFactor: "one-minus-src", }; - const alpha: IBlendComponent = { + const alpha: BlendComponent = { operation: "add", srcFactor: "one", dstFactor: "one-minus-src", diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 15ecbac..b571a07 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { IBuffer, IDraw, IFragmentState, PrimitiveState, IRenderObject, IRenderPipeline, IUniforms, VertexAttributes, IVertexState, vertexFormatMap } from "@feng3d/render-api"; +import { Buffer, IDraw, IFragmentState, PrimitiveState, IRenderObject, IRenderPipeline, IUniforms, VertexAttributes, IVertexState, vertexFormatMap } from "@feng3d/render-api"; import { getIGPUBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -245,7 +245,7 @@ export class GLTFBufferView byteStride: number; view: Uint8Array; needsUpload: boolean; - gpuBuffer: IBuffer; + gpuBuffer: Buffer; usage: number; constructor(buffer: GLTFBuffer, view: BufferView) { @@ -285,7 +285,7 @@ export class GLTFBufferView upload() { // Note: must align to 4 byte size when mapped at creation is true - const buf: IBuffer = { + const buf: Buffer = { size: alignTo(this.view.byteLength, 4), usage: this.usage, data: this.view, diff --git a/src/WebGPU.ts b/src/WebGPU.ts index a48a965..5d8c122 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,4 +1,4 @@ -import { IBuffer, ISubmit, ITextureLike } from "@feng3d/render-api"; +import { Buffer, ISubmit, ITextureLike } from "@feng3d/render-api"; import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUTexture } from "./caches/getGPUTexture"; import { getIGPUTextureLikeSize } from "./caches/getIGPUTextureSize"; @@ -149,7 +149,7 @@ export class WebGPU * @param size 读取字节数量。 * @returns CPU数据缓冲区。 */ - async readBuffer(buffer: IBuffer, offset?: GPUSize64, size?: GPUSize64) + async readBuffer(buffer: Buffer, offset?: GPUSize64, size?: GPUSize64) { const gpuBuffer = getGPUBuffer(this.device, buffer); await gpuBuffer.mapAsync(GPUMapMode.READ); diff --git a/src/caches/getGPUBuffer.ts b/src/caches/getGPUBuffer.ts index 3b9904f..1226ce4 100644 --- a/src/caches/getGPUBuffer.ts +++ b/src/caches/getGPUBuffer.ts @@ -1,4 +1,4 @@ -import { IBuffer, UnReadonly } from "@feng3d/render-api"; +import { Buffer, UnReadonly } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; /** @@ -24,9 +24,9 @@ const defaultGPUBufferUsage = 0 * @param buffer * @returns */ -export function getGPUBuffer(device: GPUDevice, buffer: IBuffer) +export function getGPUBuffer(device: GPUDevice, buffer: Buffer) { - const gBufferMap: WeakMap = device["_gBufferMap"] = device["_gBufferMap"] || new WeakMap(); + const gBufferMap: WeakMap = device["_gBufferMap"] = device["_gBufferMap"] || new WeakMap(); let gBuffer: GPUBuffer = gBufferMap.get(buffer); if (gBuffer) return gBuffer; @@ -34,7 +34,7 @@ export function getGPUBuffer(device: GPUDevice, buffer: IBuffer) const size = buffer.size; console.assert(size && (size % 4 === 0), `初始化缓冲区时必须设置缓冲区尺寸且必须为4的倍数!`); - (buffer as UnReadonly).usage = buffer.usage ?? defaultGPUBufferUsage; + (buffer as UnReadonly).usage = buffer.usage ?? defaultGPUBufferUsage; const label = buffer.label; const usage = buffer.usage; diff --git a/src/caches/getIGPUBuffer.ts b/src/caches/getIGPUBuffer.ts index 96bc2f3..52c72cc 100644 --- a/src/caches/getIGPUBuffer.ts +++ b/src/caches/getIGPUBuffer.ts @@ -1,4 +1,4 @@ -import { IBuffer, IVertexDataTypes, TypedArray, UnReadonly } from "@feng3d/render-api"; +import { Buffer, IVertexDataTypes, TypedArray, UnReadonly } from "@feng3d/render-api"; export function getIGPUBuffer(bufferSource: TypedArray) { @@ -8,7 +8,7 @@ export function getIGPUBuffer(bufferSource: TypedArray) arrayBuffer = (bufferSource as ArrayBufferView).buffer; } - const gpuBuffer: IBuffer = arrayBuffer["_IGPUBuffer"] = arrayBuffer["_IGPUBuffer"] || { + const gpuBuffer: Buffer = arrayBuffer["_IGPUBuffer"] = arrayBuffer["_IGPUBuffer"] || { size: Math.ceil(arrayBuffer.byteLength / 4) * 4, data: arrayBuffer, }; @@ -28,7 +28,7 @@ let autoVertexIndex = 0; export function getIGPUIndexBuffer(data: Uint16Array | Uint32Array) { const buffer = getIGPUBuffer(data); - (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); + (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); return buffer; } diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 9b509aa..999fbf6 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { getBlendConstantColor, IBlendState, IDepthStencilState, IFragmentState, IIndicesDataTypes, IRenderPipeline, IStencilFaceState, VertexAttributes, IVertexState, IWriteMask, PrimitiveState, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; +import { getBlendConstantColor, BlendState, IDepthStencilState, IFragmentState, IIndicesDataTypes, IRenderPipeline, IStencilFaceState, VertexAttributes, IVertexState, IWriteMask, PrimitiveState, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -433,7 +433,7 @@ function getNGPUFragmentState(fragmentState: IFragmentState, colorAttachments: r const fragmentStateMap = new ChainMap<[IFragmentState, string], NGPUFragmentState>(); -function getGPUBlendState(blend?: IBlendState): GPUBlendState +function getGPUBlendState(blend?: BlendState): GPUBlendState { if (!blend) undefined; diff --git a/src/data/IGPUBuffer.ts b/src/data/IGPUBuffer.ts index 9e1f65e..5c53df5 100644 --- a/src/data/IGPUBuffer.ts +++ b/src/data/IGPUBuffer.ts @@ -1,4 +1,4 @@ -import { IBuffer, IWriteBuffer } from "@feng3d/render-api"; +import { Buffer, IWriteBuffer } from "@feng3d/render-api"; declare module "@feng3d/render-api" { @@ -8,7 +8,7 @@ declare module "@feng3d/render-api" * {@link GPUBufferDescriptor} * {@link GPUBuffer} */ - export interface IBuffer + export interface Buffer { /** * The allowed usages for the buffer. diff --git a/src/data/IGPURenderPipeline.ts b/src/data/IGPURenderPipeline.ts index a7a5da5..fad3c53 100644 --- a/src/data/IGPURenderPipeline.ts +++ b/src/data/IGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { IBlendState } from "@feng3d/render-api"; +import { BlendState } from "@feng3d/render-api"; import { IGPUMultisampleState } from "./IGPUMultisampleState"; diff --git a/src/internal/IGPUIndexBuffer.ts b/src/internal/IGPUIndexBuffer.ts index 87838c8..6d4bf14 100644 --- a/src/internal/IGPUIndexBuffer.ts +++ b/src/internal/IGPUIndexBuffer.ts @@ -1,4 +1,4 @@ -import { IBuffer } from "@feng3d/render-api"; +import { Buffer } from "@feng3d/render-api"; /** * GPU渲染时使用的索引缓冲区。 @@ -12,7 +12,7 @@ export interface IGPUSetIndexBuffer * * 顶点索引缓冲区,包含提供给后续绘制命令使用的顶点索引数据。 */ - buffer: IBuffer; + buffer: Buffer; /** * Format of the index data contained in `buffer`. -- Gitee From 711b7dbf19e6ac3c85214819ae51d3ef42ca2860 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 01:38:16 +0800 Subject: [PATCH 008/214] CanvasContext CanvasTexture ColorTargetState CommandEncoder --- examples/src/webgpu/bitonicSort/bitonicDisplay.ts | 4 ++-- examples/src/webgpu/bitonicSort/index.ts | 4 ++-- examples/src/webgpu/bitonicSort/utils.ts | 6 +++--- examples/src/webgpu/cornell/index.ts | 6 +++--- examples/src/webgpu/cornell/radiosity.ts | 4 ++-- examples/src/webgpu/cornell/rasterizer.ts | 4 ++-- examples/src/webgpu/cornell/raytracer.ts | 4 ++-- examples/src/webgpu/cornell/tonemapper.ts | 4 ++-- src/data/IGPUCanvasContext.ts | 4 ++-- src/data/IGPUCommandEncoder.ts | 2 +- src/runs/RunWebGPU.ts | 4 ++-- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts index 05d0b72..b100283 100644 --- a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts +++ b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, ICommandEncoder, IRenderPassDescriptor, IUniforms } from "@feng3d/render-api"; +import { IBufferBinding, CommandEncoder, IRenderPassDescriptor, IUniforms } from "@feng3d/render-api"; import bitonicDisplay from "./bitonicDisplay.frag.wgsl"; import { Base2DRendererClass } from "./utils"; @@ -41,7 +41,7 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass }; } - startRun(commandEncoder: ICommandEncoder, args: BitonicDisplayRenderArgs) + startRun(commandEncoder: CommandEncoder, args: BitonicDisplayRenderArgs) { this.setArguments(args); super.executeRun(commandEncoder, this.renderPassDescriptor, this.pipeline, this.computeBGDescript); diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index b6d02f5..44dec4c 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,4 +1,4 @@ -import { Buffer, IBufferBinding, ICommandEncoder, IRenderPassDescriptor, ISubmit, IUniforms } from "@feng3d/render-api"; +import { Buffer, IBufferBinding, CommandEncoder, IRenderPassDescriptor, ISubmit, IUniforms } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -724,7 +724,7 @@ async function init( writeBuffers.push({ bufferOffset: 8, data: stepDetails }); iGPUBuffer.writeBuffers = writeBuffers; - const commandEncoder: ICommandEncoder = { passEncoders: [] }; + const commandEncoder: CommandEncoder = { passEncoders: [] }; const submit: ISubmit = { commandEncoders: [commandEncoder] }; bitonicDisplayRenderer.startRun(commandEncoder, { diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index 6b7c842..4448358 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -1,4 +1,4 @@ -import { ICommandEncoder, IRenderPass, IRenderPassDescriptor, IRenderPipeline, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, IRenderPass, IRenderPassDescriptor, IRenderPipeline, IUniforms } from "@feng3d/render-api"; const fullscreenTexturedQuad = ` @@ -39,7 +39,7 @@ export abstract class Base2DRendererClass { abstract switchBindGroup(name: string): void; abstract startRun( - commandEncoder: ICommandEncoder, + commandEncoder: CommandEncoder, ...args: unknown[] ): void; renderPassDescriptor: IRenderPassDescriptor; @@ -48,7 +48,7 @@ export abstract class Base2DRendererClass currentBindGroupName: string; executeRun( - commandEncoder: ICommandEncoder, + commandEncoder: CommandEncoder, renderPassDescriptor: IRenderPassDescriptor, pipeline: IRenderPipeline, bindingResources?: IUniforms diff --git a/examples/src/webgpu/cornell/index.ts b/examples/src/webgpu/cornell/index.ts index 43100bb..4646ea3 100644 --- a/examples/src/webgpu/cornell/index.ts +++ b/examples/src/webgpu/cornell/index.ts @@ -7,7 +7,7 @@ import Raytracer from "./raytracer"; import Scene from "./scene"; import Tonemapper from "./tonemapper"; -import { ICommandEncoder, ISubmit, ITexture } from "@feng3d/render-api"; +import { CommandEncoder, ISubmit, ITexture } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -55,13 +55,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const tonemapper = new Tonemapper(common, framebuffer, { context }); // 光栅化渲染 - const rasterizerCommandEncoder: ICommandEncoder = { passEncoders: [] }; + const rasterizerCommandEncoder: CommandEncoder = { passEncoders: [] }; radiosity.encode(rasterizerCommandEncoder); rasterizer.encode(rasterizerCommandEncoder); tonemapper.encode(rasterizerCommandEncoder); // 光线追踪渲染 - const raytracerCommandEncoder: ICommandEncoder = { passEncoders: [] }; + const raytracerCommandEncoder: CommandEncoder = { passEncoders: [] }; radiosity.encode(raytracerCommandEncoder); raytracer.encode(raytracerCommandEncoder); tonemapper.encode(raytracerCommandEncoder); diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index 99a575e..c0e5bf5 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -1,4 +1,4 @@ -import { ICommandEncoder, IPassEncoder, ITexture, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, IPassEncoder, ITexture, IUniforms } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -138,7 +138,7 @@ export default class Radiosity } private passEncoders: IPassEncoder[]; - encode(commandEncoder: ICommandEncoder) + encode(commandEncoder: CommandEncoder) { this.passEncoders.forEach((v) => { diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index 6bf211a..e51775f 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -1,4 +1,4 @@ -import { ICommandEncoder, IRenderPass, IRenderPassDescriptor, IRenderPipeline, ITexture, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, IRenderPass, IRenderPassDescriptor, IRenderPipeline, ITexture, IUniforms } from "@feng3d/render-api"; import Common from "./common"; import Radiosity from "./radiosity"; @@ -93,7 +93,7 @@ export default class Rasterizer } private renderPassEncoder: IRenderPass; - encode(commandEncoder: ICommandEncoder) + encode(commandEncoder: CommandEncoder) { commandEncoder.passEncoders.push(this.renderPassEncoder); } diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index 22a0b73..a6b0b26 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -1,4 +1,4 @@ -import { ICommandEncoder, IPassEncoder, ITexture, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, IPassEncoder, ITexture, IUniforms } from "@feng3d/render-api"; import { IGPUComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -69,7 +69,7 @@ export default class Raytracer } private passEncoder: IPassEncoder; - encode(commandEncoder: ICommandEncoder) + encode(commandEncoder: CommandEncoder) { commandEncoder.passEncoders.push(this.passEncoder); } diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index 18004fd..092bb42 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -1,4 +1,4 @@ -import { ICommandEncoder, IPassEncoder, ITexture, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, IPassEncoder, ITexture, IUniforms } from "@feng3d/render-api"; import { IGPUCanvasTexture, IGPUComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -60,7 +60,7 @@ export default class Tonemapper } private passEncoder: IPassEncoder; - encode(commandEncoder: ICommandEncoder) + encode(commandEncoder: CommandEncoder) { commandEncoder.passEncoders.push(this.passEncoder); } diff --git a/src/data/IGPUCanvasContext.ts b/src/data/IGPUCanvasContext.ts index 5f62a22..693ff13 100644 --- a/src/data/IGPUCanvasContext.ts +++ b/src/data/IGPUCanvasContext.ts @@ -1,4 +1,4 @@ -import { ICanvasContext } from "@feng3d/render-api"; +import { CanvasContext } from "@feng3d/render-api"; import { IGPUCanvasConfiguration } from "./IGPUCanvasConfiguration"; /** @@ -6,7 +6,7 @@ import { IGPUCanvasConfiguration } from "./IGPUCanvasConfiguration"; * @see HTMLCanvasElement.getContext * @see GPUCanvasContext.configure */ -export interface IGPUCanvasContext extends ICanvasContext +export interface IGPUCanvasContext extends CanvasContext { /** * 画布配置。默认有引擎自动设置。 diff --git a/src/data/IGPUCommandEncoder.ts b/src/data/IGPUCommandEncoder.ts index 952489a..08fc77b 100644 --- a/src/data/IGPUCommandEncoder.ts +++ b/src/data/IGPUCommandEncoder.ts @@ -1,4 +1,4 @@ -import { ICommandEncoder, IRenderPass } from "@feng3d/render-api"; +import { } from "@feng3d/render-api"; import { IGPUComputePass } from "./IGPUComputePass"; declare module "@feng3d/render-api" diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index beb0acf..e1431ed 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { ICommandEncoder, ICopyBufferToBuffer, ICopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IRenderObject, IRenderPass, IRenderPassObject, IRenderPipeline, IScissorRect, ISubmit, IUniforms, VertexAttributes, IViewport, PrimitiveState } from "@feng3d/render-api"; +import { CommandEncoder, ICopyBufferToBuffer, ICopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IRenderObject, IRenderPass, IRenderPassObject, IRenderPipeline, IScissorRect, ISubmit, IUniforms, VertexAttributes, IViewport, PrimitiveState } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -44,7 +44,7 @@ export class RunWebGPU anyEmitter.emit(device.queue, GPUQueue_submit); } - protected runCommandEncoder(device: GPUDevice, commandEncoder: ICommandEncoder) + protected runCommandEncoder(device: GPUDevice, commandEncoder: CommandEncoder) { const gpuCommandEncoder = device.createCommandEncoder(); -- Gitee From 14a0a98eaf3337b6931fa5f0e7d3331dab01ecf8 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 01:51:50 +0800 Subject: [PATCH 009/214] CopyBufferToBuffer CopyTextureToTexture DepthStencilState FragmentState --- examples/src/webgpu/fractalCube/index.ts | 4 ++-- examples/src/webgpu/normalMap/utils.ts | 4 ++-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 4 ++-- src/WebGPUStep.ts | 6 +++--- src/caches/getNGPURenderPipeline.ts | 12 ++++++------ src/data/IGPURenderPipeline.ts | 6 +++--- src/runs/RunWebGPU.ts | 6 +++--- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 0441c43..05aeb86 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, ICopyTextureToTexture, IRenderObject, IRenderPassDescriptor, ISampler, ISubmit, ITexture } from "@feng3d/render-api"; +import { IBufferBinding, CopyTextureToTexture, IRenderObject, IRenderPassDescriptor, ISampler, ISubmit, ITexture } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -99,7 +99,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const copyTextureToTexture: ICopyTextureToTexture = { + const copyTextureToTexture: CopyTextureToTexture = { __type: "CopyTextureToTexture", source: { texture: { context } }, destination: { texture: cubeTexture }, diff --git a/examples/src/webgpu/normalMap/utils.ts b/examples/src/webgpu/normalMap/utils.ts index 64dbc28..8e527e1 100644 --- a/examples/src/webgpu/normalMap/utils.ts +++ b/examples/src/webgpu/normalMap/utils.ts @@ -1,4 +1,4 @@ -import { IDepthStencilState, IRenderPipeline, ITexture } from "@feng3d/render-api"; +import { DepthStencilState, IRenderPipeline, ITexture } from "@feng3d/render-api"; export const create3DRenderPipeline = ( label: string, @@ -7,7 +7,7 @@ export const create3DRenderPipeline = ( depthTest = false, ) => { - let depthStencil: IDepthStencilState; + let depthStencil: DepthStencilState; if (depthTest) { depthStencil = { diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index b571a07..86b90a4 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { Buffer, IDraw, IFragmentState, PrimitiveState, IRenderObject, IRenderPipeline, IUniforms, VertexAttributes, IVertexState, vertexFormatMap } from "@feng3d/render-api"; +import { Buffer, FragmentState, IDraw, IRenderObject, IRenderPipeline, IUniforms, IVertexState, PrimitiveState, VertexAttributes, vertexFormatMap } from "@feng3d/render-api"; import { getIGPUBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -420,7 +420,7 @@ export class GLTFPrimitive code: VertexInputShaderString + vertexShader, }; - const fragmentState: IFragmentState = { + const fragmentState: FragmentState = { // Shader info code: VertexInputShaderString + fragmentShader, // Output render target info diff --git a/src/WebGPUStep.ts b/src/WebGPUStep.ts index e7735a0..4a9e6e5 100644 --- a/src/WebGPUStep.ts +++ b/src/WebGPUStep.ts @@ -1,4 +1,4 @@ -import { ICopyBufferToBuffer, ICopyTextureToTexture, IRenderObject, IRenderPass, IRenderPassDescriptor, IRenderPassObject, ISubmit } from "@feng3d/render-api"; +import { CopyBufferToBuffer, CopyTextureToTexture, IRenderObject, IRenderPass, IRenderPassDescriptor, IRenderPassObject, ISubmit } from "@feng3d/render-api"; import { IGPUComputeObject } from "./data/IGPUComputeObject"; import { IGPUComputePass } from "./data/IGPUComputePass"; @@ -52,7 +52,7 @@ export class WebGPUStep this._currentComputePassEncoder.computeObjects.push(computeObject); } - copyTextureToTexture(copyTextureToTexture: ICopyTextureToTexture) + copyTextureToTexture(copyTextureToTexture: CopyTextureToTexture) { this._currentSubmit = this._currentSubmit || { commandEncoders: [{ passEncoders: [] }] }; @@ -61,7 +61,7 @@ export class WebGPUStep this._currentSubmit.commandEncoders[0].passEncoders.push(copyTextureToTexture); } - copyBufferToBuffer(copyBufferToBuffer: ICopyBufferToBuffer) + copyBufferToBuffer(copyBufferToBuffer: CopyBufferToBuffer) { this._currentSubmit = this._currentSubmit || { commandEncoders: [{ passEncoders: [] }] }; diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 999fbf6..cf63b4d 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { getBlendConstantColor, BlendState, IDepthStencilState, IFragmentState, IIndicesDataTypes, IRenderPipeline, IStencilFaceState, VertexAttributes, IVertexState, IWriteMask, PrimitiveState, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; +import { BlendState, DepthStencilState, FragmentState, getBlendConstantColor, IIndicesDataTypes, IRenderPipeline, IStencilFaceState, IVertexState, IWriteMask, PrimitiveState, VertexAttributes, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -103,7 +103,7 @@ const renderPipelineMap = new ChainMap< * @param depthStencil * @returns */ -function getStencilReference(depthStencil?: IDepthStencilState) +function getStencilReference(depthStencil?: DepthStencilState) { if (!depthStencil) return undefined; @@ -176,7 +176,7 @@ function getGPUMultisampleState(multisampleState?: IGPUMultisampleState, sampleC * @param depthStencilFormat 深度模板附件纹理格式。 * @returns 深度模板阶段完整描述。 */ -function getGPUDepthStencilState(depthStencil: IDepthStencilState, depthStencilFormat?: GPUTextureFormat) +function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFormat?: GPUTextureFormat) { if (!depthStencilFormat) return undefined; // @@ -362,7 +362,7 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) * @param colorAttachmentTextureFormats 颜色附件格式。 * @returns 片段阶段完整描述。 */ -function getNGPUFragmentState(fragmentState: IFragmentState, colorAttachments: readonly GPUTextureFormat[]) +function getNGPUFragmentState(fragmentState: FragmentState, colorAttachments: readonly GPUTextureFormat[]) { if (!fragmentState) return undefined; @@ -419,7 +419,7 @@ function getNGPUFragmentState(fragmentState: IFragmentState, colorAttachments: r fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); // 监听变化 - const watchpropertys: gPartial = { code: "" }; + const watchpropertys: gPartial = { code: "" }; const onchanged = () => { fragmentStateMap.delete([fragmentState, colorAttachmentsKey]); @@ -431,7 +431,7 @@ function getNGPUFragmentState(fragmentState: IFragmentState, colorAttachments: r return gpuFragmentState; } -const fragmentStateMap = new ChainMap<[IFragmentState, string], NGPUFragmentState>(); +const fragmentStateMap = new ChainMap<[FragmentState, string], NGPUFragmentState>(); function getGPUBlendState(blend?: BlendState): GPUBlendState { diff --git a/src/data/IGPURenderPipeline.ts b/src/data/IGPURenderPipeline.ts index fad3c53..925be50 100644 --- a/src/data/IGPURenderPipeline.ts +++ b/src/data/IGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState } from "@feng3d/render-api"; +import { BlendState,DepthStencilState } from "@feng3d/render-api"; import { IGPUMultisampleState } from "./IGPUMultisampleState"; @@ -63,7 +63,7 @@ declare module "@feng3d/render-api" * * {@link GPUFragmentState} */ - export interface IFragmentState + export interface FragmentState { /** * The name of the function in {@link GPUProgrammableStage#module} that this stage will use to @@ -115,7 +115,7 @@ declare module "@feng3d/render-api" * * @see https://www.orillusion.com/zh/webgpu.html#depth-stencil-state */ - export interface IDepthStencilState + export interface DepthStencilState { /** * 片元的最大深度偏差。 diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index e1431ed..0b66e20 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, ICopyBufferToBuffer, ICopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IRenderObject, IRenderPass, IRenderPassObject, IRenderPipeline, IScissorRect, ISubmit, IUniforms, VertexAttributes, IViewport, PrimitiveState } from "@feng3d/render-api"; +import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IRenderObject, IRenderPass, IRenderPassObject, IRenderPipeline, IScissorRect, ISubmit, IUniforms, IViewport, PrimitiveState, VertexAttributes } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -168,7 +168,7 @@ export class RunWebGPU }); } - protected runCopyTextureToTexture(device: GPUDevice, commandEncoder: GPUCommandEncoder, copyTextureToTexture: ICopyTextureToTexture) + protected runCopyTextureToTexture(device: GPUDevice, commandEncoder: GPUCommandEncoder, copyTextureToTexture: CopyTextureToTexture) { const sourceTexture = getGPUTexture(device, copyTextureToTexture.source.texture); const destinationTexture = getGPUTexture(device, copyTextureToTexture.destination.texture); @@ -190,7 +190,7 @@ export class RunWebGPU ); } - protected runCopyBufferToBuffer(device: GPUDevice, commandEncoder: GPUCommandEncoder, v: ICopyBufferToBuffer) + protected runCopyBufferToBuffer(device: GPUDevice, commandEncoder: GPUCommandEncoder, v: CopyBufferToBuffer) { v.sourceOffset ||= 0; v.destinationOffset ||= 0; -- Gitee From 2d0b4126d5f2c478c5d376928846d1e6b62b1c3a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 02:31:45 +0800 Subject: [PATCH 010/214] RenderObject --- .../src/webgpu/RenderObjectChanges/index.ts | 6 +-- examples/src/webgpu/a-buffer/index.ts | 26 +++++------ examples/src/webgpu/animometer/index.ts | 16 +++---- .../webgpu/atmosphericScatteringSky/index.ts | 4 +- .../src/webgpu/bitonicSort/bitonicDisplay.ts | 8 ++-- examples/src/webgpu/bitonicSort/index.ts | 10 ++-- examples/src/webgpu/bitonicSort/utils.ts | 16 +++---- examples/src/webgpu/blending/index.ts | 46 ++++++++++--------- examples/src/webgpu/cameras/index.ts | 16 +++---- examples/src/webgpu/computeBoids/index.ts | 10 ++-- examples/src/webgpu/cornell/common.ts | 6 +-- examples/src/webgpu/cornell/index.ts | 6 +-- examples/src/webgpu/cornell/radiosity.ts | 6 +-- examples/src/webgpu/cornell/rasterizer.ts | 14 +++--- examples/src/webgpu/cornell/raytracer.ts | 8 ++-- examples/src/webgpu/cornell/tonemapper.ts | 6 +-- examples/src/webgpu/cubemap/index.ts | 12 ++--- .../src/webgpu/deferredRendering/index.ts | 36 +++++++-------- examples/src/webgpu/fractalCube/index.ts | 12 ++--- examples/src/webgpu/gameOfLife/index.ts | 16 +++---- examples/src/webgpu/helloTriangle/index.ts | 4 +- .../src/webgpu/helloTriangleMSAA/index.ts | 8 ++-- examples/src/webgpu/imageBlur/index.ts | 34 +++++++------- examples/src/webgpu/instancedCube/index.ts | 8 ++-- examples/src/webgpu/multipleCanvases/index.ts | 14 +++--- examples/src/webgpu/normalMap/index.ts | 30 ++++++------ examples/src/webgpu/normalMap/utils.ts | 6 +-- examples/src/webgpu/occlusionQuery/index.ts | 16 +++---- examples/src/webgpu/particles/index.ts | 20 ++++---- examples/src/webgpu/points/index.ts | 12 ++--- examples/src/webgpu/renderBundles/index.ts | 32 ++++++------- examples/src/webgpu/resizeCanvas/index.ts | 8 ++-- .../src/webgpu/resizeObserverHDDPI/index.ts | 10 ++-- examples/src/webgpu/reversedZ/index.ts | 44 +++++++++--------- examples/src/webgpu/rotatingCube/index.ts | 8 ++-- .../src/webgpu/samplerParameters/index.ts | 18 ++++---- examples/src/webgpu/shadowMapping/index.ts | 22 ++++----- examples/src/webgpu/skinnedMesh/glbUtils.ts | 16 +++---- examples/src/webgpu/skinnedMesh/gridUtils.ts | 4 +- examples/src/webgpu/skinnedMesh/index.ts | 22 ++++----- .../src/webgpu/textRenderingMsdf/index.ts | 12 ++--- .../src/webgpu/textRenderingMsdf/msdfText.ts | 18 ++++---- examples/src/webgpu/texturedCube/index.ts | 12 ++--- examples/src/webgpu/timestampQuery/index.ts | 12 ++--- .../src/webgpu/transparentCanvas/index.ts | 8 ++-- examples/src/webgpu/twoCubes/index.ts | 10 ++-- examples/src/webgpu/videoUploading/index.ts | 10 ++-- .../webgpu/volumeRenderingTexture3D/index.ts | 14 +++--- examples/src/webgpu/wireframe/index.ts | 24 +++++----- examples/src/webgpu/worker/worker.ts | 8 ++-- src/WebGPU.ts | 4 +- src/WebGPUStep.ts | 12 ++--- src/caches/getGPUBindGroup.ts | 12 ++--- src/caches/getGPURenderOcclusionQuery.ts | 6 +-- src/caches/getGPURenderPassDescriptor.ts | 24 +++++----- src/caches/getGPURenderPassFormat.ts | 4 +- src/caches/getGPURenderTimestampQuery.ts | 4 +- src/caches/getGPUSampler.ts | 8 ++-- src/caches/getGPUTexture.ts | 4 +- src/caches/getGPUTextureView.ts | 8 ++-- src/caches/getIGPUSetBindGroups.ts | 8 ++-- src/caches/getNGPURenderPipeline.ts | 8 ++-- src/data/IGPUBindingResources.ts | 6 +-- src/data/IGPUComputeObject.ts | 4 +- src/data/IGPUMultisampleState.ts | 4 +- src/data/IGPUOcclusionQuery.ts | 4 +- src/data/IGPURenderBundle.ts | 4 +- src/data/IGPURenderObject.ts | 2 +- src/data/IGPURenderPass.ts | 4 +- src/data/IGPURenderPassColorAttachment.ts | 6 +-- .../IGPURenderPassDepthStencilAttachment.ts | 6 +-- src/data/IGPURenderPassDescriptor.ts | 4 +- src/data/IGPURenderPipeline.ts | 2 +- src/data/IGPUTexture.ts | 4 +- src/data/IGPUTextureView.ts | 2 +- src/internal/IGPUBindGroupDescriptor.ts | 4 +- src/internal/IGPUTextureMultisample.ts | 4 +- src/internal/internal.ts | 6 +-- src/runs/RunWebGPU.ts | 24 +++++----- src/runs/RunWebGPUCommandCache.ts | 10 ++-- 80 files changed, 475 insertions(+), 471 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index 786a4e6..98543ac 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, ISubmit } from "@feng3d/render-api"; +import { Submit, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement) => @@ -9,7 +9,7 @@ const init = async (canvas: HTMLCanvasElement) => const webgpu = await new WebGPU().init(); // 初始化WebGPU - const renderObject: IRenderObject = { // 渲染对象 + const renderObject: RenderObject = { // 渲染对象 pipeline: { // 渲染管线 vertex: { // 顶点着色器 code: ` @@ -39,7 +39,7 @@ const init = async (canvas: HTMLCanvasElement) => uniforms: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 }; - const submit: ISubmit = { // 一次GPU提交 + const submit: Submit = { // 一次GPU提交 commandEncoders: [ // 命令编码列表 { passEncoders: [ // 通道编码列表 diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index c0e68e0..d1cbbe0 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, IPassEncoder, IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, ITextureView, VertexAttributes } from "@feng3d/render-api"; +import { IBufferBinding, IPassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -56,7 +56,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => targetWidth: undefined, }; - const opaquePipeline: IRenderPipeline = { + const opaquePipeline: RenderPipeline = { vertex: { code: opaqueWGSL, }, @@ -70,7 +70,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => label: "opaquePipeline", }; - const translucentPipeline: IRenderPipeline = { + const translucentPipeline: RenderPipeline = { vertex: { code: translucentWGSL, }, @@ -85,7 +85,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => label: "translucentPipeline", }; - const translucentPassDescriptor: IRenderPassDescriptor = { + const translucentPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { loadOp: "load", @@ -96,7 +96,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => label: "translucentPassDescriptor", }; - const compositePipeline: IRenderPipeline = { + const compositePipeline: RenderPipeline = { vertex: { code: compositeWGSL, }, @@ -118,7 +118,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => label: "compositePipeline", }; - const compositePassDescriptor: IRenderPassDescriptor = { + const compositePassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context } }, @@ -158,13 +158,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => canvas.width = canvas.clientWidth * devicePixelRatio; canvas.height = canvas.clientHeight * devicePixelRatio; - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: "depth24plus", label: "depthTexture", }; - const depthTextureView: ITextureView = { + const depthTextureView: TextureView = { label: "depthTextureView", texture: depthTexture, }; @@ -226,7 +226,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => sliceInfo: { sliceStartY: undefined }, }; - const opaquePassDescriptor: IRenderPassDescriptor = { + const opaquePassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context } }, @@ -274,7 +274,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const passEncoders: IPassEncoder[] = []; // Draw the opaque objects - const opaquePassEncoder: IRenderPass = { + const opaquePassEncoder: RenderPass = { descriptor: opaquePassDescriptor, renderObjects: [{ pipeline: opaquePipeline, @@ -309,7 +309,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Draw the translucent objects - const translucentPassEncoder: IRenderPass = { + const translucentPassEncoder: RenderPass = { descriptor: translucentPassDescriptor, renderObjects: [ // Set the scissor to only process a horizontal slice of the frame @@ -334,7 +334,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders.push(translucentPassEncoder); // Composite the opaque and translucent objects - const compositePassEncoder: IRenderPass + const compositePassEncoder: RenderPass = { descriptor: compositePassDescriptor, renderObjects: [ @@ -358,7 +358,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders.push(compositePassEncoder); } - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders, }], diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index 00511fa..bde02fd 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import animometerWGSL from "./animometer.wgsl"; -import { IRenderObject, IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, RenderObject } from "@feng3d/render-api"; import { IGPURenderBundle, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -33,7 +33,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const vec4Size = 4 * Float32Array.BYTES_PER_ELEMENT; - const pipelineDesc: IRenderPipeline = { + const pipelineDesc: RenderPipeline = { vertex: { code: animometerWGSL, }, @@ -42,7 +42,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { ...pipelineDesc, }; @@ -53,7 +53,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => 0.1, -0.1, 0, 1, /**/ 0, 0, 1, 1, ]); - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline, uniforms: {}, geometry: { @@ -90,7 +90,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => value: 0, }; - const renderObjects0: IRenderObject[] = []; + const renderObjects0: RenderObject[] = []; for (let i = 0; i < maxTriangles; ++i) { renderObjects0[i] = { @@ -104,7 +104,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; } - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -127,8 +127,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects }; - const renderPasss: IRenderPass[] = []; - const submit: ISubmit = { + const renderPasss: RenderPass[] = []; + const submit: Submit = { commandEncoders: [ { passEncoders: renderPasss, diff --git a/examples/src/webgpu/atmosphericScatteringSky/index.ts b/examples/src/webgpu/atmosphericScatteringSky/index.ts index 8328949..e4aa869 100644 --- a/examples/src/webgpu/atmosphericScatteringSky/index.ts +++ b/examples/src/webgpu/atmosphericScatteringSky/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import atmosphericScatteringSkyWGSL from "./atmosphericScatteringSky.wgsl"; -import { ITexture } from "@feng3d/render-api"; +import { Texture } from "@feng3d/render-api"; import { IGPUCanvasContext, IGPUComputeObject, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -21,7 +21,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); - const framebuffer: ITexture = { + const framebuffer: Texture = { label: "framebuffer", size: [canvas.width, canvas.height], format: "rgba16float", diff --git a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts index b100283..0cce530 100644 --- a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts +++ b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, CommandEncoder, IRenderPassDescriptor, IUniforms } from "@feng3d/render-api"; +import { IBufferBinding, CommandEncoder, RenderPassDescriptor, Uniforms } from "@feng3d/render-api"; import bitonicDisplay from "./bitonicDisplay.frag.wgsl"; import { Base2DRendererClass } from "./utils"; @@ -12,11 +12,11 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass { switchBindGroup: (name: string) => void; setArguments: (args: BitonicDisplayRenderArgs) => void; - computeBGDescript: IUniforms; + computeBGDescript: Uniforms; constructor( - renderPassDescriptor: IRenderPassDescriptor, - computeBGDescript: IUniforms, + renderPassDescriptor: RenderPassDescriptor, + computeBGDescript: Uniforms, label: string ) { diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 44dec4c..ed36aa9 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,4 +1,4 @@ -import { Buffer, IBufferBinding, CommandEncoder, IRenderPassDescriptor, ISubmit, IUniforms } from "@feng3d/render-api"; +import { Buffer, IBufferBinding, CommandEncoder, RenderPassDescriptor, Submit, Uniforms } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -283,7 +283,7 @@ async function init( bufferView: new Float32Array(4), }; - const computeBGCluster: IUniforms = { + const computeBGCluster: Uniforms = { input_data: elementsInputBuffer, data: elementsInputBuffer, output_data: elementsOutputBuffer, @@ -305,7 +305,7 @@ async function init( }; // Create bitonic debug renderer - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, // Assigned later @@ -375,7 +375,7 @@ async function init( nextBlockHeightController.setValue(2); // Reset Total Swaps by setting atomic value to 0 - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders: [{ __type: "ComputePass", @@ -725,7 +725,7 @@ async function init( iGPUBuffer.writeBuffers = writeBuffers; const commandEncoder: CommandEncoder = { passEncoders: [] }; - const submit: ISubmit = { commandEncoders: [commandEncoder] }; + const submit: Submit = { commandEncoders: [commandEncoder] }; bitonicDisplayRenderer.startRun(commandEncoder, { highlight: settings["Display Mode"] === "Elements" ? 0 : 1, diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index 4448358..cd27a95 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, IRenderPass, IRenderPassDescriptor, IRenderPipeline, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Uniforms } from "@feng3d/render-api"; const fullscreenTexturedQuad = ` @@ -42,19 +42,19 @@ export abstract class Base2DRendererClass commandEncoder: CommandEncoder, ...args: unknown[] ): void; - renderPassDescriptor: IRenderPassDescriptor; - pipeline: IRenderPipeline; + renderPassDescriptor: RenderPassDescriptor; + pipeline: RenderPipeline; bindGroupMap: Record; currentBindGroupName: string; executeRun( commandEncoder: CommandEncoder, - renderPassDescriptor: IRenderPassDescriptor, - pipeline: IRenderPipeline, - bindingResources?: IUniforms + renderPassDescriptor: RenderPassDescriptor, + pipeline: RenderPipeline, + bindingResources?: Uniforms ) { - const passEncoder: IRenderPass = { + const passEncoder: RenderPass = { descriptor: renderPassDescriptor, renderObjects: [{ pipeline, @@ -76,7 +76,7 @@ export abstract class Base2DRendererClass code: string, ) { - const renderPipeline: IRenderPipeline = { + const renderPipeline: RenderPipeline = { label: `${label}.pipeline`, vertex: { code: fullscreenTexturedQuad, diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 8c17250..6e4bc9b 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -2,9 +2,17 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import texturedQuadWGSL from "./texturedQuad.wgsl"; -import { BlendComponent, IRenderObject, IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISampler, ISubmit, ITexture, ITextureView, IUniforms } from "@feng3d/render-api"; +import { BlendComponent, RenderPassDescriptor, IRenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureView, Uniforms, RenderObject } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; +// declare module "@feng3d/render-api" +// { +// interface Uniforms +// { +// matrix: Float32Array; +// } +// } + const init = async (canvas: HTMLCanvasElement, gui: GUI) => { // creates a CSS hsl string from 3 normalized numbers (0 to 1) @@ -94,7 +102,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => canvas.height = canvas.clientHeight * devicePixelRatio; const context: IGPUCanvasContext = { canvasId: canvas.id, configuration: {} }; - const canvasTexture: ITextureView = { texture: { context } }; + const canvasTexture: TextureView = { texture: { context } }; // Get a WebGPU context from the canvas and configure it const webgpu = await new WebGPU().init(); @@ -108,7 +116,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ) { const { flipY, premultipliedAlpha } = options; - const texture: ITexture = { + const texture: Texture = { format: "rgba8unorm", size: [source.width, source.height], sources: [{ image: source, flipY, premultipliedAlpha }] @@ -135,16 +143,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { premultipliedAlpha: true } ); - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", mipmapFilter: "linear", }; - type Uniforms = { - matrix: Float32Array; - }; - // function makeUniformBufferAndValues(): Uniforms // { // // offsets to the various uniform values in float32 indices @@ -163,25 +167,25 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const srcUniform = { matrix: new Float32Array(16) }; const dstUniform = { matrix: new Float32Array(16) }; - const srcBindGroupUnpremultipliedAlpha: IUniforms = { + const srcBindGroupUnpremultipliedAlpha: Uniforms = { ourSampler: sampler, ourTexture: { texture: srcTextureUnpremultipliedAlpha }, uni: srcUniform, }; - const dstBindGroupUnpremultipliedAlpha: IUniforms = { + const dstBindGroupUnpremultipliedAlpha: Uniforms = { ourSampler: sampler, ourTexture: { texture: dstTextureUnpremultipliedAlpha }, uni: dstUniform, }; - const srcBindGroupPremultipliedAlpha: IUniforms = { + const srcBindGroupPremultipliedAlpha: Uniforms = { ourSampler: sampler, ourTexture: { texture: srcTexturePremultipliedAlpha }, uni: srcUniform, }; - const dstBindGroupPremultipliedAlpha: IUniforms = { + const dstBindGroupPremultipliedAlpha: Uniforms = { ourSampler: sampler, ourTexture: { texture: dstTexturePremultipliedAlpha }, uni: dstUniform, @@ -203,7 +207,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ]; const clearValue: [red: number, green: number, blue: number, alpha: number] = [0, 0, 0, 0]; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { label: "our basic canvas renderPass", colorAttachments: [ { @@ -429,7 +433,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => clearFolder.add(clear, "alpha", 0, 1).onChange(render); clearFolder.addColor(new GUIColorHelper(clear.color), "value").onChange(render); - const dstPipeline: IRenderPipeline = { + const dstPipeline: RenderPipeline = { label: "hardcoded textured quad pipeline", vertex: { code: texturedQuadWGSL, @@ -443,7 +447,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { gui.updateDisplay(); - const srcPipeline: IRenderPipeline = { + const srcPipeline: RenderPipeline = { label: "hardcoded textured quad pipeline", vertex: { code: texturedQuadWGSL, @@ -480,7 +484,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => function updateUniforms( uniforms: Uniforms, canvas: HTMLCanvasElement, - texture: ITexture + texture: Texture ) { const projectionMatrix = mat4.ortho( @@ -503,18 +507,18 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => updateUniforms(srcUniform, canvas, srcTexture); updateUniforms(dstUniform, canvas, dstTexture); - const ro: IRenderObject = { + const ro: RenderObject = { pipeline: dstPipeline, uniforms: dstBindGroup, - geometry:{ + geometry: { draw: { __type: "DrawVertex", vertexCount: 6 }, } }; - const ro1: IRenderObject = { + const ro1: RenderObject = { pipeline: srcPipeline, uniforms: srcBindGroup, - geometry:{ + geometry: { draw: { __type: "DrawVertex", vertexCount: 6 }, } }; @@ -524,7 +528,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ro1, ]; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index a4a3919..57a4813 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -5,7 +5,7 @@ import { ArcballCamera, WASDCamera } from "./camera"; import cubeWGSL from "./cube.wgsl"; import { createInputHandler } from "./input"; -import { IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: cubeWGSL, }, @@ -60,13 +60,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: "depth24plus", }; // Fetch the image and upload it into a GPUTexture. - let cubeTexture: ITexture; + let cubeTexture: Texture; { const response = await fetch("../../../assets/img/Di-3d.png"); const imageBitmap = await createImageBitmap(await response.blob()); @@ -79,7 +79,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } // Create a sampler with linear filtering for smooth interpolation. - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", }; @@ -92,7 +92,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => myTexture: { texture: cubeTexture }, }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline, uniforms: bindingResources, geometry:{ @@ -105,7 +105,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -124,7 +124,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index adcae5b..16a7015 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, ISubmit } from "@feng3d/render-api"; +import { RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; import { IGPUComputeObject, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -81,7 +81,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const renderPass: IRenderPassDescriptor = { + const renderPass: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -90,7 +90,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ], }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: spriteWGSL }, fragment: { code: spriteWGSL }, }, @@ -107,7 +107,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; - const renderObject1: IRenderObject = { + const renderObject1: RenderObject = { ...renderObject, geometry: { ...renderObject.geometry, @@ -129,7 +129,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => let t = 0; function frame() { - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/cornell/common.ts b/examples/src/webgpu/cornell/common.ts index 3b42357..b02e3d6 100644 --- a/examples/src/webgpu/cornell/common.ts +++ b/examples/src/webgpu/cornell/common.ts @@ -1,4 +1,4 @@ -import { IUniforms } from "@feng3d/render-api"; +import { Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -13,7 +13,7 @@ export default class Common readonly wgsl = commonWGSL; /** The common uniform buffer bind group and layout */ readonly uniforms: { - bindGroup: IUniforms; + bindGroup: Uniforms; }; private readonly uniformBuffer: Uint8Array; @@ -27,7 +27,7 @@ export default class Common + 4 * 16 // inv_mvp + 4 * 4); - const bindGroup: IUniforms = { + const bindGroup: Uniforms = { common_uniforms: { bufferView: this.uniformBuffer, }, diff --git a/examples/src/webgpu/cornell/index.ts b/examples/src/webgpu/cornell/index.ts index 4646ea3..93d2a83 100644 --- a/examples/src/webgpu/cornell/index.ts +++ b/examples/src/webgpu/cornell/index.ts @@ -7,7 +7,7 @@ import Raytracer from "./raytracer"; import Scene from "./scene"; import Tonemapper from "./tonemapper"; -import { CommandEncoder, ISubmit, ITexture } from "@feng3d/render-api"; +import { CommandEncoder, Submit, Texture } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -41,7 +41,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(undefined, { requiredFeatures }); - const framebuffer: ITexture = { + const framebuffer: Texture = { label: "framebuffer", size: [canvas.width, canvas.height], format: "rgba16float", @@ -74,7 +74,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); radiosity.run(); - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [params.renderer === "rasterizer" ? rasterizerCommandEncoder : raytracerCommandEncoder] }; diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index c0e5bf5..4c61d52 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, IPassEncoder, ITexture, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -17,7 +17,7 @@ export default class Radiosity static readonly lightmapHeight = 256; // The output lightmap. - readonly lightmap: ITexture; + readonly lightmap: Texture; // Number of photons emitted per workgroup. // This is equal to the workgroup size (one photon per invocation) @@ -39,7 +39,7 @@ export default class Radiosity private readonly scene: Scene; private readonly radiosityPipeline: IGPUComputePipeline; private readonly accumulationToLightmapPipeline: IGPUComputePipeline; - private readonly bindGroup: IUniforms; + private readonly bindGroup: Uniforms; private readonly accumulationBuffer: Uint8Array; private readonly uniformBuffer: Uint8Array; diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index e51775f..7cf7747 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, IRenderPass, IRenderPassDescriptor, IRenderPipeline, ITexture, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Texture, Uniforms } from "@feng3d/render-api"; import Common from "./common"; import Radiosity from "./radiosity"; @@ -12,15 +12,15 @@ export default class Rasterizer { private readonly common: Common; private readonly scene: Scene; - private readonly renderPassDescriptor: IRenderPassDescriptor; - private readonly pipeline: IRenderPipeline; - private readonly bindGroup: IUniforms; + private readonly renderPassDescriptor: RenderPassDescriptor; + private readonly pipeline: RenderPipeline; + private readonly bindGroup: Uniforms; constructor( common: Common, scene: Scene, radiosity: Radiosity, - framebuffer: ITexture, + framebuffer: Texture, ) { this.common = common; @@ -28,7 +28,7 @@ export default class Rasterizer const framebufferSize = framebuffer.size; - const depthTexture: ITexture = { + const depthTexture: Texture = { label: "RasterizerRenderer.depthTexture", size: [framebufferSize[0], framebufferSize[1]], format: "depth24plus", @@ -91,7 +91,7 @@ export default class Rasterizer }], }; } - private renderPassEncoder: IRenderPass; + private renderPassEncoder: RenderPass; encode(commandEncoder: CommandEncoder) { diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index a6b0b26..e925e1c 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, IPassEncoder, ITexture, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; import { IGPUComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -11,9 +11,9 @@ import raytracerWGSL from "./raytracer.wgsl"; export default class Raytracer { private readonly common: Common; - private readonly framebuffer: ITexture; + private readonly framebuffer: Texture; private readonly pipeline: IGPUComputePipeline; - private readonly bindGroup: IUniforms; + private readonly bindGroup: Uniforms; private readonly kWorkgroupSizeX = 16; private readonly kWorkgroupSizeY = 16; @@ -21,7 +21,7 @@ export default class Raytracer constructor( common: Common, radiosity: Radiosity, - framebuffer: ITexture, + framebuffer: Texture, ) { this.common = common; diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index 092bb42..1707adb 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, IPassEncoder, ITexture, IUniforms } from "@feng3d/render-api"; +import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; import { IGPUCanvasTexture, IGPUComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -10,7 +10,7 @@ import tonemapperWGSL from "./tonemapper.wgsl"; */ export default class Tonemapper { - private readonly bindGroup: IUniforms; + private readonly bindGroup: Uniforms; private readonly pipeline: IGPUComputePipeline; private readonly width: number; private readonly height: number; @@ -19,7 +19,7 @@ export default class Tonemapper constructor( common: Common, - input: ITexture, + input: Texture, output: IGPUCanvasTexture, ) { diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index 2fd1f18..1435f09 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, IRenderObject, IRenderPassDescriptor, ISampler, ISubmit, ITexture, ITextureImageSource } from "@feng3d/render-api"; +import { IBufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, ITextureImageSource, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -16,7 +16,7 @@ const init = async (canvas: HTMLCanvasElement) => // Fetch the 6 separate images for negative/positive x, y, z axis of a cubemap // and upload it into a GPUTexture. - let cubemapTexture: ITexture; + let cubemapTexture: Texture; { // The order of the array layers is [+X, -X, +Y, -Y, +Z, -Z] const imgSrcs = [ @@ -70,7 +70,7 @@ const init = async (canvas: HTMLCanvasElement) => }; } - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", }; @@ -106,7 +106,7 @@ const init = async (canvas: HTMLCanvasElement) => ); } - const renderPass: IRenderPassDescriptor = { + const renderPass: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -119,7 +119,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleCubemapWGSL }, }, @@ -148,7 +148,7 @@ const init = async (canvas: HTMLCanvasElement) => (renderObject.uniforms.uniforms as IBufferBinding).modelViewProjectionMatrix = modelViewProjectionMatrix; - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 77c7ec8..5b0b758 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -10,7 +10,7 @@ import lightUpdate from "./lightUpdate.wgsl"; import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; -import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, ITextureView, IUniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const kMaxNumLights = 1024; @@ -51,19 +51,19 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } // GBuffer texture render targets - const gBufferTexture2DFloat32: ITexture = { + const gBufferTexture2DFloat32: Texture = { size: [canvas.width, canvas.height], format: "rgba32float", }; - const gBufferTexture2DFloat16: ITexture = { + const gBufferTexture2DFloat16: Texture = { size: [canvas.width, canvas.height], format: "rgba16float", }; - const gBufferTextureAlbedo: ITexture = { + const gBufferTextureAlbedo: Texture = { size: [canvas.width, canvas.height], format: "bgra8unorm", }; - const gBufferTextureViews: ITextureView[] = [ + const gBufferTextureViews: TextureView[] = [ { texture: gBufferTexture2DFloat32 }, { texture: gBufferTexture2DFloat16 }, { texture: gBufferTextureAlbedo }, @@ -74,7 +74,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullMode: "back", }; - const writeGBuffersPipeline: IRenderPipeline = { + const writeGBuffersPipeline: RenderPipeline = { vertex: { code: vertexWriteGBuffers, }, @@ -83,7 +83,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const gBuffersDebugViewPipeline: IRenderPipeline = { + const gBuffersDebugViewPipeline: RenderPipeline = { vertex: { code: vertexTextureQuad, }, @@ -95,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }, }; - const deferredRenderPipeline: IRenderPipeline = { + const deferredRenderPipeline: RenderPipeline = { vertex: { code: vertexTextureQuad, }, @@ -104,12 +104,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: "depth24plus", }; - const writeGBufferPassDescriptor: IRenderPassDescriptor = { + const writeGBufferPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: gBufferTextureViews[0], @@ -141,7 +141,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const textureQuadPassDescriptor: IRenderPassDescriptor = { + const textureQuadPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -177,7 +177,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const cameraUniformBuffer = new Uint8Array(4 * 16); - const sceneUniformBindGroup: IUniforms = { + const sceneUniformBindGroup: Uniforms = { uniforms: { bufferView: modelUniformBuffer, }, @@ -186,7 +186,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const gBufferTexturesBindGroup: IUniforms = { + const gBufferTexturesBindGroup: Uniforms = { gBufferPosition: gBufferTextureViews[0], gBufferNormal: gBufferTextureViews[1], gBufferAlbedo: gBufferTextureViews[2], @@ -236,7 +236,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => code: lightUpdate, }, }; - const lightsBufferBindGroup: IUniforms = { + const lightsBufferBindGroup: Uniforms = { lightsBuffer: { bufferView: lightsBuffer, }, @@ -244,7 +244,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => bufferView: configUniformBuffer, }, }; - const lightsBufferComputeBindGroup: IUniforms = { + const lightsBufferComputeBindGroup: Uniforms = { lightsBuffer: { bufferView: lightsBuffer, }, @@ -322,7 +322,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => return viewProjMatrix as Float32Array; } - const passEncoders: (IGPUComputePass | IRenderPass)[] = []; + const passEncoders: (IGPUComputePass | RenderPass)[] = []; passEncoders.push({ descriptor: writeGBufferPassDescriptor, renderObjects: [ @@ -353,7 +353,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ] }); - const gBuffersPassEncoders: (IGPUComputePass | IRenderPass)[] = passEncoders.concat(); + const gBuffersPassEncoders: (IGPUComputePass | RenderPass)[] = passEncoders.concat(); gBuffersPassEncoders.push({ descriptor: textureQuadPassDescriptor, @@ -400,7 +400,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => getIGPUBuffer(cameraUniformBuffer).writeBuffers = [{ data: cameraViewProj }]; } - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders: settings.mode === "gBuffers view" ? gBuffersPassEncoders : passEncoders, diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 05aeb86..64d8071 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, CopyTextureToTexture, IRenderObject, IRenderPassDescriptor, ISampler, ISubmit, ITexture } from "@feng3d/render-api"; +import { CopyTextureToTexture, IBufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, RenderObject } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -18,13 +18,13 @@ const init = async (canvas: HTMLCanvasElement) => // We will copy the frame's rendering results into this texture and // sample it on the next frame. - const cubeTexture: ITexture = { + const cubeTexture: Texture = { size: [canvas.width, canvas.height], format: presentationFormat, }; // Create a sampler with linear filtering for smooth interpolation. - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", }; @@ -62,7 +62,7 @@ const init = async (canvas: HTMLCanvasElement) => } }; - const renderPass: IRenderPassDescriptor = { + const renderPass: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context } }, @@ -76,7 +76,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleSelfWGSL }, }, @@ -112,7 +112,7 @@ const init = async (canvas: HTMLCanvasElement) => (renderObject.uniforms.uniforms as IBufferBinding).modelViewProjectionMatrix = transformationMatrix; - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 6f6b6ce..dbcb92e 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -4,7 +4,7 @@ import computeWGSL from "./compute.wgsl"; import fragWGSL from "./frag.wgsl"; import vertWGSL from "./vert.wgsl"; -import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -74,19 +74,19 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cell: { data: buffer1, format: "uint32", stepMode: "instance" } }; - const bindGroup0: IUniforms = { + const bindGroup0: Uniforms = { size: { bufferView: sizeBuffer }, current: { bufferView: buffer0 }, next: { bufferView: buffer1 }, }; - const bindGroup1: IUniforms = { + const bindGroup1: Uniforms = { size: { bufferView: sizeBuffer }, current: { bufferView: buffer1 }, next: { bufferView: buffer0 }, }; - const renderPipeline: IRenderPipeline = { + const renderPipeline: RenderPipeline = { vertex: { code: vertWGSL, }, @@ -95,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const uniformBindGroup: IUniforms = { + const uniformBindGroup: Uniforms = { size: { bufferView: sizeBuffer, offset: 0, @@ -103,7 +103,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const renderPass: IRenderPassDescriptor = { + const renderPass: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -111,7 +111,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ], }; - const passEncodersArray: (IGPUComputePass | IRenderPass)[][] = []; + const passEncodersArray: (IGPUComputePass | RenderPass)[][] = []; for (let i = 0; i < 2; i++) { const vertices1: VertexAttributes = {}; @@ -151,7 +151,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => loopTimes = 0; render = () => { - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders: passEncodersArray[loopTimes], diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 9f69ea4..601b197 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -1,4 +1,4 @@ -import { ISubmit } from "@feng3d/render-api"; +import { Submit } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement) => @@ -9,7 +9,7 @@ const init = async (canvas: HTMLCanvasElement) => const webgpu = await new WebGPU().init(); // 初始化WebGPU - const submit: ISubmit = { // 一次GPU提交 + const submit: Submit = { // 一次GPU提交 commandEncoders: [ // 命令编码列表 { passEncoders: [ // 通道编码列表 diff --git a/examples/src/webgpu/helloTriangleMSAA/index.ts b/examples/src/webgpu/helloTriangleMSAA/index.ts index 28be374..a7c7379 100644 --- a/examples/src/webgpu/helloTriangleMSAA/index.ts +++ b/examples/src/webgpu/helloTriangleMSAA/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, ISubmit } from "@feng3d/render-api"; +import { RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import redFragWGSL from "../../shaders/red.frag.wgsl"; @@ -12,7 +12,7 @@ const init = async (canvas: HTMLCanvasElement) => const webgpu = await new WebGPU().init(); - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [{ view: { texture: { context: { canvasId: canvas.id } } }, clearValue: [0.0, 0.0, 0.0, 1.0], @@ -20,7 +20,7 @@ const init = async (canvas: HTMLCanvasElement) => sampleCount: 4, // 设置多重采样数量 }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, @@ -31,7 +31,7 @@ const init = async (canvas: HTMLCanvasElement) => function frame() { - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 44a3cf7..0e1964e 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -3,7 +3,7 @@ import { GUI } from "dat.gui"; import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgsl"; import blurWGSL from "./blur.wgsl"; -import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture, IUniforms } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; // Contants from the blur.wgsl shader. @@ -24,7 +24,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const fullscreenQuadPipeline1: IRenderPipeline = { + const fullscreenQuadPipeline1: RenderPipeline = { vertex: { code: fullscreenTexturedQuadWGSL, }, @@ -33,7 +33,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", }; @@ -47,18 +47,18 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const imageBitmap = await createImageBitmap(img); const [srcWidth, srcHeight] = [imageBitmap.width, imageBitmap.height]; - const cubeTexture1: ITexture = { + const cubeTexture1: Texture = { size: [imageBitmap.width, imageBitmap.height], format: "rgba8unorm", sources: [{ image: imageBitmap }], }; - const textures: ITexture[] = [0, 1].map(() => + const textures: Texture[] = [0, 1].map(() => ({ size: [srcWidth, srcHeight], format: "rgba8unorm", usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING, - } as ITexture)); + } as Texture)); const buffer0 = new Uint32Array([0]); @@ -66,14 +66,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const blurParamsBuffer = new Uint8Array(8); - const computeConstants: IUniforms = { + const computeConstants: Uniforms = { samp: sampler, params: { bufferView: blurParamsBuffer, }, }; - const computeBindGroup0: IUniforms = { + const computeBindGroup0: Uniforms = { inputTex: { texture: cubeTexture1 }, outputTex: { texture: textures[0] }, flip: { @@ -81,7 +81,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; - const computeBindGroup1: IUniforms = { + const computeBindGroup1: Uniforms = { inputTex: { texture: textures[0] }, outputTex: { texture: textures[1] }, flip: { @@ -89,7 +89,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const computeBindGroup2: IUniforms = { + const computeBindGroup2: Uniforms = { inputTex: { texture: textures[1] }, outputTex: { texture: textures[0] }, flip: { @@ -97,7 +97,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const showResultBindGroup1: IUniforms = { + const showResultBindGroup1: Uniforms = { mySampler: sampler, myTexture: { texture: textures[1] }, }; @@ -131,7 +131,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => updateSettings(); - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -140,7 +140,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ], }; - const gpuRenderPassEncoder: IRenderPass = { + const gpuRenderPassEncoder: RenderPass = { descriptor: renderPassDescriptor, renderObjects: [{ pipeline: fullscreenQuadPipeline1, @@ -152,7 +152,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const gpuComputePassEncoder: IGPUComputePass = { __type: "ComputePass", computeObjects: [] }; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders: [ @@ -163,15 +163,15 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ] }; - const bindingResources0: IUniforms = { + const bindingResources0: Uniforms = { ...computeConstants, ...computeBindGroup0, }; - const bindingResources1: IUniforms = { + const bindingResources1: Uniforms = { ...computeConstants, ...computeBindGroup1, }; - const bindingResources2: IUniforms = { + const bindingResources2: Uniforms = { ...computeConstants, ...computeBindGroup2, }; diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 637b96b..0e72171 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, ISubmit } from "@feng3d/render-api"; +import { RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { Mat4, mat4, vec3 } from "wgpu-matrix"; @@ -87,7 +87,7 @@ const init = async (canvas: HTMLCanvasElement) => } } - const renderPass: IRenderPassDescriptor = { + const renderPass: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -101,7 +101,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: instancedVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, @@ -122,7 +122,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index a36ca03..c92b33f 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,4 +1,4 @@ -import { IPassEncoder, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, VertexAttributes } from "@feng3d/render-api"; +import { IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; @@ -114,7 +114,7 @@ const init = async () => `, }; - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { label: "our hardcoded red triangle pipeline", vertex: { ...module, @@ -169,10 +169,10 @@ const init = async () => worldViewProjectionMatrixValue: Float32Array; worldMatrixValue: Float32Array; uniformValues: Float32Array; - bindGroup: IUniforms; + bindGroup: Uniforms; rotation: number; model: Model; - renderPassDescriptor?: IRenderPassDescriptor + renderPassDescriptor?: RenderPassDescriptor }; const outerElem = document.querySelector("#outer"); @@ -221,7 +221,7 @@ const init = async () => colorValue.set(randColor()); // Make a bind group for this uniform - const bindGroup: IUniforms = { + const bindGroup: Uniforms = { uni: { bufferView: uniformValues, worldViewProjectionMatrix: undefined, @@ -269,7 +269,7 @@ const init = async () => // Get the current texture from the canvas context and // set it as the texture to render to. - const renderPassDescriptor: IRenderPassDescriptor = canvasInfo.renderPassDescriptor = canvasInfo.renderPassDescriptor || { + const renderPassDescriptor: RenderPassDescriptor = canvasInfo.renderPassDescriptor = canvasInfo.renderPassDescriptor || { label: "our basic canvas renderPass", colorAttachments: [ { @@ -329,7 +329,7 @@ const init = async () => }); }); - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders, }] diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index 352269e..1e935e4 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -1,4 +1,4 @@ -import { IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture, IUniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -62,62 +62,62 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // Create normal mapping resources and pipeline - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: "depth24plus", }; // Fetch the image and upload it into a GPUTexture. - let woodAlbedoTexture: ITexture; + let woodAlbedoTexture: Texture; { const response = await fetch("../../../assets/img/wood_albedo.png"); const imageBitmap = await createImageBitmap(await response.blob()); woodAlbedoTexture = createTextureFromImage(imageBitmap); } - let spiralNormalTexture: ITexture; + let spiralNormalTexture: Texture; { const response = await fetch("../../../assets/img/spiral_normal.png"); const imageBitmap = await createImageBitmap(await response.blob()); spiralNormalTexture = createTextureFromImage(imageBitmap); } - let spiralHeightTexture: ITexture; + let spiralHeightTexture: Texture; { const response = await fetch("../../../assets/img/spiral_height.png"); const imageBitmap = await createImageBitmap(await response.blob()); spiralHeightTexture = createTextureFromImage(imageBitmap); } - let toyboxNormalTexture: ITexture; + let toyboxNormalTexture: Texture; { const response = await fetch("../../../assets/img/toybox_normal.png"); const imageBitmap = await createImageBitmap(await response.blob()); toyboxNormalTexture = createTextureFromImage(imageBitmap); } - let toyboxHeightTexture: ITexture; + let toyboxHeightTexture: Texture; { const response = await fetch("../../../assets/img/toybox_height.png"); const imageBitmap = await createImageBitmap(await response.blob()); toyboxHeightTexture = createTextureFromImage(imageBitmap); } - let brickwallAlbedoTexture: ITexture; + let brickwallAlbedoTexture: Texture; { const response = await fetch("../../../assets/img/brickwall_albedo.png"); const imageBitmap = await createImageBitmap(await response.blob()); brickwallAlbedoTexture = createTextureFromImage(imageBitmap); } - let brickwallNormalTexture: ITexture; + let brickwallNormalTexture: Texture; { const response = await fetch("../../../assets/img/brickwall_normal.png"); const imageBitmap = await createImageBitmap(await response.blob()); brickwallNormalTexture = createTextureFromImage(imageBitmap); } - let brickwallHeightTexture: ITexture; + let brickwallHeightTexture: Texture; { const response = await fetch("../../../assets/img/brickwall_height.png"); const imageBitmap = await createImageBitmap(await response.blob()); @@ -125,12 +125,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } // Create a sampler with linear filtering for smooth interpolation. - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -164,7 +164,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => depthLayers: undefined, }; - const bindingResources: IUniforms = { + const bindingResources: Uniforms = { spaceTransform, mapInfo, // Texture bindGroups and bindGroupLayout @@ -232,7 +232,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; - const texturedCubePipeline: IRenderPipeline = create3DRenderPipeline( + const texturedCubePipeline: RenderPipeline = create3DRenderPipeline( "NormalMappingRender", normalMapWGSL, // Position, normal uv tangent bitangent @@ -312,7 +312,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => mapInfo.depthScale = settings.depthScale; mapInfo.depthLayers = settings.depthLayers; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, diff --git a/examples/src/webgpu/normalMap/utils.ts b/examples/src/webgpu/normalMap/utils.ts index 8e527e1..8c12aea 100644 --- a/examples/src/webgpu/normalMap/utils.ts +++ b/examples/src/webgpu/normalMap/utils.ts @@ -1,4 +1,4 @@ -import { DepthStencilState, IRenderPipeline, ITexture } from "@feng3d/render-api"; +import { DepthStencilState, RenderPipeline, Texture } from "@feng3d/render-api"; export const create3DRenderPipeline = ( label: string, @@ -16,7 +16,7 @@ export const create3DRenderPipeline = ( }; } - const pipelineDescriptor: IRenderPipeline = { + const pipelineDescriptor: RenderPipeline = { label: `${label}.pipeline`, vertex: { code: vertexShader, @@ -34,7 +34,7 @@ export const createTextureFromImage = ( bitmap: ImageBitmap ) => { - const texture: ITexture = { + const texture: Texture = { size: [bitmap.width, bitmap.height], format: "rgba8unorm", sources: [{ image: bitmap }] diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 5bd1999..8e4d53a 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, IRenderObject, IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit } from "@feng3d/render-api"; +import { IBufferBinding, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, RenderObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getIGPUBuffer, IGPUOcclusionQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -22,7 +22,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: solidColorLitWGSL, }, @@ -106,7 +106,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const vertexBuf = vertexData; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -122,7 +122,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline, geometry: { primitive: { @@ -143,9 +143,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const renderObjects: IRenderObject[] = objectInfos.map((v) => + const renderObjects: RenderObject[] = objectInfos.map((v) => { - const ro: IRenderObject = { + const ro: RenderObject = { ...renderObject, uniforms: { uni: { @@ -160,13 +160,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const occlusionQueryObjects: IGPUOcclusionQuery[] = renderObjects.map((ro) => ({ __type: "OcclusionQuery", renderObjects: [ro] })); - const renderPass: IRenderPass = { + const renderPass: RenderPass = { descriptor: renderPassDescriptor, // renderObjects: renderObjects, renderObjects: occlusionQueryObjects, }; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index 33a3ef8..e1f9dee 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -7,7 +7,7 @@ import particleWGSL from "./particle.wgsl"; import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; -import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const numParticles = 50000; @@ -36,7 +36,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => color: { data: particlesBuffer, format: "float32x4", offset: particleColorOffset, arrayStride: particleInstanceByteSize, stepMode: "instance" }, }; - const renderPipeline: IRenderPipeline = { + const renderPipeline: RenderPipeline = { vertex: { code: particleWGSL, }, @@ -74,13 +74,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => + 0; const uniformBuffer = new Uint8Array(uniformBufferSize); - const uniformBindGroup: IUniforms = { + const uniformBindGroup: Uniforms = { render_params: { bufferView: uniformBuffer, }, }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -110,7 +110,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // //////////////////////////////////////////////////////////////////////////// // Texture // //////////////////////////////////////////////////////////////////////////// - let texture: ITexture; + let texture: Texture; let textureWidth = 1; let textureHeight = 1; let numMipLevels = 1; @@ -167,7 +167,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const passEncoders: IGPUComputePass[] = []; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders, @@ -179,7 +179,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { const levelWidth = textureWidth >> level; const levelHeight = textureHeight >> level; - const probabilityMapBindGroup: IUniforms = { + const probabilityMapBindGroup: Uniforms = { ubo: { bufferView: probabilityMapUBOBuffer }, buf_in: { bufferView: level & 1 ? bufferA : bufferB }, buf_out: { bufferView: level & 1 ? bufferB : bufferA }, @@ -250,7 +250,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => code: simulateWGSL, }, }; - const computeBindGroup: IUniforms = { + const computeBindGroup: Uniforms = { sim_params: { bufferView: simulationUBOBuffer, }, @@ -267,9 +267,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const view = mat4.create(); const mvp = mat4.create(); - const passEncoders: (IGPUComputePass | IRenderPass)[] = []; + const passEncoders: (IGPUComputePass | RenderPass)[] = []; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders, diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 56741f2..029f9d2 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -1,4 +1,4 @@ -import { IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; @@ -93,7 +93,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => depthCompare: "less", format: depthFormat, }, - } as IRenderPipeline) + } as RenderPipeline) ) ); @@ -114,8 +114,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ctx.textBaseline = "middle"; ctx.fillText("🦋", 32, 32); - const sampler: ISampler = {}; - const texture: ITexture = { + const sampler: Sampler = {}; + const texture: Texture = { size: [ctx.canvas.width, ctx.canvas.height], format: "rgba8unorm", sources: [ @@ -133,7 +133,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => t: { texture }, }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { label: "our basic canvas renderPass", colorAttachments: [ { @@ -192,7 +192,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => bindingResources.uni.resolution = [canvas.width, canvas.height]; // - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders: [ { diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 16e9f36..e3791b8 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPass, IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISampler, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, IRenderPassObject, RenderPipeline, Sampler, Submit, Texture, Uniforms, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, IGPURenderBundle, WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -11,11 +11,11 @@ import meshWGSL from "./mesh.wgsl"; interface Renderable { - renderObject?: IRenderObject; + renderObject?: RenderObject; vertexAttributes: VertexAttributes; indices: Uint16Array; indexCount: number; - bindGroup?: IUniforms; + bindGroup?: Uniforms; } const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => @@ -41,7 +41,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => canvasId: canvas.id, }; - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: meshWGSL, }, @@ -52,7 +52,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => // is rendered in front. }; - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: "depth24plus", }; @@ -61,7 +61,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => const uniformBuffer = new Uint8Array(uniformBufferSize); // Fetch the images and upload them into a GPUTexture. - let planetTexture: ITexture; + let planetTexture: Texture; { const response = await fetch( new URL("../../../assets/img/saturn.jpg", import.meta.url).toString() @@ -75,7 +75,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => }; } - let moonTexture: ITexture; + let moonTexture: Texture; { const response = await fetch( new URL("../../../assets/img/moon.jpg", import.meta.url).toString() @@ -89,7 +89,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => }; } - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", }; @@ -128,13 +128,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => } function createSphereBindGroup1( - texture: ITexture, + texture: Texture, transform: Float32Array - ): IUniforms + ): Uniforms { const uniformBuffer = new Float32Array(transform); - const bindGroup: IUniforms = { + const bindGroup: Uniforms = { modelMatrix: { bufferView: uniformBuffer, }, @@ -185,7 +185,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => } ensureEnoughAsteroids(); - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context } }, @@ -211,7 +211,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => ); const modelViewProjectionMatrix = mat4.create(); - const frameBindGroup: IUniforms = { + const frameBindGroup: Uniforms = { uniforms: { bufferView: uniformBuffer, }, @@ -237,7 +237,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => // same code both to render the scene normally and to build the render bundle. function renderScene() { - const ros: IRenderObject[] = []; + const ros: RenderObject[] = []; // Loop through every renderable object and draw them individually. // (Because many of these meshes are repeated, with only the transforms // differing, instancing would be highly effective here. This sample @@ -327,12 +327,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => renderObjects = renderBundle.renderObjects as any; } - const renderPass: IRenderPass = { + const renderPass: RenderPass = { descriptor: renderPassDescriptor, renderObjects, }; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders: [renderPass], diff --git a/examples/src/webgpu/resizeCanvas/index.ts b/examples/src/webgpu/resizeCanvas/index.ts index 7fc111f..e42adb7 100644 --- a/examples/src/webgpu/resizeCanvas/index.ts +++ b/examples/src/webgpu/resizeCanvas/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, ISubmit } from "@feng3d/render-api"; +import { RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import redFragWGSL from "../../shaders/red.frag.wgsl"; @@ -10,7 +10,7 @@ const init = async (canvas: HTMLCanvasElement) => { const webgpu = await new WebGPU().init(); - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [{ view: { texture: { context: { canvasId: canvas.id } } }, clearValue: [0.0, 0.0, 0.0, 1.0], @@ -18,7 +18,7 @@ const init = async (canvas: HTMLCanvasElement) => sampleCount: 4, // 设置多重采样数量 }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, @@ -36,7 +36,7 @@ const init = async (canvas: HTMLCanvasElement) => const currentHeight = canvas.clientHeight * devicePixelRatio; renderPassDescriptor.attachmentSize = { width: currentWidth, height: currentHeight }; - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index 72bf43c..93e4d5c 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -1,14 +1,14 @@ import { GUI } from "dat.gui"; import checkerWGSL from "./checker.wgsl"; -import { IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Submit, Uniforms } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement) => { const webgpu = await new WebGPU().init(); - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: checkerWGSL }, fragment: { code: checkerWGSL, @@ -21,7 +21,7 @@ const init = async (canvas: HTMLCanvasElement) => size: undefined, }; - const bindGroup: IUniforms = { + const bindGroup: Uniforms = { uni, }; @@ -88,7 +88,7 @@ return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); uni.color1 = cssColorToRGBA(settings.color1); uni.size = settings.size; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -99,7 +99,7 @@ return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); ], }; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index dd90a10..77d1ce5 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -10,7 +10,7 @@ import vertexDepthPrePassWGSL from "./vertexDepthPrePass.wgsl"; import vertexPrecisionErrorPassWGSL from "./vertexPrecisionErrorPass.wgsl"; import vertexTextureQuadWGSL from "./vertexTextureQuad.wgsl"; -import { IRenderPass, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; // Two planes close to each other for depth precision test @@ -87,7 +87,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // depthPrePass is used to render scene to the depth texture // this is not needed if you just want to use reversed z to render a scene - const depthPrePassRenderPipelineDescriptorBase: IRenderPipeline = { + const depthPrePassRenderPipelineDescriptorBase: RenderPipeline = { vertex: { code: vertexDepthPrePassWGSL, }, @@ -95,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // we need the depthCompare to fit the depth buffer mode we are using. // this is the same for other passes - const depthPrePassPipelines: IRenderPipeline[] = []; + const depthPrePassPipelines: RenderPipeline[] = []; depthPrePassPipelines[DepthBufferMode.Default] = { ...depthPrePassRenderPipelineDescriptorBase, depthStencil: { @@ -113,7 +113,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // precisionPass is to draw precision error as color of depth value stored in depth buffer // compared to that directly calcualated in the shader - const precisionPassRenderPipelineDescriptorBase: IRenderPipeline = { + const precisionPassRenderPipelineDescriptorBase: RenderPipeline = { vertex: { code: vertexPrecisionErrorPassWGSL, }, @@ -122,7 +122,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const precisionPassPipelines: IRenderPipeline[] = []; + const precisionPassPipelines: RenderPipeline[] = []; precisionPassPipelines[DepthBufferMode.Default] = { ...precisionPassRenderPipelineDescriptorBase, depthStencil: { @@ -139,7 +139,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // colorPass is the regular render pass to render the scene - const colorPassRenderPipelineDescriptorBase: IRenderPipeline = { + const colorPassRenderPipelineDescriptorBase: RenderPipeline = { vertex: { code: vertexWGSL, }, @@ -149,7 +149,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // - const colorPassPipelines: IRenderPipeline[] = []; + const colorPassPipelines: RenderPipeline[] = []; colorPassPipelines[DepthBufferMode.Default] = { ...colorPassRenderPipelineDescriptorBase, depthStencil: { @@ -168,7 +168,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // textureQuadPass is draw a full screen quad of depth texture // to see the difference of depth value using reversed z compared to default depth buffer usage // 0.0 will be the furthest and 1.0 will be the closest - const textureQuadPassPipline: IRenderPipeline = { + const textureQuadPassPipline: RenderPipeline = { vertex: { code: vertexTextureQuadWGSL, }, @@ -177,17 +177,17 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: depthBufferFormat, }; - const defaultDepthTexture: ITexture = { + const defaultDepthTexture: Texture = { size: [canvas.width, canvas.height], format: depthBufferFormat, }; - const depthPrePassDescriptor: IRenderPassDescriptor = { + const depthPrePassDescriptor: RenderPassDescriptor = { colorAttachments: [], depthStencilAttachment: { view: { texture: depthTexture }, @@ -202,7 +202,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // the scene twice using different depth buffer mode on splitted viewport // of the same canvas // see the difference of the loadOp of the colorAttachments - const drawPassDescriptor: IRenderPassDescriptor = { + const drawPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context } }, @@ -218,7 +218,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const drawPassLoadDescriptor: IRenderPassDescriptor = { + const drawPassLoadDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context } }, @@ -235,7 +235,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const drawPassDescriptors = [drawPassDescriptor, drawPassLoadDescriptor]; - const textureQuadPassDescriptor: IRenderPassDescriptor = { + const textureQuadPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -244,7 +244,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, ], }; - const textureQuadPassLoadDescriptor: IRenderPassDescriptor = { + const textureQuadPassLoadDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -259,7 +259,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => textureQuadPassLoadDescriptor, ]; - const depthTextureBindGroup: IUniforms = { + const depthTextureBindGroup: Uniforms = { depthTexture: { texture: depthTexture }, }; @@ -301,7 +301,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewProjectionMatrix: cameraMatrixReversedDepthBuffer, }; - const uniformBindGroups: IUniforms[] = [ + const uniformBindGroups: Uniforms[] = [ { uniforms, camera: camera0, @@ -351,7 +351,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; gui.add(settings, "mode", ["color", "precision-error", "depth-texture"]).onChange(updateSubmit); - const colorPassEncoders: IRenderPass[] = []; + const colorPassEncoders: RenderPass[] = []; for (const m of depthBufferModes) { @@ -379,7 +379,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); } - const precisionErrorPassEncoders: IRenderPass[] = []; + const precisionErrorPassEncoders: RenderPass[] = []; for (const m of depthBufferModes) { precisionErrorPassEncoders.push({ @@ -428,7 +428,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); } - const depthBufferPassEncoders: IRenderPass[] = []; + const depthBufferPassEncoders: RenderPass[] = []; for (const m of depthBufferModes) { depthBufferPassEncoders.push({ @@ -467,11 +467,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); } - let submit: ISubmit; + let submit: Submit; function updateSubmit() { - let passEncoders: IRenderPass[]; + let passEncoders: RenderPass[]; if (settings.mode === "color") { diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index 3416a9f..7d9f1e6 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, IRenderObject, IRenderPassDescriptor, ISubmit } from "@feng3d/render-api"; +import { IBufferBinding, RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -15,7 +15,7 @@ const init = async (canvas: HTMLCanvasElement) => const webgpu = await new WebGPU().init(); - const renderPass: IRenderPassDescriptor = { + const renderPass: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -33,7 +33,7 @@ const init = async (canvas: HTMLCanvasElement) => modelViewProjectionMatrix: new Float32Array(16) }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, @@ -84,7 +84,7 @@ const init = async (canvas: HTMLCanvasElement) => uniforms.modelViewProjectionMatrix = new Float32Array(transformationMatrix); // 使用 new Float32Array 是因为赋值不同的对象才会触发数据改变重新上传数据到GPU - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index d27e6ba..71d96b6 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -1,7 +1,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; -import { IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISampler, ISubmit, ITexture, ITextureSource, IUniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, IRenderPassObject, RenderPipeline, Sampler, Submit, Texture, ITextureSource, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import showTextureWGSL from "./showTexture.wgsl"; @@ -176,7 +176,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => */ function updateSamplerResources() { - const sampler: ISampler = { + const sampler: Sampler = { ...samplerDescriptor, maxAnisotropy: samplerDescriptor.minFilter === "linear" @@ -229,7 +229,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const kTextureMipLevels = 4; const kTextureBaseSize = 16; - const checkerboard: ITexture = { + const checkerboard: Texture = { format: "rgba8unorm", size: [kTextureBaseSize, kTextureBaseSize], mipLevelCount: 4, @@ -270,7 +270,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // "Debug" view of the actual texture contents // - const showTexturePipeline: IRenderPipeline = { + const showTexturePipeline: RenderPipeline = { vertex: { code: showTextureWGSL }, fragment: { code: showTextureWGSL } }; @@ -278,7 +278,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Pipeline for drawing the test squares // - const texturedSquarePipeline: IRenderPipeline = { + const texturedSquarePipeline: RenderPipeline = { vertex: { code: texturedSquareWGSL, constants: { kTextureBaseSize, kViewportSize } }, fragment: { code: texturedSquareWGSL }, }; @@ -293,7 +293,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const bufMatrices = kMatrices; - const renderPass: IRenderPassDescriptor = { + const renderPass: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -304,7 +304,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObjects: IRenderPassObject[] = []; - const bindingResources0: IUniforms = { + const bindingResources0: Uniforms = { config: { bufferView: bufConfig }, matrices: { bufferView: bufMatrices }, samp: null, // 帧更新中设置 @@ -330,7 +330,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ); } - const bindingResources1: IUniforms = { + const bindingResources1: Uniforms = { tex: { texture: checkerboard }, }; const kLastViewport = (kViewportGridSize - 1) * kViewportGridStride + 1; @@ -375,7 +375,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } ); - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 1585869..1beb633 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -6,7 +6,7 @@ import fragmentWGSL from "./fragment.wgsl"; import vertexWGSL from "./vertex.wgsl"; import vertexShadowWGSL from "./vertexShadow.wgsl"; -import { IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; const shadowDepthTextureSize = 1024; @@ -42,7 +42,7 @@ const init = async (canvas: HTMLCanvasElement) => } // Create the depth texture for rendering/sampling the shadow map. - const shadowDepthTexture: ITexture = { + const shadowDepthTexture: Texture = { size: [shadowDepthTextureSize, shadowDepthTextureSize, 1], format: "depth32float", }; @@ -54,7 +54,7 @@ const init = async (canvas: HTMLCanvasElement) => cullMode: "back", }; - const shadowPipeline: IRenderPipeline = { + const shadowPipeline: RenderPipeline = { vertex: { code: vertexShadowWGSL, }, @@ -67,7 +67,7 @@ const init = async (canvas: HTMLCanvasElement) => // Create a bind group layout which holds the scene uniforms and // the texture+sampler for depth. We create it manually because the WebPU // implementation doesn't infer this from the shader (yet). - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: vertexWGSL, }, @@ -83,12 +83,12 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: "depth24plus-stencil8", }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -115,13 +115,13 @@ const init = async (canvas: HTMLCanvasElement) => // Rounded to the nearest multiple of 16. const sceneUniformBuffer = new Uint8Array(2 * 4 * 16 + 4 * 4); - const sceneBindGroupForShadow: IUniforms = { + const sceneBindGroupForShadow: Uniforms = { scene: { bufferView: sceneUniformBuffer, }, }; - const sceneBindGroupForRender: IUniforms = { + const sceneBindGroupForRender: Uniforms = { scene: { bufferView: sceneUniformBuffer, }, @@ -131,7 +131,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const modelBindGroup: IUniforms = { + const modelBindGroup: Uniforms = { model: { bufferView: modelUniformBuffer, }, @@ -200,7 +200,7 @@ const init = async (canvas: HTMLCanvasElement) => return viewProjMatrix as Float32Array; } - const shadowPassDescriptor: IRenderPassDescriptor = { + const shadowPassDescriptor: RenderPassDescriptor = { colorAttachments: [], depthStencilAttachment: { view: { texture: shadowDepthTexture }, @@ -211,7 +211,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 86b90a4..f0db69a 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { Buffer, FragmentState, IDraw, IRenderObject, IRenderPipeline, IUniforms, IVertexState, PrimitiveState, VertexAttributes, vertexFormatMap } from "@feng3d/render-api"; +import { Buffer, FragmentState, IDraw, RenderPipeline, Uniforms, IVertexState, PrimitiveState, RenderObject, VertexAttributes, vertexFormatMap } from "@feng3d/render-api"; import { getIGPUBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -342,7 +342,7 @@ interface AttributeMapInterface export class GLTFPrimitive { topology: GLTFRenderMode; - renderPipeline: IRenderPipeline; + renderPipeline: RenderPipeline; private attributeMap: AttributeMapInterface; private attributes: string[] = []; vertices: VertexAttributes; @@ -427,7 +427,7 @@ export class GLTFPrimitive // targets: [{ format: colorFormat }], }; - const rpDescript: IRenderPipeline = { + const rpDescript: RenderPipeline = { label: `${label}.pipeline`, vertex: vertexState, fragment: fragmentState, @@ -441,7 +441,7 @@ export class GLTFPrimitive this.renderPipeline = rpDescript; } - render(renderObjects: IRenderObject[], bindingResources: IUniforms) + render(renderObjects: RenderObject[], bindingResources: Uniforms) { let draw: IDraw; if (this.indices) @@ -467,7 +467,7 @@ export class GLTFPrimitive }; } - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: this.renderPipeline, uniforms: bindingResources, //if skin do something with bone bind group @@ -509,7 +509,7 @@ export class GLTFMesh } } - render(renderObjects: IRenderObject[], bindingResources: IUniforms) + render(renderObjects: RenderObject[], bindingResources: Uniforms) { // We take a pretty simple approach to start. Just loop through all the primitives and // call their individual draw methods @@ -664,7 +664,7 @@ export class GLTFNode } renderDrawables( - renderObjects: IRenderObject[], bindingResources: IUniforms + renderObjects: RenderObject[], bindingResources: Uniforms ) { if (this.drawables !== undefined) @@ -733,7 +733,7 @@ export class GLTFSkin // [5, 2, 3] means our joint info is at nodes 5, 2, and 3 joints: number[]; // Bind Group for this skin's uniform buffer - skinBindGroup: IUniforms; + skinBindGroup: Uniforms; // Static bindGroupLayout shared across all skins // In a larger shader with more properties, certain bind groups // would likely have to be combined due to device limitations in the number of bind groups diff --git a/examples/src/webgpu/skinnedMesh/gridUtils.ts b/examples/src/webgpu/skinnedMesh/gridUtils.ts index 8acbba5..ac735ef 100644 --- a/examples/src/webgpu/skinnedMesh/gridUtils.ts +++ b/examples/src/webgpu/skinnedMesh/gridUtils.ts @@ -1,4 +1,4 @@ -import { IRenderPipeline, VertexAttributes } from "@feng3d/render-api"; +import { RenderPipeline, VertexAttributes } from "@feng3d/render-api"; import { gridIndices, gridJoints, gridVertices, gridWeights } from "./gridData"; @@ -24,7 +24,7 @@ export const createSkinnedGridRenderPipeline = ( fragmentShader: string, ) => { - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { label: "SkinnedGridRenderer", vertex: { code: vertexShader, diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 1e7f775..8f1367e 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -7,7 +7,7 @@ import gridWGSL from "./grid.wgsl"; import { gridIndices } from "./gridData"; import { createSkinnedGridBuffers, createSkinnedGridRenderPipeline } from "./gridUtils"; -import { IPassEncoder, IRenderObject, IRenderPass, IRenderPassDescriptor, ITexture, IUniforms } from "@feng3d/render-api"; +import { IPassEncoder, RenderPass, RenderPassDescriptor, Texture, Uniforms, RenderObject } from "@feng3d/render-api"; import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -186,14 +186,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => animFolder.add(settings, "angle", 0.05, 0.5).step(0.05); animFolder.add(settings, "speed", 10, 100).step(10); - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: "depth24plus", }; const cameraBuffer = new Float32Array(48); - const cameraBGCluster: IUniforms = { + const cameraBGCluster: Uniforms = { camera_uniforms: { bufferView: cameraBuffer, } @@ -201,7 +201,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const generalUniformsBuffer = new Uint32Array(2); - const generalUniformsBGCLuster: IUniforms = { + const generalUniformsBGCLuster: Uniforms = { general_uniforms: { bufferView: generalUniformsBuffer, }, @@ -227,7 +227,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Buffer for our uniforms, joints, and inverse bind matrices const skinnedGridJointUniformBuffer = new Uint8Array(MAT4X4_BYTES * 5); const skinnedGridInverseBindUniformBuffer = new Uint8Array(MAT4X4_BYTES * 5); - const skinnedGridBoneBGCluster: IUniforms = { + const skinnedGridBoneBGCluster: Uniforms = { joint_matrices: { bufferView: skinnedGridJointUniformBuffer }, inverse_bind_matrices: { bufferView: skinnedGridInverseBindUniformBuffer }, }; @@ -303,7 +303,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } // Pass Descriptor for GLTFs - const gltfRenderPassDescriptor: IRenderPassDescriptor = { + const gltfRenderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, // Assigned later @@ -322,7 +322,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // Pass descriptor for grid with no depth testing - const skinnedGridRenderPassDescriptor: IRenderPassDescriptor = { + const skinnedGridRenderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, // Assigned later @@ -487,8 +487,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => if (settings.object === "Whale") { - const renderObjects: IRenderObject[] = []; - const bindingResources: IUniforms = { + const renderObjects: RenderObject[] = []; + const bindingResources: Uniforms = { ...cameraBGCluster, ...generalUniformsBGCLuster, }; @@ -496,7 +496,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { scene.root.renderDrawables(renderObjects, bindingResources); } - const passEncoder: IRenderPass = { + const passEncoder: RenderPass = { descriptor: gltfRenderPassDescriptor, renderObjects }; @@ -508,7 +508,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // a separate render descriptor that does not take in a depth texture // Pass in vertex and index buffers generated from our static skinned grid // data at ./gridData.ts - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: skinnedGridPipeline, uniforms: { ...cameraBGCluster, diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index 35d6195..f0ec018 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { IRenderPassDescriptor, IRenderPassObject, IRenderPipeline, ISubmit, ITexture, IUniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, IRenderPassObject, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import basicVertWGSL from "../../shaders/basic.vert.wgsl"; @@ -141,7 +141,7 @@ setBlendConstant().`, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: basicVertWGSL, }, @@ -156,18 +156,18 @@ setBlendConstant().`, }, }; - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: depthFormat, }; const uniformBuffer = new Float32Array(16); - const uniformBindGroup: IUniforms = { + const uniformBindGroup: Uniforms = { uniforms: { bufferView: uniformBuffer }, }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, // Assigned later @@ -269,7 +269,7 @@ setBlendConstant().`, textRenderer.render(renderObjects, ...text); - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index e3fa9d8..74fed97 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -2,7 +2,7 @@ import { mat4, Mat4 } from "wgpu-matrix"; import msdfTextWGSL from "./msdfText.wgsl"; -import { IRenderPassObject, IRenderPipeline, ISampler, ITexture, IUniforms } from "@feng3d/render-api"; +import { IRenderPassObject, RenderPipeline, Sampler, Texture, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, IGPURenderBundle } from "@feng3d/webgpu"; // The kerning map stores a spare map of character ID pairs with an associated @@ -32,8 +32,8 @@ export class MsdfFont charCount: number; defaultChar: MsdfChar; constructor( - public pipeline: IRenderPipeline, - public bindGroup: IUniforms, + public pipeline: RenderPipeline, + public bindGroup: Uniforms, public lineHeight: number, public chars: { [x: number]: MsdfChar }, public kernings: KerningMap @@ -149,8 +149,8 @@ export interface MsdfTextFormattingOptions export class MsdfTextRenderer { - pipelinePromise: IRenderPipeline; - sampler: ISampler; + pipelinePromise: RenderPipeline; + sampler: Sampler; cameraUniformBuffer: Float32Array = new Float32Array(16 * 2); @@ -201,7 +201,7 @@ export class MsdfTextRenderer const response = await fetch(url); const imageBitmap = await createImageBitmap(await response.blob()); - const texture: ITexture = { + const texture: Texture = { size: [imageBitmap.width, imageBitmap.height], label: `MSDF font texture ${url}`, format: "rgba8unorm", @@ -221,7 +221,7 @@ export class MsdfTextRenderer const i = fontJsonUrl.lastIndexOf("/"); const baseUrl = i !== -1 ? fontJsonUrl.substring(0, i + 1) : undefined; - const pagePromises: Promise[] = []; + const pagePromises: Promise[] = []; for (const pageUrl of json.pages) { pagePromises.push(this.loadTexture(baseUrl + pageUrl)); @@ -253,7 +253,7 @@ export class MsdfTextRenderer const pageTextures = await Promise.all(pagePromises); - const bindGroup: IUniforms = { + const bindGroup: Uniforms = { fontTexture: { texture: pageTextures[0] }, fontSampler: this.sampler, chars: { bufferView: charsArray } @@ -330,7 +330,7 @@ export class MsdfTextRenderer ); } - const bindGroup: IUniforms = { + const bindGroup: Uniforms = { camera: { bufferView: this.cameraUniformBuffer }, text: { bufferView: textBuffer }, }; diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index a2b2955..ab9c56e 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, ISampler, ISubmit, ITexture } from "@feng3d/render-api"; +import { RenderPassDescriptor, Sampler, Submit, Texture, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -22,19 +22,19 @@ const init = async (canvas: HTMLCanvasElement) => ).toString(); await img.decode(); const imageBitmap = await createImageBitmap(img); - const cubeTexture: ITexture = { + const cubeTexture: Texture = { size: [imageBitmap.width, imageBitmap.height], format: "rgba8unorm", sources: [{ image: imageBitmap }], }; // Create a sampler with linear filtering for smooth interpolation. - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", }; - const renderPass: IRenderPassDescriptor = { + const renderPass: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -52,7 +52,7 @@ const init = async (canvas: HTMLCanvasElement) => modelViewProjectionMatrix: new Float32Array(16) }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleTextureMixColorWGSL }, }, @@ -105,7 +105,7 @@ const init = async (canvas: HTMLCanvasElement) => uniforms.modelViewProjectionMatrix = transformationMatrix.slice(); // 使用 new Float32Array 是因为赋值不同的对象才会触发数据改变重新上传数据到GPU - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index ddb97d5..63c4bff 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISubmit, ITexture, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Submit, Texture, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -61,7 +61,7 @@ const init = async (canvas: HTMLCanvasElement) => const uniforms = { modelViewProjectionMatrix: null }; - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: basicVertWGSL, }, @@ -77,12 +77,12 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: "depth24plus", }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context } }, // Assigned later @@ -101,7 +101,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline, uniforms: { uniforms, @@ -120,7 +120,7 @@ const init = async (canvas: HTMLCanvasElement) => } }; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 3c95e1f..0d5f158 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { IRenderPassDescriptor, IRenderPipeline, ITexture, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Texture, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -30,7 +30,7 @@ const init = async (canvas: HTMLCanvasElement) => uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: basicVertWGSL, }, @@ -43,7 +43,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const depthTexture: ITexture = { + const depthTexture: Texture = { size: [canvas.width, canvas.height], format: "depth24plus", }; @@ -52,7 +52,7 @@ const init = async (canvas: HTMLCanvasElement) => uniforms: { modelViewProjectionMatrix: undefined } }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context } }, // Assigned later diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index c269824..15ed695 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { IBufferBinding, IRenderObject, IRenderPassDescriptor, ISubmit } from "@feng3d/render-api"; +import { IBufferBinding, RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -17,7 +17,7 @@ const init = async (canvas: HTMLCanvasElement) => const webgpu = await new WebGPU().init(); - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -42,7 +42,7 @@ const init = async (canvas: HTMLCanvasElement) => modelViewProjectionMatrix: null, // 在帧循环中设置 }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, @@ -66,7 +66,7 @@ const init = async (canvas: HTMLCanvasElement) => modelViewProjectionMatrix: null, // 在帧循环中设置 }; - const renderObject1: IRenderObject = { + const renderObject1: RenderObject = { ...renderObject, uniforms: { uniforms: uniforms1, @@ -121,7 +121,7 @@ const init = async (canvas: HTMLCanvasElement) => ); } - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/videoUploading/index.ts b/examples/src/webgpu/videoUploading/index.ts index 4399356..98d677e 100644 --- a/examples/src/webgpu/videoUploading/index.ts +++ b/examples/src/webgpu/videoUploading/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, ISampler, ISubmit } from "@feng3d/render-api"; +import { RenderPassDescriptor, Sampler, Submit, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgsl"; @@ -23,12 +23,12 @@ const init = async (canvas: HTMLCanvasElement) => const webgpu = await new WebGPU().init(); - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", }; - const renderPass: IRenderPassDescriptor = { + const renderPass: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, @@ -37,7 +37,7 @@ const init = async (canvas: HTMLCanvasElement) => ], }; - const renderObject: IRenderObject = { + const renderObject: RenderObject = { pipeline: { vertex: { code: fullscreenTexturedQuadWGSL }, fragment: { code: sampleExternalTextureWGSL }, }, @@ -54,7 +54,7 @@ const init = async (canvas: HTMLCanvasElement) => function frame() { - const data: ISubmit = { + const data: Submit = { commandEncoders: [ { passEncoders: [ diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index 4fff613..d41f516 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import volumeWGSL from "./volume.wgsl"; -import { IRenderPassDescriptor, IRenderPipeline, ISampler, ISubmit, ITexture, IUniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const gui = new GUI(); @@ -28,7 +28,7 @@ const init = async (canvas: HTMLCanvasElement) => const sampleCount = 4; - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: volumeWGSL, }, @@ -42,7 +42,7 @@ const init = async (canvas: HTMLCanvasElement) => }; // Fetch the image and upload it into a GPUTexture. - let volumeTexture: ITexture; + let volumeTexture: Texture; { const width = 180; const height = 216; @@ -84,20 +84,20 @@ const init = async (canvas: HTMLCanvasElement) => } // Create a sampler with linear filtering for smooth interpolation. - const sampler: ISampler = { + const sampler: Sampler = { magFilter: "linear", minFilter: "linear", mipmapFilter: "linear", maxAnisotropy: 16, }; - const uniformBindGroup: IUniforms = { + const uniformBindGroup: Uniforms = { uniforms: uniformBuffer, mySampler: sampler, myTexture: { texture: volumeTexture }, }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context: { canvasId: canvas.id } } }, // Assigned later @@ -152,7 +152,7 @@ const init = async (canvas: HTMLCanvasElement) => uniformBuffer.inverseModelViewProjectionMatrix = inverseModelViewProjection; - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 6fbcbeb..578cef2 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassDescriptor, IRenderPipeline, ISubmit, IUniforms, PrimitiveState, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Submit, Uniforms, PrimitiveState, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => return model; }); - let litPipeline: IRenderPipeline; + let litPipeline: RenderPipeline; function rebuildLitPipeline() { litPipeline = { @@ -72,7 +72,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } rebuildLitPipeline(); - const wireframePipeline: IRenderPipeline = { + const wireframePipeline: RenderPipeline = { label: "wireframe pipeline", vertex: { code: wireframeWGSL, @@ -88,7 +88,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const barycentricCoordinatesBasedWireframePipeline: IRenderPipeline = { + const barycentricCoordinatesBasedWireframePipeline: RenderPipeline = { label: "barycentric coordinates based wireframe pipeline", vertex: { code: wireframeWGSL, @@ -131,8 +131,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => thickness: number; alphaThreshold: number; }; - litBindGroup: IUniforms; - wireframeBindGroups: IUniforms[]; + litBindGroup: Uniforms; + wireframeBindGroups: Uniforms[]; model: Model; }; @@ -155,7 +155,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const model = randElement(models); // Make a bind group for this uniform - const litBindGroup: IUniforms = { + const litBindGroup: Uniforms = { uni: uniformBuffer, }; @@ -177,14 +177,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // We're creating 2 bindGroups, one for each pipeline. // We could create just one since they are identical. To do // so we'd have to manually create a bindGroupLayout. - const wireframeBindGroup: IUniforms = { + const wireframeBindGroup: Uniforms = { uni: uniformBuffer, positions: { bufferView: model.vertices }, indices: { bufferView: model.indices }, line: lineUniformBuffer, }; - const barycentricCoordinatesBasedWireframeBindGroup: IUniforms = { + const barycentricCoordinatesBasedWireframeBindGroup: Uniforms = { uni: uniformBuffer, positions: { bufferView: model.vertices }, indices: { bufferView: model.indices }, @@ -204,7 +204,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); } - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { label: "our basic canvas renderPass", colorAttachments: [ { @@ -281,7 +281,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const viewProjection = mat4.multiply(projection, view); - const renderObjects: IRenderObject[] = []; + const renderObjects: RenderObject[] = []; objectInfos.forEach( ( @@ -359,7 +359,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); } - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 015315d..0b9ee04 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { IRenderPassDescriptor, IRenderPipeline, ISubmit, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; import { getOffscreenCanvasId, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -78,7 +78,7 @@ async function init(canvas: OffscreenCanvas) uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: IRenderPipeline = { + const pipeline: RenderPipeline = { vertex: { code: basicVertWGSL, }, @@ -98,7 +98,7 @@ async function init(canvas: OffscreenCanvas) uniforms: { modelViewProjectionMatrix: undefined }, }; - const renderPassDescriptor: IRenderPassDescriptor = { + const renderPassDescriptor: RenderPassDescriptor = { colorAttachments: [ { view: { texture: { context } }, // Assigned later @@ -141,7 +141,7 @@ async function init(canvas: OffscreenCanvas) return modelViewProjectionMatrix; } - const submit: ISubmit = { + const submit: Submit = { commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, diff --git a/src/WebGPU.ts b/src/WebGPU.ts index 5d8c122..61f7108 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,4 +1,4 @@ -import { Buffer, ISubmit, ITextureLike } from "@feng3d/render-api"; +import { Buffer, Submit, ITextureLike } from "@feng3d/render-api"; import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUTexture } from "./caches/getGPUTexture"; import { getIGPUTextureLikeSize } from "./caches/getIGPUTextureSize"; @@ -76,7 +76,7 @@ export class WebGPU * * @see GPUQueue.submit */ - submit(submit: ISubmit) + submit(submit: Submit) { this._runWebGPU.runSubmit(this.device, submit); } diff --git a/src/WebGPUStep.ts b/src/WebGPUStep.ts index 4a9e6e5..e714844 100644 --- a/src/WebGPUStep.ts +++ b/src/WebGPUStep.ts @@ -1,4 +1,4 @@ -import { CopyBufferToBuffer, CopyTextureToTexture, IRenderObject, IRenderPass, IRenderPassDescriptor, IRenderPassObject, ISubmit } from "@feng3d/render-api"; +import { CopyBufferToBuffer, CopyTextureToTexture, IRenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, Submit } from "@feng3d/render-api"; import { IGPUComputeObject } from "./data/IGPUComputeObject"; import { IGPUComputePass } from "./data/IGPUComputePass"; @@ -11,8 +11,8 @@ import { WebGPU } from "./WebGPU"; */ export class WebGPUStep { - private _currentSubmit: ISubmit; - private _currentRenderPassEncoder: IRenderPass; + private _currentSubmit: Submit; + private _currentRenderPassEncoder: RenderPass; private _currentComputePassEncoder: IGPUComputePass; readonly webGPU: WebGPU; @@ -22,7 +22,7 @@ export class WebGPUStep this.webGPU = webGPU; } - renderPass(descriptor: IRenderPassDescriptor) + renderPass(descriptor: RenderPassDescriptor) { this._currentSubmit = this._currentSubmit || { commandEncoders: [{ passEncoders: [] }] }; // @@ -33,7 +33,7 @@ export class WebGPUStep this._currentSubmit.commandEncoders[0].passEncoders.push(this._currentRenderPassEncoder); } - renderObject(renderObject: IRenderObject) + renderObject(renderObject: RenderObject) { (this._currentRenderPassEncoder.renderObjects as IRenderPassObject[]).push(renderObject); } @@ -77,7 +77,7 @@ export class WebGPUStep * * @see GPUQueue.submit */ - submit(submit?: ISubmit) + submit(submit?: Submit) { if (!submit) { diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 6d8a0d6..3301167 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { IBufferBinding, ISampler, ITextureView } from "@feng3d/render-api"; +import { IBufferBinding, Sampler, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; @@ -51,16 +51,16 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: IGPUBindGroupDescr entry.resource = getGPUBufferBinding(device, v.resource as IBufferBinding); }; } - else if ((v.resource as ITextureView).texture) + else if ((v.resource as TextureView).texture) { updateResource = () => { - entry.resource = getGPUTextureView(device, v.resource as ITextureView); + entry.resource = getGPUTextureView(device, v.resource as TextureView); anyEmitter.once(entry.resource, GPUTextureView_destroy, onResourceChanged); }; - if (((v.resource as ITextureView).texture as IGPUCanvasTexture).context) + if (((v.resource as TextureView).texture as IGPUCanvasTexture).context) { awaysUpdateFuncs.push(updateResource); } @@ -78,8 +78,8 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: IGPUBindGroupDescr { updateResource = () => { - entry.resource = getGPUSampler(device, v.resource as ISampler); - anyEmitter.once(v.resource as ISampler, IGPUSampler_changed, onResourceChanged); + entry.resource = getGPUSampler(device, v.resource as Sampler); + anyEmitter.once(v.resource as Sampler, IGPUSampler_changed, onResourceChanged); }; } diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index 523c9be..8a564b8 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { IRenderPass, IRenderPassObject } from "@feng3d/render-api"; +import { RenderPass, IRenderPassObject } from "@feng3d/render-api"; import { IGPUOcclusionQuery } from "../data/IGPUOcclusionQuery"; import { GPUQueue_submit } from "../eventnames"; @@ -44,7 +44,7 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly IRenderPassO * @param commandEncoder * @param renderPass */ - const resolve = (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: IRenderPass) => + const resolve = (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass) => { resolveBuf = resolveBuf || device.createBuffer({ label: "resolveBuffer", @@ -101,7 +101,7 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly IRenderPassO interface GPURenderOcclusionQuery { init: (device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor) => void - resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: IRenderPass) => void + resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass) => void } const defautRenderOcclusionQuery = { init: () => { }, resolve: () => { } }; \ No newline at end of file diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index f021fa8..8a363bb 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { IRenderPassColorAttachment, IRenderPassDepthStencilAttachment, IRenderPassDescriptor, ITextureLike, ITextureView } from "@feng3d/render-api"; +import { RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, ITextureLike, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { IGPUTexture_resize } from "../eventnames"; @@ -16,9 +16,9 @@ import { getIGPUTextureLikeSize } from "./getIGPUTextureSize"; * @param descriptor 渲染通道描述。 * @returns GPU渲染通道描述。 */ -export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: IRenderPassDescriptor): GPURenderPassDescriptor +export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: RenderPassDescriptor): GPURenderPassDescriptor { - const renderPassDescriptorMap: Map = device["_RenderPassDescriptorMap"] = device["_RenderPassDescriptorMap"] || new Map(); + const renderPassDescriptorMap: Map = device["_RenderPassDescriptorMap"] = device["_RenderPassDescriptorMap"] || new Map(); let renderPassDescriptor = renderPassDescriptorMap.get(descriptor); if (renderPassDescriptor) { @@ -127,7 +127,7 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: IRende * * @returns 渲染通道附件上的纹理描述列表。 */ -function getAttachmentTextures(colorAttachments: readonly IRenderPassColorAttachment[], depthStencilAttachment?: IRenderPassDepthStencilAttachment) +function getAttachmentTextures(colorAttachments: readonly RenderPassColorAttachment[], depthStencilAttachment?: RenderPassDepthStencilAttachment) { const textures: ITextureLike[] = []; @@ -158,7 +158,7 @@ function getAttachmentTextures(colorAttachments: readonly IRenderPassColorAttach * @param renderPass 渲染通道描述。 * @param attachmentSize 附件尺寸。 */ -function setIGPURenderPassAttachmentSize(colorAttachments: NGPURenderPassColorAttachment[], depthStencilAttachment: IRenderPassDepthStencilAttachment, attachmentSize: { width: number; height: number; }) +function setIGPURenderPassAttachmentSize(colorAttachments: NGPURenderPassColorAttachment[], depthStencilAttachment: RenderPassDepthStencilAttachment, attachmentSize: { width: number; height: number; }) { const attachmentTextures = getIGPURenderPassAttachmentTextures(colorAttachments, depthStencilAttachment); attachmentTextures.forEach((v) => setIGPUTextureSize(v, attachmentSize)); @@ -199,7 +199,7 @@ function setIGPUTextureSize(texture: ITextureLike, attachmentSize: { width: numb * @param depthStencilAttachment 深度模板附件。 * @returns 渲染通道附件上的纹理描述列表。 */ -function getIGPURenderPassAttachmentTextures(colorAttachments: NGPURenderPassColorAttachment[], depthStencilAttachment?: IRenderPassDepthStencilAttachment) +function getIGPURenderPassAttachmentTextures(colorAttachments: NGPURenderPassColorAttachment[], depthStencilAttachment?: RenderPassDepthStencilAttachment) { const textures: ITextureLike[] = []; @@ -255,7 +255,7 @@ function getMultisampleTextureView(texture: ITextureLike, sampleCount: 4) return multisampleTextureView; } -const multisampleTextureMap = new WeakMap(); +const multisampleTextureMap = new WeakMap(); /** * 获取深度模板附件完整描述。 @@ -265,7 +265,7 @@ const multisampleTextureMap = new WeakMap(); * @param multisample 多重采样次数。 * @returns 深度模板附件完整描述。 */ -function getIGPURenderPassDepthStencilAttachment(depthStencilAttachment: IRenderPassDepthStencilAttachment, attachmentSize: { width: number, height: number }, multisample: number) +function getIGPURenderPassDepthStencilAttachment(depthStencilAttachment: RenderPassDepthStencilAttachment, attachmentSize: { width: number, height: number }, multisample: number) { if (!depthStencilAttachment) return undefined; @@ -286,7 +286,7 @@ function getIGPURenderPassDepthStencilAttachment(depthStencilAttachment: IRender const depthStoreOp = depthStencilAttachment.depthStoreOp; // - const gpuDepthStencilAttachment: IRenderPassDepthStencilAttachment = { + const gpuDepthStencilAttachment: RenderPassDepthStencilAttachment = { ...depthStencilAttachment, view, depthClearValue, @@ -304,14 +304,14 @@ function getIGPURenderPassDepthStencilAttachment(depthStencilAttachment: IRender * @param sampleCount 多重采样次数。 * @returns 颜色附件完整描述列表。 */ -function getIGPURenderPassColorAttachments(colorAttachments: readonly IRenderPassColorAttachment[], sampleCount: 4) +function getIGPURenderPassColorAttachments(colorAttachments: readonly RenderPassColorAttachment[], sampleCount: 4) { const gpuColorAttachments: NGPURenderPassColorAttachment[] = colorAttachments.map((v) => { if (!v) return undefined; let view = v.view; - let resolveTarget: ITextureView; + let resolveTarget: TextureView; if (sampleCount) { @@ -336,7 +336,7 @@ function getIGPURenderPassColorAttachments(colorAttachments: readonly IRenderPas * * @param renderPass 渲染通道描述。 */ -function updateAttachmentSize(renderPass: IRenderPassDescriptor) +function updateAttachmentSize(renderPass: RenderPassDescriptor) { const attachmentTextures = getAttachmentTextures(renderPass.colorAttachments, renderPass.depthStencilAttachment); if (!renderPass.attachmentSize) diff --git a/src/caches/getGPURenderPassFormat.ts b/src/caches/getGPURenderPassFormat.ts index f54e747..214ed7b 100644 --- a/src/caches/getGPURenderPassFormat.ts +++ b/src/caches/getGPURenderPassFormat.ts @@ -1,4 +1,4 @@ -import { IRenderPassDescriptor } from "@feng3d/render-api"; +import { RenderPassDescriptor } from "@feng3d/render-api"; import { getGPUTextureFormat } from "../caches/getGPUTextureFormat"; import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; @@ -8,7 +8,7 @@ import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; * @param descriptor 渲染通道描述。 * @returns */ -export function getGPURenderPassFormat(descriptor: IRenderPassDescriptor): IGPURenderPassFormat +export function getGPURenderPassFormat(descriptor: RenderPassDescriptor): IGPURenderPassFormat { let gpuRenderPassFormat: IGPURenderPassFormat = descriptor[_RenderPassFormat]; if (gpuRenderPassFormat) return gpuRenderPassFormat; diff --git a/src/caches/getGPURenderTimestampQuery.ts b/src/caches/getGPURenderTimestampQuery.ts index 04bed5a..9e084f3 100644 --- a/src/caches/getGPURenderTimestampQuery.ts +++ b/src/caches/getGPURenderTimestampQuery.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { IRenderPass } from "@feng3d/render-api"; +import { RenderPass } from "@feng3d/render-api"; import { IGPUComputePass } from "../data/IGPUComputePass"; import { IGPUTimestampQuery } from "../data/IGPUTimestampQuery"; import { GPUQueue_submit } from "../eventnames"; @@ -121,7 +121,7 @@ export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: I interface GPURenderTimestampQuery { init: (device: GPUDevice, passDescriptor: GPURenderPassDescriptor | GPUComputePassDescriptor) => void - resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: IRenderPass | IGPUComputePass) => void + resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass | IGPUComputePass) => void } const defautGPURenderTimestampQuery = { init: () => { }, resolve: () => { } }; \ No newline at end of file diff --git a/src/caches/getGPUSampler.ts b/src/caches/getGPUSampler.ts index b3539e1..3b3e2ee 100644 --- a/src/caches/getGPUSampler.ts +++ b/src/caches/getGPUSampler.ts @@ -1,9 +1,9 @@ import { anyEmitter } from "@feng3d/event"; -import { ISampler } from "@feng3d/render-api"; +import { Sampler } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUSampler_changed } from "../eventnames"; -export function getGPUSampler(device: GPUDevice, sampler: ISampler) +export function getGPUSampler(device: GPUDevice, sampler: Sampler) { let gSampler = samplerMap.get(sampler); if (gSampler) return gSampler; @@ -32,12 +32,12 @@ export function getGPUSampler(device: GPUDevice, sampler: ISampler) return gSampler; } -const samplerMap = new WeakMap(); +const samplerMap = new WeakMap(); /** * GPU采样器默认值。 */ -const defaultSampler: ISampler = { +const defaultSampler: Sampler = { addressModeU: undefined, addressModeV: undefined, addressModeW: undefined, diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 482d1c1..a2a35b7 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { getTexImageSourceSize, getTextureBytesPerPixel, ITexture, ITextureDataSource, ITextureImageSource, ITextureLike, ITextureSize, ITextureSource } from "@feng3d/render-api"; +import { getTexImageSourceSize, getTextureBytesPerPixel, Texture, ITextureDataSource, ITextureImageSource, ITextureLike, ITextureSize, ITextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; @@ -29,7 +29,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: ITextureLike, auto return gpuTexture; } - const texture = textureLike as ITexture; + const texture = textureLike as Texture; const textureMap: Map = device[_GPUTextureMap] = device[_GPUTextureMap] || new Map(); gpuTexture = textureMap.get(texture); diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index 89560d5..9b9753b 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -1,12 +1,12 @@ import { anyEmitter } from "@feng3d/event"; -import { ITexture, ITextureView } from "@feng3d/render-api"; +import { Texture, TextureView } from "@feng3d/render-api"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { GPUTexture_destroy, GPUTextureView_destroy } from "../eventnames"; import { getGPUTexture } from "./getGPUTexture"; -export function getGPUTextureView(device: GPUDevice, view: ITextureView) +export function getGPUTextureView(device: GPUDevice, view: TextureView) { - const textureViewMap: WeakMap = device["_textureViewMap"] = device["_textureViewMap"] || new WeakMap(); + const textureViewMap: WeakMap = device["_textureViewMap"] = device["_textureViewMap"] || new WeakMap(); if ((view.texture as IGPUCanvasTexture).context) { @@ -22,7 +22,7 @@ export function getGPUTextureView(device: GPUDevice, view: ITextureView) if (textureView) return textureView; // - const texture = view.texture as ITexture; + const texture = view.texture as Texture; const gpuTexture = getGPUTexture(device, texture); const dimension = view.dimension ?? texture.dimension; diff --git a/src/caches/getIGPUSetBindGroups.ts b/src/caches/getIGPUSetBindGroups.ts index 3a15dc4..8733c01 100644 --- a/src/caches/getIGPUSetBindGroups.ts +++ b/src/caches/getIGPUSetBindGroups.ts @@ -1,6 +1,6 @@ import { watcher } from "@feng3d/watcher"; -import { IBufferBinding, IUniforms } from "@feng3d/render-api"; +import { IBufferBinding, Uniforms } from "@feng3d/render-api"; import { getIGPUPipelineLayout, getIGPUShaderKey, IGPUShader } from "../caches/getIGPUPipelineLayout"; import { IGPUBindGroupEntry } from "../internal/IGPUBindGroupDescriptor"; import { IGPUBindGroupLayoutDescriptor } from "../internal/IGPUPipelineLayoutDescriptor"; @@ -10,7 +10,7 @@ import { getBufferBindingInfo, IBufferBindingInfo } from "../utils/getBufferBind import { updateBufferBinding } from "../utils/updateBufferBinding"; import { getIGPUBuffer } from "./getIGPUBuffer"; -export function getIGPUSetBindGroups(shader: IGPUShader, bindingResources: IUniforms) +export function getIGPUSetBindGroups(shader: IGPUShader, bindingResources: Uniforms) { const shaderKey = getIGPUShaderKey(shader); // @@ -30,9 +30,9 @@ export function getIGPUSetBindGroups(shader: IGPUShader, bindingResources: IUnif return gpuSetBindGroups; } -const bindGroupsMap = new ChainMap<[string, IUniforms], IGPUSetBindGroup[]>(); +const bindGroupsMap = new ChainMap<[string, Uniforms], IGPUSetBindGroup[]>(); -function getIGPUSetBindGroup(bindGroupLayout: IGPUBindGroupLayoutDescriptor, bindingResources: IUniforms): IGPUSetBindGroup +function getIGPUSetBindGroup(bindGroupLayout: IGPUBindGroupLayoutDescriptor, bindingResources: Uniforms): IGPUSetBindGroup { const map: ChainMap, IGPUSetBindGroup> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); const subBindingResources = bindGroupLayout.entryNames.map((v) => bindingResources[v]); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index cf63b4d..334dc51 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState, DepthStencilState, FragmentState, getBlendConstantColor, IIndicesDataTypes, IRenderPipeline, IStencilFaceState, IVertexState, IWriteMask, PrimitiveState, VertexAttributes, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; +import { BlendState, DepthStencilState, FragmentState, getBlendConstantColor, IIndicesDataTypes, RenderPipeline, StencilFaceState, IVertexState, IWriteMask, PrimitiveState, VertexAttributes, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -21,7 +21,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPassFormat: IGPURenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) +export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPassFormat: IGPURenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const indexFormat = indices ? getIGPUSetIndexBuffer(indices).indexFormat : undefined; @@ -80,7 +80,7 @@ export function getNGPURenderPipeline(renderPipeline: IRenderPipeline, renderPas } const renderPipelineMap = new ChainMap< - [IRenderPipeline, string, PrimitiveState, VertexAttributes, GPUIndexFormat], + [RenderPipeline, string, PrimitiveState, VertexAttributes, GPUIndexFormat], { /** * GPU渲染管线描述。 @@ -196,7 +196,7 @@ function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFo return gpuDepthStencilState; } -function getGPUStencilFaceState(stencilFaceState?: IStencilFaceState) +function getGPUStencilFaceState(stencilFaceState?: StencilFaceState) { if (!stencilFaceState) return {}; diff --git a/src/data/IGPUBindingResources.ts b/src/data/IGPUBindingResources.ts index b650547..dc64ac2 100644 --- a/src/data/IGPUBindingResources.ts +++ b/src/data/IGPUBindingResources.ts @@ -1,12 +1,12 @@ -import { ISampler } from "@feng3d/render-api"; +import { Sampler } from "@feng3d/render-api"; import { IGPUExternalTexture } from "./IGPUExternalTexture"; declare module "@feng3d/render-api" { export interface IUniformTypeMap { - ISampler: ISampler; - ITextureView: ITextureView; + ISampler: Sampler; + ITextureView: TextureView; IGPUExternalTexture: IGPUExternalTexture; } } \ No newline at end of file diff --git a/src/data/IGPUComputeObject.ts b/src/data/IGPUComputeObject.ts index 3f5fe09..fdcd54b 100644 --- a/src/data/IGPUComputeObject.ts +++ b/src/data/IGPUComputeObject.ts @@ -1,4 +1,4 @@ -import { IUniforms } from "@feng3d/render-api"; +import { Uniforms } from "@feng3d/render-api"; import { IGPUComputePipeline } from "./IGPUComputePipeline"; import { IGPUWorkgroups } from "./IGPUWorkgroups"; @@ -21,7 +21,7 @@ export interface IGPUComputeObject /** * 绑定资源。包含数值、纹理、采样、外部纹理。 */ - readonly uniforms?: IUniforms; + readonly uniforms?: Uniforms; /** * {@link GPUComputePassEncoder.dispatchWorkgroups} diff --git a/src/data/IGPUMultisampleState.ts b/src/data/IGPUMultisampleState.ts index cfe185e..e71c5d4 100644 --- a/src/data/IGPUMultisampleState.ts +++ b/src/data/IGPUMultisampleState.ts @@ -1,9 +1,9 @@ -import { IRenderPassDescriptor } from "@feng3d/render-api"; +import { RenderPassDescriptor } from "@feng3d/render-api"; /** * 多重采样阶段描述。 * - * 多重采样次数将由 {@link IRenderPassDescriptor.sampleCount} 覆盖。 + * 多重采样次数将由 {@link RenderPassDescriptor.sampleCount} 覆盖。 */ export interface IGPUMultisampleState { diff --git a/src/data/IGPUOcclusionQuery.ts b/src/data/IGPUOcclusionQuery.ts index 7a26643..d69d303 100644 --- a/src/data/IGPUOcclusionQuery.ts +++ b/src/data/IGPUOcclusionQuery.ts @@ -1,4 +1,4 @@ -import { IRenderObject } from "@feng3d/render-api"; +import { RenderObject } from "@feng3d/render-api"; /** * 被查询的渲染对象列表 @@ -13,7 +13,7 @@ export interface IGPUOcclusionQuery /** * GPU渲染对象列表。 */ - renderObjects: IRenderObject[]; + renderObjects: RenderObject[]; /** * 临时变量, 执行过程中由引擎自动填充 diff --git a/src/data/IGPURenderBundle.ts b/src/data/IGPURenderBundle.ts index 55707c1..e782857 100644 --- a/src/data/IGPURenderBundle.ts +++ b/src/data/IGPURenderBundle.ts @@ -1,4 +1,4 @@ -import { IRenderObject } from "@feng3d/render-api"; +import { RenderObject } from "@feng3d/render-api"; /** * GPU渲染捆绑对象。 @@ -22,7 +22,7 @@ export interface IGPURenderBundle /** * GPU渲染对象列表。 */ - renderObjects: readonly IRenderObject[]; + renderObjects: readonly RenderObject[]; _version?: number; } diff --git a/src/data/IGPURenderObject.ts b/src/data/IGPURenderObject.ts index 60541fc..8a1e665 100644 --- a/src/data/IGPURenderObject.ts +++ b/src/data/IGPURenderObject.ts @@ -1,4 +1,4 @@ -import { IUniforms } from "@feng3d/render-api"; +import { Uniforms } from "@feng3d/render-api"; import { } from "./IGPUBindingResources"; declare module "@feng3d/render-api" diff --git a/src/data/IGPURenderPass.ts b/src/data/IGPURenderPass.ts index 69960f5..9510307 100644 --- a/src/data/IGPURenderPass.ts +++ b/src/data/IGPURenderPass.ts @@ -1,4 +1,4 @@ -import { IRenderPass, IRenderPassDescriptor } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor } from "@feng3d/render-api"; import { IGPUOcclusionQuery } from "./IGPUOcclusionQuery"; import { IGPURenderBundle } from "./IGPURenderBundle"; import { IGPUTimestampQuery } from "./IGPUTimestampQuery"; @@ -12,7 +12,7 @@ declare module "@feng3d/render-api" * * {@link GPURenderPassEncoder} */ - export interface IRenderPass + export interface RenderPass { /** * 渲染不被遮挡查询结果。具体数据保存在各子项的"result"属性中。 diff --git a/src/data/IGPURenderPassColorAttachment.ts b/src/data/IGPURenderPassColorAttachment.ts index 4a20b09..8ce0079 100644 --- a/src/data/IGPURenderPassColorAttachment.ts +++ b/src/data/IGPURenderPassColorAttachment.ts @@ -1,4 +1,4 @@ -import { ITextureView } from "@feng3d/render-api"; +import { TextureView } from "@feng3d/render-api"; declare module "@feng3d/render-api" { @@ -8,13 +8,13 @@ declare module "@feng3d/render-api" * * {@link GPURenderPassColorAttachment} */ - export interface IRenderPassColorAttachment + export interface RenderPassColorAttachment { /** * A {@link GPUTextureView} describing the texture subresource that will be output to for this * color attachment. */ - readonly view?: ITextureView; + readonly view?: TextureView; /** * The store operation to perform on {@link GPURenderPassColorAttachment#view} diff --git a/src/data/IGPURenderPassDepthStencilAttachment.ts b/src/data/IGPURenderPassDepthStencilAttachment.ts index badab2a..98c21a6 100644 --- a/src/data/IGPURenderPassDepthStencilAttachment.ts +++ b/src/data/IGPURenderPassDepthStencilAttachment.ts @@ -1,4 +1,4 @@ -import { IRenderPassDepthStencilAttachment, ITextureView } from "@feng3d/render-api"; +import { RenderPassDepthStencilAttachment, TextureView } from "@feng3d/render-api"; declare module "@feng3d/render-api" { @@ -7,7 +7,7 @@ declare module "@feng3d/render-api" * * @see GPURenderPassDepthStencilAttachment */ - export interface IRenderPassDepthStencilAttachment + export interface RenderPassDepthStencilAttachment { /** * A {@link GPUTextureView} describing the texture subresource that will be output to @@ -15,7 +15,7 @@ declare module "@feng3d/render-api" * * 当值为空时,将自动从颜色附件中获取尺寸来创建深度纹理。 */ - readonly view?: ITextureView; + readonly view?: TextureView; /** * The store operation to perform on {@link GPURenderPassDepthStencilAttachment#view}'s diff --git a/src/data/IGPURenderPassDescriptor.ts b/src/data/IGPURenderPassDescriptor.ts index 3e68b71..9b00ef0 100644 --- a/src/data/IGPURenderPassDescriptor.ts +++ b/src/data/IGPURenderPassDescriptor.ts @@ -1,4 +1,4 @@ -import { IRenderPassColorAttachment, IRenderPassDescriptor } from "@feng3d/render-api"; +import { RenderPassColorAttachment, RenderPassDescriptor } from "@feng3d/render-api"; declare module "@feng3d/render-api" { @@ -7,7 +7,7 @@ declare module "@feng3d/render-api" * * {@link GPURenderPassDescriptor} */ - export interface IRenderPassDescriptor + export interface RenderPassDescriptor { /** * 附件尺寸。 diff --git a/src/data/IGPURenderPipeline.ts b/src/data/IGPURenderPipeline.ts index 925be50..28f9317 100644 --- a/src/data/IGPURenderPipeline.ts +++ b/src/data/IGPURenderPipeline.ts @@ -9,7 +9,7 @@ declare module "@feng3d/render-api" * * @see https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/createRenderPipeline */ - export interface IRenderPipeline + export interface RenderPipeline { /** * 多重采样阶段描述。 diff --git a/src/data/IGPUTexture.ts b/src/data/IGPUTexture.ts index 0245156..7f1b34d 100644 --- a/src/data/IGPUTexture.ts +++ b/src/data/IGPUTexture.ts @@ -1,4 +1,4 @@ -import { ITexture } from "@feng3d/render-api"; +import { Texture } from "@feng3d/render-api"; declare module "@feng3d/render-api" { @@ -48,7 +48,7 @@ declare module "@feng3d/render-api" * @see GPUDevice.createTexture * @see GPUTextureDescriptor */ - export interface ITexture + export interface Texture { /** * Specifies what view {@link GPUTextureViewDescriptor#format} values will be allowed when calling diff --git a/src/data/IGPUTextureView.ts b/src/data/IGPUTextureView.ts index 61b2aad..a306ebe 100644 --- a/src/data/IGPUTextureView.ts +++ b/src/data/IGPUTextureView.ts @@ -18,7 +18,7 @@ declare module "@feng3d/render-api" * @see GPUTexture.createView * @see GPUTextureViewDescriptor */ - export interface ITextureView + export interface TextureView { /** * The format of the texture view. Must be either the {@link GPUTextureDescriptor#format} of the diff --git a/src/internal/IGPUBindGroupDescriptor.ts b/src/internal/IGPUBindGroupDescriptor.ts index f9c9a82..987a612 100644 --- a/src/internal/IGPUBindGroupDescriptor.ts +++ b/src/internal/IGPUBindGroupDescriptor.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, ISampler, ITextureView } from "@feng3d/render-api"; +import { IBufferBinding, Sampler, TextureView } from "@feng3d/render-api"; import { IGPUExternalTexture } from "../data/IGPUExternalTexture"; /** @@ -44,4 +44,4 @@ export interface IGPUBindGroupEntry resource: IGPUBindingResource; } -export type IGPUBindingResource = ISampler | ITextureView | IBufferBinding | IGPUExternalTexture; +export type IGPUBindingResource = Sampler | TextureView | IBufferBinding | IGPUExternalTexture; diff --git a/src/internal/IGPUTextureMultisample.ts b/src/internal/IGPUTextureMultisample.ts index 895f771..5c67ae6 100644 --- a/src/internal/IGPUTextureMultisample.ts +++ b/src/internal/IGPUTextureMultisample.ts @@ -1,9 +1,9 @@ -import { ITexture } from "@feng3d/render-api"; +import { Texture } from "@feng3d/render-api"; /** * 多重采样纹理,一般只在渲染通道中需要解决多重采样时使用。 */ -export interface IGPUTextureMultisample extends ITexture +export interface IGPUTextureMultisample extends Texture { /** * The sample count of the texture. A {@link GPUTextureDescriptor#sampleCount} > `1` indicates diff --git a/src/internal/internal.ts b/src/internal/internal.ts index 401a79e..a1a033a 100644 --- a/src/internal/internal.ts +++ b/src/internal/internal.ts @@ -1,14 +1,14 @@ -import { IRenderPassColorAttachment, ITextureView } from "@feng3d/render-api"; +import { RenderPassColorAttachment, TextureView } from "@feng3d/render-api"; /** * 内部使用 */ -export interface NGPURenderPassColorAttachment extends IRenderPassColorAttachment +export interface NGPURenderPassColorAttachment extends RenderPassColorAttachment { /** * A {@link GPUTextureView} describing the texture subresource that will receive the resolved * output for this color attachment if {@link GPURenderPassColorAttachment#view} is * multisampled. */ - resolveTarget?: ITextureView; + resolveTarget?: TextureView; } diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 0b66e20..5830c20 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IRenderObject, IRenderPass, IRenderPassObject, IRenderPipeline, IScissorRect, ISubmit, IUniforms, IViewport, PrimitiveState, VertexAttributes } from "@feng3d/render-api"; +import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, RenderPass, IRenderPassObject, RenderPipeline, ScissorRect, Submit, Uniforms, IViewport, PrimitiveState, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -29,7 +29,7 @@ import { ChainMap } from "../utils/ChainMap"; export class RunWebGPU { - runSubmit(device: GPUDevice, submit: ISubmit) + runSubmit(device: GPUDevice, submit: Submit) { const commandBuffers = submit.commandEncoders.map((v) => { @@ -52,7 +52,7 @@ export class RunWebGPU { if (!passEncoder.__type) { - this.runRenderPass(device, gpuCommandEncoder, passEncoder as IRenderPass); + this.runRenderPass(device, gpuCommandEncoder, passEncoder as RenderPass); } else if (passEncoder.__type === "RenderPass") { @@ -79,7 +79,7 @@ export class RunWebGPU return gpuCommandEncoder.finish(); } - protected runRenderPass(device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: IRenderPass) + protected runRenderPass(device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass) { const { descriptor, renderObjects } = renderPass; @@ -115,7 +115,7 @@ export class RunWebGPU { if (!element.__type) { - this.runRenderObject(device, passEncoder, renderPassFormat, element as IRenderObject); + this.runRenderObject(device, passEncoder, renderPassFormat, element as RenderObject); } else if (element.__type === "RenderObject") { @@ -240,12 +240,12 @@ export class RunWebGPU passEncoder.executeBundles([gpuRenderBundle]); } - protected runRenderBundleObjects(device: GPUDevice, passEncoder: GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObjects?: readonly IRenderObject[]) + protected runRenderBundleObjects(device: GPUDevice, passEncoder: GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObjects?: readonly RenderObject[]) { // renderObjects.forEach((element) => { - this.runRenderObject(device, passEncoder, renderPassFormat, element as IRenderObject); + this.runRenderObject(device, passEncoder, renderPassFormat, element as RenderObject); }); } @@ -297,7 +297,7 @@ export class RunWebGPU * @param renderObject 渲染对象。 * @param renderPass 渲染通道。 */ - protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: IRenderObject) + protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: RenderObject) { const { viewport, scissorRect, pipeline, uniforms: bindingResources, geometry } = renderObject; @@ -332,7 +332,7 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { // const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); @@ -394,7 +394,7 @@ export class RunWebGPU } } - protected runScissorRect(passEncoder: GPURenderPassEncoder, attachmentSize: { width: number, height: number }, scissorRect: IScissorRect) + protected runScissorRect(passEncoder: GPURenderPassEncoder, attachmentSize: { width: number, height: number }, scissorRect: ScissorRect) { if (scissorRect) { @@ -417,7 +417,7 @@ export class RunWebGPU } } - protected runBindingResources(device: GPUDevice, passEncoder: GPUBindingCommandsMixin, shader: IGPUShader, bindingResources: IUniforms) + protected runBindingResources(device: GPUDevice, passEncoder: GPUBindingCommandsMixin, shader: IGPUShader, bindingResources: Uniforms) { // 计算 bindGroups const setBindGroups = getIGPUSetBindGroups(shader, bindingResources); @@ -429,7 +429,7 @@ export class RunWebGPU }); } - protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: IRenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const renderPipeline = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/runs/RunWebGPUCommandCache.ts index 778d1eb..2e809e3 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/runs/RunWebGPUCommandCache.ts @@ -1,4 +1,4 @@ -import { IRenderObject, IRenderPassObject } from "@feng3d/render-api"; +import { IRenderPassObject, RenderObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; @@ -47,9 +47,9 @@ export class RunWebGPUCommandCache extends RunWebGPU runCommands(passEncoder, caches); } - protected runRenderBundleObjects(device: GPUDevice, bundleEncoder: GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObjects?: IRenderObject[]) + protected runRenderBundleObjects(device: GPUDevice, bundleEncoder: GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObjects?: RenderObject[]) { - const map: ChainMap<[string, IRenderObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); + const map: ChainMap<[string, RenderObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); let caches = map.get([renderPassFormat._key, renderObjects]); if (!caches) { @@ -86,9 +86,9 @@ export class RunWebGPUCommandCache extends RunWebGPU runCommands(bundleEncoder, { ...caches, commands }); } - protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: IRenderObject) + protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: RenderObject) { - const map: ChainMap<[string, IRenderObject], Array> = device["_IGPURenderObjectCommandMap"] = device["_IGPURenderObjectCommandMap"] || new ChainMap(); + const map: ChainMap<[string, RenderObject], Array> = device["_IGPURenderObjectCommandMap"] = device["_IGPURenderObjectCommandMap"] || new ChainMap(); const _commands = passEncoder["_commands"] as any[]; const commands = map.get([renderPassFormat._key, renderObject]); -- Gitee From 27ba180e25c18d9cedeb9a6e26355d8593625e7d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 02:44:34 +0800 Subject: [PATCH 011/214] Uniforms VertexState Viewport BufferBinding --- examples/src/webgpu/a-buffer/index.ts | 8 ++++---- examples/src/webgpu/bitonicSort/bitonicDisplay.ts | 4 ++-- examples/src/webgpu/bitonicSort/index.ts | 10 +++++----- examples/src/webgpu/blending/index.ts | 14 +++++++------- examples/src/webgpu/computeBoids/index.ts | 4 ++-- examples/src/webgpu/cubemap/index.ts | 4 ++-- examples/src/webgpu/fractalCube/index.ts | 4 ++-- examples/src/webgpu/helloTriangle/index.ts | 2 +- examples/src/webgpu/occlusionQuery/index.ts | 4 ++-- examples/src/webgpu/rotatingCube/index.ts | 4 ++-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 4 ++-- examples/src/webgpu/twoCubes/index.ts | 6 +++--- src/caches/getGPUBindGroup.ts | 6 +++--- src/caches/getGPUBufferBinding.ts | 4 ++-- src/caches/getIGPUSetBindGroups.ts | 4 ++-- src/caches/getNGPURenderPipeline.ts | 8 ++++---- src/data/IGPURenderObject.ts | 2 +- src/data/IGPURenderPipeline.ts | 2 +- src/internal/IGPUBindGroupDescriptor.ts | 4 ++-- src/internal/NGPUVertexState.ts | 4 ++-- src/runs/RunWebGPU.ts | 4 ++-- src/utils/updateBufferBinding.ts | 6 +++--- 22 files changed, 56 insertions(+), 56 deletions(-) diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index d1cbbe0..5a93f41 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, IPassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; +import { BufferBinding, IPassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -49,7 +49,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => 16 * Float32Array.BYTES_PER_ELEMENT + 2 * Uint32Array.BYTES_PER_ELEMENT, 16 ); - const uniforms: IBufferBinding = { + const uniforms: BufferBinding = { bufferView: new Uint8Array(uniformsSize), modelViewProjectionMatrix: undefined, maxStorableFragments: undefined, @@ -190,7 +190,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const sliceHeight = Math.ceil(canvas.height / numSlices); const linkedListBufferSize = sliceHeight * bytesPerline; - const linkedListBuffer: IBufferBinding = { + const linkedListBuffer: BufferBinding = { bufferView: new Uint8Array(linkedListBufferSize), // data: [{ color: undefined, depth: undefined, next: undefined }] }; @@ -209,7 +209,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // for a given pixel. // * numFragments : u32 // * data : array - const headsBuffer: IBufferBinding = { + const headsBuffer: BufferBinding = { bufferView: new Uint32Array(1 + canvas.width * sliceHeight), numFragments: undefined, data: undefined, diff --git a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts index 0cce530..42126a6 100644 --- a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts +++ b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, CommandEncoder, RenderPassDescriptor, Uniforms } from "@feng3d/render-api"; +import { BufferBinding, CommandEncoder, RenderPassDescriptor, Uniforms } from "@feng3d/render-api"; import bitonicDisplay from "./bitonicDisplay.frag.wgsl"; import { Base2DRendererClass } from "./utils"; @@ -24,7 +24,7 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass this.renderPassDescriptor = renderPassDescriptor; this.computeBGDescript = computeBGDescript; - const fragment_uniforms: IBufferBinding = { + const fragment_uniforms: BufferBinding = { highlight: undefined, }; diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index ed36aa9..4a278bd 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,4 +1,4 @@ -import { Buffer, IBufferBinding, CommandEncoder, RenderPassDescriptor, Submit, Uniforms } from "@feng3d/render-api"; +import { Buffer, BufferBinding, CommandEncoder, RenderPassDescriptor, Submit, Uniforms } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -256,10 +256,10 @@ async function init( const elementsBufferSize = Float32Array.BYTES_PER_ELEMENT * totalElementOptions[0]; // Initialize input, output, staging buffers - const elementsInputBuffer: IBufferBinding = { + const elementsInputBuffer: BufferBinding = { bufferView: new Uint8Array(elementsBufferSize) }; - const elementsOutputBuffer: IBufferBinding = { + const elementsOutputBuffer: BufferBinding = { bufferView: new Uint8Array(elementsBufferSize) }; const elementsStagingBuffer: Buffer = { @@ -269,7 +269,7 @@ async function init( // Initialize atomic swap buffer on GPU and CPU. Counts number of swaps actually performed by // compute shader (when value at index x is greater than value at index y) - const atomicSwapsOutputBuffer: IBufferBinding = { + const atomicSwapsOutputBuffer: BufferBinding = { bufferView: new Uint32Array(1) }; const atomicSwapsStagingBuffer: Buffer = { @@ -278,7 +278,7 @@ async function init( }; // Create uniform buffer for compute shader - const computeUniformsBuffer: IBufferBinding = { + const computeUniformsBuffer: BufferBinding = { // width, height, blockHeight, algo bufferView: new Float32Array(4), }; diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 6e4bc9b..fe03757 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -5,13 +5,13 @@ import texturedQuadWGSL from "./texturedQuad.wgsl"; import { BlendComponent, RenderPassDescriptor, IRenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureView, Uniforms, RenderObject } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; -// declare module "@feng3d/render-api" -// { -// interface Uniforms -// { -// matrix: Float32Array; -// } -// } +declare module "@feng3d/render-api" +{ + interface Uniforms + { + matrix?: Float32Array; + } +} const init = async (canvas: HTMLCanvasElement, gui: GUI) => { diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index 16a7015..1b66729 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -71,11 +71,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uniforms: { ...computeObject0.uniforms, particlesA: { - ...computeObject0.uniforms.particlesA, + ...computeObject0.uniforms.particlesA as {}, bufferView: particleBuffers[1], }, particlesB: { - ...computeObject0.uniforms.particlesA, + ...computeObject0.uniforms.particlesA as {}, bufferView: particleBuffers[0], }, }, diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index 1435f09..845ea05 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, ITextureImageSource, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, ITextureImageSource, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -146,7 +146,7 @@ const init = async (canvas: HTMLCanvasElement) => { updateTransformationMatrix(); - (renderObject.uniforms.uniforms as IBufferBinding).modelViewProjectionMatrix = modelViewProjectionMatrix; + (renderObject.uniforms.uniforms as BufferBinding).modelViewProjectionMatrix = modelViewProjectionMatrix; const data: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 64d8071..9d1fb26 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -1,4 +1,4 @@ -import { CopyTextureToTexture, IBufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, RenderObject } from "@feng3d/render-api"; +import { CopyTextureToTexture, BufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, RenderObject } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -110,7 +110,7 @@ const init = async (canvas: HTMLCanvasElement) => { const transformationMatrix = getTransformationMatrix(); - (renderObject.uniforms.uniforms as IBufferBinding).modelViewProjectionMatrix = transformationMatrix; + (renderObject.uniforms.uniforms as BufferBinding).modelViewProjectionMatrix = transformationMatrix; const data: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 601b197..40b4d0a 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement) => indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 draw: { __type: "DrawIndexed", indexCount: 3 }, // 绘制命令 }, - uniforms: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 + uniforms: { color: [1, 0, 0, 0] }, // Uniform 颜色值。 }] }, ] diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 8e4d53a..cc1d9ef 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, RenderObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getIGPUBuffer, IGPUOcclusionQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -224,7 +224,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => mat4.transpose(mat4.inverse(world), worldInverseTranspose); mat4.multiply(viewProjection, world, worldViewProjection); - const buffer = (renderObjects[i].uniforms.uni as IBufferBinding).bufferView; + const buffer = (renderObjects[i].uniforms.uni as BufferBinding).bufferView; getIGPUBuffer(buffer).data = uniformValues.slice(); } ); diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index 7d9f1e6..903b90a 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -29,7 +29,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const uniforms: IBufferBinding = { + const uniforms: BufferBinding = { modelViewProjectionMatrix: new Float32Array(16) }; diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index f0db69a..2442fd5 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { Buffer, FragmentState, IDraw, RenderPipeline, Uniforms, IVertexState, PrimitiveState, RenderObject, VertexAttributes, vertexFormatMap } from "@feng3d/render-api"; +import { Buffer, FragmentState, IDraw, PrimitiveState, RenderObject, RenderPipeline, Uniforms, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { getIGPUBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -415,7 +415,7 @@ export class GLTFPrimitive ); VertexInputShaderString += "}"; - const vertexState: IVertexState = { + const vertexState: VertexState = { // Shader stage info code: VertexInputShaderString + vertexShader, }; diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index 15ed695..3d9b0fc 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { IBufferBinding, RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -37,7 +37,7 @@ const init = async (canvas: HTMLCanvasElement) => const uniformBuffer = new ArrayBuffer(uniformBufferSize); - const uniforms: IBufferBinding = { + const uniforms: BufferBinding = { bufferView: new Uint8Array(uniformBuffer, 0, matrixSize), modelViewProjectionMatrix: null, // 在帧循环中设置 }; @@ -61,7 +61,7 @@ const init = async (canvas: HTMLCanvasElement) => } }; - const uniforms1: IBufferBinding = { + const uniforms1: BufferBinding = { bufferView: new Uint8Array(uniformBuffer, offset, matrixSize), modelViewProjectionMatrix: null, // 在帧循环中设置 }; diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 3301167..19fb1a2 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { IBufferBinding, Sampler, TextureView } from "@feng3d/render-api"; +import { BufferBinding, Sampler, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; @@ -44,11 +44,11 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: IGPUBindGroupDescr }; // - if ((v.resource as IBufferBinding).bufferView) + if ((v.resource as BufferBinding).bufferView) { updateResource = () => { - entry.resource = getGPUBufferBinding(device, v.resource as IBufferBinding); + entry.resource = getGPUBufferBinding(device, v.resource as BufferBinding); }; } else if ((v.resource as TextureView).texture) diff --git a/src/caches/getGPUBufferBinding.ts b/src/caches/getGPUBufferBinding.ts index 02e368d..7415f85 100644 --- a/src/caches/getGPUBufferBinding.ts +++ b/src/caches/getGPUBufferBinding.ts @@ -1,8 +1,8 @@ -import { IBufferBinding } from "@feng3d/render-api"; +import { BufferBinding } from "@feng3d/render-api"; import { getGPUBuffer } from "./getGPUBuffer"; import { getIGPUBuffer } from "./getIGPUBuffer"; -export function getGPUBufferBinding(device: GPUDevice, resource: IBufferBinding): GPUBufferBinding +export function getGPUBufferBinding(device: GPUDevice, resource: BufferBinding): GPUBufferBinding { const b = getIGPUBuffer(resource.bufferView); const buffer = getGPUBuffer(device, b); diff --git a/src/caches/getIGPUSetBindGroups.ts b/src/caches/getIGPUSetBindGroups.ts index 8733c01..82d0ca8 100644 --- a/src/caches/getIGPUSetBindGroups.ts +++ b/src/caches/getIGPUSetBindGroups.ts @@ -1,6 +1,6 @@ import { watcher } from "@feng3d/watcher"; -import { IBufferBinding, Uniforms } from "@feng3d/render-api"; +import { BufferBinding, Uniforms } from "@feng3d/render-api"; import { getIGPUPipelineLayout, getIGPUShaderKey, IGPUShader } from "../caches/getIGPUPipelineLayout"; import { IGPUBindGroupEntry } from "../internal/IGPUBindGroupDescriptor"; import { IGPUBindGroupLayoutDescriptor } from "../internal/IGPUPipelineLayoutDescriptor"; @@ -62,7 +62,7 @@ function getIGPUSetBindGroup(bindGroupLayout: IGPUBindGroupLayoutDescriptor, bin // if (entry1.buffer) { - const bufferBinding = ((typeof bindingResource === "number") ? [bindingResource] : bindingResource) as IBufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 + const bufferBinding = ((typeof bindingResource === "number") ? [bindingResource] : bindingResource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 const bufferBindingInfo: IBufferBindingInfo = variableInfo["_bufferBindingInfo"] ||= getBufferBindingInfo(variableInfo.type); // 更新缓冲区绑定的数据。 updateBufferBinding(resourceName, bufferBindingInfo, bufferBinding); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 334dc51..b19ce3c 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState, DepthStencilState, FragmentState, getBlendConstantColor, IIndicesDataTypes, RenderPipeline, StencilFaceState, IVertexState, IWriteMask, PrimitiveState, VertexAttributes, vertexFormatMap, WGSLVertexType } from "@feng3d/render-api"; +import { BlendState, DepthStencilState, FragmentState, getBlendConstantColor, IIndicesDataTypes, IWriteMask, PrimitiveState, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -217,7 +217,7 @@ function getGPUStencilFaceState(stencilFaceState?: StencilFaceState) * @param vertices 顶点数据。 * @returns 完整的顶点阶段描述与顶点缓冲区列表。 */ -function getNGPUVertexState(vertexState: IVertexState, vertices: VertexAttributes) +function getNGPUVertexState(vertexState: VertexState, vertices: VertexAttributes) { let result = vertexStateMap.get([vertexState, vertices]); if (result) return result; @@ -252,7 +252,7 @@ function getNGPUVertexState(vertexState: IVertexState, vertices: VertexAttribute vertexStateMap.set([vertexState, vertices], result); // 监听变化 - const watchpropertys: gPartial = { code: "" }; + const watchpropertys: gPartial = { code: "" }; const onchanged = () => { vertexStateMap.delete([vertexState, vertices]); @@ -264,7 +264,7 @@ function getNGPUVertexState(vertexState: IVertexState, vertices: VertexAttribute return result; } -const vertexStateMap = new ChainMap<[IVertexState, VertexAttributes], { +const vertexStateMap = new ChainMap<[VertexState, VertexAttributes], { gpuVertexState: NGPUVertexState; vertexBuffers: NGPUVertexBuffer[]; /** diff --git a/src/data/IGPURenderObject.ts b/src/data/IGPURenderObject.ts index 8a1e665..14449cc 100644 --- a/src/data/IGPURenderObject.ts +++ b/src/data/IGPURenderObject.ts @@ -10,7 +10,7 @@ declare module "@feng3d/render-api" * * {@link GPURenderPassEncoder.setViewport} */ - export interface IViewport + export interface Viewport { /** * Minimum depth value of the viewport. diff --git a/src/data/IGPURenderPipeline.ts b/src/data/IGPURenderPipeline.ts index 28f9317..02f55ea 100644 --- a/src/data/IGPURenderPipeline.ts +++ b/src/data/IGPURenderPipeline.ts @@ -26,7 +26,7 @@ declare module "@feng3d/render-api" * * @see GPUVertexState */ - export interface IVertexState + export interface VertexState { /** * The name of the function in {@link GPUProgrammableStage#module} that this stage will use to diff --git a/src/internal/IGPUBindGroupDescriptor.ts b/src/internal/IGPUBindGroupDescriptor.ts index 987a612..8d1e062 100644 --- a/src/internal/IGPUBindGroupDescriptor.ts +++ b/src/internal/IGPUBindGroupDescriptor.ts @@ -1,4 +1,4 @@ -import { IBufferBinding, Sampler, TextureView } from "@feng3d/render-api"; +import { BufferBinding, IUniformType, Sampler, TextureView } from "@feng3d/render-api"; import { IGPUExternalTexture } from "../data/IGPUExternalTexture"; /** @@ -44,4 +44,4 @@ export interface IGPUBindGroupEntry resource: IGPUBindingResource; } -export type IGPUBindingResource = Sampler | TextureView | IBufferBinding | IGPUExternalTexture; +export type IGPUBindingResource = Sampler | TextureView | IGPUExternalTexture | IUniformType; diff --git a/src/internal/NGPUVertexState.ts b/src/internal/NGPUVertexState.ts index 41728b6..70d4d45 100644 --- a/src/internal/NGPUVertexState.ts +++ b/src/internal/NGPUVertexState.ts @@ -1,9 +1,9 @@ -import { IVertexState } from "@feng3d/render-api"; +import { VertexState } from "@feng3d/render-api"; /** * 内部对象。 */ -export interface NGPUVertexState extends IVertexState +export interface NGPUVertexState extends VertexState { readonly entryPoint: string; readonly constants: Readonly).bufferView = new Uint8Array(size); + (uniformData as UnReadonly).bufferView = new Uint8Array(size); } const buffer = getIGPUBuffer(uniformData.bufferView); -- Gitee From 02af3f1033c81cc9673a3f3267170dc83130da94 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 02:59:27 +0800 Subject: [PATCH 012/214] BlendState.getBlendConstantColor?(): IColor --- src/caches/getNGPURenderPipeline.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index b19ce3c..e482549 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState, DepthStencilState, FragmentState, getBlendConstantColor, IIndicesDataTypes, IWriteMask, PrimitiveState, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; +import { BlendState, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -47,7 +47,7 @@ export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPass // const stencilReference = getStencilReference(renderPipeline.depthStencil); // - const blendConstantColor = getBlendConstantColor(renderPipeline.fragment?.targets?.[0]?.blend); + const blendConstantColor = BlendState.getInstance(renderPipeline.fragment?.targets?.[0]?.blend)?.getBlendConstantColor(); // const pipeline: NGPURenderPipeline = { -- Gitee From 7f378c26714a30027da2fa48a0d818a1996fa45b Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 03:22:21 +0800 Subject: [PATCH 013/214] TextureImageSource.getTexImageSourceSize Texture.getTextureBytesPerPixel TextureImageSource.getTexImageSourceSize --- examples/src/webgpu/cubemap/index.ts | 4 ++-- src/caches/getGPUTexture.ts | 12 ++++++------ src/caches/getIGPUTextureSize.ts | 6 +++--- src/caches/getNGPURenderPipeline.ts | 2 +- src/data/IGPUTexture.ts | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index 845ea05..7b1428e 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, ITextureImageSource, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, TextureImageSource, RenderObject } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -55,7 +55,7 @@ const init = async (canvas: HTMLCanvasElement) => const imageBitmaps = await Promise.all(promises); const textureSource = imageBitmaps.map((v, i) => { - const item: ITextureImageSource = { + const item: TextureImageSource = { image: v, textureOrigin: [0, 0, i] }; diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index a2a35b7..49c1a1f 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { getTexImageSourceSize, getTextureBytesPerPixel, Texture, ITextureDataSource, ITextureImageSource, ITextureLike, ITextureSize, ITextureSource } from "@feng3d/render-api"; +import { ITextureDataSource, ITextureLike, ITextureSize, ITextureSource, Texture, TextureImageSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; @@ -102,13 +102,14 @@ export function getGPUTexture(device: GPUDevice, textureLike: ITextureLike, auto texture.writeTextures.forEach((v) => { // 处理图片纹理 - const imageSource = v as ITextureImageSource; + const imageSource = v as TextureImageSource; if (imageSource.image) { const { image, flipY, colorSpace, premultipliedAlpha, mipLevel, textureOrigin, aspect } = imageSource; // - const copySize = imageSource.size || getTexImageSourceSize(imageSource.image); + const imageSize = TextureImageSource.getTexImageSourceSize(imageSource); + const copySize = imageSource.size || imageSize; let imageOrigin = imageSource.imageOrigin; @@ -118,7 +119,6 @@ export function getGPUTexture(device: GPUDevice, textureLike: ITextureLike, auto const x = imageOrigin?.[0]; let y = imageOrigin?.[1]; - const imageSize = getTexImageSourceSize(image); y = imageSize[1] - y - copySize[1]; imageOrigin = [x, y]; @@ -147,7 +147,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: ITextureLike, auto copySize ); -return; + return; } // 处理数据纹理 @@ -170,7 +170,7 @@ return; const depthOrArrayLayers = dataImageOrigin?.[2] || 0; // 获取纹理每个像素对应的字节数量。 - const bytesPerPixel = getTextureBytesPerPixel(texture.format); + const bytesPerPixel = Texture.getTextureBytesPerPixel(texture.format); // 计算偏移 const gpuOffset diff --git a/src/caches/getIGPUTextureSize.ts b/src/caches/getIGPUTextureSize.ts index 0fca5e4..4f0a95c 100644 --- a/src/caches/getIGPUTextureSize.ts +++ b/src/caches/getIGPUTextureSize.ts @@ -1,4 +1,4 @@ -import { getTexImageSourceSize, ITextureImageSource, ITextureLike, ITextureSize } from "@feng3d/render-api"; +import { ITextureLike, ITextureSize, TextureImageSource } from "@feng3d/render-api"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; /** @@ -20,7 +20,7 @@ export function getIGPUTextureLikeSize(texture: ITextureLike) return texture.size; } -export function getIGPUTextureSourceSize(source?: ITextureImageSource[]): ITextureSize +export function getIGPUTextureSourceSize(source?: TextureImageSource[]): ITextureSize { if (!source) return undefined; @@ -34,7 +34,7 @@ export function getIGPUTextureSourceSize(source?: ITextureImageSource[]): ITextu // 获取mipLevel为0的资源尺寸。 if (!element.mipLevel) { - const copySize = element.size || getTexImageSourceSize(element.image); + const copySize = element.size || TextureImageSource.getTexImageSourceSize(element); if (width || height) { console.assert(width === copySize[0] && height === copySize[1], `纹理资源中提供的尺寸不正确!`); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index e482549..4199294 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -47,7 +47,7 @@ export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPass // const stencilReference = getStencilReference(renderPipeline.depthStencil); // - const blendConstantColor = BlendState.getInstance(renderPipeline.fragment?.targets?.[0]?.blend)?.getBlendConstantColor(); + const blendConstantColor = BlendState.getBlendConstantColor(renderPipeline.fragment?.targets?.[0]?.blend); // const pipeline: NGPURenderPipeline = { diff --git a/src/data/IGPUTexture.ts b/src/data/IGPUTexture.ts index 7f1b34d..346dcc2 100644 --- a/src/data/IGPUTexture.ts +++ b/src/data/IGPUTexture.ts @@ -7,7 +7,7 @@ declare module "@feng3d/render-api" * * @see GPUQueue.copyExternalImageToTexture */ - export interface ITextureImageSource + export interface TextureImageSource { /** * Defines which aspects of the {@link GPUImageCopyTexture#texture} to copy to/from. -- Gitee From e2be9314ecca294db33032753fb18c4b293654f5 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 03:29:29 +0800 Subject: [PATCH 014/214] RenderPipeline -> Material --- examples/src/webgpu/a-buffer/index.ts | 8 ++++---- examples/src/webgpu/animometer/index.ts | 6 +++--- examples/src/webgpu/bitonicSort/utils.ts | 8 ++++---- examples/src/webgpu/blending/index.ts | 6 +++--- examples/src/webgpu/cameras/index.ts | 4 ++-- examples/src/webgpu/cornell/rasterizer.ts | 4 ++-- examples/src/webgpu/deferredRendering/index.ts | 8 ++++---- examples/src/webgpu/gameOfLife/index.ts | 4 ++-- examples/src/webgpu/imageBlur/index.ts | 4 ++-- examples/src/webgpu/multipleCanvases/index.ts | 4 ++-- examples/src/webgpu/normalMap/index.ts | 4 ++-- examples/src/webgpu/normalMap/utils.ts | 4 ++-- examples/src/webgpu/occlusionQuery/index.ts | 4 ++-- examples/src/webgpu/particles/index.ts | 4 ++-- examples/src/webgpu/points/index.ts | 4 ++-- examples/src/webgpu/renderBundles/index.ts | 4 ++-- examples/src/webgpu/resizeObserverHDDPI/index.ts | 4 ++-- examples/src/webgpu/reversedZ/index.ts | 16 ++++++++-------- examples/src/webgpu/samplerParameters/index.ts | 6 +++--- examples/src/webgpu/shadowMapping/index.ts | 6 +++--- examples/src/webgpu/skinnedMesh/glbUtils.ts | 6 +++--- examples/src/webgpu/skinnedMesh/gridUtils.ts | 4 ++-- examples/src/webgpu/textRenderingMsdf/index.ts | 4 ++-- .../src/webgpu/textRenderingMsdf/msdfText.ts | 6 +++--- examples/src/webgpu/timestampQuery/index.ts | 4 ++-- examples/src/webgpu/transparentCanvas/index.ts | 4 ++-- .../src/webgpu/volumeRenderingTexture3D/index.ts | 4 ++-- examples/src/webgpu/wireframe/index.ts | 8 ++++---- examples/src/webgpu/worker/worker.ts | 4 ++-- src/caches/getNGPURenderPipeline.ts | 6 +++--- src/data/IGPURenderPipeline.ts | 2 +- src/runs/RunWebGPU.ts | 6 +++--- 32 files changed, 85 insertions(+), 85 deletions(-) diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 5a93f41..ae1af8b 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, IPassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; +import { BufferBinding, IPassEncoder, RenderPass, RenderPassDescriptor, Material, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -56,7 +56,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => targetWidth: undefined, }; - const opaquePipeline: RenderPipeline = { + const opaquePipeline: Material = { vertex: { code: opaqueWGSL, }, @@ -70,7 +70,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => label: "opaquePipeline", }; - const translucentPipeline: RenderPipeline = { + const translucentPipeline: Material = { vertex: { code: translucentWGSL, }, @@ -96,7 +96,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => label: "translucentPassDescriptor", }; - const compositePipeline: RenderPipeline = { + const compositePipeline: Material = { vertex: { code: compositeWGSL, }, diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index bde02fd..dfbea5d 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import animometerWGSL from "./animometer.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, RenderObject } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, Material, Submit, RenderObject } from "@feng3d/render-api"; import { IGPURenderBundle, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -33,7 +33,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const vec4Size = 4 * Float32Array.BYTES_PER_ELEMENT; - const pipelineDesc: RenderPipeline = { + const pipelineDesc: Material = { vertex: { code: animometerWGSL, }, @@ -42,7 +42,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const pipeline: RenderPipeline = { + const pipeline: Material = { ...pipelineDesc, }; diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index cd27a95..f5cd1e9 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Uniforms } from "@feng3d/render-api"; +import { CommandEncoder, RenderPass, RenderPassDescriptor, Material, Uniforms } from "@feng3d/render-api"; const fullscreenTexturedQuad = ` @@ -43,14 +43,14 @@ export abstract class Base2DRendererClass ...args: unknown[] ): void; renderPassDescriptor: RenderPassDescriptor; - pipeline: RenderPipeline; + pipeline: Material; bindGroupMap: Record; currentBindGroupName: string; executeRun( commandEncoder: CommandEncoder, renderPassDescriptor: RenderPassDescriptor, - pipeline: RenderPipeline, + pipeline: Material, bindingResources?: Uniforms ) { @@ -76,7 +76,7 @@ export abstract class Base2DRendererClass code: string, ) { - const renderPipeline: RenderPipeline = { + const renderPipeline: Material = { label: `${label}.pipeline`, vertex: { code: fullscreenTexturedQuad, diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index fe03757..03e96b6 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import texturedQuadWGSL from "./texturedQuad.wgsl"; -import { BlendComponent, RenderPassDescriptor, IRenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureView, Uniforms, RenderObject } from "@feng3d/render-api"; +import { BlendComponent, RenderPassDescriptor, IRenderPassObject, Material, Sampler, Submit, Texture, TextureView, Uniforms, RenderObject } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; declare module "@feng3d/render-api" @@ -433,7 +433,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => clearFolder.add(clear, "alpha", 0, 1).onChange(render); clearFolder.addColor(new GUIColorHelper(clear.color), "value").onChange(render); - const dstPipeline: RenderPipeline = { + const dstPipeline: Material = { label: "hardcoded textured quad pipeline", vertex: { code: texturedQuadWGSL, @@ -447,7 +447,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { gui.updateDisplay(); - const srcPipeline: RenderPipeline = { + const srcPipeline: Material = { label: "hardcoded textured quad pipeline", vertex: { code: texturedQuadWGSL, diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index 57a4813..c86bef4 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -5,7 +5,7 @@ import { ArcballCamera, WASDCamera } from "./camera"; import cubeWGSL from "./cube.wgsl"; import { createInputHandler } from "./input"; -import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Sampler, Submit, Texture, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: cubeWGSL, }, diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index 7cf7747..0e361ce 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Texture, Uniforms } from "@feng3d/render-api"; +import { CommandEncoder, RenderPass, RenderPassDescriptor, Material, Texture, Uniforms } from "@feng3d/render-api"; import Common from "./common"; import Radiosity from "./radiosity"; @@ -13,7 +13,7 @@ export default class Rasterizer private readonly common: Common; private readonly scene: Scene; private readonly renderPassDescriptor: RenderPassDescriptor; - private readonly pipeline: RenderPipeline; + private readonly pipeline: Material; private readonly bindGroup: Uniforms; constructor( diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 5b0b758..de461c1 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -10,7 +10,7 @@ import lightUpdate from "./lightUpdate.wgsl"; import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, Material, Submit, Texture, TextureView, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const kMaxNumLights = 1024; @@ -74,7 +74,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullMode: "back", }; - const writeGBuffersPipeline: RenderPipeline = { + const writeGBuffersPipeline: Material = { vertex: { code: vertexWriteGBuffers, }, @@ -83,7 +83,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const gBuffersDebugViewPipeline: RenderPipeline = { + const gBuffersDebugViewPipeline: Material = { vertex: { code: vertexTextureQuad, }, @@ -95,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }, }; - const deferredRenderPipeline: RenderPipeline = { + const deferredRenderPipeline: Material = { vertex: { code: vertexTextureQuad, }, diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index dbcb92e..1f3673c 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -4,7 +4,7 @@ import computeWGSL from "./compute.wgsl"; import fragWGSL from "./frag.wgsl"; import vertWGSL from "./vert.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, Material, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -86,7 +86,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => next: { bufferView: buffer0 }, }; - const renderPipeline: RenderPipeline = { + const renderPipeline: Material = { vertex: { code: vertWGSL, }, diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 0e1964e..99b2315 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -3,7 +3,7 @@ import { GUI } from "dat.gui"; import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgsl"; import blurWGSL from "./blur.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, Material, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; // Contants from the blur.wgsl shader. @@ -24,7 +24,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const fullscreenQuadPipeline1: RenderPipeline = { + const fullscreenQuadPipeline1: Material = { vertex: { code: fullscreenTexturedQuadWGSL, }, diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index c92b33f..b8d1168 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,4 +1,4 @@ -import { IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { IPassEncoder, RenderPassDescriptor, Material, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; @@ -114,7 +114,7 @@ const init = async () => `, }; - const pipeline: RenderPipeline = { + const pipeline: Material = { label: "our hardcoded red triangle pipeline", vertex: { ...module, diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index 1e935e4..182b79e 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -232,7 +232,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; - const texturedCubePipeline: RenderPipeline = create3DRenderPipeline( + const texturedCubePipeline: Material = create3DRenderPipeline( "NormalMappingRender", normalMapWGSL, // Position, normal uv tangent bitangent diff --git a/examples/src/webgpu/normalMap/utils.ts b/examples/src/webgpu/normalMap/utils.ts index 8c12aea..e741305 100644 --- a/examples/src/webgpu/normalMap/utils.ts +++ b/examples/src/webgpu/normalMap/utils.ts @@ -1,4 +1,4 @@ -import { DepthStencilState, RenderPipeline, Texture } from "@feng3d/render-api"; +import { DepthStencilState, Material, Texture } from "@feng3d/render-api"; export const create3DRenderPipeline = ( label: string, @@ -16,7 +16,7 @@ export const create3DRenderPipeline = ( }; } - const pipelineDescriptor: RenderPipeline = { + const pipelineDescriptor: Material = { label: `${label}.pipeline`, vertex: { code: vertexShader, diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index cc1d9ef..24480aa 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderPass, RenderPassDescriptor, Material, Submit, RenderObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getIGPUBuffer, IGPUOcclusionQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -22,7 +22,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: solidColorLitWGSL, }, diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index e1f9dee..a479236 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -7,7 +7,7 @@ import particleWGSL from "./particle.wgsl"; import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, Material, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const numParticles = 50000; @@ -36,7 +36,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => color: { data: particlesBuffer, format: "float32x4", offset: particleColorOffset, arrayStride: particleInstanceByteSize, stepMode: "instance" }, }; - const renderPipeline: RenderPipeline = { + const renderPipeline: Material = { vertex: { code: particleWGSL, }, diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 029f9d2..1378091 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; @@ -93,7 +93,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => depthCompare: "less", format: depthFormat, }, - } as RenderPipeline) + } as Material) ) ); diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index e3791b8..d032fbb 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,4 +1,4 @@ -import { RenderPass, RenderPassDescriptor, IRenderPassObject, RenderPipeline, Sampler, Submit, Texture, Uniforms, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, IRenderPassObject, Material, Sampler, Submit, Texture, Uniforms, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, IGPURenderBundle, WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -41,7 +41,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => canvasId: canvas.id, }; - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: meshWGSL, }, diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index 93e4d5c..23c8b3b 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -1,14 +1,14 @@ import { GUI } from "dat.gui"; import checkerWGSL from "./checker.wgsl"; -import { RenderPassDescriptor, RenderPipeline, Submit, Uniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Submit, Uniforms } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement) => { const webgpu = await new WebGPU().init(); - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: checkerWGSL }, fragment: { code: checkerWGSL, diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 77d1ce5..74ae794 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -10,7 +10,7 @@ import vertexDepthPrePassWGSL from "./vertexDepthPrePass.wgsl"; import vertexPrecisionErrorPassWGSL from "./vertexPrecisionErrorPass.wgsl"; import vertexTextureQuadWGSL from "./vertexTextureQuad.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, Material, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; // Two planes close to each other for depth precision test @@ -87,7 +87,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // depthPrePass is used to render scene to the depth texture // this is not needed if you just want to use reversed z to render a scene - const depthPrePassRenderPipelineDescriptorBase: RenderPipeline = { + const depthPrePassRenderPipelineDescriptorBase: Material = { vertex: { code: vertexDepthPrePassWGSL, }, @@ -95,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // we need the depthCompare to fit the depth buffer mode we are using. // this is the same for other passes - const depthPrePassPipelines: RenderPipeline[] = []; + const depthPrePassPipelines: Material[] = []; depthPrePassPipelines[DepthBufferMode.Default] = { ...depthPrePassRenderPipelineDescriptorBase, depthStencil: { @@ -113,7 +113,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // precisionPass is to draw precision error as color of depth value stored in depth buffer // compared to that directly calcualated in the shader - const precisionPassRenderPipelineDescriptorBase: RenderPipeline = { + const precisionPassRenderPipelineDescriptorBase: Material = { vertex: { code: vertexPrecisionErrorPassWGSL, }, @@ -122,7 +122,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const precisionPassPipelines: RenderPipeline[] = []; + const precisionPassPipelines: Material[] = []; precisionPassPipelines[DepthBufferMode.Default] = { ...precisionPassRenderPipelineDescriptorBase, depthStencil: { @@ -139,7 +139,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // colorPass is the regular render pass to render the scene - const colorPassRenderPipelineDescriptorBase: RenderPipeline = { + const colorPassRenderPipelineDescriptorBase: Material = { vertex: { code: vertexWGSL, }, @@ -149,7 +149,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // - const colorPassPipelines: RenderPipeline[] = []; + const colorPassPipelines: Material[] = []; colorPassPipelines[DepthBufferMode.Default] = { ...colorPassRenderPipelineDescriptorBase, depthStencil: { @@ -168,7 +168,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // textureQuadPass is draw a full screen quad of depth texture // to see the difference of depth value using reversed z compared to default depth buffer usage // 0.0 will be the furthest and 1.0 will be the closest - const textureQuadPassPipline: RenderPipeline = { + const textureQuadPassPipline: Material = { vertex: { code: vertexTextureQuadWGSL, }, diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index 71d96b6..c56342f 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -1,7 +1,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; -import { RenderPassDescriptor, IRenderPassObject, RenderPipeline, Sampler, Submit, Texture, ITextureSource, Uniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, IRenderPassObject, Material, Sampler, Submit, Texture, ITextureSource, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import showTextureWGSL from "./showTexture.wgsl"; @@ -270,7 +270,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // "Debug" view of the actual texture contents // - const showTexturePipeline: RenderPipeline = { + const showTexturePipeline: Material = { vertex: { code: showTextureWGSL }, fragment: { code: showTextureWGSL } }; @@ -278,7 +278,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Pipeline for drawing the test squares // - const texturedSquarePipeline: RenderPipeline = { + const texturedSquarePipeline: Material = { vertex: { code: texturedSquareWGSL, constants: { kTextureBaseSize, kViewportSize } }, fragment: { code: texturedSquareWGSL }, }; diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 1beb633..7873a60 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -6,7 +6,7 @@ import fragmentWGSL from "./fragment.wgsl"; import vertexWGSL from "./vertex.wgsl"; import vertexShadowWGSL from "./vertexShadow.wgsl"; -import { RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; const shadowDepthTextureSize = 1024; @@ -54,7 +54,7 @@ const init = async (canvas: HTMLCanvasElement) => cullMode: "back", }; - const shadowPipeline: RenderPipeline = { + const shadowPipeline: Material = { vertex: { code: vertexShadowWGSL, }, @@ -67,7 +67,7 @@ const init = async (canvas: HTMLCanvasElement) => // Create a bind group layout which holds the scene uniforms and // the texture+sampler for depth. We create it manually because the WebPU // implementation doesn't infer this from the shader (yet). - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: vertexWGSL, }, diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 2442fd5..3c3568b 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { Buffer, FragmentState, IDraw, PrimitiveState, RenderObject, RenderPipeline, Uniforms, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; +import { Buffer, FragmentState, IDraw, PrimitiveState, RenderObject, Material, Uniforms, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { getIGPUBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -342,7 +342,7 @@ interface AttributeMapInterface export class GLTFPrimitive { topology: GLTFRenderMode; - renderPipeline: RenderPipeline; + renderPipeline: Material; private attributeMap: AttributeMapInterface; private attributes: string[] = []; vertices: VertexAttributes; @@ -427,7 +427,7 @@ export class GLTFPrimitive // targets: [{ format: colorFormat }], }; - const rpDescript: RenderPipeline = { + const rpDescript: Material = { label: `${label}.pipeline`, vertex: vertexState, fragment: fragmentState, diff --git a/examples/src/webgpu/skinnedMesh/gridUtils.ts b/examples/src/webgpu/skinnedMesh/gridUtils.ts index ac735ef..80d6f6d 100644 --- a/examples/src/webgpu/skinnedMesh/gridUtils.ts +++ b/examples/src/webgpu/skinnedMesh/gridUtils.ts @@ -1,4 +1,4 @@ -import { RenderPipeline, VertexAttributes } from "@feng3d/render-api"; +import { Material, VertexAttributes } from "@feng3d/render-api"; import { gridIndices, gridJoints, gridVertices, gridWeights } from "./gridData"; @@ -24,7 +24,7 @@ export const createSkinnedGridRenderPipeline = ( fragmentShader: string, ) => { - const pipeline: RenderPipeline = { + const pipeline: Material = { label: "SkinnedGridRenderer", vertex: { code: vertexShader, diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index f0ec018..0079d58 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { RenderPassDescriptor, IRenderPassObject, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, IRenderPassObject, Material, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import basicVertWGSL from "../../shaders/basic.vert.wgsl"; @@ -141,7 +141,7 @@ setBlendConstant().`, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: basicVertWGSL, }, diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index 74fed97..0d6d7b7 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -2,7 +2,7 @@ import { mat4, Mat4 } from "wgpu-matrix"; import msdfTextWGSL from "./msdfText.wgsl"; -import { IRenderPassObject, RenderPipeline, Sampler, Texture, Uniforms } from "@feng3d/render-api"; +import { IRenderPassObject, Material, Sampler, Texture, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, IGPURenderBundle } from "@feng3d/webgpu"; // The kerning map stores a spare map of character ID pairs with an associated @@ -32,7 +32,7 @@ export class MsdfFont charCount: number; defaultChar: MsdfChar; constructor( - public pipeline: RenderPipeline, + public pipeline: Material, public bindGroup: Uniforms, public lineHeight: number, public chars: { [x: number]: MsdfChar }, @@ -149,7 +149,7 @@ export interface MsdfTextFormattingOptions export class MsdfTextRenderer { - pipelinePromise: RenderPipeline; + pipelinePromise: Material; sampler: Sampler; cameraUniformBuffer: Float32Array = new Float32Array(16 * 2); diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 63c4bff..434017f 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, RenderPipeline, Submit, Texture, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Submit, Texture, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -61,7 +61,7 @@ const init = async (canvas: HTMLCanvasElement) => const uniforms = { modelViewProjectionMatrix: null }; - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: basicVertWGSL, }, diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 0d5f158..64264fc 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { RenderPassDescriptor, RenderPipeline, Texture, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Texture, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -30,7 +30,7 @@ const init = async (canvas: HTMLCanvasElement) => uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: basicVertWGSL, }, diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index d41f516..cb6334a 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import volumeWGSL from "./volume.wgsl"; -import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const gui = new GUI(); @@ -28,7 +28,7 @@ const init = async (canvas: HTMLCanvasElement) => const sampleCount = 4; - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: volumeWGSL, }, diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 578cef2..8c18a49 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, RenderPipeline, Submit, Uniforms, PrimitiveState, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Submit, Uniforms, PrimitiveState, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => return model; }); - let litPipeline: RenderPipeline; + let litPipeline: Material; function rebuildLitPipeline() { litPipeline = { @@ -72,7 +72,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } rebuildLitPipeline(); - const wireframePipeline: RenderPipeline = { + const wireframePipeline: Material = { label: "wireframe pipeline", vertex: { code: wireframeWGSL, @@ -88,7 +88,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const barycentricCoordinatesBasedWireframePipeline: RenderPipeline = { + const barycentricCoordinatesBasedWireframePipeline: Material = { label: "barycentric coordinates based wireframe pipeline", vertex: { code: wireframeWGSL, diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 0b9ee04..971c6b3 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, Material, Submit, VertexAttributes } from "@feng3d/render-api"; import { getOffscreenCanvasId, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -78,7 +78,7 @@ async function init(canvas: OffscreenCanvas) uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: RenderPipeline = { + const pipeline: Material = { vertex: { code: basicVertWGSL, }, diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 4199294..4221274 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; +import { BlendState, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, Material, PrimitiveState, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -21,7 +21,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPassFormat: IGPURenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) +export function getNGPURenderPipeline(renderPipeline: Material, renderPassFormat: IGPURenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const indexFormat = indices ? getIGPUSetIndexBuffer(indices).indexFormat : undefined; @@ -80,7 +80,7 @@ export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPass } const renderPipelineMap = new ChainMap< - [RenderPipeline, string, PrimitiveState, VertexAttributes, GPUIndexFormat], + [Material, string, PrimitiveState, VertexAttributes, GPUIndexFormat], { /** * GPU渲染管线描述。 diff --git a/src/data/IGPURenderPipeline.ts b/src/data/IGPURenderPipeline.ts index 02f55ea..22e3d29 100644 --- a/src/data/IGPURenderPipeline.ts +++ b/src/data/IGPURenderPipeline.ts @@ -9,7 +9,7 @@ declare module "@feng3d/render-api" * * @see https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/createRenderPipeline */ - export interface RenderPipeline + export interface Material { /** * 多重采样阶段描述。 diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 2ab0e1a..f8cfda6 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, RenderPass, IRenderPassObject, RenderPipeline, ScissorRect, Submit, Uniforms, Viewport, PrimitiveState, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IRenderPassObject, Material, PrimitiveState, RenderObject, RenderPass, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -332,7 +332,7 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: Material, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { // const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); @@ -429,7 +429,7 @@ export class RunWebGPU }); } - protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: Material, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const renderPipeline = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); -- Gitee From 39393c0d9cbbe0b3e9ce3d3a8c84cfcd44a048d7 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 11:39:58 +0800 Subject: [PATCH 015/214] WriteBuffer --- src/data/IGPUBuffer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/IGPUBuffer.ts b/src/data/IGPUBuffer.ts index 5c53df5..7864d95 100644 --- a/src/data/IGPUBuffer.ts +++ b/src/data/IGPUBuffer.ts @@ -1,4 +1,4 @@ -import { Buffer, IWriteBuffer } from "@feng3d/render-api"; +import { } from "@feng3d/render-api"; declare module "@feng3d/render-api" { -- Gitee From 3e5dbe2efa110e3cf3b63672284e4db8fbcfbb9e Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 12:36:21 +0800 Subject: [PATCH 016/214] TextureImageSource.getInstance --- src/data/IGPURenderObject.ts | 26 ++++++++++++++++++-------- src/runs/RunWebGPU.ts | 8 +++----- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/data/IGPURenderObject.ts b/src/data/IGPURenderObject.ts index 14449cc..0f6c677 100644 --- a/src/data/IGPURenderObject.ts +++ b/src/data/IGPURenderObject.ts @@ -1,4 +1,4 @@ -import { Uniforms } from "@feng3d/render-api"; +import { DrawIndexed, DrawVertex, Viewport } from "@feng3d/render-api"; import { } from "./IGPUBindingResources"; declare module "@feng3d/render-api" @@ -19,7 +19,7 @@ declare module "@feng3d/render-api" * * 默认为 0 。 */ - readonly minDepth: number, + minDepth?: number, /** * Maximum depth value of the viewport. @@ -28,7 +28,7 @@ declare module "@feng3d/render-api" * * 默认为 1 。 */ - readonly maxDepth: number + maxDepth?: number } /** @@ -38,12 +38,14 @@ declare module "@feng3d/render-api" * * @see GPURenderCommandsMixin.draw */ - export interface IDrawVertex + export interface DrawVertex { /** * First instance to draw. + * + * 默认为 0 。 */ - readonly firstInstance?: number; + firstInstance?: number; } /** @@ -51,20 +53,28 @@ declare module "@feng3d/render-api" * * {@link GPURenderCommandsMixin.drawIndexed} */ - export interface IDrawIndexed + export interface DrawIndexed { /** * Added to each index value before indexing into the vertex buffers. * * 默认为 0 。 */ - readonly baseVertex?: number; + baseVertex?: number; /** * First instance to draw. * * 默认为 0 。 */ - readonly firstInstance?: number; + firstInstance?: number; } } + +Viewport.prototype.minDepth = 0; +Viewport.prototype.maxDepth = 1; + +DrawVertex.prototype.firstInstance = 0 + +DrawIndexed.prototype.baseVertex = 0; +DrawIndexed.prototype.firstInstance = 0; \ No newline at end of file diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index f8cfda6..72f97f8 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, IDrawIndexed, IDrawVertex, IIndicesDataTypes, IRenderPassObject, Material, PrimitiveState, RenderObject, RenderPass, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, Material, PrimitiveState, RenderObject, RenderPass, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -456,16 +456,14 @@ export class RunWebGPU passEncoder.setIndexBuffer(gBuffer, indexFormat, offset, size); } - protected runDrawVertex(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, drawVertex: IDrawVertex) + protected runDrawVertex(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, drawVertex: DrawVertex) { - if (!drawVertex) return; // passEncoder.draw(drawVertex.vertexCount, drawVertex.instanceCount, drawVertex.firstVertex, drawVertex.firstInstance); } - protected runDrawIndexed(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, drawIndexed: IDrawIndexed) + protected runDrawIndexed(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, drawIndexed: DrawIndexed) { - if (!drawIndexed) return; // passEncoder.drawIndexed(drawIndexed.indexCount, drawIndexed.instanceCount, drawIndexed.firstIndex, drawIndexed.baseVertex, drawIndexed.firstInstance); } -- Gitee From fc1daec7d1af0d1a3bf5d8004be5d23e5a8f07f5 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 14:38:19 +0800 Subject: [PATCH 017/214] TextureSource --- examples/src/webgpu/samplerParameters/index.ts | 4 ++-- src/caches/getGPUTexture.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index c56342f..fa509c5 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -1,7 +1,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; -import { RenderPassDescriptor, IRenderPassObject, Material, Sampler, Submit, Texture, ITextureSource, Uniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, IRenderPassObject, Material, Sampler, Submit, Texture, TextureSource, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import showTextureWGSL from "./showTexture.wgsl"; @@ -241,7 +241,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => [255, 193, 7, 255], // yellow [216, 27, 96, 255], // pink ]; - const writeTextures: ITextureSource[] = []; + const writeTextures: TextureSource[] = []; for (let mipLevel = 0; mipLevel < kTextureMipLevels; ++mipLevel) { const size = 2 ** (kTextureMipLevels - mipLevel); // 16, 8, 4, 2 diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 49c1a1f..ef3af54 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { ITextureDataSource, ITextureLike, ITextureSize, ITextureSource, Texture, TextureImageSource } from "@feng3d/render-api"; +import { ITextureDataSource, ITextureLike, ITextureSize, Texture, TextureImageSource, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; @@ -84,7 +84,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: ITextureLike, auto { if (texture.sources) { - const writeTextures: ITextureSource[] = []; + const writeTextures: TextureSource[] = []; texture.sources.forEach((v) => { writeTextures.push(v); -- Gitee From 457552140d55c3742c9d2877ef87ab7b2e5f65c8 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 19:22:43 +0800 Subject: [PATCH 018/214] =?UTF-8?q?=5F=5Ftype=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E4=B8=BA=20=5F=5Ftype=5F=5F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/webgpu/RenderObjectChanges/index.ts | 2 +- examples/src/webgpu/a-buffer/index.ts | 8 +++---- examples/src/webgpu/animometer/index.ts | 4 ++-- .../webgpu/atmosphericScatteringSky/index.ts | 2 +- examples/src/webgpu/bitonicSort/index.ts | 8 +++---- examples/src/webgpu/bitonicSort/utils.ts | 2 +- examples/src/webgpu/blending/index.ts | 4 ++-- examples/src/webgpu/cameras/index.ts | 2 +- examples/src/webgpu/computeBoids/index.ts | 4 ++-- examples/src/webgpu/cornell/radiosity.ts | 2 +- examples/src/webgpu/cornell/rasterizer.ts | 2 +- examples/src/webgpu/cornell/raytracer.ts | 2 +- examples/src/webgpu/cornell/tonemapper.ts | 2 +- examples/src/webgpu/cubemap/index.ts | 2 +- .../src/webgpu/deferredRendering/index.ts | 8 +++---- examples/src/webgpu/fractalCube/index.ts | 4 ++-- examples/src/webgpu/gameOfLife/index.ts | 4 ++-- examples/src/webgpu/helloTriangle/index.ts | 2 +- .../src/webgpu/helloTriangleMSAA/index.ts | 2 +- examples/src/webgpu/imageBlur/index.ts | 4 ++-- examples/src/webgpu/instancedCube/index.ts | 2 +- examples/src/webgpu/multipleCanvases/index.ts | 2 +- examples/src/webgpu/normalMap/index.ts | 2 +- examples/src/webgpu/occlusionQuery/index.ts | 4 ++-- examples/src/webgpu/particles/index.ts | 8 +++---- examples/src/webgpu/points/index.ts | 2 +- examples/src/webgpu/renderBundles/index.ts | 6 ++--- examples/src/webgpu/resizeCanvas/index.ts | 2 +- .../src/webgpu/resizeObserverHDDPI/index.ts | 2 +- examples/src/webgpu/reversedZ/index.ts | 10 ++++----- examples/src/webgpu/rotatingCube/index.ts | 2 +- .../src/webgpu/samplerParameters/index.ts | 12 +++++----- examples/src/webgpu/shadowMapping/index.ts | 4 ++-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 4 ++-- examples/src/webgpu/skinnedMesh/index.ts | 2 +- .../src/webgpu/textRenderingMsdf/index.ts | 2 +- .../src/webgpu/textRenderingMsdf/msdfText.ts | 4 ++-- examples/src/webgpu/texturedCube/index.ts | 2 +- examples/src/webgpu/timestampQuery/index.ts | 2 +- .../src/webgpu/transparentCanvas/index.ts | 2 +- examples/src/webgpu/twoCubes/index.ts | 2 +- examples/src/webgpu/videoUploading/index.ts | 2 +- .../webgpu/volumeRenderingTexture3D/index.ts | 4 ++-- examples/src/webgpu/wireframe/index.ts | 4 ++-- examples/src/webgpu/worker/worker.ts | 2 +- src/WebGPUStep.ts | 2 +- src/caches/getGPURenderOcclusionQuery.ts | 2 +- src/data/IGPUComputePass.ts | 2 +- src/data/IGPUOcclusionQuery.ts | 2 +- src/data/IGPURenderBundle.ts | 2 +- src/runs/RunWebGPU.ts | 22 +++++++++---------- 51 files changed, 96 insertions(+), 96 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index 98543ac..2ff32d8 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -34,7 +34,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 }, indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 - draw: { __type: "DrawIndexed", indexCount: 3 }, // 绘制命令 + draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 }, uniforms: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 }; diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index ae1af8b..61541af 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -285,7 +285,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, vertices, indices, - draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, + draw: { __type__: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, } }] }; @@ -295,7 +295,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { // initialize the heads buffer passEncoders.push({ - __type: "CopyBufferToBuffer", + __type__: "CopyBufferToBuffer", source: getIGPUBuffer(headsInitBuffer), destination: getIGPUBuffer(headsBuffer.bufferView), }); @@ -326,7 +326,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, vertices, indices, - draw: { __type: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, + draw: { __type__: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, } } ], @@ -350,7 +350,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => primitive: { topology: "triangle-list", }, - draw: { __type: "DrawVertex", vertexCount: 6 }, + draw: { __type__: "DrawVertex", vertexCount: 6 }, } } ] diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index dfbea5d..75e5f6a 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -64,7 +64,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => position: { data: vertexBuffer, format: "float32x4", offset: 0, arrayStride: 2 * vec4Size }, color: { data: vertexBuffer, format: "float32x4", offset: vec4Size, arrayStride: 2 * vec4Size }, }, - draw: { __type: "DrawVertex", vertexCount: 3, instanceCount: 1 }, + draw: { __type__: "DrawVertex", vertexCount: 3, instanceCount: 1 }, }, }; @@ -123,7 +123,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const uniformTime = new Float32Array([0]); const renderBundleObject: IGPURenderBundle = { - __type: "RenderBundle", + __type__: "RenderBundle", renderObjects }; diff --git a/examples/src/webgpu/atmosphericScatteringSky/index.ts b/examples/src/webgpu/atmosphericScatteringSky/index.ts index e4aa869..7358735 100644 --- a/examples/src/webgpu/atmosphericScatteringSky/index.ts +++ b/examples/src/webgpu/atmosphericScatteringSky/index.ts @@ -59,7 +59,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => function frame() { webgpu.submit({ - commandEncoders: [{ passEncoders: [{ __type: "ComputePass", computeObjects: [computeObject0] }] }] + commandEncoders: [{ passEncoders: [{ __type__: "ComputePass", computeObjects: [computeObject0] }] }] }); ++t; diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 4a278bd..5c9dc0c 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -378,7 +378,7 @@ async function init( const submit: Submit = { commandEncoders: [{ passEncoders: [{ - __type: "ComputePass", + __type__: "ComputePass", computeObjects: [{ pipeline: atomicToZeroComputePipeline, uniforms: computeBGCluster, @@ -736,7 +736,7 @@ async function init( ) { const computePassEncoder: IGPUComputePass = { - __type: "ComputePass", + __type__: "ComputePass", timestampQuery: querySet, computeObjects: [{ pipeline: computePipeline, @@ -795,7 +795,7 @@ async function init( // Copy GPU accessible buffers to CPU accessible buffers commandEncoder.passEncoders.push( { - __type: "CopyBufferToBuffer", + __type__: "CopyBufferToBuffer", source: getIGPUBuffer(elementsOutputBuffer.bufferView), sourceOffset: 0, destination: elementsStagingBuffer, @@ -803,7 +803,7 @@ async function init( size: elementsBufferSize }, { - __type: "CopyBufferToBuffer", + __type__: "CopyBufferToBuffer", source: getIGPUBuffer(atomicSwapsOutputBuffer.bufferView), sourceOffset: 0, destination: atomicSwapsStagingBuffer, diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index f5cd1e9..5e69710 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -64,7 +64,7 @@ export abstract class Base2DRendererClass topology: "triangle-list", cullFace: "none", }, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1 } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1 } } }], }; diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 03e96b6..4d4e018 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -511,7 +511,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: dstPipeline, uniforms: dstBindGroup, geometry: { - draw: { __type: "DrawVertex", vertexCount: 6 }, + draw: { __type__: "DrawVertex", vertexCount: 6 }, } }; @@ -519,7 +519,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: srcPipeline, uniforms: srcBindGroup, geometry: { - draw: { __type: "DrawVertex", vertexCount: 6 }, + draw: { __type__: "DrawVertex", vertexCount: 6 }, } }; diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index c86bef4..4c56661 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -101,7 +101,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullFace: "back", }, vertices, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } }; diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index 1b66729..45d8cae 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -103,7 +103,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => a_particleVel: { data: particleBuffers[0], format: "float32x2", offset: 2 * 4, arrayStride: 4 * 4, stepMode: "instance" }, a_pos: { data: vertexBufferData, format: "float32x2" }, }, - draw: { __type: "DrawVertex", vertexCount: 3, instanceCount: numParticles } + draw: { __type__: "DrawVertex", vertexCount: 3, instanceCount: numParticles } } }; @@ -133,7 +133,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => commandEncoders: [ { passEncoders: [ - { __type: "ComputePass", computeObjects: [[computeObject0, computeObject1][t % 2]] }, + { __type__: "ComputePass", computeObjects: [[computeObject0, computeObject1][t % 2]] }, { descriptor: renderPass, renderObjects: [[renderObject, renderObject1][(t + 1) % 2]] }, ] } diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index 4c61d52..fe59c07 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -109,7 +109,7 @@ export default class Radiosity const lightmapSize = this.lightmap.size; this.passEncoders = [{ - __type: "ComputePass", + __type__: "ComputePass", computeObjects: [ // Dispatch the radiosity workgroups { diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index 0e361ce..71fb308 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -86,7 +86,7 @@ export default class Rasterizer }, vertices: this.scene.vertexAttributes, indices: this.scene.indices, - draw: { __type: "DrawIndexed", indexCount: this.scene.indexCount }, + draw: { __type__: "DrawIndexed", indexCount: this.scene.indexCount }, }, }], }; diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index e925e1c..0b3a725 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -53,7 +53,7 @@ export default class Raytracer const framebufferSize = this.framebuffer.size; // this.passEncoder = { - __type: "ComputePass", + __type__: "ComputePass", computeObjects: [{ pipeline: this.pipeline, uniforms: { diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index 1707adb..dfaadbc 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -45,7 +45,7 @@ export default class Tonemapper // this.passEncoder = { - __type: "ComputePass", + __type__: "ComputePass", computeObjects: [{ pipeline: this.pipeline, uniforms: { diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index 7b1428e..c59c937 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -138,7 +138,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } }; diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index de461c1..8ea9a1e 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -335,13 +335,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => primitive, vertices, indices: indexBuffer, - draw: { __type: "DrawIndexed", indexCount }, + draw: { __type__: "DrawIndexed", indexCount }, } }, ] }); passEncoders.push({ - __type: "ComputePass", + __type__: "ComputePass", computeObjects: [ { pipeline: lightUpdateComputePipeline, @@ -365,7 +365,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, geometry: { primitive, - draw: { __type: "DrawVertex", vertexCount: 6 }, + draw: { __type__: "DrawVertex", vertexCount: 6 }, } }, ] @@ -382,7 +382,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, geometry: { primitive, - draw: { __type: "DrawVertex", vertexCount: 6 }, + draw: { __type__: "DrawVertex", vertexCount: 6 }, }, }, ] diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 9d1fb26..098043a 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -88,7 +88,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }, uniforms: { uniforms: { @@ -100,7 +100,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const copyTextureToTexture: CopyTextureToTexture = { - __type: "CopyTextureToTexture", + __type__: "CopyTextureToTexture", source: { texture: { context } }, destination: { texture: cubeTexture }, copySize: [canvas.width, canvas.height], diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 1f3673c..88a1a10 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -119,7 +119,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncodersArray[i] = [ { - __type: "ComputePass", + __type__: "ComputePass", computeObjects: [{ pipeline: computePipeline, uniforms: i ? bindGroup1 : bindGroup0, @@ -140,7 +140,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => topology: "triangle-strip", }, vertices: vertices1, - draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: length }, + draw: { __type__: "DrawVertex", vertexCount: 4, instanceCount: length }, } } ], diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 40b4d0a..2c94fab 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -45,7 +45,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 }, indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 - draw: { __type: "DrawIndexed", indexCount: 3 }, // 绘制命令 + draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 }, uniforms: { color: [1, 0, 0, 0] }, // Uniform 颜色值。 }] diff --git a/examples/src/webgpu/helloTriangleMSAA/index.ts b/examples/src/webgpu/helloTriangleMSAA/index.ts index a7c7379..47ed4b3 100644 --- a/examples/src/webgpu/helloTriangleMSAA/index.ts +++ b/examples/src/webgpu/helloTriangleMSAA/index.ts @@ -25,7 +25,7 @@ const init = async (canvas: HTMLCanvasElement) => vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, geometry: { - draw: { __type: "DrawVertex", vertexCount: 3 }, + draw: { __type__: "DrawVertex", vertexCount: 3 }, }, }; diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 99b2315..bf5823c 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -146,12 +146,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: fullscreenQuadPipeline1, uniforms: showResultBindGroup1, geometry: { - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, }, }], }; - const gpuComputePassEncoder: IGPUComputePass = { __type: "ComputePass", computeObjects: [] }; + const gpuComputePassEncoder: IGPUComputePass = { __type__: "ComputePass", computeObjects: [] }; const submit: Submit = { commandEncoders: [ { diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 0e72171..5df30fb 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -113,7 +113,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: numInstances } + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: numInstances } }, uniforms: { uniforms: { diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index b8d1168..aade987 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -323,7 +323,7 @@ const init = async () => }, vertices: vertexAttributes, indices, - draw: { __type: "DrawIndexed", indexCount: indices.length }, + draw: { __type__: "DrawIndexed", indexCount: indices.length }, }, }], }); diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index 182b79e..ef42460 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -337,7 +337,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => vert_bitan: { data: box.vertices, offset: 44, format: "float32x3", arrayStride: box.vertexStride }, }, indices: box.indices, - draw: { __type: "DrawIndexed", indexCount: box.indices.length }, + draw: { __type__: "DrawIndexed", indexCount: box.indices.length }, } }], }] diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 24480aa..ab571cd 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -134,7 +134,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => normal: { data: vertexBuf, offset: 12, arrayStride: 6 * 4, format: "float32x3" }, }, indices, - draw: { __type: "DrawIndexed", indexCount: indices.length }, + draw: { __type__: "DrawIndexed", indexCount: indices.length }, }, uniforms: { uni: { @@ -158,7 +158,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); const occlusionQueryObjects: IGPUOcclusionQuery[] = renderObjects.map((ro) => - ({ __type: "OcclusionQuery", renderObjects: [ro] })); + ({ __type__: "OcclusionQuery", renderObjects: [ro] })); const renderPass: RenderPass = { descriptor: renderPassDescriptor, diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index a479236..115e09b 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -201,7 +201,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => if (level === 0) { passEncoders.push({ - __type: "ComputePass", + __type__: "ComputePass", computeObjects: [{ pipeline: probabilityMapImportLevelPipeline, uniforms: { ...probabilityMapBindGroup }, @@ -212,7 +212,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => else { passEncoders.push({ - __type: "ComputePass", + __type__: "ComputePass", computeObjects: [{ pipeline: probabilityMapExportLevelPipeline, uniforms: { ...probabilityMapBindGroup }, @@ -279,7 +279,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders.push( { - __type: "ComputePass", + __type__: "ComputePass", computeObjects: [{ pipeline: computePipeline, uniforms: { ...computeBindGroup }, @@ -293,7 +293,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uniforms: { ...uniformBindGroup }, geometry: { vertices: { ...particlesVertices, ...quadVertices }, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: numParticles, firstVertex: 0, firstInstance: 0 }, + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: numParticles, firstVertex: 0, firstInstance: 0 }, }, }], } diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 1378091..19abf9a 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -202,7 +202,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uniforms: bindingResources, geometry: { vertices, - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, } }] } diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index d032fbb..809a0aa 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -261,7 +261,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => }, vertices: renderable.vertexAttributes, indices: renderable.indices, - draw: { __type: "DrawIndexed", indexCount: renderable.indexCount }, + draw: { __type__: "DrawIndexed", indexCount: renderable.indexCount }, } }; } @@ -289,14 +289,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => // such as when using frustrum or occlusion culling, will not benefit from // using render bundles as much. let renderBundle: IGPURenderBundle = { - __type: "RenderBundle", + __type__: "RenderBundle", renderObjects: [], }; renderBundle.renderObjects = renderScene(); function updateRenderBundle() { const renderBundleEncoder: IGPURenderBundle = { - __type: "RenderBundle", + __type__: "RenderBundle", renderObjects: [], }; renderBundleEncoder.renderObjects = renderScene(); diff --git a/examples/src/webgpu/resizeCanvas/index.ts b/examples/src/webgpu/resizeCanvas/index.ts index e42adb7..9f13846 100644 --- a/examples/src/webgpu/resizeCanvas/index.ts +++ b/examples/src/webgpu/resizeCanvas/index.ts @@ -23,7 +23,7 @@ const init = async (canvas: HTMLCanvasElement) => vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, geometry:{ - draw: { __type: "DrawVertex", vertexCount: 3 }, + draw: { __type__: "DrawVertex", vertexCount: 3 }, } }; diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index 23c8b3b..4484483 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -107,7 +107,7 @@ return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); pipeline, uniforms: bindGroup, geometry:{ - draw: { __type: "DrawVertex", vertexCount: 3 }, + draw: { __type__: "DrawVertex", vertexCount: 3 }, } }] }] diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 74ae794..8a174ea 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -373,7 +373,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullFace: "back", }, vertices, - draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } }] }); @@ -400,7 +400,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullFace: "back", }, vertices, - draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } }] }); @@ -422,7 +422,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullFace: "back", }, vertices, - draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } }] }); @@ -449,7 +449,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullFace: "back", }, vertices, - draw: { __type: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, + draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } }] }); @@ -461,7 +461,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: textureQuadPassPipline, uniforms: { ...depthTextureBindGroup }, geometry: { - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, } }] }); diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index 903b90a..f1ee0fc 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -45,7 +45,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }, uniforms: { uniforms, diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index fa509c5..8df5c9b 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -257,7 +257,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } } writeTextures.push({ - __type: "TextureDataSource", + __type__: "TextureDataSource", mipLevel, data, dataLayout: { width: size }, @@ -324,7 +324,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: texturedSquarePipeline, uniforms: bindingResources0, geometry:{ - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } } } ); @@ -340,7 +340,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: showTexturePipeline, uniforms: bindingResources1, geometry:{ - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } } } ); @@ -350,7 +350,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: showTexturePipeline, uniforms: bindingResources1, geometry:{ - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } } } ); @@ -360,7 +360,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: showTexturePipeline, uniforms: bindingResources1, geometry:{ - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } } } ); @@ -370,7 +370,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: showTexturePipeline, uniforms: bindingResources1, geometry:{ - draw: { __type: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } } } ); diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 7873a60..dcdd22c 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -228,7 +228,7 @@ const init = async (canvas: HTMLCanvasElement) => primitive, vertices, indices: indexBuffer, - draw: { __type: "DrawIndexed", indexCount }, + draw: { __type__: "DrawIndexed", indexCount }, } }, ] @@ -246,7 +246,7 @@ const init = async (canvas: HTMLCanvasElement) => primitive, vertices, indices: indexBuffer, - draw: { __type: "DrawIndexed", indexCount }, + draw: { __type__: "DrawIndexed", indexCount }, } } ], diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 3c3568b..5605353 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -446,7 +446,7 @@ export class GLTFPrimitive let draw: IDraw; if (this.indices) { - draw = { __type: "DrawIndexed", indexCount: this.indices.length }; + draw = { __type__: "DrawIndexed", indexCount: this.indices.length }; } else { @@ -454,7 +454,7 @@ export class GLTFPrimitive const vertexCount = vertexAttribute.data.byteLength / vertexFormatMap[vertexAttribute.format].byteSize; - draw = { __type: "DrawVertex", vertexCount }; + draw = { __type__: "DrawVertex", vertexCount }; } // Our loader only supports triangle lists and strips, so by default we set diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 8f1367e..1682ca3 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -521,7 +521,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, vertices: skinnedGridVertexBuffers.vertices, indices: skinnedGridVertexBuffers.indices, - draw: { __type: "DrawIndexed", indexCount: gridIndices.length }, + draw: { __type__: "DrawIndexed", indexCount: gridIndices.length }, } }; // diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index 0079d58..250057e 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -263,7 +263,7 @@ setBlendConstant().`, cullFace: "back", }, vertices: verticesBuffer, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: 1 }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: 1 }, } }); diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index 0d6d7b7..aa95973 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -336,7 +336,7 @@ export class MsdfTextRenderer }; const renderBundle: IGPURenderBundle = { - __type: "RenderBundle", + __type__: "RenderBundle", renderObjects: [ { pipeline: font.pipeline, @@ -348,7 +348,7 @@ export class MsdfTextRenderer primitive: { topology: "triangle-strip", }, - draw: { __type: "DrawVertex", vertexCount: 4, instanceCount: measurements.printedCharCount }, + draw: { __type__: "DrawVertex", vertexCount: 4, instanceCount: measurements.printedCharCount }, } } ], diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index ab9c56e..fac63a6 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -69,7 +69,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } }; diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 434017f..3aef6d4 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -116,7 +116,7 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, vertices, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } }; diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 64264fc..699883c 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -109,7 +109,7 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, vertices: verticesBuffer, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } }] }] diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index 3d9b0fc..46a5e94 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -57,7 +57,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } }; diff --git a/examples/src/webgpu/videoUploading/index.ts b/examples/src/webgpu/videoUploading/index.ts index 98d677e..24fbd17 100644 --- a/examples/src/webgpu/videoUploading/index.ts +++ b/examples/src/webgpu/videoUploading/index.ts @@ -48,7 +48,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }, geometry: { - draw: { __type: "DrawVertex", vertexCount: 6 }, + draw: { __type__: "DrawVertex", vertexCount: 6 }, } }; diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index cb6334a..5076e00 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -75,7 +75,7 @@ const init = async (canvas: HTMLCanvasElement) => size: [width, height, depth], format, sources: [{ - __type: "TextureDataSource", + __type__: "TextureDataSource", data: byteArray, dataLayout: { width, height }, size: [width, height, depth], @@ -164,7 +164,7 @@ const init = async (canvas: HTMLCanvasElement) => topology: "triangle-list", cullFace: "back", }, - draw: { __type: "DrawVertex", vertexCount: 3 }, + draw: { __type__: "DrawVertex", vertexCount: 3 }, } }], }] diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 8c18a49..68c9cb4 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -326,7 +326,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, vertices: vertexAttributes, indices, - draw: { __type: "DrawIndexed", indexCount: indices.length }, + draw: { __type__: "DrawIndexed", indexCount: indices.length }, } }); } @@ -353,7 +353,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uniforms: wireframeBindGroups[bindGroupNdx], geometry: { primitive, - draw: { __type: "DrawVertex", vertexCount: indices.length * countMult }, + draw: { __type__: "DrawVertex", vertexCount: indices.length * countMult }, } }); }); diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 971c6b3..49bc015 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -159,7 +159,7 @@ async function init(canvas: OffscreenCanvas) frontFace: "ccw", }, vertices: verticesBuffer, - draw: { __type: "DrawVertex", vertexCount: cubeVertexCount } + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount } } }] }] diff --git a/src/WebGPUStep.ts b/src/WebGPUStep.ts index e714844..1e7ed02 100644 --- a/src/WebGPUStep.ts +++ b/src/WebGPUStep.ts @@ -43,7 +43,7 @@ export class WebGPUStep this._currentSubmit = this._currentSubmit || { commandEncoders: [{ passEncoders: [] }] }; // this._currentRenderPassEncoder = null; - this._currentComputePassEncoder = { __type: "ComputePass", computeObjects: [] }; + this._currentComputePassEncoder = { __type__: "ComputePass", computeObjects: [] }; this._currentSubmit.commandEncoders[0].passEncoders.push(this._currentComputePassEncoder); } diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index 8a564b8..2798640 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -10,7 +10,7 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly IRenderPassO let renderOcclusionQuery: GPURenderOcclusionQuery = renderObjects["_GPURenderOcclusionQuery"]; if (renderOcclusionQuery) return renderOcclusionQuery; - const occlusionQueryObjects: IGPUOcclusionQuery[] = renderObjects.filter((cv) => cv.__type === "OcclusionQuery") as any; + const occlusionQueryObjects: IGPUOcclusionQuery[] = renderObjects.filter((cv) => cv.__type__ === "OcclusionQuery") as any; if (occlusionQueryObjects.length === 0) { renderObjects["_GPURenderOcclusionQuery"] = defautRenderOcclusionQuery; diff --git a/src/data/IGPUComputePass.ts b/src/data/IGPUComputePass.ts index 241ef74..d8e57f6 100644 --- a/src/data/IGPUComputePass.ts +++ b/src/data/IGPUComputePass.ts @@ -12,7 +12,7 @@ export interface IGPUComputePass /** * 数据类型。 */ - readonly __type: "ComputePass"; + readonly __type__: "ComputePass"; /** * 计算对象列表。 diff --git a/src/data/IGPUOcclusionQuery.ts b/src/data/IGPUOcclusionQuery.ts index d69d303..62f8527 100644 --- a/src/data/IGPUOcclusionQuery.ts +++ b/src/data/IGPUOcclusionQuery.ts @@ -8,7 +8,7 @@ export interface IGPUOcclusionQuery /** * 数据类型。 */ - readonly __type: "OcclusionQuery"; + readonly __type__: "OcclusionQuery"; /** * GPU渲染对象列表。 diff --git a/src/data/IGPURenderBundle.ts b/src/data/IGPURenderBundle.ts index e782857..bd7d200 100644 --- a/src/data/IGPURenderBundle.ts +++ b/src/data/IGPURenderBundle.ts @@ -12,7 +12,7 @@ export interface IGPURenderBundle /** * 数据类型。 */ - readonly __type: "RenderBundle"; + readonly __type__: "RenderBundle"; /** * GPU渲染捆绑编码器描述。 diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 72f97f8..85c3657 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -50,23 +50,23 @@ export class RunWebGPU commandEncoder.passEncoders.forEach((passEncoder) => { - if (!passEncoder.__type) + if (!passEncoder.__type__) { this.runRenderPass(device, gpuCommandEncoder, passEncoder as RenderPass); } - else if (passEncoder.__type === "RenderPass") + else if (passEncoder.__type__ === "RenderPass") { this.runRenderPass(device, gpuCommandEncoder, passEncoder); } - else if (passEncoder.__type === "ComputePass") + else if (passEncoder.__type__ === "ComputePass") { this.runComputePass(device, gpuCommandEncoder, passEncoder); } - else if (passEncoder.__type === "CopyTextureToTexture") + else if (passEncoder.__type__ === "CopyTextureToTexture") { this.runCopyTextureToTexture(device, gpuCommandEncoder, passEncoder); } - else if (passEncoder.__type === "CopyBufferToBuffer") + else if (passEncoder.__type__ === "CopyBufferToBuffer") { this.runCopyBufferToBuffer(device, gpuCommandEncoder, passEncoder); } @@ -113,25 +113,25 @@ export class RunWebGPU // renderObjects.forEach((element) => { - if (!element.__type) + if (!element.__type__) { this.runRenderObject(device, passEncoder, renderPassFormat, element as RenderObject); } - else if (element.__type === "RenderObject") + else if (element.__type__ === "RenderObject") { this.runRenderObject(device, passEncoder, renderPassFormat, element); } - else if (element.__type === "RenderBundle") + else if (element.__type__ === "RenderBundle") { this.runRenderBundle(device, passEncoder, renderPassFormat, element); } - else if (element.__type === "OcclusionQuery") + else if (element.__type__ === "OcclusionQuery") { this.runRenderOcclusionQueryObject(device, passEncoder, renderPassFormat, element); } else { - throw `未处理 ${(element as IRenderPassObject).__type} 类型的渲染通道对象!`; + throw `未处理 ${(element as IRenderPassObject).__type__} 类型的渲染通道对象!`; } }); } @@ -322,7 +322,7 @@ export class RunWebGPU this.runIndices(device, passEncoder, indices); - if (draw.__type === 'DrawVertex') + if (draw.__type__ === 'DrawVertex') { this.runDrawVertex(passEncoder, draw); } -- Gitee From 4a202709fa50b20ad6de05c0dcf43b81a2392a9c Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 22:31:10 +0800 Subject: [PATCH 019/214] @Data.type --- src/caches/getGPUTexture.ts | 4 ++-- src/data/IGPUTexture.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index ef3af54..36a019d 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { ITextureDataSource, ITextureLike, ITextureSize, Texture, TextureImageSource, TextureSource } from "@feng3d/render-api"; +import { ITextureLike, ITextureSize, Texture, TextureDataSource, TextureImageSource, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; @@ -151,7 +151,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: ITextureLike, auto } // 处理数据纹理 - const bufferSource = v as ITextureDataSource; + const bufferSource = v as TextureDataSource; const { data, dataLayout, dataImageOrigin, size, mipLevel, textureOrigin, aspect } = bufferSource; const gpuDestination: GPUImageCopyTexture = { diff --git a/src/data/IGPUTexture.ts b/src/data/IGPUTexture.ts index 346dcc2..e39661e 100644 --- a/src/data/IGPUTexture.ts +++ b/src/data/IGPUTexture.ts @@ -33,7 +33,7 @@ declare module "@feng3d/render-api" * * @see GPUQueue.writeTexture */ - export interface ITextureDataSource + export interface TextureDataSource { /** * Defines which aspects of the {@link GPUImageCopyTexture#texture} to copy to/from. -- Gitee From 994ca2c7d0da2e9aff2477b2c6dd77d688f470ec Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 22:37:32 +0800 Subject: [PATCH 020/214] RenderObject.material: Material --- src/runs/RunWebGPU.ts | 2 +- src/runs/RunWebGPUCommandCache.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 85c3657..29cc940 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -299,7 +299,7 @@ export class RunWebGPU */ protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: RenderObject) { - const { viewport, scissorRect, pipeline, uniforms: bindingResources, geometry } = renderObject; + const { viewport, scissorRect, material: pipeline, uniforms: bindingResources, geometry } = renderObject; const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/runs/RunWebGPUCommandCache.ts index 2e809e3..a4bb994 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/runs/RunWebGPUCommandCache.ts @@ -111,9 +111,9 @@ export class RunWebGPUCommandCache extends RunWebGPU map.delete([renderPassFormat._key, renderObject]); // renderObject._version = ~~renderObject._version + 1; - watcher.unwatch(renderObject.pipeline, '_version', onchanged); + watcher.unwatch(renderObject.material, '_version', onchanged); } - watcher.watch(renderObject.pipeline, '_version', onchanged); + watcher.watch(renderObject.material, '_version', onchanged); } } -- Gitee From aa503c2dce1f198966eebfac5c67164939068ecc Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Feb 2025 22:47:25 +0800 Subject: [PATCH 021/214] RenderObject.material: Material --- .gitlab-ci.yml | 32 ------------------- .gitpod.yml | 3 -- .../src/webgpu/RenderObjectChanges/index.ts | 6 ++-- examples/src/webgpu/a-buffer/index.ts | 6 ++-- examples/src/webgpu/animometer/index.ts | 4 +-- .../webgpu/atmosphericScatteringSky/index.ts | 2 +- .../src/webgpu/bitonicSort/bitonicDisplay.ts | 4 +-- examples/src/webgpu/bitonicSort/index.ts | 4 +-- examples/src/webgpu/bitonicSort/utils.ts | 6 ++-- examples/src/webgpu/blending/index.ts | 4 +-- examples/src/webgpu/cameras/index.ts | 4 +-- examples/src/webgpu/computeBoids/index.ts | 4 +-- examples/src/webgpu/cornell/radiosity.ts | 4 +-- examples/src/webgpu/cornell/rasterizer.ts | 6 ++-- examples/src/webgpu/cornell/raytracer.ts | 6 ++-- examples/src/webgpu/cornell/tonemapper.ts | 6 ++-- examples/src/webgpu/cubemap/index.ts | 2 +- .../src/webgpu/deferredRendering/index.ts | 8 ++--- examples/src/webgpu/fractalCube/index.ts | 2 +- examples/src/webgpu/gameOfLife/index.ts | 4 +-- examples/src/webgpu/helloTriangle/index.ts | 2 +- .../src/webgpu/helloTriangleMSAA/index.ts | 2 +- examples/src/webgpu/imageBlur/index.ts | 10 +++--- examples/src/webgpu/instancedCube/index.ts | 2 +- examples/src/webgpu/multipleCanvases/index.ts | 4 +-- examples/src/webgpu/normalMap/index.ts | 2 +- examples/src/webgpu/occlusionQuery/index.ts | 4 +-- examples/src/webgpu/particles/index.ts | 8 ++--- examples/src/webgpu/points/index.ts | 6 ++-- examples/src/webgpu/renderBundles/index.ts | 4 +-- examples/src/webgpu/resizeCanvas/index.ts | 2 +- .../src/webgpu/resizeObserverHDDPI/index.ts | 4 +-- examples/src/webgpu/reversedZ/index.ts | 10 +++--- examples/src/webgpu/rotatingCube/index.ts | 2 +- .../src/webgpu/samplerParameters/index.ts | 10 +++--- examples/src/webgpu/shadowMapping/index.ts | 6 ++-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 2 +- examples/src/webgpu/skinnedMesh/gridUtils.ts | 4 +-- examples/src/webgpu/skinnedMesh/index.ts | 2 +- .../src/webgpu/textRenderingMsdf/index.ts | 4 +-- .../src/webgpu/textRenderingMsdf/msdfText.ts | 4 +-- examples/src/webgpu/texturedCube/index.ts | 2 +- examples/src/webgpu/timestampQuery/index.ts | 4 +-- .../src/webgpu/transparentCanvas/index.ts | 4 +-- examples/src/webgpu/twoCubes/index.ts | 2 +- examples/src/webgpu/videoUploading/index.ts | 2 +- .../webgpu/volumeRenderingTexture3D/index.ts | 4 +-- examples/src/webgpu/wireframe/index.ts | 6 ++-- examples/src/webgpu/worker/worker.ts | 4 +-- src/caches/getNGPURenderPipeline.ts | 6 ++-- src/data/IGPUComputeObject.ts | 2 +- src/runs/RunWebGPU.ts | 20 ++++++------ 52 files changed, 116 insertions(+), 151 deletions(-) delete mode 100644 .gitlab-ci.yml delete mode 100644 .gitpod.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 9b7957a..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,32 +0,0 @@ -# To contribute improvements to CI/CD templates, please follow the Development guide at: -# https://docs.gitlab.com/ee/development/cicd/templates.html -# This specific template is located at: -# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/npm.gitlab-ci.yml - -image: node:latest - -cache: - paths: - - node_modules/ - - example/node_modules/ - -test: - stage: test - script: - - npm i -g pnpm - - pnpm i --no-frozen-lockfile - - npm run test - rules: - - if: $CI_MERGE_REQUEST_IID - - if: $CI_COMMIT_TAG - - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - -pages: - stage: deploy - script: - - npm run docs - artifacts: - paths: - - public - only: - - master diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index c165d7f..0000000 --- a/.gitpod.yml +++ /dev/null @@ -1,3 +0,0 @@ -tasks: - - init: npm i -g pnpm && pnpm i - command: npm run watch diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index 2ff32d8..a6c7ac5 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -10,7 +10,7 @@ const init = async (canvas: HTMLCanvasElement) => const webgpu = await new WebGPU().init(); // 初始化WebGPU const renderObject: RenderObject = { // 渲染对象 - pipeline: { // 渲染管线 + material: { // 渲染管线 vertex: { // 顶点着色器 code: ` @vertex @@ -68,7 +68,7 @@ const init = async (canvas: HTMLCanvasElement) => window.onclick = () => { // 修改顶点着色器代码 - renderObject.pipeline.vertex.code = ` + renderObject.material.vertex.code = ` @vertex fn main( @location(0) position: vec2, @@ -80,7 +80,7 @@ const init = async (canvas: HTMLCanvasElement) => `; // 修改片段着色器代码 - renderObject.pipeline.fragment.code = ` + renderObject.material.fragment.code = ` @binding(0) @group(0) var color : vec4; @fragment fn main() -> @location(0) vec4f { diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 61541af..66243b3 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -277,7 +277,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const opaquePassEncoder: RenderPass = { descriptor: opaquePassDescriptor, renderObjects: [{ - pipeline: opaquePipeline, + material: opaquePipeline, uniforms: bindingResources, geometry: { primitive: { @@ -315,7 +315,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Set the scissor to only process a horizontal slice of the frame { scissorRect: { x: scissorX, y: scissorY, width: scissorWidth, height: scissorHeight }, - pipeline: translucentPipeline, + material: translucentPipeline, uniforms: { ...bindingResources, sliceInfo: sliceInfoBuffer[slice], @@ -341,7 +341,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Set the scissor to only process a horizontal slice of the frame { scissorRect: { x: scissorX, y: scissorY, width: scissorWidth, height: scissorHeight }, - pipeline: compositePipeline, + material: compositePipeline, uniforms: { ...bindingResources, sliceInfo: sliceInfoBuffer[slice] diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index 75e5f6a..08c16b5 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -42,7 +42,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const pipeline: Material = { + const material: Material = { ...pipelineDesc, }; @@ -54,7 +54,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ]); const renderObject: RenderObject = { - pipeline, + material, uniforms: {}, geometry: { primitive: { diff --git a/examples/src/webgpu/atmosphericScatteringSky/index.ts b/examples/src/webgpu/atmosphericScatteringSky/index.ts index 7358735..eaba57c 100644 --- a/examples/src/webgpu/atmosphericScatteringSky/index.ts +++ b/examples/src/webgpu/atmosphericScatteringSky/index.ts @@ -45,7 +45,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const computeObject0: IGPUComputeObject = { - pipeline: { + material: { compute: { code: atmosphericScatteringSkyWGSL } }, uniforms: { diff --git a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts index 42126a6..5c2f8bd 100644 --- a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts +++ b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts @@ -30,7 +30,7 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass computeBGDescript.fragment_uniforms = fragment_uniforms; - this.pipeline = super.create2DRenderPipeline( + this.material = super.create2DRenderPipeline( label, bitonicDisplay, ); @@ -44,6 +44,6 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass startRun(commandEncoder: CommandEncoder, args: BitonicDisplayRenderArgs) { this.setArguments(args); - super.executeRun(commandEncoder, this.renderPassDescriptor, this.pipeline, this.computeBGDescript); + super.executeRun(commandEncoder, this.renderPassDescriptor, this.material, this.computeBGDescript); } } diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 5c9dc0c..f14b17a 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -380,7 +380,7 @@ async function init( passEncoders: [{ __type__: "ComputePass", computeObjects: [{ - pipeline: atomicToZeroComputePipeline, + material: atomicToZeroComputePipeline, uniforms: computeBGCluster, workgroups: { workgroupCountX: 1 }, }] @@ -739,7 +739,7 @@ async function init( __type__: "ComputePass", timestampQuery: querySet, computeObjects: [{ - pipeline: computePipeline, + material: computePipeline, uniforms: computeBGCluster, workgroups: { workgroupCountX: settings["Workgroups Per Step"] }, }] diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index 5e69710..73d2e26 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -43,21 +43,21 @@ export abstract class Base2DRendererClass ...args: unknown[] ): void; renderPassDescriptor: RenderPassDescriptor; - pipeline: Material; + material: Material; bindGroupMap: Record; currentBindGroupName: string; executeRun( commandEncoder: CommandEncoder, renderPassDescriptor: RenderPassDescriptor, - pipeline: Material, + material: Material, bindingResources?: Uniforms ) { const passEncoder: RenderPass = { descriptor: renderPassDescriptor, renderObjects: [{ - pipeline, + material, uniforms: bindingResources, geometry: { primitive: { diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 4d4e018..2eb173e 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -508,7 +508,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => updateUniforms(dstUniform, canvas, dstTexture); const ro: RenderObject = { - pipeline: dstPipeline, + material: dstPipeline, uniforms: dstBindGroup, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6 }, @@ -516,7 +516,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const ro1: RenderObject = { - pipeline: srcPipeline, + material: srcPipeline, uniforms: srcBindGroup, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6 }, diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index 4c56661..3a73139 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: Material = { + const material: Material = { vertex: { code: cubeWGSL, }, @@ -93,7 +93,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const renderObject: RenderObject = { - pipeline, + material, uniforms: bindingResources, geometry:{ primitive: { diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index 45d8cae..60dbe27 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -51,7 +51,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } const computeObject0: IGPUComputeObject = { - pipeline: { + material: { compute: { code: updateSpritesWGSL } }, uniforms: { @@ -91,7 +91,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: spriteWGSL }, fragment: { code: spriteWGSL }, }, geometry: { diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index fe59c07..d876493 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -113,7 +113,7 @@ export default class Radiosity computeObjects: [ // Dispatch the radiosity workgroups { - pipeline: this.radiosityPipeline, + material: this.radiosityPipeline, uniforms: { ...this.common.uniforms.bindGroup, ...this.bindGroup, @@ -122,7 +122,7 @@ export default class Radiosity }, // Then copy the 'accumulation' data to 'lightmap' { - pipeline: this.accumulationToLightmapPipeline, + material: this.accumulationToLightmapPipeline, uniforms: { ...this.common.uniforms.bindGroup, ...this.bindGroup, diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index 71fb308..8291daa 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -13,7 +13,7 @@ export default class Rasterizer private readonly common: Common; private readonly scene: Scene; private readonly renderPassDescriptor: RenderPassDescriptor; - private readonly pipeline: Material; + private readonly material: Material; private readonly bindGroup: Uniforms; constructor( @@ -61,7 +61,7 @@ export default class Rasterizer }, }; - this.pipeline = { + this.material = { label: "RasterizerRenderer.pipeline", vertex: { code: rasterizerWGSL + common.wgsl, @@ -75,7 +75,7 @@ export default class Rasterizer this.renderPassEncoder = { descriptor: this.renderPassDescriptor, renderObjects: [{ - pipeline: this.pipeline, + material: this.material, uniforms: { ...this.common.uniforms.bindGroup, ...this.bindGroup, diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index 0b3a725..e702085 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -12,7 +12,7 @@ export default class Raytracer { private readonly common: Common; private readonly framebuffer: Texture; - private readonly pipeline: IGPUComputePipeline; + private readonly material: IGPUComputePipeline; private readonly bindGroup: Uniforms; private readonly kWorkgroupSizeX = 16; @@ -39,7 +39,7 @@ export default class Raytracer framebuffer: { texture: framebuffer }, }; - this.pipeline = { + this.material = { label: "raytracerPipeline", compute: { code: raytracerWGSL + common.wgsl, @@ -55,7 +55,7 @@ export default class Raytracer this.passEncoder = { __type__: "ComputePass", computeObjects: [{ - pipeline: this.pipeline, + material: this.material, uniforms: { ...this.common.uniforms.bindGroup, ...this.bindGroup, diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index dfaadbc..bf80a7a 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -11,7 +11,7 @@ import tonemapperWGSL from "./tonemapper.wgsl"; export default class Tonemapper { private readonly bindGroup: Uniforms; - private readonly pipeline: IGPUComputePipeline; + private readonly material: IGPUComputePipeline; private readonly width: number; private readonly height: number; private readonly kWorkgroupSizeX = 16; @@ -32,7 +32,7 @@ export default class Tonemapper output: { texture: output }, }; - this.pipeline = { + this.material = { label: "Tonemap.pipeline", compute: { code: tonemapperWGSL.replace("{OUTPUT_FORMAT}", output.context.configuration.format), @@ -47,7 +47,7 @@ export default class Tonemapper this.passEncoder = { __type__: "ComputePass", computeObjects: [{ - pipeline: this.pipeline, + material: this.material, uniforms: { ...this.bindGroup, }, diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index c59c937..52f96e4 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -120,7 +120,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: basicVertWGSL }, fragment: { code: sampleCubemapWGSL }, }, uniforms: { diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 8ea9a1e..4784cf9 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -327,7 +327,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: writeGBufferPassDescriptor, renderObjects: [ { - pipeline: writeGBuffersPipeline, + material: writeGBuffersPipeline, uniforms: { ...sceneUniformBindGroup, }, @@ -344,7 +344,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => __type__: "ComputePass", computeObjects: [ { - pipeline: lightUpdateComputePipeline, + material: lightUpdateComputePipeline, uniforms: { ...lightsBufferComputeBindGroup, }, @@ -359,7 +359,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: textureQuadPassDescriptor, renderObjects: [ { - pipeline: gBuffersDebugViewPipeline, + material: gBuffersDebugViewPipeline, uniforms: { ...gBufferTexturesBindGroup, }, @@ -375,7 +375,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: textureQuadPassDescriptor, renderObjects: [ { - pipeline: deferredRenderPipeline, + material: deferredRenderPipeline, uniforms: { ...gBufferTexturesBindGroup, ...lightsBufferBindGroup, diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 098043a..24daa4b 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -77,7 +77,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: basicVertWGSL }, fragment: { code: sampleSelfWGSL }, }, geometry: { diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 88a1a10..dc1bcf2 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -121,7 +121,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { __type__: "ComputePass", computeObjects: [{ - pipeline: computePipeline, + material: computePipeline, uniforms: i ? bindGroup1 : bindGroup0, workgroups: { workgroupCountX: GameOptions.width / GameOptions.workgroupSize, @@ -133,7 +133,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: renderPass, renderObjects: [ { - pipeline: renderPipeline, + material: renderPipeline, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 2c94fab..9ae605c 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -21,7 +21,7 @@ const init = async (canvas: HTMLCanvasElement) => }], }, renderObjects: [{ // 渲染对象 - pipeline: { // 渲染管线 + material: { // 渲染管线 vertex: { // 顶点着色器 code: ` @vertex diff --git a/examples/src/webgpu/helloTriangleMSAA/index.ts b/examples/src/webgpu/helloTriangleMSAA/index.ts index 47ed4b3..f965dd3 100644 --- a/examples/src/webgpu/helloTriangleMSAA/index.ts +++ b/examples/src/webgpu/helloTriangleMSAA/index.ts @@ -21,7 +21,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, geometry: { diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index bf5823c..8d4ca98 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -143,7 +143,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const gpuRenderPassEncoder: RenderPass = { descriptor: renderPassDescriptor, renderObjects: [{ - pipeline: fullscreenQuadPipeline1, + material: fullscreenQuadPipeline1, uniforms: showResultBindGroup1, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, @@ -182,12 +182,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gpuComputePassEncoder.computeObjects = [ { - pipeline: blurPipeline, + material: blurPipeline, uniforms: bindingResources0, workgroups: { workgroupCountX: Math.ceil(srcWidth / blockDim), workgroupCountY: Math.ceil(srcHeight / batch[1]) } }, { - pipeline: blurPipeline, + material: blurPipeline, uniforms: bindingResources1, workgroups: { workgroupCountX: Math.ceil(srcHeight / blockDim), workgroupCountY: Math.ceil(srcWidth / batch[1]) } }, @@ -197,7 +197,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { gpuComputePassEncoder.computeObjects.push( { - pipeline: blurPipeline, + material: blurPipeline, uniforms: bindingResources2, workgroups: { workgroupCountX: Math.ceil(srcWidth / blockDim), workgroupCountY: Math.ceil(srcHeight / batch[1]) } } @@ -205,7 +205,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gpuComputePassEncoder.computeObjects.push( { - pipeline: blurPipeline, + material: blurPipeline, uniforms: bindingResources1, workgroups: { workgroupCountX: Math.ceil(srcHeight / blockDim), workgroupCountY: Math.ceil(srcWidth / batch[1]) } } diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 5df30fb..0d8437b 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -102,7 +102,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: instancedVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, geometry: { diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index aade987..a074962 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -114,7 +114,7 @@ const init = async () => `, }; - const pipeline: Material = { + const material: Material = { label: "our hardcoded red triangle pipeline", vertex: { ...module, @@ -315,7 +315,7 @@ const init = async () => passEncoders.push({ descriptor: renderPassDescriptor, renderObjects: [{ - pipeline, + material, uniforms: bindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index ef42460..a2b3c9c 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -317,7 +317,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - pipeline: texturedCubePipeline, + material: texturedCubePipeline, uniforms: bindingResourcesList[currentSurfaceBindGroup], // * position : float32x3 // * normal : float32x3 diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index ab571cd..696cfdf 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -22,7 +22,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); - const pipeline: Material = { + const material: Material = { vertex: { code: solidColorLitWGSL, }, @@ -123,7 +123,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const renderObject: RenderObject = { - pipeline, + material, geometry: { primitive: { topology: "triangle-list", diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index 115e09b..34737e4 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -203,7 +203,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders.push({ __type__: "ComputePass", computeObjects: [{ - pipeline: probabilityMapImportLevelPipeline, + material: probabilityMapImportLevelPipeline, uniforms: { ...probabilityMapBindGroup }, workgroups: { workgroupCountX: Math.ceil(levelWidth / 64), workgroupCountY: levelHeight }, }], @@ -214,7 +214,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders.push({ __type__: "ComputePass", computeObjects: [{ - pipeline: probabilityMapExportLevelPipeline, + material: probabilityMapExportLevelPipeline, uniforms: { ...probabilityMapBindGroup }, workgroups: { workgroupCountX: Math.ceil(levelWidth / 64), workgroupCountY: levelHeight }, }], @@ -281,7 +281,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { __type__: "ComputePass", computeObjects: [{ - pipeline: computePipeline, + material: computePipeline, uniforms: { ...computeBindGroup }, workgroups: { workgroupCountX: Math.ceil(numParticles / 64) }, }] @@ -289,7 +289,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { descriptor: renderPassDescriptor, renderObjects: [{ - pipeline: renderPipeline, + material: renderPipeline, uniforms: { ...uniformBindGroup }, geometry: { vertices: { ...particlesVertices, ...quadVertices }, diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 19abf9a..0d695dd 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, Material, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; +import { Material, RenderPassDescriptor, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; @@ -168,7 +168,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const { size, fixedSize, textured } = settings; - const pipeline = pipelines[fixedSize ? 1 : 0][textured ? 1 : 0]; + const material = pipelines[fixedSize ? 1 : 0][textured ? 1 : 0]; // Set the size in the uniform values bindingResources.uni.size = size; @@ -198,7 +198,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { descriptor: renderPassDescriptor, renderObjects: [{ - pipeline, + material, uniforms: bindingResources, geometry: { vertices, diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 809a0aa..aa69acc 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -41,7 +41,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => canvasId: canvas.id, }; - const pipeline: Material = { + const material: Material = { vertex: { code: meshWGSL, }, @@ -250,7 +250,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => if (!renderable.renderObject) { renderable.renderObject = { - pipeline, + material, uniforms: { ...frameBindGroup, ...renderable.bindGroup }, geometry: { primitive: { diff --git a/examples/src/webgpu/resizeCanvas/index.ts b/examples/src/webgpu/resizeCanvas/index.ts index 9f13846..cc26ac0 100644 --- a/examples/src/webgpu/resizeCanvas/index.ts +++ b/examples/src/webgpu/resizeCanvas/index.ts @@ -19,7 +19,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, geometry:{ diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index 4484483..5bf0573 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -8,7 +8,7 @@ const init = async (canvas: HTMLCanvasElement) => { const webgpu = await new WebGPU().init(); - const pipeline: Material = { + const material: Material = { vertex: { code: checkerWGSL }, fragment: { code: checkerWGSL, @@ -104,7 +104,7 @@ return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - pipeline, + material, uniforms: bindGroup, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 3 }, diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 8a174ea..684b0d8 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -366,7 +366,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - pipeline: colorPassPipelines[m], + material: colorPassPipelines[m], uniforms: { ...uniformBindGroups[m] }, geometry: { primitive: { @@ -393,7 +393,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - pipeline: depthPrePassPipelines[m], + material: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, geometry: { primitive: { @@ -415,7 +415,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - pipeline: precisionPassPipelines[m], + material: precisionPassPipelines[m], uniforms: { ...uniformBindGroups[m], ...depthTextureBindGroup }, geometry: { primitive: { @@ -442,7 +442,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - pipeline: depthPrePassPipelines[m], + material: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, geometry: { primitive: { @@ -458,7 +458,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - pipeline: textureQuadPassPipline, + material: textureQuadPassPipline, uniforms: { ...depthTextureBindGroup }, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index f1ee0fc..0acc2fa 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -34,7 +34,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, geometry:{ diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index 8df5c9b..d736bc8 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -321,7 +321,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: vpX, y: vpY, width: kViewportSize, height: kViewportSize, minDepth: 0, maxDepth: 1 }, - pipeline: texturedSquarePipeline, + material: texturedSquarePipeline, uniforms: bindingResources0, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } @@ -337,7 +337,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: kLastViewport, y: kLastViewport, width: 32, height: 32, minDepth: 0, maxDepth: 1 }, - pipeline: showTexturePipeline, + material: showTexturePipeline, uniforms: bindingResources1, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } @@ -347,7 +347,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport, width: 16, height: 16, minDepth: 0, maxDepth: 1 }, - pipeline: showTexturePipeline, + material: showTexturePipeline, uniforms: bindingResources1, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } @@ -357,7 +357,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 16, width: 8, height: 8, minDepth: 0, maxDepth: 1 }, - pipeline: showTexturePipeline, + material: showTexturePipeline, uniforms: bindingResources1, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } @@ -367,7 +367,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 24, width: 4, height: 4, minDepth: 0, maxDepth: 1 }, - pipeline: showTexturePipeline, + material: showTexturePipeline, uniforms: bindingResources1, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index dcdd22c..ef7aa57 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -67,7 +67,7 @@ const init = async (canvas: HTMLCanvasElement) => // Create a bind group layout which holds the scene uniforms and // the texture+sampler for depth. We create it manually because the WebPU // implementation doesn't infer this from the shader (yet). - const pipeline: Material = { + const material: Material = { vertex: { code: vertexWGSL, }, @@ -219,7 +219,7 @@ const init = async (canvas: HTMLCanvasElement) => descriptor: shadowPassDescriptor, renderObjects: [ { - pipeline: shadowPipeline, + material: shadowPipeline, uniforms: { ...sceneBindGroupForShadow, ...modelBindGroup, @@ -237,7 +237,7 @@ const init = async (canvas: HTMLCanvasElement) => descriptor: renderPassDescriptor, renderObjects: [ { - pipeline, + material, uniforms: { ...sceneBindGroupForRender, ...modelBindGroup, diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 5605353..9920e08 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -468,7 +468,7 @@ export class GLTFPrimitive } const renderObject: RenderObject = { - pipeline: this.renderPipeline, + material: this.renderPipeline, uniforms: bindingResources, //if skin do something with bone bind group geometry: { diff --git a/examples/src/webgpu/skinnedMesh/gridUtils.ts b/examples/src/webgpu/skinnedMesh/gridUtils.ts index 80d6f6d..a63ef62 100644 --- a/examples/src/webgpu/skinnedMesh/gridUtils.ts +++ b/examples/src/webgpu/skinnedMesh/gridUtils.ts @@ -24,7 +24,7 @@ export const createSkinnedGridRenderPipeline = ( fragmentShader: string, ) => { - const pipeline: Material = { + const material: Material = { label: "SkinnedGridRenderer", vertex: { code: vertexShader, @@ -34,5 +34,5 @@ export const createSkinnedGridRenderPipeline = ( }, }; -return pipeline; + return material; }; diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 1682ca3..79a13f1 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -509,7 +509,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Pass in vertex and index buffers generated from our static skinned grid // data at ./gridData.ts const renderObject: RenderObject = { - pipeline: skinnedGridPipeline, + material: skinnedGridPipeline, uniforms: { ...cameraBGCluster, ...generalUniformsBGCLuster, diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index 250057e..6308a95 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -141,7 +141,7 @@ setBlendConstant().`, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: Material = { + const material: Material = { vertex: { code: basicVertWGSL, }, @@ -253,7 +253,7 @@ setBlendConstant().`, const renderObjects: IRenderPassObject[] = []; renderObjects.push({ - pipeline, + material, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index aa95973..4f5860a 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -32,7 +32,7 @@ export class MsdfFont charCount: number; defaultChar: MsdfChar; constructor( - public pipeline: Material, + public material: Material, public bindGroup: Uniforms, public lineHeight: number, public chars: { [x: number]: MsdfChar }, @@ -339,7 +339,7 @@ export class MsdfTextRenderer __type__: "RenderBundle", renderObjects: [ { - pipeline: font.pipeline, + material: font.material, uniforms: { ...font.bindGroup, ...bindGroup, diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index fac63a6..20e51b6 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -53,7 +53,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: basicVertWGSL }, fragment: { code: sampleTextureMixColorWGSL }, }, uniforms: { diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 3aef6d4..17f7791 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -61,7 +61,7 @@ const init = async (canvas: HTMLCanvasElement) => const uniforms = { modelViewProjectionMatrix: null }; - const pipeline: Material = { + const material: Material = { vertex: { code: basicVertWGSL, }, @@ -102,7 +102,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline, + material, uniforms: { uniforms, }, diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 699883c..4e185f9 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -30,7 +30,7 @@ const init = async (canvas: HTMLCanvasElement) => uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: Material = { + const material: Material = { vertex: { code: basicVertWGSL, }, @@ -101,7 +101,7 @@ const init = async (canvas: HTMLCanvasElement) => passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - pipeline, + material, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index 46a5e94..8e72673 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -43,7 +43,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, uniforms: { diff --git a/examples/src/webgpu/videoUploading/index.ts b/examples/src/webgpu/videoUploading/index.ts index 24fbd17..43363b6 100644 --- a/examples/src/webgpu/videoUploading/index.ts +++ b/examples/src/webgpu/videoUploading/index.ts @@ -38,7 +38,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - pipeline: { + material: { vertex: { code: fullscreenTexturedQuadWGSL }, fragment: { code: sampleExternalTextureWGSL }, }, uniforms: { diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index 5076e00..416dc0c 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -28,7 +28,7 @@ const init = async (canvas: HTMLCanvasElement) => const sampleCount = 4; - const pipeline: Material = { + const material: Material = { vertex: { code: volumeWGSL, }, @@ -157,7 +157,7 @@ const init = async (canvas: HTMLCanvasElement) => passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - pipeline, + material, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 68c9cb4..a0ea7e5 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -318,7 +318,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => if (settings.models) { renderObjects.push({ - pipeline: litPipeline, + material: litPipeline, uniforms: litBindGroup, geometry: { primitive: { @@ -338,7 +338,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Note: If we're using the line-list based pipeline then we need to // multiply the vertex count by 2 since we need to emit 6 vertices // for each triangle (3 edges). - const [bindGroupNdx, countMult, pipeline, primitive] + const [bindGroupNdx, countMult, material, primitive] = settings.barycentricCoordinatesBased ? [1, 1, barycentricCoordinatesBasedWireframePipeline, { topology: "triangle-list", @@ -349,7 +349,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => objectInfos.forEach(({ wireframeBindGroups, model: { indices } }) => { renderObjects.push({ - pipeline, + material, uniforms: wireframeBindGroups[bindGroupNdx], geometry: { primitive, diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 49bc015..22dead4 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -78,7 +78,7 @@ async function init(canvas: OffscreenCanvas) uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const pipeline: Material = { + const material: Material = { vertex: { code: basicVertWGSL, }, @@ -146,7 +146,7 @@ async function init(canvas: OffscreenCanvas) passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - pipeline, + material, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 4221274..9768cb2 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -50,7 +50,7 @@ export function getNGPURenderPipeline(renderPipeline: Material, renderPassFormat const blendConstantColor = BlendState.getBlendConstantColor(renderPipeline.fragment?.targets?.[0]?.blend); // - const pipeline: NGPURenderPipeline = { + const material: NGPURenderPipeline = { label, primitive: gpuPrimitive, vertex: vertexStateResult.gpuVertexState, @@ -61,7 +61,7 @@ export function getNGPURenderPipeline(renderPipeline: Material, renderPassFormat blendConstantColor, }; - result = { _version: 0, pipeline, vertexBuffers: vertexStateResult.vertexBuffers }; + result = { _version: 0, material, vertexBuffers: vertexStateResult.vertexBuffers }; renderPipelineMap.set([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat], result); // 监听管线变化 @@ -85,7 +85,7 @@ const renderPipelineMap = new ChainMap< /** * GPU渲染管线描述。 */ - pipeline: NGPURenderPipeline; + material: NGPURenderPipeline; /** * GPU渲染时使用的顶点缓冲区列表。 */ diff --git a/src/data/IGPUComputeObject.ts b/src/data/IGPUComputeObject.ts index fdcd54b..1f09a1c 100644 --- a/src/data/IGPUComputeObject.ts +++ b/src/data/IGPUComputeObject.ts @@ -16,7 +16,7 @@ export interface IGPUComputeObject /** * 计算管线。 */ - readonly pipeline: IGPUComputePipeline; + readonly material: IGPUComputePipeline; /** * 绑定资源。包含数值、纹理、采样、外部纹理。 diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 29cc940..2583a61 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -258,20 +258,20 @@ export class RunWebGPU */ protected runComputeObject(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObject: IGPUComputeObject) { - const { pipeline, uniforms: bindingResources, workgroups } = computeObject; + const { material, uniforms: bindingResources, workgroups } = computeObject; - const shader: IGPUShader = { compute: pipeline.compute.code }; + const shader: IGPUShader = { compute: material.compute.code }; - this.runComputePipeline(device, passEncoder, pipeline); + this.runComputePipeline(device, passEncoder, material); this.runBindingResources(device, passEncoder, shader, bindingResources); this.runWorkgroups(passEncoder, workgroups); } - protected runComputePipeline(device: GPUDevice, passEncoder: GPUComputePassEncoder, pipeline: IGPUComputePipeline) + protected runComputePipeline(device: GPUDevice, passEncoder: GPUComputePassEncoder, material: IGPUComputePipeline) { - const gpuComputePipeline = getIGPUComputePipeline(pipeline); + const gpuComputePipeline = getIGPUComputePipeline(material); const computePipeline = getGPUComputePipeline(device, gpuComputePipeline); passEncoder.setPipeline(computePipeline); @@ -332,12 +332,12 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: Material, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, material: Material, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { // - const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); + const renderPipelineResult = getNGPURenderPipeline(material, renderPassFormat, primitive, vertices, indices); - const nPipeline = renderPipelineResult.pipeline; + const nPipeline = renderPipelineResult.material; const gpuRenderPipeline = getGPURenderPipeline(device, nPipeline); @@ -429,9 +429,9 @@ export class RunWebGPU }); } - protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, pipeline: Material, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, material: Material, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { - const renderPipeline = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); + const renderPipeline = getNGPURenderPipeline(material, renderPassFormat, primitive, vertices, indices); // renderPipeline.vertexBuffers?.forEach((vertexBuffer, index) => -- Gitee From d47ecbf4f7a7cd041f8f0e38dffde8c9b2c7b149 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 23 Feb 2025 14:01:42 +0800 Subject: [PATCH 022/214] TextureImageSource.getTexImageSourceSize --- src/caches/getGPUTexture.ts | 2 +- src/caches/getIGPUTextureSize.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 36a019d..6cfaeb7 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -108,7 +108,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: ITextureLike, auto const { image, flipY, colorSpace, premultipliedAlpha, mipLevel, textureOrigin, aspect } = imageSource; // - const imageSize = TextureImageSource.getTexImageSourceSize(imageSource); + const imageSize = TextureImageSource.getTexImageSourceSize(imageSource.image); const copySize = imageSource.size || imageSize; let imageOrigin = imageSource.imageOrigin; diff --git a/src/caches/getIGPUTextureSize.ts b/src/caches/getIGPUTextureSize.ts index 4f0a95c..baa5ad7 100644 --- a/src/caches/getIGPUTextureSize.ts +++ b/src/caches/getIGPUTextureSize.ts @@ -34,7 +34,7 @@ export function getIGPUTextureSourceSize(source?: TextureImageSource[]): ITextur // 获取mipLevel为0的资源尺寸。 if (!element.mipLevel) { - const copySize = element.size || TextureImageSource.getTexImageSourceSize(element); + const copySize = element.size || TextureImageSource.getTexImageSourceSize(element.image); if (width || height) { console.assert(width === copySize[0] && height === copySize[1], `纹理资源中提供的尺寸不正确!`); -- Gitee From e852e3e8d9e1eb389c5d35fe30943486496caa0f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 23 Feb 2025 15:57:56 +0800 Subject: [PATCH 023/214] submit = Submit.getInstance(submit); --- examples/src/webgpu/helloTriangle/index.ts | 2 +- src/WebGPU.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 9ae605c..2505670 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -45,7 +45,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 }, indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 - draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 + // draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 }, uniforms: { color: [1, 0, 0, 0] }, // Uniform 颜色值。 }] diff --git a/src/WebGPU.ts b/src/WebGPU.ts index 61f7108..f113871 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,4 +1,4 @@ -import { Buffer, Submit, ITextureLike } from "@feng3d/render-api"; +import { Buffer, ITextureLike, Submit } from "@feng3d/render-api"; import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUTexture } from "./caches/getGPUTexture"; import { getIGPUTextureLikeSize } from "./caches/getIGPUTextureSize"; @@ -78,6 +78,7 @@ export class WebGPU */ submit(submit: Submit) { + submit = Submit.getInstance(submit); this._runWebGPU.runSubmit(this.device, submit); } -- Gitee From d12d7280d74ad7d2d297e56ce639729b9f3863cd Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 6 Mar 2025 20:12:27 +0800 Subject: [PATCH 024/214] 1 --- test/types/VertexFormat.spec.ts | 81 --------------------------------- 1 file changed, 81 deletions(-) delete mode 100644 test/types/VertexFormat.spec.ts diff --git a/test/types/VertexFormat.spec.ts b/test/types/VertexFormat.spec.ts deleted file mode 100644 index 23604f3..0000000 --- a/test/types/VertexFormat.spec.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { assert, describe, it } from "vitest"; -const { ok, equal, deepEqual, strictEqual } = assert; - -import { GPUVertexFormatValue, WGSLVertexType, gpuVertexFormatMap, wgslVertexTypeMap } from "../../src/types/VertexFormat"; - -describe("VertexFormat", () => -{ - const WGSLVertexTypes: WGSLVertexType[] = [ - "vec2", - "vec4", - "vec2", - "vec4", - "vec2", - "vec4", - "vec2", - "vec4", - "f32", - "vec3", - "u32", - "vec3", - "i32", - "vec3", - ]; - - const GPUVertexFormats: GPUVertexFormat[] = [ - "uint8x2", - "uint8x4", - "sint8x2", - "sint8x4", - "unorm8x2", - "unorm8x4", - "snorm8x2", - "snorm8x4", - "uint16x2", - "uint16x4", - "sint16x2", - "sint16x4", - "unorm16x2", - "unorm16x4", - "snorm16x2", - "snorm16x4", - "float16x2", - "float16x4", - "float32", - "float32x2", - "float32x3", - "float32x4", - "uint32", - "uint32x2", - "uint32x3", - "uint32x4", - "sint32", - "sint32x2", - "sint32x3", - "sint32x4", - "unorm10-10-10-2", - ]; - - it("constructor", () => - { - const wgslVertexTypes = Object.keys(wgslVertexTypeMap) as WGSLVertexType[]; - equal(wgslVertexTypes.length, WGSLVertexTypes.length); - - const gpuVertexFormats = Object.keys(gpuVertexFormatMap) as GPUVertexFormat[]; - equal(gpuVertexFormats.length, GPUVertexFormats.length); - - // - wgslVertexTypes.forEach((wgslVertexType) => - { - const wgslVertexTypeValue = wgslVertexTypeMap[wgslVertexType]; - equal(wgslVertexTypeValue.possibleFormats.includes(wgslVertexTypeValue.format), true); - - wgslVertexTypeValue.possibleFormats.forEach((gpuVertexFormat) => - { - const gpuVertexFormatValue = gpuVertexFormatMap[gpuVertexFormat] as GPUVertexFormatValue; - - equal(gpuVertexFormatValue.wgslType, wgslVertexType); - }); - }); - }); -}); -- Gitee From 67591c2a2365b29527723247307a7deb56084a38 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 7 Mar 2025 21:08:02 +0800 Subject: [PATCH 025/214] =?UTF-8?q?feat(WebGPU):=20=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E6=B8=B2=E6=9F=93=E5=AF=B9=E8=B1=A1=E7=9A=84=E6=9D=90?= =?UTF-8?q?=E8=B4=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 runRenderObject 方法中添加了 Material.init(pipeline) 调用,用于初始化渲染对象的材质。这一步骤确保了材质的正确设置和使用,提高了渲染的准确性和效率。 --- src/runs/RunWebGPU.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 2583a61..5fedcbe 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -300,6 +300,7 @@ export class RunWebGPU protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: RenderObject) { const { viewport, scissorRect, material: pipeline, uniforms: bindingResources, geometry } = renderObject; + Material.init(pipeline); const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; -- Gitee From ff57303117e84bcb8f8b7a1fae7f8b0d3268cc78 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 8 Mar 2025 23:01:25 +0800 Subject: [PATCH 026/214] =?UTF-8?q?build:=20=E6=9B=B4=E6=96=B0=20@feng3d/w?= =?UTF-8?q?atcher=20=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 @feng3d/watcher 依赖版本从 0.8.9 升级到 0.8.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 330d8e8..a4391f6 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "dependencies": { "@feng3d/render-api": "0.0.2", "@feng3d/event": "^0.8.4", - "@feng3d/watcher": "^0.8.9", + "@feng3d/watcher": "^0.8.11", "@webgpu/types": "0.1.49", "stats.js": "^0.17.0", "wgsl_reflect": "^1.0.16" -- Gitee From f2365790def16b89a2567f71316b0b1551866a54 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 9 Mar 2025 00:18:38 +0800 Subject: [PATCH 027/214] =?UTF-8?q?refactor(webgpu):=20=E5=B0=86=20Materia?= =?UTF-8?q?l=20=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20RenderPipeline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在多个示例文件中,将 Material 类重命名为 RenderPipeline,以更好地反映其在渲染流程中的作用。同时更新了相关代码结构,以适应这一变更。 --- .../src/webgpu/RenderObjectChanges/index.ts | 6 ++--- examples/src/webgpu/a-buffer/index.ts | 14 +++++----- examples/src/webgpu/animometer/index.ts | 8 +++--- .../webgpu/atmosphericScatteringSky/index.ts | 2 +- examples/src/webgpu/bitonicSort/index.ts | 4 +-- examples/src/webgpu/bitonicSort/utils.ts | 10 +++---- examples/src/webgpu/blending/index.ts | 10 +++---- examples/src/webgpu/cameras/index.ts | 6 ++--- examples/src/webgpu/computeBoids/index.ts | 4 +-- examples/src/webgpu/cornell/radiosity.ts | 4 +-- examples/src/webgpu/cornell/rasterizer.ts | 8 +++--- examples/src/webgpu/cornell/raytracer.ts | 2 +- examples/src/webgpu/cornell/tonemapper.ts | 2 +- examples/src/webgpu/cubemap/index.ts | 2 +- .../src/webgpu/deferredRendering/index.ts | 16 ++++++------ examples/src/webgpu/fractalCube/index.ts | 4 +-- examples/src/webgpu/gameOfLife/index.ts | 8 +++--- examples/src/webgpu/helloTriangle/index.ts | 2 +- .../src/webgpu/helloTriangleMSAA/index.ts | 2 +- examples/src/webgpu/imageBlur/index.ts | 14 +++++----- examples/src/webgpu/instancedCube/index.ts | 2 +- examples/src/webgpu/multipleCanvases/index.ts | 6 ++--- examples/src/webgpu/normalMap/index.ts | 6 ++--- examples/src/webgpu/normalMap/utils.ts | 4 +-- examples/src/webgpu/occlusionQuery/index.ts | 6 ++--- examples/src/webgpu/particles/index.ts | 12 ++++----- examples/src/webgpu/points/index.ts | 8 +++--- examples/src/webgpu/renderBundles/index.ts | 6 ++--- examples/src/webgpu/resizeCanvas/index.ts | 2 +- .../src/webgpu/resizeObserverHDDPI/index.ts | 6 ++--- examples/src/webgpu/reversedZ/index.ts | 26 +++++++++---------- examples/src/webgpu/rotatingCube/index.ts | 4 +-- .../src/webgpu/samplerParameters/index.ts | 16 ++++++------ examples/src/webgpu/shadowMapping/index.ts | 13 +++++----- examples/src/webgpu/skinnedMesh/glbUtils.ts | 8 +++--- examples/src/webgpu/skinnedMesh/gridUtils.ts | 4 +-- examples/src/webgpu/skinnedMesh/index.ts | 2 +- .../src/webgpu/textRenderingMsdf/index.ts | 6 ++--- .../src/webgpu/textRenderingMsdf/msdfText.ts | 8 +++--- examples/src/webgpu/texturedCube/index.ts | 4 +-- examples/src/webgpu/timestampQuery/index.ts | 6 ++--- .../src/webgpu/transparentCanvas/index.ts | 6 ++--- examples/src/webgpu/twoCubes/index.ts | 2 +- examples/src/webgpu/videoUploading/index.ts | 2 +- .../webgpu/volumeRenderingTexture3D/index.ts | 6 ++--- examples/src/webgpu/wireframe/index.ts | 14 +++++----- examples/src/webgpu/worker/worker.ts | 6 ++--- src/caches/getNGPURenderPipeline.ts | 6 ++--- src/data/IGPUComputeObject.ts | 2 +- src/data/IGPURenderPipeline.ts | 2 +- src/runs/RunWebGPU.ts | 12 ++++----- src/runs/RunWebGPUCommandCache.ts | 4 +-- 52 files changed, 172 insertions(+), 173 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index a6c7ac5..2ff32d8 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -10,7 +10,7 @@ const init = async (canvas: HTMLCanvasElement) => const webgpu = await new WebGPU().init(); // 初始化WebGPU const renderObject: RenderObject = { // 渲染对象 - material: { // 渲染管线 + pipeline: { // 渲染管线 vertex: { // 顶点着色器 code: ` @vertex @@ -68,7 +68,7 @@ const init = async (canvas: HTMLCanvasElement) => window.onclick = () => { // 修改顶点着色器代码 - renderObject.material.vertex.code = ` + renderObject.pipeline.vertex.code = ` @vertex fn main( @location(0) position: vec2, @@ -80,7 +80,7 @@ const init = async (canvas: HTMLCanvasElement) => `; // 修改片段着色器代码 - renderObject.material.fragment.code = ` + renderObject.pipeline.fragment.code = ` @binding(0) @group(0) var color : vec4; @fragment fn main() -> @location(0) vec4f { diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 66243b3..3457c32 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, IPassEncoder, RenderPass, RenderPassDescriptor, Material, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; +import { BufferBinding, IPassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -56,7 +56,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => targetWidth: undefined, }; - const opaquePipeline: Material = { + const opaquePipeline: RenderPipeline = { vertex: { code: opaqueWGSL, }, @@ -70,7 +70,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => label: "opaquePipeline", }; - const translucentPipeline: Material = { + const translucentPipeline: RenderPipeline = { vertex: { code: translucentWGSL, }, @@ -96,7 +96,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => label: "translucentPassDescriptor", }; - const compositePipeline: Material = { + const compositePipeline: RenderPipeline = { vertex: { code: compositeWGSL, }, @@ -277,7 +277,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const opaquePassEncoder: RenderPass = { descriptor: opaquePassDescriptor, renderObjects: [{ - material: opaquePipeline, + pipeline: opaquePipeline, uniforms: bindingResources, geometry: { primitive: { @@ -315,7 +315,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Set the scissor to only process a horizontal slice of the frame { scissorRect: { x: scissorX, y: scissorY, width: scissorWidth, height: scissorHeight }, - material: translucentPipeline, + pipeline: translucentPipeline, uniforms: { ...bindingResources, sliceInfo: sliceInfoBuffer[slice], @@ -341,7 +341,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Set the scissor to only process a horizontal slice of the frame { scissorRect: { x: scissorX, y: scissorY, width: scissorWidth, height: scissorHeight }, - material: compositePipeline, + pipeline: compositePipeline, uniforms: { ...bindingResources, sliceInfo: sliceInfoBuffer[slice] diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index 08c16b5..c628923 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import animometerWGSL from "./animometer.wgsl"; -import { RenderPass, RenderPassDescriptor, Material, Submit, RenderObject } from "@feng3d/render-api"; +import { RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; import { IGPURenderBundle, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -33,7 +33,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const vec4Size = 4 * Float32Array.BYTES_PER_ELEMENT; - const pipelineDesc: Material = { + const pipelineDesc: RenderPipeline = { vertex: { code: animometerWGSL, }, @@ -42,7 +42,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const material: Material = { + const pipeline: RenderPipeline = { ...pipelineDesc, }; @@ -54,7 +54,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ]); const renderObject: RenderObject = { - material, + pipeline: pipeline, uniforms: {}, geometry: { primitive: { diff --git a/examples/src/webgpu/atmosphericScatteringSky/index.ts b/examples/src/webgpu/atmosphericScatteringSky/index.ts index eaba57c..7358735 100644 --- a/examples/src/webgpu/atmosphericScatteringSky/index.ts +++ b/examples/src/webgpu/atmosphericScatteringSky/index.ts @@ -45,7 +45,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const computeObject0: IGPUComputeObject = { - material: { + pipeline: { compute: { code: atmosphericScatteringSkyWGSL } }, uniforms: { diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index f14b17a..5c9dc0c 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -380,7 +380,7 @@ async function init( passEncoders: [{ __type__: "ComputePass", computeObjects: [{ - material: atomicToZeroComputePipeline, + pipeline: atomicToZeroComputePipeline, uniforms: computeBGCluster, workgroups: { workgroupCountX: 1 }, }] @@ -739,7 +739,7 @@ async function init( __type__: "ComputePass", timestampQuery: querySet, computeObjects: [{ - material: computePipeline, + pipeline: computePipeline, uniforms: computeBGCluster, workgroups: { workgroupCountX: settings["Workgroups Per Step"] }, }] diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index 73d2e26..d1ebecc 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, RenderPass, RenderPassDescriptor, Material, Uniforms } from "@feng3d/render-api"; +import { CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Uniforms } from "@feng3d/render-api"; const fullscreenTexturedQuad = ` @@ -43,21 +43,21 @@ export abstract class Base2DRendererClass ...args: unknown[] ): void; renderPassDescriptor: RenderPassDescriptor; - material: Material; + material: RenderPipeline; bindGroupMap: Record; currentBindGroupName: string; executeRun( commandEncoder: CommandEncoder, renderPassDescriptor: RenderPassDescriptor, - material: Material, + pipeline: RenderPipeline, bindingResources?: Uniforms ) { const passEncoder: RenderPass = { descriptor: renderPassDescriptor, renderObjects: [{ - material, + pipeline: pipeline, uniforms: bindingResources, geometry: { primitive: { @@ -76,7 +76,7 @@ export abstract class Base2DRendererClass code: string, ) { - const renderPipeline: Material = { + const renderPipeline: RenderPipeline = { label: `${label}.pipeline`, vertex: { code: fullscreenTexturedQuad, diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 2eb173e..5319702 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import texturedQuadWGSL from "./texturedQuad.wgsl"; -import { BlendComponent, RenderPassDescriptor, IRenderPassObject, Material, Sampler, Submit, Texture, TextureView, Uniforms, RenderObject } from "@feng3d/render-api"; +import { BlendComponent, IRenderPassObject, RenderObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, TextureView, Uniforms } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; declare module "@feng3d/render-api" @@ -433,7 +433,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => clearFolder.add(clear, "alpha", 0, 1).onChange(render); clearFolder.addColor(new GUIColorHelper(clear.color), "value").onChange(render); - const dstPipeline: Material = { + const dstPipeline: RenderPipeline = { label: "hardcoded textured quad pipeline", vertex: { code: texturedQuadWGSL, @@ -447,7 +447,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { gui.updateDisplay(); - const srcPipeline: Material = { + const srcPipeline: RenderPipeline = { label: "hardcoded textured quad pipeline", vertex: { code: texturedQuadWGSL, @@ -508,7 +508,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => updateUniforms(dstUniform, canvas, dstTexture); const ro: RenderObject = { - material: dstPipeline, + pipeline: dstPipeline, uniforms: dstBindGroup, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6 }, @@ -516,7 +516,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const ro1: RenderObject = { - material: srcPipeline, + pipeline: srcPipeline, uniforms: srcBindGroup, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6 }, diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index 3a73139..d3fa1a2 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -5,7 +5,7 @@ import { ArcballCamera, WASDCamera } from "./camera"; import cubeWGSL from "./cube.wgsl"; import { createInputHandler } from "./input"; -import { RenderPassDescriptor, Material, Sampler, Submit, Texture, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { RenderObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: cubeWGSL, }, @@ -93,7 +93,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const renderObject: RenderObject = { - material, + pipeline: pipeline, uniforms: bindingResources, geometry:{ primitive: { diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index 60dbe27..45d8cae 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -51,7 +51,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } const computeObject0: IGPUComputeObject = { - material: { + pipeline: { compute: { code: updateSpritesWGSL } }, uniforms: { @@ -91,7 +91,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: spriteWGSL }, fragment: { code: spriteWGSL }, }, geometry: { diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index d876493..fe59c07 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -113,7 +113,7 @@ export default class Radiosity computeObjects: [ // Dispatch the radiosity workgroups { - material: this.radiosityPipeline, + pipeline: this.radiosityPipeline, uniforms: { ...this.common.uniforms.bindGroup, ...this.bindGroup, @@ -122,7 +122,7 @@ export default class Radiosity }, // Then copy the 'accumulation' data to 'lightmap' { - material: this.accumulationToLightmapPipeline, + pipeline: this.accumulationToLightmapPipeline, uniforms: { ...this.common.uniforms.bindGroup, ...this.bindGroup, diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index 8291daa..deeb746 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, RenderPass, RenderPassDescriptor, Material, Texture, Uniforms } from "@feng3d/render-api"; +import { CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Texture, Uniforms } from "@feng3d/render-api"; import Common from "./common"; import Radiosity from "./radiosity"; @@ -13,7 +13,7 @@ export default class Rasterizer private readonly common: Common; private readonly scene: Scene; private readonly renderPassDescriptor: RenderPassDescriptor; - private readonly material: Material; + private readonly pipeline: RenderPipeline; private readonly bindGroup: Uniforms; constructor( @@ -61,7 +61,7 @@ export default class Rasterizer }, }; - this.material = { + this.pipeline = { label: "RasterizerRenderer.pipeline", vertex: { code: rasterizerWGSL + common.wgsl, @@ -75,7 +75,7 @@ export default class Rasterizer this.renderPassEncoder = { descriptor: this.renderPassDescriptor, renderObjects: [{ - material: this.material, + pipeline: this.pipeline, uniforms: { ...this.common.uniforms.bindGroup, ...this.bindGroup, diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index e702085..455a955 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -55,7 +55,7 @@ export default class Raytracer this.passEncoder = { __type__: "ComputePass", computeObjects: [{ - material: this.material, + pipeline: this.material, uniforms: { ...this.common.uniforms.bindGroup, ...this.bindGroup, diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index bf80a7a..d188e7d 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -47,7 +47,7 @@ export default class Tonemapper this.passEncoder = { __type__: "ComputePass", computeObjects: [{ - material: this.material, + pipeline: this.material, uniforms: { ...this.bindGroup, }, diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index 52f96e4..c59c937 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -120,7 +120,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleCubemapWGSL }, }, uniforms: { diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 4784cf9..0ed4fff 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -10,7 +10,7 @@ import lightUpdate from "./lightUpdate.wgsl"; import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; -import { RenderPass, RenderPassDescriptor, Material, Submit, Texture, TextureView, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const kMaxNumLights = 1024; @@ -74,7 +74,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullMode: "back", }; - const writeGBuffersPipeline: Material = { + const writeGBuffersPipeline: RenderPipeline = { vertex: { code: vertexWriteGBuffers, }, @@ -83,7 +83,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const gBuffersDebugViewPipeline: Material = { + const gBuffersDebugViewPipeline: RenderPipeline = { vertex: { code: vertexTextureQuad, }, @@ -95,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }, }; - const deferredRenderPipeline: Material = { + const deferredRenderPipeline: RenderPipeline = { vertex: { code: vertexTextureQuad, }, @@ -327,7 +327,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: writeGBufferPassDescriptor, renderObjects: [ { - material: writeGBuffersPipeline, + pipeline: writeGBuffersPipeline, uniforms: { ...sceneUniformBindGroup, }, @@ -344,7 +344,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => __type__: "ComputePass", computeObjects: [ { - material: lightUpdateComputePipeline, + pipeline: lightUpdateComputePipeline, uniforms: { ...lightsBufferComputeBindGroup, }, @@ -359,7 +359,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: textureQuadPassDescriptor, renderObjects: [ { - material: gBuffersDebugViewPipeline, + pipeline: gBuffersDebugViewPipeline, uniforms: { ...gBufferTexturesBindGroup, }, @@ -375,7 +375,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: textureQuadPassDescriptor, renderObjects: [ { - material: deferredRenderPipeline, + pipeline: deferredRenderPipeline, uniforms: { ...gBufferTexturesBindGroup, ...lightsBufferBindGroup, diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 24daa4b..7a8e2c9 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -1,4 +1,4 @@ -import { CopyTextureToTexture, BufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, CopyTextureToTexture, RenderObject, RenderPassDescriptor, Sampler, Submit, Texture } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -77,7 +77,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleSelfWGSL }, }, geometry: { diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index dc1bcf2..f8b6aa4 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -4,7 +4,7 @@ import computeWGSL from "./compute.wgsl"; import fragWGSL from "./frag.wgsl"; import vertWGSL from "./vert.wgsl"; -import { RenderPass, RenderPassDescriptor, Material, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -86,7 +86,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => next: { bufferView: buffer0 }, }; - const renderPipeline: Material = { + const renderPipeline: RenderPipeline = { vertex: { code: vertWGSL, }, @@ -121,7 +121,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { __type__: "ComputePass", computeObjects: [{ - material: computePipeline, + pipeline: computePipeline, uniforms: i ? bindGroup1 : bindGroup0, workgroups: { workgroupCountX: GameOptions.width / GameOptions.workgroupSize, @@ -133,7 +133,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: renderPass, renderObjects: [ { - material: renderPipeline, + pipeline: renderPipeline, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 2505670..6c63efe 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -21,7 +21,7 @@ const init = async (canvas: HTMLCanvasElement) => }], }, renderObjects: [{ // 渲染对象 - material: { // 渲染管线 + pipeline: { // 渲染管线 vertex: { // 顶点着色器 code: ` @vertex diff --git a/examples/src/webgpu/helloTriangleMSAA/index.ts b/examples/src/webgpu/helloTriangleMSAA/index.ts index f965dd3..47ed4b3 100644 --- a/examples/src/webgpu/helloTriangleMSAA/index.ts +++ b/examples/src/webgpu/helloTriangleMSAA/index.ts @@ -21,7 +21,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, geometry: { diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 8d4ca98..58668f7 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -3,7 +3,7 @@ import { GUI } from "dat.gui"; import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgsl"; import blurWGSL from "./blur.wgsl"; -import { RenderPass, RenderPassDescriptor, Material, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; // Contants from the blur.wgsl shader. @@ -24,7 +24,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const fullscreenQuadPipeline1: Material = { + const fullscreenQuadPipeline1: RenderPipeline = { vertex: { code: fullscreenTexturedQuadWGSL, }, @@ -143,7 +143,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const gpuRenderPassEncoder: RenderPass = { descriptor: renderPassDescriptor, renderObjects: [{ - material: fullscreenQuadPipeline1, + pipeline: fullscreenQuadPipeline1, uniforms: showResultBindGroup1, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, @@ -182,12 +182,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gpuComputePassEncoder.computeObjects = [ { - material: blurPipeline, + pipeline: blurPipeline, uniforms: bindingResources0, workgroups: { workgroupCountX: Math.ceil(srcWidth / blockDim), workgroupCountY: Math.ceil(srcHeight / batch[1]) } }, { - material: blurPipeline, + pipeline: blurPipeline, uniforms: bindingResources1, workgroups: { workgroupCountX: Math.ceil(srcHeight / blockDim), workgroupCountY: Math.ceil(srcWidth / batch[1]) } }, @@ -197,7 +197,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { gpuComputePassEncoder.computeObjects.push( { - material: blurPipeline, + pipeline: blurPipeline, uniforms: bindingResources2, workgroups: { workgroupCountX: Math.ceil(srcWidth / blockDim), workgroupCountY: Math.ceil(srcHeight / batch[1]) } } @@ -205,7 +205,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gpuComputePassEncoder.computeObjects.push( { - material: blurPipeline, + pipeline: blurPipeline, uniforms: bindingResources1, workgroups: { workgroupCountX: Math.ceil(srcHeight / blockDim), workgroupCountY: Math.ceil(srcWidth / batch[1]) } } diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 0d8437b..5df30fb 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -102,7 +102,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: instancedVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, geometry: { diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index a074962..b7a759b 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,4 +1,4 @@ -import { IPassEncoder, RenderPassDescriptor, Material, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; @@ -114,7 +114,7 @@ const init = async () => `, }; - const material: Material = { + const pipeline: RenderPipeline = { label: "our hardcoded red triangle pipeline", vertex: { ...module, @@ -315,7 +315,7 @@ const init = async () => passEncoders.push({ descriptor: renderPassDescriptor, renderObjects: [{ - material, + pipeline: pipeline, uniforms: bindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index a2b3c9c..5b06cfc 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, Material, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -232,7 +232,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; - const texturedCubePipeline: Material = create3DRenderPipeline( + const texturedCubePipeline: RenderPipeline = create3DRenderPipeline( "NormalMappingRender", normalMapWGSL, // Position, normal uv tangent bitangent @@ -317,7 +317,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - material: texturedCubePipeline, + pipeline: texturedCubePipeline, uniforms: bindingResourcesList[currentSurfaceBindGroup], // * position : float32x3 // * normal : float32x3 diff --git a/examples/src/webgpu/normalMap/utils.ts b/examples/src/webgpu/normalMap/utils.ts index e741305..8c12aea 100644 --- a/examples/src/webgpu/normalMap/utils.ts +++ b/examples/src/webgpu/normalMap/utils.ts @@ -1,4 +1,4 @@ -import { DepthStencilState, Material, Texture } from "@feng3d/render-api"; +import { DepthStencilState, RenderPipeline, Texture } from "@feng3d/render-api"; export const create3DRenderPipeline = ( label: string, @@ -16,7 +16,7 @@ export const create3DRenderPipeline = ( }; } - const pipelineDescriptor: Material = { + const pipelineDescriptor: RenderPipeline = { label: `${label}.pipeline`, vertex: { code: vertexShader, diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 696cfdf..3aa6cef 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, RenderPass, RenderPassDescriptor, Material, Submit, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getIGPUBuffer, IGPUOcclusionQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -22,7 +22,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: solidColorLitWGSL, }, @@ -123,7 +123,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; const renderObject: RenderObject = { - material, + pipeline: pipeline, geometry: { primitive: { topology: "triangle-list", diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index 34737e4..f8f5d1f 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -7,7 +7,7 @@ import particleWGSL from "./particle.wgsl"; import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; -import { RenderPass, RenderPassDescriptor, Material, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; const numParticles = 50000; @@ -36,7 +36,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => color: { data: particlesBuffer, format: "float32x4", offset: particleColorOffset, arrayStride: particleInstanceByteSize, stepMode: "instance" }, }; - const renderPipeline: Material = { + const renderPipeline: RenderPipeline = { vertex: { code: particleWGSL, }, @@ -203,7 +203,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders.push({ __type__: "ComputePass", computeObjects: [{ - material: probabilityMapImportLevelPipeline, + pipeline: probabilityMapImportLevelPipeline, uniforms: { ...probabilityMapBindGroup }, workgroups: { workgroupCountX: Math.ceil(levelWidth / 64), workgroupCountY: levelHeight }, }], @@ -214,7 +214,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders.push({ __type__: "ComputePass", computeObjects: [{ - material: probabilityMapExportLevelPipeline, + pipeline: probabilityMapExportLevelPipeline, uniforms: { ...probabilityMapBindGroup }, workgroups: { workgroupCountX: Math.ceil(levelWidth / 64), workgroupCountY: levelHeight }, }], @@ -281,7 +281,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { __type__: "ComputePass", computeObjects: [{ - material: computePipeline, + pipeline: computePipeline, uniforms: { ...computeBindGroup }, workgroups: { workgroupCountX: Math.ceil(numParticles / 64) }, }] @@ -289,7 +289,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { descriptor: renderPassDescriptor, renderObjects: [{ - material: renderPipeline, + pipeline: renderPipeline, uniforms: { ...uniformBindGroup }, geometry: { vertices: { ...particlesVertices, ...quadVertices }, diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 0d695dd..507dc5b 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -1,4 +1,4 @@ -import { Material, RenderPassDescriptor, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; @@ -93,7 +93,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => depthCompare: "less", format: depthFormat, }, - } as Material) + } as RenderPipeline) ) ); @@ -168,7 +168,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const { size, fixedSize, textured } = settings; - const material = pipelines[fixedSize ? 1 : 0][textured ? 1 : 0]; + const pipeline = pipelines[fixedSize ? 1 : 0][textured ? 1 : 0]; // Set the size in the uniform values bindingResources.uni.size = size; @@ -198,7 +198,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { descriptor: renderPassDescriptor, renderObjects: [{ - material, + pipeline: pipeline, uniforms: bindingResources, geometry: { vertices, diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index aa69acc..97d2f77 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,4 +1,4 @@ -import { RenderPass, RenderPassDescriptor, IRenderPassObject, Material, Sampler, Submit, Texture, Uniforms, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { IRenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, IGPURenderBundle, WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -41,7 +41,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => canvasId: canvas.id, }; - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: meshWGSL, }, @@ -250,7 +250,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => if (!renderable.renderObject) { renderable.renderObject = { - material, + pipeline: pipeline, uniforms: { ...frameBindGroup, ...renderable.bindGroup }, geometry: { primitive: { diff --git a/examples/src/webgpu/resizeCanvas/index.ts b/examples/src/webgpu/resizeCanvas/index.ts index cc26ac0..9f13846 100644 --- a/examples/src/webgpu/resizeCanvas/index.ts +++ b/examples/src/webgpu/resizeCanvas/index.ts @@ -19,7 +19,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, geometry:{ diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index 5bf0573..d446017 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -1,14 +1,14 @@ import { GUI } from "dat.gui"; import checkerWGSL from "./checker.wgsl"; -import { RenderPassDescriptor, Material, Submit, Uniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Submit, Uniforms } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement) => { const webgpu = await new WebGPU().init(); - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: checkerWGSL }, fragment: { code: checkerWGSL, @@ -104,7 +104,7 @@ return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - material, + pipeline: pipeline, uniforms: bindGroup, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 3 }, diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 684b0d8..9b3f492 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -10,7 +10,7 @@ import vertexDepthPrePassWGSL from "./vertexDepthPrePass.wgsl"; import vertexPrecisionErrorPassWGSL from "./vertexPrecisionErrorPass.wgsl"; import vertexTextureQuadWGSL from "./vertexTextureQuad.wgsl"; -import { RenderPass, RenderPassDescriptor, Material, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; // Two planes close to each other for depth precision test @@ -87,7 +87,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // depthPrePass is used to render scene to the depth texture // this is not needed if you just want to use reversed z to render a scene - const depthPrePassRenderPipelineDescriptorBase: Material = { + const depthPrePassRenderPipelineDescriptorBase: RenderPipeline = { vertex: { code: vertexDepthPrePassWGSL, }, @@ -95,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // we need the depthCompare to fit the depth buffer mode we are using. // this is the same for other passes - const depthPrePassPipelines: Material[] = []; + const depthPrePassPipelines: RenderPipeline[] = []; depthPrePassPipelines[DepthBufferMode.Default] = { ...depthPrePassRenderPipelineDescriptorBase, depthStencil: { @@ -113,7 +113,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // precisionPass is to draw precision error as color of depth value stored in depth buffer // compared to that directly calcualated in the shader - const precisionPassRenderPipelineDescriptorBase: Material = { + const precisionPassRenderPipelineDescriptorBase: RenderPipeline = { vertex: { code: vertexPrecisionErrorPassWGSL, }, @@ -122,7 +122,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const precisionPassPipelines: Material[] = []; + const precisionPassPipelines: RenderPipeline[] = []; precisionPassPipelines[DepthBufferMode.Default] = { ...precisionPassRenderPipelineDescriptorBase, depthStencil: { @@ -139,7 +139,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // colorPass is the regular render pass to render the scene - const colorPassRenderPipelineDescriptorBase: Material = { + const colorPassRenderPipelineDescriptorBase: RenderPipeline = { vertex: { code: vertexWGSL, }, @@ -149,7 +149,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // - const colorPassPipelines: Material[] = []; + const colorPassPipelines: RenderPipeline[] = []; colorPassPipelines[DepthBufferMode.Default] = { ...colorPassRenderPipelineDescriptorBase, depthStencil: { @@ -168,7 +168,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // textureQuadPass is draw a full screen quad of depth texture // to see the difference of depth value using reversed z compared to default depth buffer usage // 0.0 will be the furthest and 1.0 will be the closest - const textureQuadPassPipline: Material = { + const textureQuadPassPipline: RenderPipeline = { vertex: { code: vertexTextureQuadWGSL, }, @@ -366,7 +366,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - material: colorPassPipelines[m], + pipeline: colorPassPipelines[m], uniforms: { ...uniformBindGroups[m] }, geometry: { primitive: { @@ -393,7 +393,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - material: depthPrePassPipelines[m], + pipeline: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, geometry: { primitive: { @@ -415,7 +415,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - material: precisionPassPipelines[m], + pipeline: precisionPassPipelines[m], uniforms: { ...uniformBindGroups[m], ...depthTextureBindGroup }, geometry: { primitive: { @@ -442,7 +442,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - material: depthPrePassPipelines[m], + pipeline: depthPrePassPipelines[m], uniforms: { ...uniformBindGroups[m] }, geometry: { primitive: { @@ -458,7 +458,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, - material: textureQuadPassPipline, + pipeline: textureQuadPassPipline, uniforms: { ...depthTextureBindGroup }, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index 0acc2fa..9e2960b 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderObject, RenderPassDescriptor, Submit } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -34,7 +34,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, geometry:{ diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index d736bc8..87cf3e5 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -1,7 +1,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; -import { RenderPassDescriptor, IRenderPassObject, Material, Sampler, Submit, Texture, TextureSource, Uniforms } from "@feng3d/render-api"; +import { IRenderPassObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, TextureSource, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import showTextureWGSL from "./showTexture.wgsl"; @@ -270,7 +270,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // "Debug" view of the actual texture contents // - const showTexturePipeline: Material = { + const showTexturePipeline: RenderPipeline = { vertex: { code: showTextureWGSL }, fragment: { code: showTextureWGSL } }; @@ -278,7 +278,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Pipeline for drawing the test squares // - const texturedSquarePipeline: Material = { + const texturedSquarePipeline: RenderPipeline = { vertex: { code: texturedSquareWGSL, constants: { kTextureBaseSize, kViewportSize } }, fragment: { code: texturedSquareWGSL }, }; @@ -321,7 +321,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: vpX, y: vpY, width: kViewportSize, height: kViewportSize, minDepth: 0, maxDepth: 1 }, - material: texturedSquarePipeline, + pipeline: texturedSquarePipeline, uniforms: bindingResources0, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } @@ -337,7 +337,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: kLastViewport, y: kLastViewport, width: 32, height: 32, minDepth: 0, maxDepth: 1 }, - material: showTexturePipeline, + pipeline: showTexturePipeline, uniforms: bindingResources1, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } @@ -347,7 +347,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport, width: 16, height: 16, minDepth: 0, maxDepth: 1 }, - material: showTexturePipeline, + pipeline: showTexturePipeline, uniforms: bindingResources1, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } @@ -357,7 +357,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 16, width: 8, height: 8, minDepth: 0, maxDepth: 1 }, - material: showTexturePipeline, + pipeline: showTexturePipeline, uniforms: bindingResources1, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } @@ -367,7 +367,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 24, width: 4, height: 4, minDepth: 0, maxDepth: 1 }, - material: showTexturePipeline, + pipeline: showTexturePipeline, uniforms: bindingResources1, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index ef7aa57..d46fb20 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -1,3 +1,5 @@ +import { RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; import { mesh } from "../../meshes/stanfordDragon"; @@ -6,9 +8,6 @@ import fragmentWGSL from "./fragment.wgsl"; import vertexWGSL from "./vertex.wgsl"; import vertexShadowWGSL from "./vertexShadow.wgsl"; -import { RenderPassDescriptor, Material, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; - const shadowDepthTextureSize = 1024; const init = async (canvas: HTMLCanvasElement) => @@ -54,7 +53,7 @@ const init = async (canvas: HTMLCanvasElement) => cullMode: "back", }; - const shadowPipeline: Material = { + const shadowPipeline: RenderPipeline = { vertex: { code: vertexShadowWGSL, }, @@ -67,7 +66,7 @@ const init = async (canvas: HTMLCanvasElement) => // Create a bind group layout which holds the scene uniforms and // the texture+sampler for depth. We create it manually because the WebPU // implementation doesn't infer this from the shader (yet). - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: vertexWGSL, }, @@ -219,7 +218,7 @@ const init = async (canvas: HTMLCanvasElement) => descriptor: shadowPassDescriptor, renderObjects: [ { - material: shadowPipeline, + pipeline: shadowPipeline, uniforms: { ...sceneBindGroupForShadow, ...modelBindGroup, @@ -237,7 +236,7 @@ const init = async (canvas: HTMLCanvasElement) => descriptor: renderPassDescriptor, renderObjects: [ { - material, + pipeline: pipeline, uniforms: { ...sceneBindGroupForRender, ...modelBindGroup, diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 9920e08..6c246da 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { Buffer, FragmentState, IDraw, PrimitiveState, RenderObject, Material, Uniforms, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; +import { Buffer, FragmentState, IDraw, PrimitiveState, RenderObject, RenderPipeline, Uniforms, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { getIGPUBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -342,7 +342,7 @@ interface AttributeMapInterface export class GLTFPrimitive { topology: GLTFRenderMode; - renderPipeline: Material; + renderPipeline: RenderPipeline; private attributeMap: AttributeMapInterface; private attributes: string[] = []; vertices: VertexAttributes; @@ -427,7 +427,7 @@ export class GLTFPrimitive // targets: [{ format: colorFormat }], }; - const rpDescript: Material = { + const rpDescript: RenderPipeline = { label: `${label}.pipeline`, vertex: vertexState, fragment: fragmentState, @@ -468,7 +468,7 @@ export class GLTFPrimitive } const renderObject: RenderObject = { - material: this.renderPipeline, + pipeline: this.renderPipeline, uniforms: bindingResources, //if skin do something with bone bind group geometry: { diff --git a/examples/src/webgpu/skinnedMesh/gridUtils.ts b/examples/src/webgpu/skinnedMesh/gridUtils.ts index a63ef62..3104480 100644 --- a/examples/src/webgpu/skinnedMesh/gridUtils.ts +++ b/examples/src/webgpu/skinnedMesh/gridUtils.ts @@ -1,4 +1,4 @@ -import { Material, VertexAttributes } from "@feng3d/render-api"; +import { RenderPipeline, VertexAttributes } from "@feng3d/render-api"; import { gridIndices, gridJoints, gridVertices, gridWeights } from "./gridData"; @@ -24,7 +24,7 @@ export const createSkinnedGridRenderPipeline = ( fragmentShader: string, ) => { - const material: Material = { + const material: RenderPipeline = { label: "SkinnedGridRenderer", vertex: { code: vertexShader, diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 79a13f1..1682ca3 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -509,7 +509,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Pass in vertex and index buffers generated from our static skinned grid // data at ./gridData.ts const renderObject: RenderObject = { - material: skinnedGridPipeline, + pipeline: skinnedGridPipeline, uniforms: { ...cameraBGCluster, ...generalUniformsBGCLuster, diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index 6308a95..ba8f96d 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { RenderPassDescriptor, IRenderPassObject, Material, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { IRenderPassObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import basicVertWGSL from "../../shaders/basic.vert.wgsl"; @@ -141,7 +141,7 @@ setBlendConstant().`, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: basicVertWGSL, }, @@ -253,7 +253,7 @@ setBlendConstant().`, const renderObjects: IRenderPassObject[] = []; renderObjects.push({ - material, + pipeline: pipeline, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index 4f5860a..2b139ed 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -2,7 +2,7 @@ import { mat4, Mat4 } from "wgpu-matrix"; import msdfTextWGSL from "./msdfText.wgsl"; -import { IRenderPassObject, Material, Sampler, Texture, Uniforms } from "@feng3d/render-api"; +import { IRenderPassObject, RenderPipeline, Sampler, Texture, Uniforms } from "@feng3d/render-api"; import { getIGPUBuffer, IGPURenderBundle } from "@feng3d/webgpu"; // The kerning map stores a spare map of character ID pairs with an associated @@ -32,7 +32,7 @@ export class MsdfFont charCount: number; defaultChar: MsdfChar; constructor( - public material: Material, + public material: RenderPipeline, public bindGroup: Uniforms, public lineHeight: number, public chars: { [x: number]: MsdfChar }, @@ -149,7 +149,7 @@ export interface MsdfTextFormattingOptions export class MsdfTextRenderer { - pipelinePromise: Material; + pipelinePromise: RenderPipeline; sampler: Sampler; cameraUniformBuffer: Float32Array = new Float32Array(16 * 2); @@ -339,7 +339,7 @@ export class MsdfTextRenderer __type__: "RenderBundle", renderObjects: [ { - material: font.material, + pipeline: font.material, uniforms: { ...font.bindGroup, ...bindGroup, diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index 20e51b6..4814798 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, Sampler, Submit, Texture, RenderObject } from "@feng3d/render-api"; +import { RenderObject, RenderPassDescriptor, Sampler, Submit, Texture } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -53,7 +53,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleTextureMixColorWGSL }, }, uniforms: { diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 17f7791..311b228 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, Material, Submit, Texture, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { RenderObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -61,7 +61,7 @@ const init = async (canvas: HTMLCanvasElement) => const uniforms = { modelViewProjectionMatrix: null }; - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: basicVertWGSL, }, @@ -102,7 +102,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material, + pipeline: pipeline, uniforms: { uniforms, }, diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 4e185f9..3f0a9a7 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { RenderPassDescriptor, Material, Texture, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Texture, VertexAttributes } from "@feng3d/render-api"; import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -30,7 +30,7 @@ const init = async (canvas: HTMLCanvasElement) => uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: basicVertWGSL, }, @@ -101,7 +101,7 @@ const init = async (canvas: HTMLCanvasElement) => passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - material, + pipeline: pipeline, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index 8e72673..46a5e94 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -43,7 +43,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, uniforms: { diff --git a/examples/src/webgpu/videoUploading/index.ts b/examples/src/webgpu/videoUploading/index.ts index 43363b6..24fbd17 100644 --- a/examples/src/webgpu/videoUploading/index.ts +++ b/examples/src/webgpu/videoUploading/index.ts @@ -38,7 +38,7 @@ const init = async (canvas: HTMLCanvasElement) => }; const renderObject: RenderObject = { - material: { + pipeline: { vertex: { code: fullscreenTexturedQuadWGSL }, fragment: { code: sampleExternalTextureWGSL }, }, uniforms: { diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index 416dc0c..ac7cd18 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import volumeWGSL from "./volume.wgsl"; -import { RenderPassDescriptor, Material, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const gui = new GUI(); @@ -28,7 +28,7 @@ const init = async (canvas: HTMLCanvasElement) => const sampleCount = 4; - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: volumeWGSL, }, @@ -157,7 +157,7 @@ const init = async (canvas: HTMLCanvasElement) => passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - material, + pipeline, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index a0ea7e5..78ca8f4 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, Material, Submit, Uniforms, PrimitiveState, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Submit, Uniforms, PrimitiveState, RenderObject, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => return model; }); - let litPipeline: Material; + let litPipeline: RenderPipeline; function rebuildLitPipeline() { litPipeline = { @@ -72,7 +72,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } rebuildLitPipeline(); - const wireframePipeline: Material = { + const wireframePipeline: RenderPipeline = { label: "wireframe pipeline", vertex: { code: wireframeWGSL, @@ -88,7 +88,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const barycentricCoordinatesBasedWireframePipeline: Material = { + const barycentricCoordinatesBasedWireframePipeline: RenderPipeline = { label: "barycentric coordinates based wireframe pipeline", vertex: { code: wireframeWGSL, @@ -318,7 +318,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => if (settings.models) { renderObjects.push({ - material: litPipeline, + pipeline: litPipeline, uniforms: litBindGroup, geometry: { primitive: { @@ -338,7 +338,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Note: If we're using the line-list based pipeline then we need to // multiply the vertex count by 2 since we need to emit 6 vertices // for each triangle (3 edges). - const [bindGroupNdx, countMult, material, primitive] + const [bindGroupNdx, countMult, pipeline, primitive] = settings.barycentricCoordinatesBased ? [1, 1, barycentricCoordinatesBasedWireframePipeline, { topology: "triangle-list", @@ -349,7 +349,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => objectInfos.forEach(({ wireframeBindGroups, model: { indices } }) => { renderObjects.push({ - material, + pipeline, uniforms: wireframeBindGroups[bindGroupNdx], geometry: { primitive, diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 22dead4..ba3c545 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { RenderPassDescriptor, Material, Submit, VertexAttributes } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; import { getOffscreenCanvasId, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -78,7 +78,7 @@ async function init(canvas: OffscreenCanvas) uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }; - const material: Material = { + const pipeline: RenderPipeline = { vertex: { code: basicVertWGSL, }, @@ -146,7 +146,7 @@ async function init(canvas: OffscreenCanvas) passEncoders: [{ descriptor: renderPassDescriptor, renderObjects: [{ - material, + pipeline, uniforms: uniformBindGroup, geometry: { primitive: { diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 9768cb2..ca8de5b 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, Material, PrimitiveState, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; +import { BlendState, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -21,7 +21,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(renderPipeline: Material, renderPassFormat: IGPURenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) +export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPassFormat: IGPURenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const indexFormat = indices ? getIGPUSetIndexBuffer(indices).indexFormat : undefined; @@ -80,7 +80,7 @@ export function getNGPURenderPipeline(renderPipeline: Material, renderPassFormat } const renderPipelineMap = new ChainMap< - [Material, string, PrimitiveState, VertexAttributes, GPUIndexFormat], + [RenderPipeline, string, PrimitiveState, VertexAttributes, GPUIndexFormat], { /** * GPU渲染管线描述。 diff --git a/src/data/IGPUComputeObject.ts b/src/data/IGPUComputeObject.ts index 1f09a1c..fdcd54b 100644 --- a/src/data/IGPUComputeObject.ts +++ b/src/data/IGPUComputeObject.ts @@ -16,7 +16,7 @@ export interface IGPUComputeObject /** * 计算管线。 */ - readonly material: IGPUComputePipeline; + readonly pipeline: IGPUComputePipeline; /** * 绑定资源。包含数值、纹理、采样、外部纹理。 diff --git a/src/data/IGPURenderPipeline.ts b/src/data/IGPURenderPipeline.ts index 22e3d29..02f55ea 100644 --- a/src/data/IGPURenderPipeline.ts +++ b/src/data/IGPURenderPipeline.ts @@ -9,7 +9,7 @@ declare module "@feng3d/render-api" * * @see https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/createRenderPipeline */ - export interface Material + export interface RenderPipeline { /** * 多重采样阶段描述。 diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 5fedcbe..f9cc6d6 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, Material, PrimitiveState, RenderObject, RenderPass, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, RenderPipeline, PrimitiveState, RenderObject, RenderPass, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -258,7 +258,7 @@ export class RunWebGPU */ protected runComputeObject(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObject: IGPUComputeObject) { - const { material, uniforms: bindingResources, workgroups } = computeObject; + const { pipeline: material, uniforms: bindingResources, workgroups } = computeObject; const shader: IGPUShader = { compute: material.compute.code }; @@ -299,8 +299,8 @@ export class RunWebGPU */ protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: RenderObject) { - const { viewport, scissorRect, material: pipeline, uniforms: bindingResources, geometry } = renderObject; - Material.init(pipeline); + const { viewport, scissorRect, pipeline, uniforms: bindingResources, geometry } = renderObject; + RenderPipeline.init(pipeline); const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; @@ -333,7 +333,7 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, material: Material, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { // const renderPipelineResult = getNGPURenderPipeline(material, renderPassFormat, primitive, vertices, indices); @@ -430,7 +430,7 @@ export class RunWebGPU }); } - protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, material: Material, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const renderPipeline = getNGPURenderPipeline(material, renderPassFormat, primitive, vertices, indices); diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/runs/RunWebGPUCommandCache.ts index a4bb994..2e809e3 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/runs/RunWebGPUCommandCache.ts @@ -111,9 +111,9 @@ export class RunWebGPUCommandCache extends RunWebGPU map.delete([renderPassFormat._key, renderObject]); // renderObject._version = ~~renderObject._version + 1; - watcher.unwatch(renderObject.material, '_version', onchanged); + watcher.unwatch(renderObject.pipeline, '_version', onchanged); } - watcher.watch(renderObject.material, '_version', onchanged); + watcher.watch(renderObject.pipeline, '_version', onchanged); } } -- Gitee From 11ecd6dc442b4ff1ebb273fc64628b6ad3448c35 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 9 Mar 2025 01:34:17 +0800 Subject: [PATCH 028/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20helloTriangle=20=E7=A4=BA=E4=BE=8B=E5=B9=B6=E7=AE=80?= =?UTF-8?q?=E5=8C=96=20WebGPU=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 helloTriangle 示例中,重新启用绘制命令注释 - 在 WebGPU 类的 submit 方法中,移除不必要的参数处理 --- examples/src/webgpu/helloTriangle/index.ts | 2 +- src/WebGPU.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 6c63efe..2c94fab 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -45,7 +45,7 @@ const init = async (canvas: HTMLCanvasElement) => position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 }, indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 - // draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 + draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 }, uniforms: { color: [1, 0, 0, 0] }, // Uniform 颜色值。 }] diff --git a/src/WebGPU.ts b/src/WebGPU.ts index f113871..cb860d8 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -78,7 +78,6 @@ export class WebGPU */ submit(submit: Submit) { - submit = Submit.getInstance(submit); this._runWebGPU.runSubmit(this.device, submit); } -- Gitee From f802f1a0874cff262cc9e8182633b9408cb07c30 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 9 Mar 2025 21:09:27 +0800 Subject: [PATCH 029/214] =?UTF-8?q?refactor(WebGPU):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E9=81=93=E7=9A=84=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E5=86=97=E4=BD=99=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 runRenderObject 方法中对 RenderPipeline.init(pipeline) 的调用 - 优化了渲染流程,减少了不必要的初始化操作 --- src/runs/RunWebGPU.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index f9cc6d6..f94a821 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -300,7 +300,6 @@ export class RunWebGPU protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: RenderObject) { const { viewport, scissorRect, pipeline, uniforms: bindingResources, geometry } = renderObject; - RenderPipeline.init(pipeline); const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; -- Gitee From cd29d5e2f2f5fcd906c700a436d769c60eefbf8a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 12 Mar 2025 09:53:52 +0800 Subject: [PATCH 030/214] =?UTF-8?q?refactor(data):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E9=BB=98=E8=AE=A4=E5=80=BC?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 IGPUPrimitiveState.ts 中的 unclippedDepth 默认值设置 - 移除了 IGPURenderObject.ts 中的多个属性默认值设置 --- src/data/IGPUPrimitiveState.ts | 1 - src/data/IGPURenderObject.ts | 8 -------- 2 files changed, 9 deletions(-) diff --git a/src/data/IGPUPrimitiveState.ts b/src/data/IGPUPrimitiveState.ts index 6c556e0..c400f9c 100644 --- a/src/data/IGPUPrimitiveState.ts +++ b/src/data/IGPUPrimitiveState.ts @@ -17,4 +17,3 @@ declare module "@feng3d/render-api" } } -PrimitiveState.prototype.unclippedDepth = false; diff --git a/src/data/IGPURenderObject.ts b/src/data/IGPURenderObject.ts index 0f6c677..b1a8aa7 100644 --- a/src/data/IGPURenderObject.ts +++ b/src/data/IGPURenderObject.ts @@ -70,11 +70,3 @@ declare module "@feng3d/render-api" firstInstance?: number; } } - -Viewport.prototype.minDepth = 0; -Viewport.prototype.maxDepth = 1; - -DrawVertex.prototype.firstInstance = 0 - -DrawIndexed.prototype.baseVertex = 0; -DrawIndexed.prototype.firstInstance = 0; \ No newline at end of file -- Gitee From 24da77aa7d9076968de2f9068b7841bd8da633b0 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 12 Mar 2025 14:16:04 +0800 Subject: [PATCH 031/214] =?UTF-8?q?refactor(WebGPU):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E7=9B=B8=E5=85=B3=E7=B1=BB=E5=9E=8B=E5=92=8C?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 ITextureLike 重命名为 TextureLike - 更新相关函数和接口中的 I --- src/WebGPU.ts | 10 ++++----- src/caches/getGPURenderPassDescriptor.ts | 12 +++++------ src/caches/getGPUTexture.ts | 6 +++--- src/caches/getGPUTextureFormat.ts | 4 ++-- src/caches/getIGPUTextureSize.ts | 4 ++-- src/data/IGPUOcclusionQuery.ts | 27 ++---------------------- src/data/IGPUReadPixels.ts | 6 +++--- src/data/IGPUTextureView.ts | 4 ++-- 8 files changed, 25 insertions(+), 48 deletions(-) diff --git a/src/WebGPU.ts b/src/WebGPU.ts index cb860d8..a4903ab 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,4 +1,4 @@ -import { Buffer, ITextureLike, Submit } from "@feng3d/render-api"; +import { Buffer, TextureLike, Submit } from "@feng3d/render-api"; import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUTexture } from "./caches/getGPUTexture"; import { getIGPUTextureLikeSize } from "./caches/getIGPUTextureSize"; @@ -86,7 +86,7 @@ export class WebGPU * * @param texture 需要被销毁的纹理。 */ - destoryTexture(texture: ITextureLike) + destoryTexture(texture: TextureLike) { getGPUTexture(this.device, texture, false)?.destroy(); } @@ -98,7 +98,7 @@ export class WebGPU * @param invertY 是否Y轴翻转 * @param premultiplyAlpha 是否预乘Alpha。 */ - textureInvertYPremultiplyAlpha(texture: ITextureLike, options: { invertY?: boolean, premultiplyAlpha?: boolean }) + textureInvertYPremultiplyAlpha(texture: TextureLike, options: { invertY?: boolean, premultiplyAlpha?: boolean }) { const gpuTexture = getGPUTexture(this.device, texture); @@ -112,7 +112,7 @@ export class WebGPU * @param sourceTexture 源纹理。 * @param targetTexture 目标纹理。 */ - copyDepthTexture(sourceTexture: ITextureLike, targetTexture: ITextureLike) + copyDepthTexture(sourceTexture: TextureLike, targetTexture: TextureLike) { const gpuSourceTexture = getGPUTexture(this.device, sourceTexture); const gpuTargetTexture = getGPUTexture(this.device, targetTexture); @@ -161,7 +161,7 @@ export class WebGPU return result; } - getGPUTextureSize(input: ITextureLike) + getGPUTextureSize(input: TextureLike) { return getIGPUTextureLikeSize(input); } diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 8a363bb..8bb47e2 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, ITextureLike, TextureView } from "@feng3d/render-api"; +import { RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { IGPUTexture_resize } from "../eventnames"; @@ -129,7 +129,7 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render */ function getAttachmentTextures(colorAttachments: readonly RenderPassColorAttachment[], depthStencilAttachment?: RenderPassDepthStencilAttachment) { - const textures: ITextureLike[] = []; + const textures: TextureLike[] = []; for (let i = 0; i < colorAttachments.length; i++) { @@ -170,7 +170,7 @@ function setIGPURenderPassAttachmentSize(colorAttachments: NGPURenderPassColorAt * @param texture 纹理描述。 * @param attachmentSize 附件尺寸。 */ -function setIGPUTextureSize(texture: ITextureLike, attachmentSize: { width: number, height: number }) +function setIGPUTextureSize(texture: TextureLike, attachmentSize: { width: number, height: number }) { if ("context" in texture) { @@ -201,7 +201,7 @@ function setIGPUTextureSize(texture: ITextureLike, attachmentSize: { width: numb */ function getIGPURenderPassAttachmentTextures(colorAttachments: NGPURenderPassColorAttachment[], depthStencilAttachment?: RenderPassDepthStencilAttachment) { - const textures: ITextureLike[] = []; + const textures: TextureLike[] = []; for (let i = 0; i < colorAttachments.length; i++) { @@ -234,7 +234,7 @@ function getIGPURenderPassAttachmentTextures(colorAttachments: NGPURenderPassCol * @param sampleCount 多重采样数量。 * @returns 用于解决多重采样的纹理视图。 */ -function getMultisampleTextureView(texture: ITextureLike, sampleCount: 4) +function getMultisampleTextureView(texture: TextureLike, sampleCount: 4) { let multisampleTextureView = multisampleTextureMap.get(texture); if (!multisampleTextureView) @@ -255,7 +255,7 @@ function getMultisampleTextureView(texture: ITextureLike, sampleCount: 4) return multisampleTextureView; } -const multisampleTextureMap = new WeakMap(); +const multisampleTextureMap = new WeakMap(); /** * 获取深度模板附件完整描述。 diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 6cfaeb7..569f3c5 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { ITextureLike, ITextureSize, Texture, TextureDataSource, TextureImageSource, TextureSource } from "@feng3d/render-api"; +import { TextureLike, ITextureSize, Texture, TextureDataSource, TextureImageSource, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; @@ -16,7 +16,7 @@ import { getTextureUsageFromFormat } from "./getTextureUsageFromFormat"; * @param iGPUTextureBase 纹理描述。 * @returns GPU纹理。 */ -export function getGPUTexture(device: GPUDevice, textureLike: ITextureLike, autoCreate = true) +export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoCreate = true) { let gpuTexture: GPUTexture; if ("context" in textureLike) @@ -31,7 +31,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: ITextureLike, auto const texture = textureLike as Texture; - const textureMap: Map = device[_GPUTextureMap] = device[_GPUTextureMap] || new Map(); + const textureMap: Map = device[_GPUTextureMap] = device[_GPUTextureMap] || new Map(); gpuTexture = textureMap.get(texture); if (gpuTexture) return gpuTexture; diff --git a/src/caches/getGPUTextureFormat.ts b/src/caches/getGPUTextureFormat.ts index fc6b04b..effe6ee 100644 --- a/src/caches/getGPUTextureFormat.ts +++ b/src/caches/getGPUTextureFormat.ts @@ -1,4 +1,4 @@ -import { ITextureLike } from "@feng3d/render-api"; +import { TextureLike } from "@feng3d/render-api"; /** * 获取纹理格式。 @@ -6,7 +6,7 @@ import { ITextureLike } from "@feng3d/render-api"; * @param texture 纹理。 * @returns 纹理格式。 */ -export function getGPUTextureFormat(texture: ITextureLike) +export function getGPUTextureFormat(texture: TextureLike) { if (!texture) return undefined; diff --git a/src/caches/getIGPUTextureSize.ts b/src/caches/getIGPUTextureSize.ts index baa5ad7..ff67c74 100644 --- a/src/caches/getIGPUTextureSize.ts +++ b/src/caches/getIGPUTextureSize.ts @@ -1,4 +1,4 @@ -import { ITextureLike, ITextureSize, TextureImageSource } from "@feng3d/render-api"; +import { TextureLike, ITextureSize, TextureImageSource } from "@feng3d/render-api"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; /** @@ -7,7 +7,7 @@ import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; * @param texture 纹理。 * @returns 纹理尺寸。 */ -export function getIGPUTextureLikeSize(texture: ITextureLike) +export function getIGPUTextureLikeSize(texture: TextureLike) { if ("context" in texture) { diff --git a/src/data/IGPUOcclusionQuery.ts b/src/data/IGPUOcclusionQuery.ts index 62f8527..e57631d 100644 --- a/src/data/IGPUOcclusionQuery.ts +++ b/src/data/IGPUOcclusionQuery.ts @@ -1,20 +1,10 @@ -import { RenderObject } from "@feng3d/render-api"; +import { OcclusionQuery } from "@feng3d/render-api"; /** * 被查询的渲染对象列表 */ -export interface IGPUOcclusionQuery +export interface IGPUOcclusionQuery extends OcclusionQuery { - /** - * 数据类型。 - */ - readonly __type__: "OcclusionQuery"; - - /** - * GPU渲染对象列表。 - */ - renderObjects: RenderObject[]; - /** * 临时变量, 执行过程中由引擎自动填充 * @@ -22,18 +12,5 @@ export interface IGPUOcclusionQuery */ _queryIndex?: GPUSize32; - /** - * 渲染完成后由引擎自动填充。 - */ - result?: IGLQueryResult; - _version?: number; } - -export interface IGLQueryResult -{ - /** - * 查询结果。 - */ - result: number; -} \ No newline at end of file diff --git a/src/data/IGPUReadPixels.ts b/src/data/IGPUReadPixels.ts index c361a94..50d943e 100644 --- a/src/data/IGPUReadPixels.ts +++ b/src/data/IGPUReadPixels.ts @@ -1,14 +1,14 @@ -import { ITextureLike } from "@feng3d/render-api"; +import { TextureLike, ReadPixels } from "@feng3d/render-api"; /** * 读取GPU纹理像素 */ -export interface IGPUReadPixels +export interface IGPUReadPixels extends ReadPixels { /** * GPU纹理 */ - texture: ITextureLike, + texture: TextureLike, /** * 读取位置。 diff --git a/src/data/IGPUTextureView.ts b/src/data/IGPUTextureView.ts index a306ebe..99b5c1a 100644 --- a/src/data/IGPUTextureView.ts +++ b/src/data/IGPUTextureView.ts @@ -1,9 +1,9 @@ -import { ITextureLike } from "@feng3d/render-api"; +import { TextureLike } from "@feng3d/render-api"; import { IGPUCanvasTexture } from "./IGPUCanvasTexture"; declare module "@feng3d/render-api" { - export interface ITextureLikeMap + export interface TextureLikeMap { /** * 画布纹理。 -- Gitee From 220d73f720c14a86c12d44550751e462c38b5cf4 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 12 Mar 2025 15:41:25 +0800 Subject: [PATCH 032/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20occlusion=20query=20=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新导入语句,移除未使用的 IGPUOcclusionQuery - 将 IGPUOcclusionQuery 重命名为 OcclusionQuery - 调整相关函数和接口,使用新的 OcclusionQuery 类型 - 移除 IGPURenderPass 中的 occlusionQueryResults 属性 - 优化 readPixels 函数,支持不同纹理格式 --- examples/src/webgpu/occlusionQuery/index.ts | 6 +-- src/caches/getGPURenderOcclusionQuery.ts | 6 +-- src/caches/getGPUTexture.ts | 4 +- src/caches/getGPUTextureDimension.ts | 4 +- src/caches/getIGPUTextureSize.ts | 6 +-- src/data/IGPUOcclusionQuery.ts | 23 +++++------ src/data/IGPUReadPixels.ts | 15 ------- src/data/IGPURenderPass.ts | 5 +-- src/runs/RunWebGPU.ts | 6 +-- src/utils/readPixels.ts | 44 ++++++--------------- 10 files changed, 42 insertions(+), 77 deletions(-) diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 3aa6cef..049a4f8 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -1,6 +1,6 @@ -import { BufferBinding, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; +import { BufferBinding, OcclusionQuery, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { getIGPUBuffer, IGPUOcclusionQuery, WebGPU } from "@feng3d/webgpu"; +import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; @@ -157,7 +157,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => return ro; }); - const occlusionQueryObjects: IGPUOcclusionQuery[] = renderObjects.map((ro) => + const occlusionQueryObjects: OcclusionQuery[] = renderObjects.map((ro) => ({ __type__: "OcclusionQuery", renderObjects: [ro] })); const renderPass: RenderPass = { diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index 2798640..37023d9 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -1,7 +1,7 @@ import { anyEmitter } from "@feng3d/event"; -import { RenderPass, IRenderPassObject } from "@feng3d/render-api"; +import { IRenderPassObject, OcclusionQuery, RenderPass } from "@feng3d/render-api"; -import { IGPUOcclusionQuery } from "../data/IGPUOcclusionQuery"; +import { } from "../data/IGPUOcclusionQuery"; import { GPUQueue_submit } from "../eventnames"; export function getGPURenderOcclusionQuery(renderObjects?: readonly IRenderPassObject[]): GPURenderOcclusionQuery @@ -10,7 +10,7 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly IRenderPassO let renderOcclusionQuery: GPURenderOcclusionQuery = renderObjects["_GPURenderOcclusionQuery"]; if (renderOcclusionQuery) return renderOcclusionQuery; - const occlusionQueryObjects: IGPUOcclusionQuery[] = renderObjects.filter((cv) => cv.__type__ === "OcclusionQuery") as any; + const occlusionQueryObjects: OcclusionQuery[] = renderObjects.filter((cv) => cv.__type__ === "OcclusionQuery") as any; if (occlusionQueryObjects.length === 0) { renderObjects["_GPURenderOcclusionQuery"] = defautRenderOcclusionQuery; diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 569f3c5..8a66531 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { TextureLike, ITextureSize, Texture, TextureDataSource, TextureImageSource, TextureSource } from "@feng3d/render-api"; +import { TextureLike, TextureSize, Texture, TextureDataSource, TextureImageSource, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; @@ -200,7 +200,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC watcher.watch(texture, "writeTextures", updateWriteTextures); // 监听纹理尺寸发生变化 - const resize = (newValue: ITextureSize, oldValue: ITextureSize) => + const resize = (newValue: TextureSize, oldValue: TextureSize) => { if (!!newValue && !!oldValue) { diff --git a/src/caches/getGPUTextureDimension.ts b/src/caches/getGPUTextureDimension.ts index b1142e5..4f73e9e 100644 --- a/src/caches/getGPUTextureDimension.ts +++ b/src/caches/getGPUTextureDimension.ts @@ -1,6 +1,6 @@ -import { ITextureDimension } from "@feng3d/render-api"; +import { TextureDimension } from "@feng3d/render-api"; -export function getGPUTextureDimension(dimension: ITextureDimension) +export function getGPUTextureDimension(dimension: TextureDimension) { const textureDimension: GPUTextureDimension = dimensionMap[dimension]; diff --git a/src/caches/getIGPUTextureSize.ts b/src/caches/getIGPUTextureSize.ts index ff67c74..87c924b 100644 --- a/src/caches/getIGPUTextureSize.ts +++ b/src/caches/getIGPUTextureSize.ts @@ -1,4 +1,4 @@ -import { TextureLike, ITextureSize, TextureImageSource } from "@feng3d/render-api"; +import { TextureLike, TextureSize, TextureImageSource } from "@feng3d/render-api"; import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; /** @@ -14,13 +14,13 @@ export function getIGPUTextureLikeSize(texture: TextureLike) const element = document.getElementById(texture.context.canvasId) as HTMLCanvasElement; console.assert(!!element, `在 document 上没有找到 canvasId 为 ${(texture as IGPUCanvasTexture).context.canvasId} 的画布。`); - return [element.width, element.height, 1] as ITextureSize; + return [element.width, element.height, 1] as TextureSize; } return texture.size; } -export function getIGPUTextureSourceSize(source?: TextureImageSource[]): ITextureSize +export function getIGPUTextureSourceSize(source?: TextureImageSource[]): TextureSize { if (!source) return undefined; diff --git a/src/data/IGPUOcclusionQuery.ts b/src/data/IGPUOcclusionQuery.ts index e57631d..19141e7 100644 --- a/src/data/IGPUOcclusionQuery.ts +++ b/src/data/IGPUOcclusionQuery.ts @@ -1,16 +1,17 @@ import { OcclusionQuery } from "@feng3d/render-api"; -/** - * 被查询的渲染对象列表 - */ -export interface IGPUOcclusionQuery extends OcclusionQuery +declare module "@feng3d/render-api" { - /** - * 临时变量, 执行过程中由引擎自动填充 - * - * @internal - */ - _queryIndex?: GPUSize32; + export interface OcclusionQuery + { + /** + * 临时变量, 执行过程中由引擎自动填充 + * + * @internal + */ + _queryIndex?: GPUSize32; - _version?: number; + _version?: number; + } } + diff --git a/src/data/IGPUReadPixels.ts b/src/data/IGPUReadPixels.ts index 50d943e..cd82c4d 100644 --- a/src/data/IGPUReadPixels.ts +++ b/src/data/IGPUReadPixels.ts @@ -9,19 +9,4 @@ export interface IGPUReadPixels extends ReadPixels * GPU纹理 */ texture: TextureLike, - - /** - * 读取位置。 - */ - origin: GPUOrigin3D, - - /** - * 读取尺寸 - */ - copySize: { width: number, height: number } - - /** - * 用于保存最后结果。 - */ - result?: Uint8Array; } \ No newline at end of file diff --git a/src/data/IGPURenderPass.ts b/src/data/IGPURenderPass.ts index 9510307..d9c7995 100644 --- a/src/data/IGPURenderPass.ts +++ b/src/data/IGPURenderPass.ts @@ -1,5 +1,5 @@ import { RenderPass, RenderPassDescriptor } from "@feng3d/render-api"; -import { IGPUOcclusionQuery } from "./IGPUOcclusionQuery"; +import { } from "./IGPUOcclusionQuery"; import { IGPURenderBundle } from "./IGPURenderBundle"; import { IGPUTimestampQuery } from "./IGPUTimestampQuery"; @@ -19,7 +19,7 @@ declare module "@feng3d/render-api" * * 当提交WebGPU后自动获取结果后填充该属性。 */ - occlusionQueryResults?: IGPUOcclusionQuery[]; + occlusionQueryResults?: OcclusionQuery[]; /** * 查询通道运行消耗时长(单位为纳秒)。 @@ -32,6 +32,5 @@ declare module "@feng3d/render-api" export interface IRenderPassObjectMap { IGPURenderBundle: IGPURenderBundle; - IGPUOcclusionQuery: IGPUOcclusionQuery; } } diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index f94a821..0420263 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, RenderPipeline, PrimitiveState, RenderObject, RenderPass, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, RenderPipeline, PrimitiveState, RenderObject, RenderPass, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport, OcclusionQuery } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -19,7 +19,7 @@ import { getRealGPUBindGroup } from "../const"; import { IGPUComputeObject } from "../data/IGPUComputeObject"; import { IGPUComputePass } from "../data/IGPUComputePass"; import { IGPUComputePipeline } from "../data/IGPUComputePipeline"; -import { IGPUOcclusionQuery } from "../data/IGPUOcclusionQuery"; +import { } from "../data/IGPUOcclusionQuery"; import { IGPURenderBundle } from "../data/IGPURenderBundle"; import { IGPUWorkgroups } from "../data/IGPUWorkgroups"; import { GPUQueue_submit } from "../eventnames"; @@ -209,7 +209,7 @@ export class RunWebGPU ); } - protected runRenderOcclusionQueryObject(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IGPURenderPassFormat, renderOcclusionQueryObject: IGPUOcclusionQuery) + protected runRenderOcclusionQueryObject(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IGPURenderPassFormat, renderOcclusionQueryObject: OcclusionQuery) { passEncoder.beginOcclusionQuery(renderOcclusionQueryObject._queryIndex); renderOcclusionQueryObject.renderObjects.forEach((renderObject) => diff --git a/src/utils/readPixels.ts b/src/utils/readPixels.ts index 700519e..2f39e1a 100644 --- a/src/utils/readPixels.ts +++ b/src/utils/readPixels.ts @@ -1,3 +1,6 @@ +import { Texture } from "@feng3d/render-api"; +import { getGPUTextureFormat } from "../caches/getGPUTextureFormat"; + /** * 从 GPU纹理 上读取数据。 * @@ -10,16 +13,21 @@ * * @returns 读取到的数据。 */ -export async function readPixels(device: GPUDevice, params: { texture: GPUTexture, origin: GPUOrigin3D, copySize: { width: number, height: number } }) +export async function readPixels(device: GPUDevice, params: { texture: GPUTexture, origin: [x: number, y: number], copySize: [width: number, height: number] }) { const commandEncoder = device.createCommandEncoder(); const { texture, origin, copySize } = params; - const { width, height } = copySize; + const [width, height] = copySize; + + const bytesPerPixel = Texture.getTextureBytesPerPixel(texture.format); + const dataConstructor = Texture.getTextureDataConstructor(texture.format); - const bytesPerRow = Math.ceil((width * 4) / 256) * 256; + const bytesPerRow = width * bytesPerPixel; const bufferSize = bytesPerRow * height; + const bufferData = new dataConstructor(bufferSize / dataConstructor.BYTES_PER_ELEMENT); + // const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ }); commandEncoder.copyTextureToBuffer( @@ -38,40 +46,12 @@ export async function readPixels(device: GPUDevice, params: { texture: GPUTextur device.queue.submit([commandEncoder.finish()]); await buffer.mapAsync(GPUMapMode.READ); - const bufferData = new Uint8Array(buffer.size); const source = new Uint8Array(buffer.getMappedRange()); bufferData.set(source); - buffer.unmap(); buffer.destroy(); - const result = new Uint8Array(width * height * 4); - - for (let i = 0; i < width; i++) - { - for (let j = 0; j < height; j++) - { - // rgba8unorm - let rgba = [ - bufferData[j * bytesPerRow + i * 4], - bufferData[j * bytesPerRow + i * 4 + 1], - bufferData[j * bytesPerRow + i * 4 + 2], - bufferData[j * bytesPerRow + i * 4 + 3], - ]; - - if (texture.format === "bgra8unorm") - { - rgba = [rgba[2], rgba[1], rgba[0], rgba[3]]; - } - - result[j * width * 4 + i * 4] = rgba[0]; - result[j * width * 4 + i * 4 + 1] = rgba[1]; - result[j * width * 4 + i * 4 + 2] = rgba[2]; - result[j * width * 4 + i * 4 + 3] = rgba[3]; - } - } - - return result; + return bufferData; } -- Gitee From 0194ab5dda15e6de385ef29a9deab9cec462243e Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 12 Mar 2025 18:05:32 +0800 Subject: [PATCH 033/214] =?UTF-8?q?refactor(data):=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 IUniformTypeMap 改为 UniformTypeMap - 将 IPassEncoderMap 改为 PassEncoderMap - 将 IRenderPassObjectMap 改为 RenderPassObjectMap --- src/data/IGPUBindingResources.ts | 2 +- src/data/IGPUCommandEncoder.ts | 2 +- src/data/IGPURenderPass.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/IGPUBindingResources.ts b/src/data/IGPUBindingResources.ts index dc64ac2..29a8c36 100644 --- a/src/data/IGPUBindingResources.ts +++ b/src/data/IGPUBindingResources.ts @@ -3,7 +3,7 @@ import { IGPUExternalTexture } from "./IGPUExternalTexture"; declare module "@feng3d/render-api" { - export interface IUniformTypeMap + export interface UniformTypeMap { ISampler: Sampler; ITextureView: TextureView; diff --git a/src/data/IGPUCommandEncoder.ts b/src/data/IGPUCommandEncoder.ts index 08fc77b..7788dd4 100644 --- a/src/data/IGPUCommandEncoder.ts +++ b/src/data/IGPUCommandEncoder.ts @@ -3,7 +3,7 @@ import { IGPUComputePass } from "./IGPUComputePass"; declare module "@feng3d/render-api" { - export interface IPassEncoderMap + export interface PassEncoderMap { IGPUComputePass: IGPUComputePass; } diff --git a/src/data/IGPURenderPass.ts b/src/data/IGPURenderPass.ts index d9c7995..0cd2d8a 100644 --- a/src/data/IGPURenderPass.ts +++ b/src/data/IGPURenderPass.ts @@ -29,7 +29,7 @@ declare module "@feng3d/render-api" timestampQuery?: IGPUTimestampQuery; } - export interface IRenderPassObjectMap + export interface RenderPassObjectMap { IGPURenderBundle: IGPURenderBundle; } -- Gitee From 0a1be03d9b1c6ca21dd1226993ccf072cc1fc6bd Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 12 Mar 2025 19:47:05 +0800 Subject: [PATCH 034/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新导入路径和接口名称,以更好地与 render-api 集成 - 重命名 IGPUCanvasContext 为 CanvasContext - 移除未使用的 IGPUBindingResources、IGPUBuffer 和 IGPUCanvasConfiguration 文件 - 更新相关示例代码以适应新接口 --- examples/src/webgpu/a-buffer/index.ts | 6 +++--- .../webgpu/atmosphericScatteringSky/index.ts | 6 +++--- examples/src/webgpu/blending/index.ts | 6 +++--- examples/src/webgpu/cornell/index.ts | 6 +++--- examples/src/webgpu/fractalCube/index.ts | 6 +++--- examples/src/webgpu/multipleCanvases/index.ts | 8 ++++---- examples/src/webgpu/renderBundles/index.ts | 6 +++--- examples/src/webgpu/reversedZ/index.ts | 6 +++--- examples/src/webgpu/timestampQuery/index.ts | 6 +++--- .../src/webgpu/transparentCanvas/index.ts | 6 +++--- examples/src/webgpu/worker/worker.ts | 6 +++--- src/caches/getGPUCanvasContext.ts | 5 +++-- ...iguration.ts => GPUCanvasConfiguration.ts} | 2 +- src/data/IGPUCanvasContext.ts | 20 ++++++++++--------- src/data/IGPUCanvasTexture.ts | 4 ++-- src/data/IGPURenderObject.ts | 2 +- .../{IGPUBuffer.ts => polyfills/Buffer.ts} | 0 .../Uniforms.ts} | 6 +++--- src/index.ts | 4 ++-- 19 files changed, 57 insertions(+), 54 deletions(-) rename src/data/{IGPUCanvasConfiguration.ts => GPUCanvasConfiguration.ts} (97%) rename src/data/{IGPUBuffer.ts => polyfills/Buffer.ts} (100%) rename src/data/{IGPUBindingResources.ts => polyfills/Uniforms.ts} (59%) diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 3457c32..8dae440 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -1,5 +1,5 @@ -import { BufferBinding, IPassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; +import { BufferBinding, CanvasContext, IPassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; +import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -23,7 +23,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); - const context: IGPUCanvasContext = { + const context: CanvasContext = { canvasId: canvas.id, configuration: { alphaMode: "opaque" } }; diff --git a/examples/src/webgpu/atmosphericScatteringSky/index.ts b/examples/src/webgpu/atmosphericScatteringSky/index.ts index 7358735..133ae15 100644 --- a/examples/src/webgpu/atmosphericScatteringSky/index.ts +++ b/examples/src/webgpu/atmosphericScatteringSky/index.ts @@ -2,8 +2,8 @@ import { GUI } from "dat.gui"; import atmosphericScatteringSkyWGSL from "./atmosphericScatteringSky.wgsl"; -import { Texture } from "@feng3d/render-api"; -import { IGPUCanvasContext, IGPUComputeObject, WebGPU } from "@feng3d/webgpu"; +import { CanvasContext, Texture } from "@feng3d/render-api"; +import { IGPUComputeObject, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -11,7 +11,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => canvas.width = canvas.clientWidth * devicePixelRatio; canvas.height = canvas.clientHeight * devicePixelRatio; - const context: IGPUCanvasContext = { + const context: CanvasContext = { canvasId: canvas.id, configuration: { format: "rgba16float", diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 5319702..7becf26 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -2,8 +2,8 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import texturedQuadWGSL from "./texturedQuad.wgsl"; -import { BlendComponent, IRenderPassObject, RenderObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, TextureView, Uniforms } from "@feng3d/render-api"; -import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; +import { BlendComponent, CanvasContext, IRenderPassObject, RenderObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, TextureView, Uniforms } from "@feng3d/render-api"; +import { WebGPU } from "@feng3d/webgpu"; declare module "@feng3d/render-api" { @@ -101,7 +101,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => canvas.width = canvas.clientWidth * devicePixelRatio; canvas.height = canvas.clientHeight * devicePixelRatio; - const context: IGPUCanvasContext = { canvasId: canvas.id, configuration: {} }; + const context: CanvasContext = { canvasId: canvas.id, configuration: {} }; const canvasTexture: TextureView = { texture: { context } }; // Get a WebGPU context from the canvas and configure it diff --git a/examples/src/webgpu/cornell/index.ts b/examples/src/webgpu/cornell/index.ts index 93d2a83..de7669c 100644 --- a/examples/src/webgpu/cornell/index.ts +++ b/examples/src/webgpu/cornell/index.ts @@ -7,8 +7,8 @@ import Raytracer from "./raytracer"; import Scene from "./scene"; import Tonemapper from "./tonemapper"; -import { CommandEncoder, Submit, Texture } from "@feng3d/render-api"; -import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; +import { CanvasContext, CommandEncoder, Submit, Texture } from "@feng3d/render-api"; +import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -16,7 +16,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const requiredFeatures: GPUFeatureName[] = presentationFormat === "bgra8unorm" ? ["bgra8unorm-storage"] : []; - const context: IGPUCanvasContext = { + const context: CanvasContext = { canvasId: canvas.id, configuration: { format: "rgba16float", diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 7a8e2c9..35b72d9 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -1,5 +1,5 @@ -import { BufferBinding, CopyTextureToTexture, RenderObject, RenderPassDescriptor, Sampler, Submit, Texture } from "@feng3d/render-api"; -import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; +import { BufferBinding, CanvasContext, CopyTextureToTexture, RenderObject, RenderPassDescriptor, Sampler, Submit, Texture } from "@feng3d/render-api"; +import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -55,7 +55,7 @@ const init = async (canvas: HTMLCanvasElement) => return modelViewProjectionMatrix as Float32Array; } - const context: IGPUCanvasContext = { + const context: CanvasContext = { canvasId: canvas.id, configuration: { usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index b7a759b..2856e97 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,5 +1,5 @@ -import { IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; +import { CanvasContext, IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; @@ -164,7 +164,7 @@ const init = async () => }); type CanvasInfo = { - context: IGPUCanvasContext; + context: CanvasContext; clearValue: [number, number, number, number]; worldViewProjectionMatrixValue: Float32Array; worldMatrixValue: Float32Array; @@ -201,7 +201,7 @@ const init = async () => // Get a WebGPU context and configure it. canvas.id = canvas.id || `gpuCanvas___${globalThis["gpuCanvasAutoID"] = ~~globalThis["gpuCanvasAutoID"] + 1}`; - const context: IGPUCanvasContext = { canvasId: canvas.id }; + const context: CanvasContext = { canvasId: canvas.id }; // Make a uniform buffer and type array views // for our uniforms. diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 97d2f77..efa346f 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,5 +1,5 @@ -import { IRenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { IGPUCanvasContext, IGPURenderBundle, WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; +import { CanvasContext, IRenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { IGPURenderBundle, WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats-js"; @@ -37,7 +37,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => canvas.height = canvas.clientHeight * devicePixelRatio; const webgpu = await new WebGPU().init(); - const context: IGPUCanvasContext = { + const context: CanvasContext = { canvasId: canvas.id, }; diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 9b3f492..d63623d 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -10,8 +10,8 @@ import vertexDepthPrePassWGSL from "./vertexDepthPrePass.wgsl"; import vertexPrecisionErrorPassWGSL from "./vertexPrecisionErrorPass.wgsl"; import vertexTextureQuadWGSL from "./vertexTextureQuad.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; +import { CanvasContext, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { WebGPU } from "@feng3d/webgpu"; // Two planes close to each other for depth precision test const geometryVertexSize = 4 * 8; // Byte size of one geometry vertex. @@ -74,7 +74,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => canvas.width = canvas.clientWidth * devicePixelRatio; canvas.height = canvas.clientHeight * devicePixelRatio; - const context: IGPUCanvasContext = { canvasId: canvas.id }; + const context: CanvasContext = { canvasId: canvas.id }; const webgpu = await new WebGPU().init(); diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 311b228..5c6fad6 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -1,5 +1,5 @@ -import { RenderObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { IGPUCanvasContext, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; +import { CanvasContext, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; +import { IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -49,7 +49,7 @@ const init = async (canvas: HTMLCanvasElement) => const webgpu = await new WebGPU().init(); // - const context: IGPUCanvasContext = { canvasId: canvas.id }; + const context: CanvasContext = { canvasId: canvas.id }; const perfDisplay = document.querySelector("#info pre"); diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 3f0a9a7..bb82e63 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -1,7 +1,7 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { RenderPassDescriptor, RenderPipeline, Texture, VertexAttributes } from "@feng3d/render-api"; -import { IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; +import { CanvasContext, RenderPassDescriptor, RenderPipeline, Texture, VertexAttributes } from "@feng3d/render-api"; +import { WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -16,7 +16,7 @@ const init = async (canvas: HTMLCanvasElement) => canvas.width = canvas.clientWidth * devicePixelRatio; canvas.height = canvas.clientHeight * devicePixelRatio; - const context: IGPUCanvasContext = { + const context: CanvasContext = { canvasId: canvas.id, configuration: { // The canvas alphaMode defaults to 'opaque', use 'premultiplied' for transparency. diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index ba3c545..f90e5d3 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -1,7 +1,7 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; -import { getOffscreenCanvasId, IGPUCanvasContext, WebGPU } from "@feng3d/webgpu"; +import { CanvasContext, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; +import { getOffscreenCanvasId, WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -70,7 +70,7 @@ self.addEventListener("message", (ev) => async function init(canvas: OffscreenCanvas) { const webgpu = await new WebGPU().init(); - const context: IGPUCanvasContext = { canvasId: getOffscreenCanvasId(canvas) }; + const context: CanvasContext = { canvasId: getOffscreenCanvasId(canvas) }; // Create a vertex buffer from the cube data. const verticesBuffer: VertexAttributes = { diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index 8c08e37..c23e1d1 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -1,7 +1,8 @@ import { watcher } from "@feng3d/watcher"; -import { IGPUCanvasContext } from "../data/IGPUCanvasContext"; +import "../data/IGPUCanvasContext"; +import { CanvasContext } from "@feng3d/render-api"; -export function getGPUCanvasContext(device: GPUDevice, context: IGPUCanvasContext) +export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) { let gpuCanvasContext = canvasContextMap[context.canvasId]; if (gpuCanvasContext) return gpuCanvasContext; diff --git a/src/data/IGPUCanvasConfiguration.ts b/src/data/GPUCanvasConfiguration.ts similarity index 97% rename from src/data/IGPUCanvasConfiguration.ts rename to src/data/GPUCanvasConfiguration.ts index 55b0627..64b9a43 100644 --- a/src/data/IGPUCanvasConfiguration.ts +++ b/src/data/GPUCanvasConfiguration.ts @@ -4,7 +4,7 @@ * @see GPUCanvasConfiguration * @see GPUCanvasContext.configure */ -export interface IGPUCanvasConfiguration +export interface CanvasConfiguration { /** * The usage that textures returned by {@link GPUCanvasContext#getCurrentTexture} will have. diff --git a/src/data/IGPUCanvasContext.ts b/src/data/IGPUCanvasContext.ts index 693ff13..af2ab43 100644 --- a/src/data/IGPUCanvasContext.ts +++ b/src/data/IGPUCanvasContext.ts @@ -1,15 +1,17 @@ import { CanvasContext } from "@feng3d/render-api"; -import { IGPUCanvasConfiguration } from "./IGPUCanvasConfiguration"; +import { CanvasConfiguration } from "./GPUCanvasConfiguration"; -/** - * @see GPUCanvasContext - * @see HTMLCanvasElement.getContext - * @see GPUCanvasContext.configure - */ -export interface IGPUCanvasContext extends CanvasContext +declare module "@feng3d/render-api" { /** - * 画布配置。默认有引擎自动设置。 + * @see GPUCanvasContext + * @see GPUCanvasContext.configure */ - configuration?: IGPUCanvasConfiguration; + export interface CanvasContext + { + /** + * 画布配置。默认有引擎自动设置。 + */ + configuration?: CanvasConfiguration; + } } diff --git a/src/data/IGPUCanvasTexture.ts b/src/data/IGPUCanvasTexture.ts index 7c9f77a..aa25cd9 100644 --- a/src/data/IGPUCanvasTexture.ts +++ b/src/data/IGPUCanvasTexture.ts @@ -1,9 +1,9 @@ -import { IGPUCanvasContext } from "./IGPUCanvasContext"; +import { CanvasContext } from "@feng3d/render-api"; /** * 画布纹理,从画布的WebGPU上下文获取纹理 */ export interface IGPUCanvasTexture { - context: IGPUCanvasContext; + context: CanvasContext; } diff --git a/src/data/IGPURenderObject.ts b/src/data/IGPURenderObject.ts index b1a8aa7..3994f5d 100644 --- a/src/data/IGPURenderObject.ts +++ b/src/data/IGPURenderObject.ts @@ -1,5 +1,5 @@ import { DrawIndexed, DrawVertex, Viewport } from "@feng3d/render-api"; -import { } from "./IGPUBindingResources"; +import { } from "./polyfills/Uniforms"; declare module "@feng3d/render-api" { diff --git a/src/data/IGPUBuffer.ts b/src/data/polyfills/Buffer.ts similarity index 100% rename from src/data/IGPUBuffer.ts rename to src/data/polyfills/Buffer.ts diff --git a/src/data/IGPUBindingResources.ts b/src/data/polyfills/Uniforms.ts similarity index 59% rename from src/data/IGPUBindingResources.ts rename to src/data/polyfills/Uniforms.ts index 29a8c36..baaa981 100644 --- a/src/data/IGPUBindingResources.ts +++ b/src/data/polyfills/Uniforms.ts @@ -1,12 +1,12 @@ import { Sampler } from "@feng3d/render-api"; -import { IGPUExternalTexture } from "./IGPUExternalTexture"; +import { IGPUExternalTexture } from "../IGPUExternalTexture"; declare module "@feng3d/render-api" { export interface UniformTypeMap { - ISampler: Sampler; - ITextureView: TextureView; + Sampler: Sampler; + TextureView: TextureView; IGPUExternalTexture: IGPUExternalTexture; } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 620c38f..e2746df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,6 @@ export * from "./WebGPU"; -export * from "./data/IGPUBindingResources"; -export * from "./data/IGPUBuffer"; +export * from "./data/polyfills/Buffer"; export * from "./data/IGPUCanvasContext"; export * from "./data/IGPUCanvasTexture"; export * from "./data/IGPUCommandEncoder"; @@ -21,6 +20,7 @@ export * from "./data/IGPURenderPipeline"; export * from "./data/IGPUTexture"; export * from "./data/IGPUTextureView"; export * from "./data/IGPUTimestampQuery"; +export * from "./data/polyfills/Uniforms"; export * from "./caches/getIGPUBuffer"; export * from "./types/VertexFormat"; -- Gitee From 0ab860766ac401fc211275899a9b865b701a971d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 12 Mar 2025 20:25:23 +0800 Subject: [PATCH 035/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新了多个文件中的接口和类名,以更好地与 WebGPU 规范保持一致 - 例如:IGPUComputePipeline 改为 GPU_ComputePipeline,IGPUComputeObject 改为 GPUComputeObject 等 - 移除了不必要的接口和文件,简化了模块结构 - 优化了部分代码实现,提高了可读性和性能 --- .../webgpu/atmosphericScatteringSky/index.ts | 4 ++-- examples/src/webgpu/bitonicSort/index.ts | 10 ++++----- examples/src/webgpu/computeBoids/index.ts | 6 ++--- examples/src/webgpu/cornell/radiosity.ts | 6 ++--- examples/src/webgpu/cornell/raytracer.ts | 4 ++-- examples/src/webgpu/cornell/tonemapper.ts | 8 +++---- .../src/webgpu/deferredRendering/index.ts | 8 +++---- examples/src/webgpu/gameOfLife/index.ts | 6 ++--- examples/src/webgpu/imageBlur/index.ts | 6 ++--- examples/src/webgpu/particles/index.ts | 12 +++++----- examples/src/webgpu/timestampQuery/index.ts | 4 ++-- src/WebGPUStep.ts | 8 +++---- src/caches/getGPUBindGroup.ts | 5 ++--- src/caches/getGPUComputePipeline.ts | 6 ++--- src/caches/getGPURenderPassDescriptor.ts | 9 ++++---- src/caches/getGPURenderTimestampQuery.ts | 8 +++---- src/caches/getGPUTexture.ts | 5 ++--- src/caches/getGPUTextureView.ts | 5 ++--- src/caches/getIGPUComputePipeline.ts | 10 ++++----- src/caches/getIGPUTextureSize.ts | 5 ++--- ...PUComputeObject.ts => GPUComputeObject.ts} | 10 ++++----- .../{IGPUComputePass.ts => GPUComputePass.ts} | 12 +++++----- ...guration.ts => GPU_CanvasConfiguration.ts} | 6 ++--- ...putePipeline.ts => GPU_ComputePipeline.ts} | 6 ++--- src/data/IGPUCanvasTexture.ts | 9 -------- src/data/IGPUComputeStage.ts | 2 +- src/data/IGPURenderPass.ts | 4 ++-- src/data/IGPUTextureView.ts | 5 ++--- src/data/IGPUTimestampQuery.ts | 2 +- src/data/IGPUWorkgroups.ts | 2 +- .../CanvasContext.ts} | 4 ++-- .../CommandEncoder.ts} | 4 ++-- src/index.ts | 13 +++++------ src/runs/RunWebGPU.ts | 22 +++++++++---------- 34 files changed, 110 insertions(+), 126 deletions(-) rename src/data/{IGPUComputeObject.ts => GPUComputeObject.ts} (69%) rename src/data/{IGPUComputePass.ts => GPUComputePass.ts} (68%) rename src/data/{GPUCanvasConfiguration.ts => GPU_CanvasConfiguration.ts} (95%) rename src/data/{IGPUComputePipeline.ts => GPU_ComputePipeline.ts} (68%) delete mode 100644 src/data/IGPUCanvasTexture.ts rename src/data/{IGPUCanvasContext.ts => polyfills/CanvasContext.ts} (71%) rename src/data/{IGPUCommandEncoder.ts => polyfills/CommandEncoder.ts} (57%) diff --git a/examples/src/webgpu/atmosphericScatteringSky/index.ts b/examples/src/webgpu/atmosphericScatteringSky/index.ts index 133ae15..9ea4e05 100644 --- a/examples/src/webgpu/atmosphericScatteringSky/index.ts +++ b/examples/src/webgpu/atmosphericScatteringSky/index.ts @@ -3,7 +3,7 @@ import { GUI } from "dat.gui"; import atmosphericScatteringSkyWGSL from "./atmosphericScatteringSky.wgsl"; import { CanvasContext, Texture } from "@feng3d/render-api"; -import { IGPUComputeObject, WebGPU } from "@feng3d/webgpu"; +import { GPUComputeObject, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -44,7 +44,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => skyColor: [1, 1, 1, 1], }; - const computeObject0: IGPUComputeObject = { + const computeObject0: GPUComputeObject = { pipeline: { compute: { code: atmosphericScatteringSkyWGSL } }, diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 5c9dc0c..a1f79b8 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,6 +1,6 @@ import { Buffer, BufferBinding, CommandEncoder, RenderPassDescriptor, Submit, Uniforms } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; +import { getIGPUBuffer, GPUComputePass, GPU_ComputePipeline, GPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats.js"; @@ -103,7 +103,7 @@ async function init( const maxInvocationsX = webgpu.device.limits.maxComputeWorkgroupSizeX; // Handle timestamp query stuff - const querySet: IGPUTimestampQuery = {}; + const querySet: GPUTimestampQuery = {}; watcher.watch(querySet, "elapsedNs", () => { // Calculate new step, sort, and average sort times @@ -291,14 +291,14 @@ async function init( uniforms: computeUniformsBuffer, }; - let computePipeline: IGPUComputePipeline = { + let computePipeline: GPU_ComputePipeline = { compute: { code: NaiveBitonicCompute(settings["Workgroup Size"]), }, }; // Simple pipeline that zeros out an atomic value at group 0 binding 3 - const atomicToZeroComputePipeline: IGPUComputePipeline = { + const atomicToZeroComputePipeline: GPU_ComputePipeline = { compute: { code: atomicToZero, }, @@ -735,7 +735,7 @@ async function init( && highestBlockHeight < settings["Total Elements"] * 2 ) { - const computePassEncoder: IGPUComputePass = { + const computePassEncoder: GPUComputePass = { __type__: "ComputePass", timestampQuery: querySet, computeObjects: [{ diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index 45d8cae..b5be688 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -1,5 +1,5 @@ import { RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; -import { IGPUComputeObject, WebGPU } from "@feng3d/webgpu"; +import { GPUComputeObject, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import spriteWGSL from "./sprite.wgsl"; @@ -50,7 +50,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => particleBuffers[i] = initialParticleData.slice(); } - const computeObject0: IGPUComputeObject = { + const computeObject0: GPUComputeObject = { pipeline: { compute: { code: updateSpritesWGSL } }, @@ -66,7 +66,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => workgroups: { workgroupCountX: Math.ceil(numParticles / 64) }, }; - const computeObject1: IGPUComputeObject = { + const computeObject1: GPUComputeObject = { ...computeObject0, uniforms: { ...computeObject0.uniforms, diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index fe59c07..726e6e9 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -1,5 +1,5 @@ import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; -import { getIGPUBuffer, IGPUComputePipeline } from "@feng3d/webgpu"; +import { getIGPUBuffer, GPU_ComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; import radiosityWGSL from "./radiosity.wgsl"; @@ -37,8 +37,8 @@ export default class Radiosity private readonly common: Common; private readonly scene: Scene; - private readonly radiosityPipeline: IGPUComputePipeline; - private readonly accumulationToLightmapPipeline: IGPUComputePipeline; + private readonly radiosityPipeline: GPU_ComputePipeline; + private readonly accumulationToLightmapPipeline: GPU_ComputePipeline; private readonly bindGroup: Uniforms; private readonly accumulationBuffer: Uint8Array; private readonly uniformBuffer: Uint8Array; diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index 455a955..c37eb47 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -1,5 +1,5 @@ import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; -import { IGPUComputePipeline } from "@feng3d/webgpu"; +import { GPU_ComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; import Radiosity from "./radiosity"; @@ -12,7 +12,7 @@ export default class Raytracer { private readonly common: Common; private readonly framebuffer: Texture; - private readonly material: IGPUComputePipeline; + private readonly material: GPU_ComputePipeline; private readonly bindGroup: Uniforms; private readonly kWorkgroupSizeX = 16; diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index d188e7d..ccc5765 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -1,5 +1,5 @@ -import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; -import { IGPUCanvasTexture, IGPUComputePipeline } from "@feng3d/webgpu"; +import { CanvasTexture, CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; +import { GPU_ComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; import tonemapperWGSL from "./tonemapper.wgsl"; @@ -11,7 +11,7 @@ import tonemapperWGSL from "./tonemapper.wgsl"; export default class Tonemapper { private readonly bindGroup: Uniforms; - private readonly material: IGPUComputePipeline; + private readonly material: GPU_ComputePipeline; private readonly width: number; private readonly height: number; private readonly kWorkgroupSizeX = 16; @@ -20,7 +20,7 @@ export default class Tonemapper constructor( common: Common, input: Texture, - output: IGPUCanvasTexture, + output: CanvasTexture, ) { const inputSize = input.size; diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 0ed4fff..61bcb9c 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -11,7 +11,7 @@ import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; +import { getIGPUBuffer, GPUComputePass, GPU_ComputePipeline, WebGPU } from "@feng3d/webgpu"; const kMaxNumLights = 1024; const lightExtentMin = vec3.fromValues(-50, -30, -50); @@ -231,7 +231,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => lightExtentData.set(lightExtentMax, 4); getIGPUBuffer(lightExtentBuffer).writeBuffers = [{ data: lightExtentData }]; - const lightUpdateComputePipeline: IGPUComputePipeline = { + const lightUpdateComputePipeline: GPU_ComputePipeline = { compute: { code: lightUpdate, }, @@ -322,7 +322,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => return viewProjMatrix as Float32Array; } - const passEncoders: (IGPUComputePass | RenderPass)[] = []; + const passEncoders: (GPUComputePass | RenderPass)[] = []; passEncoders.push({ descriptor: writeGBufferPassDescriptor, renderObjects: [ @@ -353,7 +353,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ] }); - const gBuffersPassEncoders: (IGPUComputePass | RenderPass)[] = passEncoders.concat(); + const gBuffersPassEncoders: (GPUComputePass | RenderPass)[] = passEncoders.concat(); gBuffersPassEncoders.push({ descriptor: textureQuadPassDescriptor, diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index f8b6aa4..4d47484 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -5,7 +5,7 @@ import fragWGSL from "./frag.wgsl"; import vertWGSL from "./vert.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; +import { GPUComputePass, GPU_ComputePipeline, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => function resetGameData() { // compute pipeline - const computePipeline: IGPUComputePipeline = { + const computePipeline: GPU_ComputePipeline = { compute: { code: computeWGSL, constants: { @@ -111,7 +111,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ], }; - const passEncodersArray: (IGPUComputePass | RenderPass)[][] = []; + const passEncodersArray: (GPUComputePass | RenderPass)[][] = []; for (let i = 0; i < 2; i++) { const vertices1: VertexAttributes = {}; diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 58668f7..5dc2187 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -4,7 +4,7 @@ import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgs import blurWGSL from "./blur.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; -import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; +import { getIGPUBuffer, GPUComputePass, GPU_ComputePipeline, WebGPU } from "@feng3d/webgpu"; // Contants from the blur.wgsl shader. const tileDim = 128; @@ -18,7 +18,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); - const blurPipeline: IGPUComputePipeline = { + const blurPipeline: GPU_ComputePipeline = { compute: { code: blurWGSL, }, @@ -151,7 +151,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }], }; - const gpuComputePassEncoder: IGPUComputePass = { __type__: "ComputePass", computeObjects: [] }; + const gpuComputePassEncoder: GPUComputePass = { __type__: "ComputePass", computeObjects: [] }; const submit: Submit = { commandEncoders: [ { diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index f8f5d1f..33744cc 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -8,7 +8,7 @@ import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, IGPUComputePass, IGPUComputePipeline, WebGPU } from "@feng3d/webgpu"; +import { getIGPUBuffer, GPUComputePass, GPU_ComputePipeline, WebGPU } from "@feng3d/webgpu"; const numParticles = 50000; const particlePositionOffset = 0; @@ -145,12 +145,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // probabilities up to the top 1x1 mip level. // //////////////////////////////////////////////////////////////////////////// { - const probabilityMapImportLevelPipeline: IGPUComputePipeline = { + const probabilityMapImportLevelPipeline: GPU_ComputePipeline = { compute: { code: importLevelWGSL, }, }; - const probabilityMapExportLevelPipeline: IGPUComputePipeline = { + const probabilityMapExportLevelPipeline: GPU_ComputePipeline = { compute: { code: probabilityMapWGSL, }, @@ -165,7 +165,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const bufferB = new Uint8Array(textureWidth * textureHeight * 4); getIGPUBuffer(probabilityMapUBOBuffer).writeBuffers = [{ data: new Int32Array([textureWidth]) }]; - const passEncoders: IGPUComputePass[] = []; + const passEncoders: GPUComputePass[] = []; const submit: Submit = { commandEncoders: [ @@ -245,7 +245,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gui.add(simulationParams, k as any); }); - const computePipeline: IGPUComputePipeline = { + const computePipeline: GPU_ComputePipeline = { compute: { code: simulateWGSL, }, @@ -267,7 +267,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const view = mat4.create(); const mvp = mat4.create(); - const passEncoders: (IGPUComputePass | RenderPass)[] = []; + const passEncoders: (GPUComputePass | RenderPass)[] = []; const submit: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 5c6fad6..42bd582 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -1,5 +1,5 @@ import { CanvasContext, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { IGPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; +import { GPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -17,7 +17,7 @@ const init = async (canvas: HTMLCanvasElement) => // NB: Look for 'timestampQueryManager' in this file to locate parts of this // snippets that are related to timestamps. Most of the logic is in // TimestampQueryManager.ts. - const timestampQuery: IGPUTimestampQuery = {}; + const timestampQuery: GPUTimestampQuery = {}; // const timestampQueryManager = new TimestampQueryManager(device); const renderPassDurationCounter = new PerfCounter(); diff --git a/src/WebGPUStep.ts b/src/WebGPUStep.ts index 1e7ed02..a78a38f 100644 --- a/src/WebGPUStep.ts +++ b/src/WebGPUStep.ts @@ -1,7 +1,7 @@ import { CopyBufferToBuffer, CopyTextureToTexture, IRenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, Submit } from "@feng3d/render-api"; -import { IGPUComputeObject } from "./data/IGPUComputeObject"; -import { IGPUComputePass } from "./data/IGPUComputePass"; +import { GPUComputeObject } from "./data/IGPUComputeObject"; +import { GPUComputePass } from "./data/IGPUComputePass"; import { WebGPU } from "./WebGPU"; /** @@ -13,7 +13,7 @@ export class WebGPUStep { private _currentSubmit: Submit; private _currentRenderPassEncoder: RenderPass; - private _currentComputePassEncoder: IGPUComputePass; + private _currentComputePassEncoder: GPUComputePass; readonly webGPU: WebGPU; @@ -47,7 +47,7 @@ export class WebGPUStep this._currentSubmit.commandEncoders[0].passEncoders.push(this._currentComputePassEncoder); } - computeObject(computeObject: IGPUComputeObject) + computeObject(computeObject: GPUComputeObject) { this._currentComputePassEncoder.computeObjects.push(computeObject); } diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 19fb1a2..94f864f 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,8 +1,7 @@ import { anyEmitter } from "@feng3d/event"; -import { BufferBinding, Sampler, TextureView } from "@feng3d/render-api"; +import { BufferBinding, CanvasTexture, Sampler, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; -import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { IGPUExternalTexture } from "../data/IGPUExternalTexture"; import { GPUTextureView_destroy, IGPUSampler_changed } from "../eventnames"; import { IGPUBindGroupDescriptor } from "../internal/IGPUBindGroupDescriptor"; @@ -60,7 +59,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: IGPUBindGroupDescr anyEmitter.once(entry.resource, GPUTextureView_destroy, onResourceChanged); }; - if (((v.resource as TextureView).texture as IGPUCanvasTexture).context) + if (((v.resource as TextureView).texture as CanvasTexture).context) { awaysUpdateFuncs.push(updateResource); } diff --git a/src/caches/getGPUComputePipeline.ts b/src/caches/getGPUComputePipeline.ts index c7a3004..c883c1d 100644 --- a/src/caches/getGPUComputePipeline.ts +++ b/src/caches/getGPUComputePipeline.ts @@ -1,11 +1,11 @@ -import { IGPUComputePipeline } from "../data/IGPUComputePipeline"; +import { GPU_ComputePipeline } from "../data/GPU_ComputePipeline"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; import { getGPUShaderModule } from "./getGPUShaderModule"; import { getIGPUPipelineLayout } from "./getIGPUPipelineLayout"; -export function getGPUComputePipeline(device: GPUDevice, computePipeline: IGPUComputePipeline) +export function getGPUComputePipeline(device: GPUDevice, computePipeline: GPU_ComputePipeline) { - const computePipelineMap: WeakMap = device["_computePipelineMap"] = device["_computePipelineMap"] || new WeakMap(); + const computePipelineMap: WeakMap = device["_computePipelineMap"] = device["_computePipelineMap"] || new WeakMap(); let pipeline = computePipelineMap.get(computePipeline); if (pipeline) return pipeline; diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 8bb47e2..f559248 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,7 +1,6 @@ import { anyEmitter } from "@feng3d/event"; -import { RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; +import { CanvasTexture, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { IGPUTexture_resize } from "../eventnames"; import { IGPUTextureMultisample } from "../internal/IGPUTextureMultisample"; import { NGPURenderPassColorAttachment } from "../internal/internal"; @@ -72,7 +71,7 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render updateView(); // - if ((v.view.texture as IGPUCanvasTexture).context) + if ((v.view.texture as CanvasTexture).context) { _updates.push(updateView); } @@ -87,7 +86,7 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render }; updateResolveTarget(); // - if ((v.resolveTarget?.texture as IGPUCanvasTexture)?.context) + if ((v.resolveTarget?.texture as CanvasTexture)?.context) { _updates.push(updateResolveTarget); } @@ -174,7 +173,7 @@ function setIGPUTextureSize(texture: TextureLike, attachmentSize: { width: numbe { if ("context" in texture) { - texture = texture as IGPUCanvasTexture; + texture = texture as CanvasTexture; const element = document.getElementById(texture.context.canvasId) as HTMLCanvasElement; if (element.width !== attachmentSize.width) element.width = attachmentSize.width; if (element.height !== attachmentSize.height) element.height = attachmentSize.height; diff --git a/src/caches/getGPURenderTimestampQuery.ts b/src/caches/getGPURenderTimestampQuery.ts index 9e084f3..f1bcf8e 100644 --- a/src/caches/getGPURenderTimestampQuery.ts +++ b/src/caches/getGPURenderTimestampQuery.ts @@ -1,10 +1,10 @@ import { anyEmitter } from "@feng3d/event"; import { RenderPass } from "@feng3d/render-api"; -import { IGPUComputePass } from "../data/IGPUComputePass"; -import { IGPUTimestampQuery } from "../data/IGPUTimestampQuery"; +import { GPUComputePass } from "../data/GPUComputePass"; +import { GPUTimestampQuery } from "../data/IGPUTimestampQuery"; import { GPUQueue_submit } from "../eventnames"; -export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: IGPUTimestampQuery): GPURenderTimestampQuery +export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: GPUTimestampQuery): GPURenderTimestampQuery { if (!timestampQuery) return defautGPURenderTimestampQuery; let renderTimestampQuery: GPURenderTimestampQuery = timestampQuery["_GPURenderTimestampQuery"]; @@ -121,7 +121,7 @@ export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: I interface GPURenderTimestampQuery { init: (device: GPUDevice, passDescriptor: GPURenderPassDescriptor | GPUComputePassDescriptor) => void - resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass | IGPUComputePass) => void + resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass | GPUComputePass) => void } const defautGPURenderTimestampQuery = { init: () => { }, resolve: () => { } }; \ No newline at end of file diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 8a66531..e7bd982 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,7 +1,6 @@ import { anyEmitter } from "@feng3d/event"; -import { TextureLike, TextureSize, Texture, TextureDataSource, TextureImageSource, TextureSource } from "@feng3d/render-api"; +import { TextureLike, TextureSize, Texture, TextureDataSource, TextureImageSource, TextureSource, CanvasTexture } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; import { IGPUTextureMultisample } from "../internal/IGPUTextureMultisample"; import { generateMipmap } from "../utils/generate-mipmap"; @@ -21,7 +20,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC let gpuTexture: GPUTexture; if ("context" in textureLike) { - const canvasTexture = textureLike as IGPUCanvasTexture; + const canvasTexture = textureLike as CanvasTexture; const context = getGPUCanvasContext(device, canvasTexture.context); gpuTexture = context.getCurrentTexture(); diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index 9b9753b..36c60e9 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -1,6 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { Texture, TextureView } from "@feng3d/render-api"; -import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; +import { CanvasTexture, Texture, TextureView } from "@feng3d/render-api"; import { GPUTexture_destroy, GPUTextureView_destroy } from "../eventnames"; import { getGPUTexture } from "./getGPUTexture"; @@ -8,7 +7,7 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) { const textureViewMap: WeakMap = device["_textureViewMap"] = device["_textureViewMap"] || new WeakMap(); - if ((view.texture as IGPUCanvasTexture).context) + if ((view.texture as CanvasTexture).context) { const texture = getGPUTexture(device, view.texture); diff --git a/src/caches/getIGPUComputePipeline.ts b/src/caches/getIGPUComputePipeline.ts index 82e8a20..016203b 100644 --- a/src/caches/getIGPUComputePipeline.ts +++ b/src/caches/getIGPUComputePipeline.ts @@ -1,7 +1,7 @@ import { FunctionInfo } from "wgsl_reflect"; +import { GPU_ComputePipeline } from "../data/GPU_ComputePipeline"; +import { GPUComputeStage } from "../data/IGPUComputeStage"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; -import { IGPUComputePipeline } from "../data/IGPUComputePipeline"; -import { IGPUComputeStage } from "../data/IGPUComputeStage"; /** * 从渲染管线描述、渲染通道描述以及完整的顶点属性数据映射获得完整的渲染管线描述以及顶点缓冲区数组。 @@ -10,7 +10,7 @@ import { IGPUComputeStage } from "../data/IGPUComputeStage"; * @param computePipeline 计算管线描述。 * @returns 完整的计算管线描述。 */ -export function getIGPUComputePipeline(computePipeline: IGPUComputePipeline): IGPUComputePipeline +export function getIGPUComputePipeline(computePipeline: GPU_ComputePipeline): GPU_ComputePipeline { let gpuComputePipeline = computePipelineMap.get(computePipeline); if (gpuComputePipeline) return gpuComputePipeline; @@ -27,7 +27,7 @@ export function getIGPUComputePipeline(computePipeline: IGPUComputePipeline): IG return gpuComputePipeline; } -const computePipelineMap = new Map(); +const computePipelineMap = new Map(); /** * 获取计算阶段完整描述。 @@ -35,7 +35,7 @@ const computePipelineMap = new Map(); * @param computeStage 计算阶段描述。 * @returns 计算阶段完整描述。 */ -function getIGPUComputeStage(computeStage: IGPUComputeStage) +function getIGPUComputeStage(computeStage: GPUComputeStage) { const reflect = getWGSLReflectInfo(computeStage.code); let compute: FunctionInfo; diff --git a/src/caches/getIGPUTextureSize.ts b/src/caches/getIGPUTextureSize.ts index 87c924b..2d3b27e 100644 --- a/src/caches/getIGPUTextureSize.ts +++ b/src/caches/getIGPUTextureSize.ts @@ -1,5 +1,4 @@ -import { TextureLike, TextureSize, TextureImageSource } from "@feng3d/render-api"; -import { IGPUCanvasTexture } from "../data/IGPUCanvasTexture"; +import { TextureLike, TextureSize, TextureImageSource, CanvasTexture } from "@feng3d/render-api"; /** * 获取纹理尺寸。 @@ -12,7 +11,7 @@ export function getIGPUTextureLikeSize(texture: TextureLike) if ("context" in texture) { const element = document.getElementById(texture.context.canvasId) as HTMLCanvasElement; - console.assert(!!element, `在 document 上没有找到 canvasId 为 ${(texture as IGPUCanvasTexture).context.canvasId} 的画布。`); + console.assert(!!element, `在 document 上没有找到 canvasId 为 ${(texture as CanvasTexture).context.canvasId} 的画布。`); return [element.width, element.height, 1] as TextureSize; } diff --git a/src/data/IGPUComputeObject.ts b/src/data/GPUComputeObject.ts similarity index 69% rename from src/data/IGPUComputeObject.ts rename to src/data/GPUComputeObject.ts index fdcd54b..269b095 100644 --- a/src/data/IGPUComputeObject.ts +++ b/src/data/GPUComputeObject.ts @@ -1,6 +1,6 @@ import { Uniforms } from "@feng3d/render-api"; -import { IGPUComputePipeline } from "./IGPUComputePipeline"; -import { IGPUWorkgroups } from "./IGPUWorkgroups"; +import { GPU_ComputePipeline } from "./GPU_ComputePipeline"; +import { GPUWorkgroups } from "./IGPUWorkgroups"; /** * GPU计算对象,包含GPU一次计算所有数据。 @@ -11,12 +11,12 @@ import { IGPUWorkgroups } from "./IGPUWorkgroups"; * * {@link GPUComputePassEncoder.dispatchWorkgroups} */ -export interface IGPUComputeObject +export interface GPUComputeObject { /** * 计算管线。 */ - readonly pipeline: IGPUComputePipeline; + readonly pipeline: GPU_ComputePipeline; /** * 绑定资源。包含数值、纹理、采样、外部纹理。 @@ -28,5 +28,5 @@ export interface IGPUComputeObject * * 分配的工作组。 */ - readonly workgroups?: IGPUWorkgroups; + readonly workgroups?: GPUWorkgroups; } diff --git a/src/data/IGPUComputePass.ts b/src/data/GPUComputePass.ts similarity index 68% rename from src/data/IGPUComputePass.ts rename to src/data/GPUComputePass.ts index d8e57f6..107c219 100644 --- a/src/data/IGPUComputePass.ts +++ b/src/data/GPUComputePass.ts @@ -1,5 +1,5 @@ -import { IGPUComputeObject } from "./IGPUComputeObject"; -import { IGPUTimestampQuery } from "./IGPUTimestampQuery"; +import { GPUComputeObject } from "./GPUComputeObject"; +import { GPUTimestampQuery } from "./IGPUTimestampQuery"; /** * GPU计算通道编码器。 @@ -7,7 +7,7 @@ import { IGPUTimestampQuery } from "./IGPUTimestampQuery"; * @see GPUCommandEncoder.beginComputePass * @see GPUComputePassEncoder */ -export interface IGPUComputePass +export interface GPUComputePass { /** * 数据类型。 @@ -17,12 +17,12 @@ export interface IGPUComputePass /** * 计算对象列表。 */ - computeObjects: IGPUComputeObject[]; + computeObjects: GPUComputeObject[]; /** * 查询通道运行消耗时长(单位为纳秒)。 * * 如果需要查询通道运行消耗时长,需要为该属性赋值,如 `pass.timestampQuery = {};`。WebGPU渲染完成后引擎自动填充结果到属性`elapsedNs`。 */ - timestampQuery?: IGPUTimestampQuery; -} + timestampQuery?: GPUTimestampQuery; +} \ No newline at end of file diff --git a/src/data/GPUCanvasConfiguration.ts b/src/data/GPU_CanvasConfiguration.ts similarity index 95% rename from src/data/GPUCanvasConfiguration.ts rename to src/data/GPU_CanvasConfiguration.ts index 64b9a43..1dbdf12 100644 --- a/src/data/GPUCanvasConfiguration.ts +++ b/src/data/GPU_CanvasConfiguration.ts @@ -4,7 +4,7 @@ * @see GPUCanvasConfiguration * @see GPUCanvasContext.configure */ -export interface CanvasConfiguration +export interface GPU_CanvasConfiguration { /** * The usage that textures returned by {@link GPUCanvasContext#getCurrentTexture} will have. @@ -35,7 +35,7 @@ export interface CanvasConfiguration * The formats that views created from textures returned by * {@link GPUCanvasContext#getCurrentTexture} may use. */ - viewFormats?: Iterable; + viewFormats?: GPUTextureFormat[]; /** * The color space that values written into textures returned by * {@link GPUCanvasContext#getCurrentTexture} should be displayed with. @@ -46,4 +46,4 @@ export interface CanvasConfiguration * {@link GPUCanvasContext#getCurrentTexture} are to be displayed. */ toneMapping?: GPUCanvasToneMapping; -} +} \ No newline at end of file diff --git a/src/data/IGPUComputePipeline.ts b/src/data/GPU_ComputePipeline.ts similarity index 68% rename from src/data/IGPUComputePipeline.ts rename to src/data/GPU_ComputePipeline.ts index 4c28001..2d72f44 100644 --- a/src/data/IGPUComputePipeline.ts +++ b/src/data/GPU_ComputePipeline.ts @@ -1,4 +1,4 @@ -import { IGPUComputeStage } from "./IGPUComputeStage"; +import { GPUComputeStage } from "./IGPUComputeStage"; /** * GPU计算管线。 @@ -6,7 +6,7 @@ import { IGPUComputeStage } from "./IGPUComputeStage"; * {@link GPUDevice.createComputePipeline} * {@link GPUComputePipelineDescriptor} */ -export interface IGPUComputePipeline +export interface GPU_ComputePipeline { /** * The initial value of {@link GPUObjectBase#label|GPUObjectBase.label}. @@ -16,5 +16,5 @@ export interface IGPUComputePipeline /** * 计算程序。 */ - readonly compute: IGPUComputeStage; + readonly compute: GPUComputeStage; } \ No newline at end of file diff --git a/src/data/IGPUCanvasTexture.ts b/src/data/IGPUCanvasTexture.ts deleted file mode 100644 index aa25cd9..0000000 --- a/src/data/IGPUCanvasTexture.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { CanvasContext } from "@feng3d/render-api"; - -/** - * 画布纹理,从画布的WebGPU上下文获取纹理 - */ -export interface IGPUCanvasTexture -{ - context: CanvasContext; -} diff --git a/src/data/IGPUComputeStage.ts b/src/data/IGPUComputeStage.ts index 9c5786d..0a3cdad 100644 --- a/src/data/IGPUComputeStage.ts +++ b/src/data/IGPUComputeStage.ts @@ -1,7 +1,7 @@ /** * GPU计算阶段。 */ -export interface IGPUComputeStage +export interface GPUComputeStage { /** * 着色器源码,将由 {@link GPUDevice.createShaderModule} 生成 {@link GPUShaderModule} 。 diff --git a/src/data/IGPURenderPass.ts b/src/data/IGPURenderPass.ts index 0cd2d8a..83e764a 100644 --- a/src/data/IGPURenderPass.ts +++ b/src/data/IGPURenderPass.ts @@ -1,7 +1,7 @@ import { RenderPass, RenderPassDescriptor } from "@feng3d/render-api"; import { } from "./IGPUOcclusionQuery"; import { IGPURenderBundle } from "./IGPURenderBundle"; -import { IGPUTimestampQuery } from "./IGPUTimestampQuery"; +import { GPUTimestampQuery } from "./IGPUTimestampQuery"; declare module "@feng3d/render-api" { @@ -26,7 +26,7 @@ declare module "@feng3d/render-api" * * 如果需要查询通道运行消耗时长,需要为该属性赋值,如 `pass.timestampQuery = {};`。WebGPU渲染完成后引擎自动填充结果到属性`elapsedNs`。 */ - timestampQuery?: IGPUTimestampQuery; + timestampQuery?: GPUTimestampQuery; } export interface RenderPassObjectMap diff --git a/src/data/IGPUTextureView.ts b/src/data/IGPUTextureView.ts index 99b5c1a..603bebc 100644 --- a/src/data/IGPUTextureView.ts +++ b/src/data/IGPUTextureView.ts @@ -1,5 +1,4 @@ -import { TextureLike } from "@feng3d/render-api"; -import { IGPUCanvasTexture } from "./IGPUCanvasTexture"; +import { CanvasTexture, TextureLike } from "@feng3d/render-api"; declare module "@feng3d/render-api" { @@ -8,7 +7,7 @@ declare module "@feng3d/render-api" /** * 画布纹理。 */ - IGPUCanvasTexture: IGPUCanvasTexture; + CanvasTexture: CanvasTexture; } /** diff --git a/src/data/IGPUTimestampQuery.ts b/src/data/IGPUTimestampQuery.ts index e7e8718..3a821f2 100644 --- a/src/data/IGPUTimestampQuery.ts +++ b/src/data/IGPUTimestampQuery.ts @@ -1,7 +1,7 @@ /** * 查询通道运行消耗时长(单位为纳秒)。 */ -export interface IGPUTimestampQuery +export interface GPUTimestampQuery { /** * (单位为纳秒) diff --git a/src/data/IGPUWorkgroups.ts b/src/data/IGPUWorkgroups.ts index 87f340a..5a64b75 100644 --- a/src/data/IGPUWorkgroups.ts +++ b/src/data/IGPUWorkgroups.ts @@ -3,7 +3,7 @@ * * {@link GPUComputePassEncoder.dispatchWorkgroups} */ -export interface IGPUWorkgroups +export interface GPUWorkgroups { /** * X的维度工作组数量。 diff --git a/src/data/IGPUCanvasContext.ts b/src/data/polyfills/CanvasContext.ts similarity index 71% rename from src/data/IGPUCanvasContext.ts rename to src/data/polyfills/CanvasContext.ts index af2ab43..b65c3b8 100644 --- a/src/data/IGPUCanvasContext.ts +++ b/src/data/polyfills/CanvasContext.ts @@ -1,5 +1,5 @@ import { CanvasContext } from "@feng3d/render-api"; -import { CanvasConfiguration } from "./GPUCanvasConfiguration"; +import { GPU_CanvasConfiguration } from "../GPU_CanvasConfiguration"; declare module "@feng3d/render-api" { @@ -12,6 +12,6 @@ declare module "@feng3d/render-api" /** * 画布配置。默认有引擎自动设置。 */ - configuration?: CanvasConfiguration; + configuration?: GPU_CanvasConfiguration; } } diff --git a/src/data/IGPUCommandEncoder.ts b/src/data/polyfills/CommandEncoder.ts similarity index 57% rename from src/data/IGPUCommandEncoder.ts rename to src/data/polyfills/CommandEncoder.ts index 7788dd4..477fb31 100644 --- a/src/data/IGPUCommandEncoder.ts +++ b/src/data/polyfills/CommandEncoder.ts @@ -1,10 +1,10 @@ import { } from "@feng3d/render-api"; -import { IGPUComputePass } from "./IGPUComputePass"; +import { GPUComputePass } from "../GPUComputePass"; declare module "@feng3d/render-api" { export interface PassEncoderMap { - IGPUComputePass: IGPUComputePass; + GPUComputePass: GPUComputePass; } } diff --git a/src/index.ts b/src/index.ts index e2746df..ff5f916 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,8 @@ export * from "./WebGPU"; -export * from "./data/polyfills/Buffer"; -export * from "./data/IGPUCanvasContext"; -export * from "./data/IGPUCanvasTexture"; -export * from "./data/IGPUCommandEncoder"; -export * from "./data/IGPUComputeObject"; -export * from "./data/IGPUComputePass"; -export * from "./data/IGPUComputePipeline"; +export * from "./data/GPU_ComputePipeline"; +export * from "./data/GPUComputeObject"; +export * from "./data/GPUComputePass"; export * from "./data/IGPUOcclusionQuery"; export * from "./data/IGPUPrimitiveState"; export * from "./data/IGPUReadPixels"; @@ -20,6 +16,9 @@ export * from "./data/IGPURenderPipeline"; export * from "./data/IGPUTexture"; export * from "./data/IGPUTextureView"; export * from "./data/IGPUTimestampQuery"; +export * from "./data/polyfills/Buffer"; +export * from "./data/polyfills/CanvasContext"; +export * from "./data/polyfills/CommandEncoder"; export * from "./data/polyfills/Uniforms"; export * from "./caches/getIGPUBuffer"; diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 0420263..14178d1 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, RenderPipeline, PrimitiveState, RenderObject, RenderPass, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport, OcclusionQuery } from "@feng3d/render-api"; +import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -16,12 +16,12 @@ import { IGPUShader } from "../caches/getIGPUPipelineLayout"; import { getIGPUSetBindGroups } from "../caches/getIGPUSetBindGroups"; import { getNGPURenderPipeline } from "../caches/getNGPURenderPipeline"; import { getRealGPUBindGroup } from "../const"; -import { IGPUComputeObject } from "../data/IGPUComputeObject"; -import { IGPUComputePass } from "../data/IGPUComputePass"; -import { IGPUComputePipeline } from "../data/IGPUComputePipeline"; -import { } from "../data/IGPUOcclusionQuery"; +import { GPUComputeObject } from "../data/GPUComputeObject"; +import { GPUComputePass } from "../data/GPUComputePass"; +import { GPU_ComputePipeline } from "../data/GPU_ComputePipeline"; +import { } from "../data/IGPUOcclusionQuery"; import { IGPURenderBundle } from "../data/IGPURenderBundle"; -import { IGPUWorkgroups } from "../data/IGPUWorkgroups"; +import { GPUWorkgroups } from "../data/IGPUWorkgroups"; import { GPUQueue_submit } from "../eventnames"; import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; import { getIGPUSetIndexBuffer } from "../internal/getIGPUSetIndexBuffer"; @@ -143,7 +143,7 @@ export class RunWebGPU * @param commandEncoder 命令编码器。 * @param computePass 计算通道。 */ - protected runComputePass(device: GPUDevice, commandEncoder: GPUCommandEncoder, computePass: IGPUComputePass) + protected runComputePass(device: GPUDevice, commandEncoder: GPUCommandEncoder, computePass: GPUComputePass) { const descriptor: GPUComputePassDescriptor = {}; // 处理时间戳查询 @@ -160,7 +160,7 @@ export class RunWebGPU timestampQuery.resolve(device, commandEncoder, computePass); } - protected runComputeObjects(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObjects: IGPUComputeObject[]) + protected runComputeObjects(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObjects: GPUComputeObject[]) { computeObjects.forEach((computeObject) => { @@ -256,7 +256,7 @@ export class RunWebGPU * @param passEncoder 计算通道编码器。 * @param computeObject 计算对象。 */ - protected runComputeObject(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObject: IGPUComputeObject) + protected runComputeObject(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObject: GPUComputeObject) { const { pipeline: material, uniforms: bindingResources, workgroups } = computeObject; @@ -269,7 +269,7 @@ export class RunWebGPU this.runWorkgroups(passEncoder, workgroups); } - protected runComputePipeline(device: GPUDevice, passEncoder: GPUComputePassEncoder, material: IGPUComputePipeline) + protected runComputePipeline(device: GPUDevice, passEncoder: GPUComputePassEncoder, material: GPU_ComputePipeline) { const gpuComputePipeline = getIGPUComputePipeline(material); @@ -283,7 +283,7 @@ export class RunWebGPU * @param passEncoder 计算通道编码器。 * @param workgroups 计算工作组。 */ - protected runWorkgroups(passEncoder: GPUComputePassEncoder, workgroups?: IGPUWorkgroups) + protected runWorkgroups(passEncoder: GPUComputePassEncoder, workgroups?: GPUWorkgroups) { const { workgroupCountX, workgroupCountY, workgroupCountZ } = workgroups; passEncoder.dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ); -- Gitee From fd8a030bf5f9904ab0af82a949a0c0df028e39f1 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 12 Mar 2025 21:33:46 +0800 Subject: [PATCH 036/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新了多个示例文件中的导入语句和类型引用 - 重命名了一些接口和类,使其与 WebGPU 规范更加一致 - 移除了不必要的接口和类型定义 - 优化了部分代码结构,提高了可读性和可维护性 --- examples/src/webgpu/animometer/index.ts | 4 +- .../webgpu/atmosphericScatteringSky/index.ts | 4 +- examples/src/webgpu/bitonicSort/index.ts | 10 ++-- examples/src/webgpu/computeBoids/index.ts | 8 +-- examples/src/webgpu/cornell/radiosity.ts | 6 +-- examples/src/webgpu/cornell/raytracer.ts | 4 +- examples/src/webgpu/cornell/tonemapper.ts | 4 +- .../src/webgpu/deferredRendering/index.ts | 8 +-- examples/src/webgpu/gameOfLife/index.ts | 6 +-- examples/src/webgpu/imageBlur/index.ts | 6 +-- examples/src/webgpu/particles/index.ts | 12 ++--- examples/src/webgpu/renderBundles/index.ts | 6 +-- .../src/webgpu/textRenderingMsdf/msdfText.ts | 6 +-- examples/src/webgpu/timestampQuery/index.ts | 4 +- src/WebGPU.ts | 6 +-- src/caches/getGPUBindGroup.ts | 54 +++++++++++++++++-- src/caches/getGPUCanvasContext.ts | 4 +- src/caches/getGPUComputePipeline.ts | 25 +++++++-- src/caches/getGPURenderOcclusionQuery.ts | 2 +- src/caches/getGPURenderTimestampQuery.ts | 8 +-- src/caches/getIGPUComputePipeline.ts | 47 ++-------------- src/caches/getIGPUSetBindGroups.ts | 23 +++++++- src/caches/getNGPURenderPipeline.ts | 4 +- ...onfiguration.ts => CanvasConfiguration.ts} | 4 +- .../{GPUComputeObject.ts => ComputeObject.ts} | 12 ++--- .../{GPUComputePass.ts => ComputePass.ts} | 12 ++--- ..._ComputePipeline.ts => ComputePipeline.ts} | 8 +-- .../{IGPUComputeStage.ts => ComputeStage.ts} | 4 +- src/data/IGPUReadPixels.ts | 12 ----- src/data/IGPUStencilFaceState.ts | 35 ------------ ...ultisampleState.ts => MultisampleState.ts} | 6 ++- .../{IGPURenderBundle.ts => RenderBundle.ts} | 6 +-- ...GPUTimestampQuery.ts => TimestampQuery.ts} | 2 +- ...IGPUExternalTexture.ts => VideoTexture.ts} | 10 ++-- src/data/{IGPUWorkgroups.ts => Workgroups.ts} | 4 +- src/data/polyfills/CanvasContext.ts | 6 +-- src/data/polyfills/CommandEncoder.ts | 4 +- .../OcclusionQuery.ts} | 0 .../PrimitiveState.ts} | 0 src/data/polyfills/ReadPixels.ts | 12 +++++ .../RenderObject.ts} | 2 +- .../RenderPass.ts} | 10 ++-- .../RenderPassColorAttachment.ts} | 0 .../RenderPassDepthStencilAttachment.ts} | 0 .../RenderPassDescriptor.ts} | 0 .../RenderPipeline.ts} | 4 +- .../{IGPUTexture.ts => polyfills/Texture.ts} | 0 .../TextureView.ts} | 0 src/data/polyfills/Uniforms.ts | 4 +- src/index.ts | 33 ++++++------ src/internal/IGPUBindGroupDescriptor.ts | 47 ---------------- src/internal/IGPUSetBindGroup.ts | 21 -------- src/runs/RunWebGPU.ts | 30 ++++++----- 53 files changed, 248 insertions(+), 301 deletions(-) rename src/data/{GPU_CanvasConfiguration.ts => CanvasConfiguration.ts} (96%) rename src/data/{GPUComputeObject.ts => ComputeObject.ts} (62%) rename src/data/{GPUComputePass.ts => ComputePass.ts} (65%) rename src/data/{GPU_ComputePipeline.ts => ComputePipeline.ts} (62%) rename src/data/{IGPUComputeStage.ts => ComputeStage.ts} (96%) delete mode 100644 src/data/IGPUReadPixels.ts delete mode 100644 src/data/IGPUStencilFaceState.ts rename src/data/{IGPUMultisampleState.ts => MultisampleState.ts} (80%) rename src/data/{IGPURenderBundle.ts => RenderBundle.ts} (89%) rename src/data/{IGPUTimestampQuery.ts => TimestampQuery.ts} (86%) rename src/data/{IGPUExternalTexture.ts => VideoTexture.ts} (82%) rename src/data/{IGPUWorkgroups.ts => Workgroups.ts} (85%) rename src/data/{IGPUOcclusionQuery.ts => polyfills/OcclusionQuery.ts} (100%) rename src/data/{IGPUPrimitiveState.ts => polyfills/PrimitiveState.ts} (100%) create mode 100644 src/data/polyfills/ReadPixels.ts rename src/data/{IGPURenderObject.ts => polyfills/RenderObject.ts} (97%) rename src/data/{IGPURenderPass.ts => polyfills/RenderPass.ts} (79%) rename src/data/{IGPURenderPassColorAttachment.ts => polyfills/RenderPassColorAttachment.ts} (100%) rename src/data/{IGPURenderPassDepthStencilAttachment.ts => polyfills/RenderPassDepthStencilAttachment.ts} (100%) rename src/data/{IGPURenderPassDescriptor.ts => polyfills/RenderPassDescriptor.ts} (100%) rename src/data/{IGPURenderPipeline.ts => polyfills/RenderPipeline.ts} (97%) rename src/data/{IGPUTexture.ts => polyfills/Texture.ts} (100%) rename src/data/{IGPUTextureView.ts => polyfills/TextureView.ts} (100%) delete mode 100644 src/internal/IGPUBindGroupDescriptor.ts delete mode 100644 src/internal/IGPUSetBindGroup.ts diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index c628923..0fa6136 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -3,7 +3,7 @@ import { GUI } from "dat.gui"; import animometerWGSL from "./animometer.wgsl"; import { RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; -import { IGPURenderBundle, WebGPU } from "@feng3d/webgpu"; +import { RenderBundle, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -122,7 +122,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => let startTime: number; const uniformTime = new Float32Array([0]); - const renderBundleObject: IGPURenderBundle = { + const renderBundleObject: RenderBundle = { __type__: "RenderBundle", renderObjects }; diff --git a/examples/src/webgpu/atmosphericScatteringSky/index.ts b/examples/src/webgpu/atmosphericScatteringSky/index.ts index 9ea4e05..42932df 100644 --- a/examples/src/webgpu/atmosphericScatteringSky/index.ts +++ b/examples/src/webgpu/atmosphericScatteringSky/index.ts @@ -3,7 +3,7 @@ import { GUI } from "dat.gui"; import atmosphericScatteringSkyWGSL from "./atmosphericScatteringSky.wgsl"; import { CanvasContext, Texture } from "@feng3d/render-api"; -import { GPUComputeObject, WebGPU } from "@feng3d/webgpu"; +import { ComputeObject, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -44,7 +44,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => skyColor: [1, 1, 1, 1], }; - const computeObject0: GPUComputeObject = { + const computeObject0: ComputeObject = { pipeline: { compute: { code: atmosphericScatteringSkyWGSL } }, diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index a1f79b8..fcbf677 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,6 +1,6 @@ import { Buffer, BufferBinding, CommandEncoder, RenderPassDescriptor, Submit, Uniforms } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { getIGPUBuffer, GPUComputePass, GPU_ComputePipeline, GPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; +import { ComputePipeline, getIGPUBuffer, ComputePass, TimestampQuery, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats.js"; @@ -103,7 +103,7 @@ async function init( const maxInvocationsX = webgpu.device.limits.maxComputeWorkgroupSizeX; // Handle timestamp query stuff - const querySet: GPUTimestampQuery = {}; + const querySet: TimestampQuery = {}; watcher.watch(querySet, "elapsedNs", () => { // Calculate new step, sort, and average sort times @@ -291,14 +291,14 @@ async function init( uniforms: computeUniformsBuffer, }; - let computePipeline: GPU_ComputePipeline = { + let computePipeline: ComputePipeline = { compute: { code: NaiveBitonicCompute(settings["Workgroup Size"]), }, }; // Simple pipeline that zeros out an atomic value at group 0 binding 3 - const atomicToZeroComputePipeline: GPU_ComputePipeline = { + const atomicToZeroComputePipeline: ComputePipeline = { compute: { code: atomicToZero, }, @@ -735,7 +735,7 @@ async function init( && highestBlockHeight < settings["Total Elements"] * 2 ) { - const computePassEncoder: GPUComputePass = { + const computePassEncoder: ComputePass = { __type__: "ComputePass", timestampQuery: querySet, computeObjects: [{ diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index b5be688..65c4ca0 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -1,5 +1,5 @@ -import { RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; -import { GPUComputeObject, WebGPU } from "@feng3d/webgpu"; +import { RenderObject, RenderPassDescriptor, Submit } from "@feng3d/render-api"; +import { ComputeObject, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import spriteWGSL from "./sprite.wgsl"; @@ -50,7 +50,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => particleBuffers[i] = initialParticleData.slice(); } - const computeObject0: GPUComputeObject = { + const computeObject0: ComputeObject = { pipeline: { compute: { code: updateSpritesWGSL } }, @@ -66,7 +66,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => workgroups: { workgroupCountX: Math.ceil(numParticles / 64) }, }; - const computeObject1: GPUComputeObject = { + const computeObject1: ComputeObject = { ...computeObject0, uniforms: { ...computeObject0.uniforms, diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index 726e6e9..1bbf97c 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -1,5 +1,5 @@ import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; -import { getIGPUBuffer, GPU_ComputePipeline } from "@feng3d/webgpu"; +import { ComputePipeline, getIGPUBuffer } from "@feng3d/webgpu"; import Common from "./common"; import radiosityWGSL from "./radiosity.wgsl"; @@ -37,8 +37,8 @@ export default class Radiosity private readonly common: Common; private readonly scene: Scene; - private readonly radiosityPipeline: GPU_ComputePipeline; - private readonly accumulationToLightmapPipeline: GPU_ComputePipeline; + private readonly radiosityPipeline: ComputePipeline; + private readonly accumulationToLightmapPipeline: ComputePipeline; private readonly bindGroup: Uniforms; private readonly accumulationBuffer: Uint8Array; private readonly uniformBuffer: Uint8Array; diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index c37eb47..c32d73e 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -1,5 +1,5 @@ import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; -import { GPU_ComputePipeline } from "@feng3d/webgpu"; +import { ComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; import Radiosity from "./radiosity"; @@ -12,7 +12,7 @@ export default class Raytracer { private readonly common: Common; private readonly framebuffer: Texture; - private readonly material: GPU_ComputePipeline; + private readonly material: ComputePipeline; private readonly bindGroup: Uniforms; private readonly kWorkgroupSizeX = 16; diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index ccc5765..2658e78 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -1,5 +1,5 @@ import { CanvasTexture, CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; -import { GPU_ComputePipeline } from "@feng3d/webgpu"; +import { ComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; import tonemapperWGSL from "./tonemapper.wgsl"; @@ -11,7 +11,7 @@ import tonemapperWGSL from "./tonemapper.wgsl"; export default class Tonemapper { private readonly bindGroup: Uniforms; - private readonly material: GPU_ComputePipeline; + private readonly material: ComputePipeline; private readonly width: number; private readonly height: number; private readonly kWorkgroupSizeX = 16; diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 61bcb9c..e2f44d5 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -11,7 +11,7 @@ import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, GPUComputePass, GPU_ComputePipeline, WebGPU } from "@feng3d/webgpu"; +import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU } from "@feng3d/webgpu"; const kMaxNumLights = 1024; const lightExtentMin = vec3.fromValues(-50, -30, -50); @@ -231,7 +231,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => lightExtentData.set(lightExtentMax, 4); getIGPUBuffer(lightExtentBuffer).writeBuffers = [{ data: lightExtentData }]; - const lightUpdateComputePipeline: GPU_ComputePipeline = { + const lightUpdateComputePipeline: ComputePipeline = { compute: { code: lightUpdate, }, @@ -322,7 +322,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => return viewProjMatrix as Float32Array; } - const passEncoders: (GPUComputePass | RenderPass)[] = []; + const passEncoders: (ComputePass | RenderPass)[] = []; passEncoders.push({ descriptor: writeGBufferPassDescriptor, renderObjects: [ @@ -353,7 +353,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ] }); - const gBuffersPassEncoders: (GPUComputePass | RenderPass)[] = passEncoders.concat(); + const gBuffersPassEncoders: (ComputePass | RenderPass)[] = passEncoders.concat(); gBuffersPassEncoders.push({ descriptor: textureQuadPassDescriptor, diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 4d47484..50a2826 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -5,7 +5,7 @@ import fragWGSL from "./frag.wgsl"; import vertWGSL from "./vert.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { GPUComputePass, GPU_ComputePipeline, WebGPU } from "@feng3d/webgpu"; +import { ComputePipeline, ComputePass, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => function resetGameData() { // compute pipeline - const computePipeline: GPU_ComputePipeline = { + const computePipeline: ComputePipeline = { compute: { code: computeWGSL, constants: { @@ -111,7 +111,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ], }; - const passEncodersArray: (GPUComputePass | RenderPass)[][] = []; + const passEncodersArray: (ComputePass | RenderPass)[][] = []; for (let i = 0; i < 2; i++) { const vertices1: VertexAttributes = {}; diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 5dc2187..410af05 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -4,7 +4,7 @@ import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgs import blurWGSL from "./blur.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; -import { getIGPUBuffer, GPUComputePass, GPU_ComputePipeline, WebGPU } from "@feng3d/webgpu"; +import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU } from "@feng3d/webgpu"; // Contants from the blur.wgsl shader. const tileDim = 128; @@ -18,7 +18,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const webgpu = await new WebGPU().init(); - const blurPipeline: GPU_ComputePipeline = { + const blurPipeline: ComputePipeline = { compute: { code: blurWGSL, }, @@ -151,7 +151,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }], }; - const gpuComputePassEncoder: GPUComputePass = { __type__: "ComputePass", computeObjects: [] }; + const gpuComputePassEncoder: ComputePass = { __type__: "ComputePass", computeObjects: [] }; const submit: Submit = { commandEncoders: [ { diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index 33744cc..9307b26 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -8,7 +8,7 @@ import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, GPUComputePass, GPU_ComputePipeline, WebGPU } from "@feng3d/webgpu"; +import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU } from "@feng3d/webgpu"; const numParticles = 50000; const particlePositionOffset = 0; @@ -145,12 +145,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // probabilities up to the top 1x1 mip level. // //////////////////////////////////////////////////////////////////////////// { - const probabilityMapImportLevelPipeline: GPU_ComputePipeline = { + const probabilityMapImportLevelPipeline: ComputePipeline = { compute: { code: importLevelWGSL, }, }; - const probabilityMapExportLevelPipeline: GPU_ComputePipeline = { + const probabilityMapExportLevelPipeline: ComputePipeline = { compute: { code: probabilityMapWGSL, }, @@ -165,7 +165,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const bufferB = new Uint8Array(textureWidth * textureHeight * 4); getIGPUBuffer(probabilityMapUBOBuffer).writeBuffers = [{ data: new Int32Array([textureWidth]) }]; - const passEncoders: GPUComputePass[] = []; + const passEncoders: ComputePass[] = []; const submit: Submit = { commandEncoders: [ @@ -245,7 +245,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gui.add(simulationParams, k as any); }); - const computePipeline: GPU_ComputePipeline = { + const computePipeline: ComputePipeline = { compute: { code: simulateWGSL, }, @@ -267,7 +267,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const view = mat4.create(); const mvp = mat4.create(); - const passEncoders: (GPUComputePass | RenderPass)[] = []; + const passEncoders: (ComputePass | RenderPass)[] = []; const submit: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index efa346f..ad1bb1d 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,5 +1,5 @@ import { CanvasContext, IRenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { IGPURenderBundle, WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; +import { RenderBundle, WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats-js"; @@ -288,14 +288,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => // textures used. Cases where the executed commands differ from frame-to-frame, // such as when using frustrum or occlusion culling, will not benefit from // using render bundles as much. - let renderBundle: IGPURenderBundle = { + let renderBundle: RenderBundle = { __type__: "RenderBundle", renderObjects: [], }; renderBundle.renderObjects = renderScene(); function updateRenderBundle() { - const renderBundleEncoder: IGPURenderBundle = { + const renderBundleEncoder: RenderBundle = { __type__: "RenderBundle", renderObjects: [], }; diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index 2b139ed..d467dcb 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -3,7 +3,7 @@ import { mat4, Mat4 } from "wgpu-matrix"; import msdfTextWGSL from "./msdfText.wgsl"; import { IRenderPassObject, RenderPipeline, Sampler, Texture, Uniforms } from "@feng3d/render-api"; -import { getIGPUBuffer, IGPURenderBundle } from "@feng3d/webgpu"; +import { getIGPUBuffer, RenderBundle } from "@feng3d/webgpu"; // The kerning map stores a spare map of character ID pairs with an associated // X offset that should be applied to the character spacing when the second @@ -87,7 +87,7 @@ export class MsdfText private bufferArrayDirty = true; constructor( - private renderBundle: IGPURenderBundle, + private renderBundle: RenderBundle, public measurements: MsdfTextMeasurements, public font: MsdfFont, public textBuffer: Float32Array @@ -335,7 +335,7 @@ export class MsdfTextRenderer text: { bufferView: textBuffer }, }; - const renderBundle: IGPURenderBundle = { + const renderBundle: RenderBundle = { __type__: "RenderBundle", renderObjects: [ { diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 42bd582..9b70a63 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -1,5 +1,5 @@ import { CanvasContext, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { GPUTimestampQuery, WebGPU } from "@feng3d/webgpu"; +import { TimestampQuery, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -17,7 +17,7 @@ const init = async (canvas: HTMLCanvasElement) => // NB: Look for 'timestampQueryManager' in this file to locate parts of this // snippets that are related to timestamps. Most of the logic is in // TimestampQueryManager.ts. - const timestampQuery: GPUTimestampQuery = {}; + const timestampQuery: TimestampQuery = {}; // const timestampQueryManager = new TimestampQueryManager(device); const renderPassDurationCounter = new PerfCounter(); diff --git a/src/WebGPU.ts b/src/WebGPU.ts index a4903ab..9b1634a 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,8 +1,8 @@ -import { Buffer, TextureLike, Submit } from "@feng3d/render-api"; +import { Buffer, ReadPixels, Submit, TextureLike } from "@feng3d/render-api"; import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUTexture } from "./caches/getGPUTexture"; import { getIGPUTextureLikeSize } from "./caches/getIGPUTextureSize"; -import { IGPUReadPixels } from "./data/IGPUReadPixels"; +import "./data/polyfills/ReadPixels"; import { RunWebGPU } from "./runs/RunWebGPU"; import { RunWebGPUCommandCache } from "./runs/RunWebGPUCommandCache"; import { copyDepthTexture } from "./utils/copyDepthTexture"; @@ -127,7 +127,7 @@ export class WebGPU * * @returns 读取到的数据。 */ - async readPixels(gpuReadPixels: IGPUReadPixels) + async readPixels(gpuReadPixels: ReadPixels) { const gpuTexture = getGPUTexture(this.device, gpuReadPixels.texture, false); diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 94f864f..8781bf6 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,10 +1,9 @@ import { anyEmitter } from "@feng3d/event"; -import { BufferBinding, CanvasTexture, Sampler, TextureView } from "@feng3d/render-api"; +import { BufferBinding, CanvasTexture, Sampler, TextureView, UniformType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; -import { IGPUExternalTexture } from "../data/IGPUExternalTexture"; +import { VideoTexture } from "../data/VideoTexture"; import { GPUTextureView_destroy, IGPUSampler_changed } from "../eventnames"; -import { IGPUBindGroupDescriptor } from "../internal/IGPUBindGroupDescriptor"; import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; import { getGPUBufferBinding } from "./getGPUBufferBinding"; import { getGPUSampler } from "./getGPUSampler"; @@ -64,11 +63,11 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: IGPUBindGroupDescr awaysUpdateFuncs.push(updateResource); } } - else if ((v.resource as IGPUExternalTexture).source) + else if ((v.resource as VideoTexture).source) { updateResource = () => { - entry.resource = device.importExternalTexture(v.resource as IGPUExternalTexture); + entry.resource = device.importExternalTexture(v.resource as VideoTexture); }; awaysUpdateFuncs.push(updateResource); @@ -123,3 +122,48 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: IGPUBindGroupDescr return gBindGroup; } + +/** + * GPU 绑定组。 + * + * @see GPUBindGroupDescriptor + * @see GPUDevice.createBindGroup + */ +export interface IGPUBindGroupDescriptor +{ + /** + * The initial value of {@link GPUObjectBase#label|GPUObjectBase.label}. + */ + label?: string; + + /** + * The {@link IGPUBindGroupLayoutDescriptor} the entries of this bind group will conform to. + */ + layout: GPUBindGroupLayoutDescriptor; + + /** + * A list of entries describing the resources to expose to the shader for each binding + * described by the {@link GPUBindGroupDescriptor#layout}. + * + * {@link GPUBindGroupEntry} + */ + entries: IGPUBindGroupEntry[]; +} + +/** + * 绑定资源入口,指定资源绑定的位置。 + * + * @see GPUBindGroupEntry + */ +export interface IGPUBindGroupEntry +{ + binding: GPUIndex32; + + /** + * The resource to bind, which may be a {@link GPUSampler}, {@link GPUTextureView}, + * {@link GPUExternalTexture}, or {@link GPUBufferBinding}. + */ + resource: BindingResource; +} + +export type BindingResource = Sampler | TextureView | VideoTexture | UniformType; diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index c23e1d1..3637463 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -1,6 +1,6 @@ -import { watcher } from "@feng3d/watcher"; -import "../data/IGPUCanvasContext"; import { CanvasContext } from "@feng3d/render-api"; +import { watcher } from "@feng3d/watcher"; +import "../data/polyfills/CanvasContext"; export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) { diff --git a/src/caches/getGPUComputePipeline.ts b/src/caches/getGPUComputePipeline.ts index c883c1d..dd8515b 100644 --- a/src/caches/getGPUComputePipeline.ts +++ b/src/caches/getGPUComputePipeline.ts @@ -1,15 +1,34 @@ -import { GPU_ComputePipeline } from "../data/GPU_ComputePipeline"; +import { UnReadonly } from "@feng3d/render-api"; +import { ComputePipeline } from "../data/ComputePipeline"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; import { getGPUShaderModule } from "./getGPUShaderModule"; import { getIGPUPipelineLayout } from "./getIGPUPipelineLayout"; +import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; +import { ComputeStage } from "../data/ComputeStage"; -export function getGPUComputePipeline(device: GPUDevice, computePipeline: GPU_ComputePipeline) +export function getGPUComputePipeline(device: GPUDevice, computePipeline: ComputePipeline) { - const computePipelineMap: WeakMap = device["_computePipelineMap"] = device["_computePipelineMap"] || new WeakMap(); + const computePipelineMap: WeakMap = device["_computePipelineMap"] = device["_computePipelineMap"] || new WeakMap(); let pipeline = computePipelineMap.get(computePipeline); if (pipeline) return pipeline; + const computeStage = computePipeline.compute; + + const reflect = getWGSLReflectInfo(computeStage.code); + if (!computeStage.entryPoint) + { + const compute = reflect.entry.compute[0]; + console.assert(!!compute, `WGSL着色器 ${computeStage.code} 中不存在计算入口点。`); + (computeStage as UnReadonly).entryPoint = compute.name; + } + else + { + // 验证着色器中包含指定片段入口函数。 + const compute = reflect.entry.compute.filter((v) => v.name === computeStage.entryPoint)[0]; + console.assert(!!compute, `WGSL着色器 ${computeStage.code} 中不存在指定的计算入口点 ${computeStage.entryPoint}`); + } + // 从GPU管线中获取管线布局。 const gpuPipelineLayout = getIGPUPipelineLayout({ compute: computePipeline.compute.code }); diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index 37023d9..154befc 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -1,7 +1,7 @@ import { anyEmitter } from "@feng3d/event"; import { IRenderPassObject, OcclusionQuery, RenderPass } from "@feng3d/render-api"; -import { } from "../data/IGPUOcclusionQuery"; +import { } from "../data/polyfills/OcclusionQuery"; import { GPUQueue_submit } from "../eventnames"; export function getGPURenderOcclusionQuery(renderObjects?: readonly IRenderPassObject[]): GPURenderOcclusionQuery diff --git a/src/caches/getGPURenderTimestampQuery.ts b/src/caches/getGPURenderTimestampQuery.ts index f1bcf8e..3584401 100644 --- a/src/caches/getGPURenderTimestampQuery.ts +++ b/src/caches/getGPURenderTimestampQuery.ts @@ -1,10 +1,10 @@ import { anyEmitter } from "@feng3d/event"; import { RenderPass } from "@feng3d/render-api"; -import { GPUComputePass } from "../data/GPUComputePass"; -import { GPUTimestampQuery } from "../data/IGPUTimestampQuery"; +import { ComputePass } from "../data/ComputePass"; +import { TimestampQuery } from "../data/TimestampQuery"; import { GPUQueue_submit } from "../eventnames"; -export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: GPUTimestampQuery): GPURenderTimestampQuery +export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: TimestampQuery): GPURenderTimestampQuery { if (!timestampQuery) return defautGPURenderTimestampQuery; let renderTimestampQuery: GPURenderTimestampQuery = timestampQuery["_GPURenderTimestampQuery"]; @@ -121,7 +121,7 @@ export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: G interface GPURenderTimestampQuery { init: (device: GPUDevice, passDescriptor: GPURenderPassDescriptor | GPUComputePassDescriptor) => void - resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass | GPUComputePass) => void + resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass | ComputePass) => void } const defautGPURenderTimestampQuery = { init: () => { }, resolve: () => { } }; \ No newline at end of file diff --git a/src/caches/getIGPUComputePipeline.ts b/src/caches/getIGPUComputePipeline.ts index 016203b..9e4faad 100644 --- a/src/caches/getIGPUComputePipeline.ts +++ b/src/caches/getIGPUComputePipeline.ts @@ -1,6 +1,6 @@ -import { FunctionInfo } from "wgsl_reflect"; -import { GPU_ComputePipeline } from "../data/GPU_ComputePipeline"; -import { GPUComputeStage } from "../data/IGPUComputeStage"; +import { UnReadonly } from "@feng3d/render-api"; +import { ComputePipeline } from "../data/ComputePipeline"; +import { ComputeStage } from "../data/ComputeStage"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; /** @@ -10,47 +10,10 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param computePipeline 计算管线描述。 * @returns 完整的计算管线描述。 */ -export function getIGPUComputePipeline(computePipeline: GPU_ComputePipeline): GPU_ComputePipeline +export function getIGPUComputePipeline(computePipeline: ComputePipeline): ComputePipeline { - let gpuComputePipeline = computePipelineMap.get(computePipeline); - if (gpuComputePipeline) return gpuComputePipeline; - const gpuComputeStage = getIGPUComputeStage(computePipeline.compute); - gpuComputePipeline = { - ...computePipeline, - compute: gpuComputeStage, - }; - - computePipelineMap.set(computePipeline, gpuComputePipeline); - - return gpuComputePipeline; + return computePipeline; } -const computePipelineMap = new Map(); - -/** -* 获取计算阶段完整描述。 -* -* @param computeStage 计算阶段描述。 -* @returns 计算阶段完整描述。 -*/ -function getIGPUComputeStage(computeStage: GPUComputeStage) -{ - const reflect = getWGSLReflectInfo(computeStage.code); - let compute: FunctionInfo; - if (!computeStage.entryPoint) - { - compute = reflect.entry.compute[0]; - console.assert(!!compute, `WGSL着色器 ${computeStage.code} 中不存在计算入口点。`); - (computeStage as any).entryPoint = compute.name; - } - else - { - // 验证着色器中包含指定片段入口函数。 - compute = reflect.entry.compute.filter((v) => v.name === computeStage.entryPoint)[0]; - console.assert(!!compute, `WGSL着色器 ${computeStage.code} 中不存在指定的计算入口点 ${computeStage.entryPoint}`); - } - - return computeStage; -} diff --git a/src/caches/getIGPUSetBindGroups.ts b/src/caches/getIGPUSetBindGroups.ts index 82d0ca8..59d8132 100644 --- a/src/caches/getIGPUSetBindGroups.ts +++ b/src/caches/getIGPUSetBindGroups.ts @@ -2,13 +2,12 @@ import { watcher } from "@feng3d/watcher"; import { BufferBinding, Uniforms } from "@feng3d/render-api"; import { getIGPUPipelineLayout, getIGPUShaderKey, IGPUShader } from "../caches/getIGPUPipelineLayout"; -import { IGPUBindGroupEntry } from "../internal/IGPUBindGroupDescriptor"; import { IGPUBindGroupLayoutDescriptor } from "../internal/IGPUPipelineLayoutDescriptor"; -import { IGPUSetBindGroup } from "../internal/IGPUSetBindGroup"; import { ChainMap } from "../utils/ChainMap"; import { getBufferBindingInfo, IBufferBindingInfo } from "../utils/getBufferBindingInfo"; import { updateBufferBinding } from "../utils/updateBufferBinding"; import { getIGPUBuffer } from "./getIGPUBuffer"; +import { IGPUBindGroupDescriptor, IGPUBindGroupEntry } from "./getGPUBindGroup"; export function getIGPUSetBindGroups(shader: IGPUShader, bindingResources: Uniforms) { @@ -85,3 +84,23 @@ function getIGPUSetBindGroup(bindGroupLayout: IGPUBindGroupLayoutDescriptor, bin return setBindGroup; } + +/** + * GPU渲染时使用的绑定组。 + * + * {@link GPUBindingCommandsMixin.setBindGroup} + */ +interface IGPUSetBindGroup +{ + /** + * GPU绑定组。 + * + * Bind group to use for subsequent render or compute commands. + */ + bindGroup: IGPUBindGroupDescriptor; + + /** + * Array containing buffer offsets in bytes for each entry in `bindGroup` marked as {@link GPUBindGroupLayoutEntry#buffer}.{@link GPUBufferBindingLayout#hasDynamicOffset}.--> + */ + dynamicOffsets?: number[]; +} diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index ca8de5b..aa055d6 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -3,7 +3,7 @@ import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; import { gPartial } from "@feng3d/polyfill"; -import { IGPUMultisampleState } from "../data/IGPUMultisampleState"; +import { MultisampleState } from "../data/MultisampleState"; import { getIGPUSetIndexBuffer } from "../internal/getIGPUSetIndexBuffer"; import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; import { NGPUFragmentState } from "../internal/NGPUFragmentState"; @@ -157,7 +157,7 @@ function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndex return gpuPrimitive; } -function getGPUMultisampleState(multisampleState?: IGPUMultisampleState, sampleCount?: 4) +function getGPUMultisampleState(multisampleState?: MultisampleState, sampleCount?: 4) { if (!sampleCount) return undefined; diff --git a/src/data/GPU_CanvasConfiguration.ts b/src/data/CanvasConfiguration.ts similarity index 96% rename from src/data/GPU_CanvasConfiguration.ts rename to src/data/CanvasConfiguration.ts index 1dbdf12..14885a2 100644 --- a/src/data/GPU_CanvasConfiguration.ts +++ b/src/data/CanvasConfiguration.ts @@ -1,10 +1,10 @@ /** - * GPU画布配置。 + * WebGPU画布配置。 * * @see GPUCanvasConfiguration * @see GPUCanvasContext.configure */ -export interface GPU_CanvasConfiguration +export interface CanvasConfiguration { /** * The usage that textures returned by {@link GPUCanvasContext#getCurrentTexture} will have. diff --git a/src/data/GPUComputeObject.ts b/src/data/ComputeObject.ts similarity index 62% rename from src/data/GPUComputeObject.ts rename to src/data/ComputeObject.ts index 269b095..b87dfc8 100644 --- a/src/data/GPUComputeObject.ts +++ b/src/data/ComputeObject.ts @@ -1,9 +1,9 @@ import { Uniforms } from "@feng3d/render-api"; -import { GPU_ComputePipeline } from "./GPU_ComputePipeline"; -import { GPUWorkgroups } from "./IGPUWorkgroups"; +import { ComputePipeline } from "./ComputePipeline"; +import { Workgroups } from "./Workgroups"; /** - * GPU计算对象,包含GPU一次计算所有数据。 + * WebGPU计算对象,包含GPU一次计算所有数据。 * * {@link GPUComputePassEncoder.setPipeline} * @@ -11,12 +11,12 @@ import { GPUWorkgroups } from "./IGPUWorkgroups"; * * {@link GPUComputePassEncoder.dispatchWorkgroups} */ -export interface GPUComputeObject +export interface ComputeObject { /** * 计算管线。 */ - readonly pipeline: GPU_ComputePipeline; + readonly pipeline: ComputePipeline; /** * 绑定资源。包含数值、纹理、采样、外部纹理。 @@ -28,5 +28,5 @@ export interface GPUComputeObject * * 分配的工作组。 */ - readonly workgroups?: GPUWorkgroups; + readonly workgroups?: Workgroups; } diff --git a/src/data/GPUComputePass.ts b/src/data/ComputePass.ts similarity index 65% rename from src/data/GPUComputePass.ts rename to src/data/ComputePass.ts index 107c219..c992269 100644 --- a/src/data/GPUComputePass.ts +++ b/src/data/ComputePass.ts @@ -1,13 +1,13 @@ -import { GPUComputeObject } from "./GPUComputeObject"; -import { GPUTimestampQuery } from "./IGPUTimestampQuery"; +import { ComputeObject } from "./ComputeObject"; +import { TimestampQuery } from "./TimestampQuery"; /** - * GPU计算通道编码器。 + * WebGPU计算通道编码器。 * * @see GPUCommandEncoder.beginComputePass * @see GPUComputePassEncoder */ -export interface GPUComputePass +export interface ComputePass { /** * 数据类型。 @@ -17,12 +17,12 @@ export interface GPUComputePass /** * 计算对象列表。 */ - computeObjects: GPUComputeObject[]; + computeObjects: ComputeObject[]; /** * 查询通道运行消耗时长(单位为纳秒)。 * * 如果需要查询通道运行消耗时长,需要为该属性赋值,如 `pass.timestampQuery = {};`。WebGPU渲染完成后引擎自动填充结果到属性`elapsedNs`。 */ - timestampQuery?: GPUTimestampQuery; + timestampQuery?: TimestampQuery; } \ No newline at end of file diff --git a/src/data/GPU_ComputePipeline.ts b/src/data/ComputePipeline.ts similarity index 62% rename from src/data/GPU_ComputePipeline.ts rename to src/data/ComputePipeline.ts index 2d72f44..10c4703 100644 --- a/src/data/GPU_ComputePipeline.ts +++ b/src/data/ComputePipeline.ts @@ -1,12 +1,12 @@ -import { GPUComputeStage } from "./IGPUComputeStage"; +import { ComputeStage as ComputeStage } from "./ComputeStage"; /** - * GPU计算管线。 + * WebGPU计算管线。 * * {@link GPUDevice.createComputePipeline} * {@link GPUComputePipelineDescriptor} */ -export interface GPU_ComputePipeline +export interface ComputePipeline { /** * The initial value of {@link GPUObjectBase#label|GPUObjectBase.label}. @@ -16,5 +16,5 @@ export interface GPU_ComputePipeline /** * 计算程序。 */ - readonly compute: GPUComputeStage; + readonly compute: ComputeStage; } \ No newline at end of file diff --git a/src/data/IGPUComputeStage.ts b/src/data/ComputeStage.ts similarity index 96% rename from src/data/IGPUComputeStage.ts rename to src/data/ComputeStage.ts index 0a3cdad..bcdd154 100644 --- a/src/data/IGPUComputeStage.ts +++ b/src/data/ComputeStage.ts @@ -1,7 +1,7 @@ /** - * GPU计算阶段。 + * WebGPU计算阶段。 */ -export interface GPUComputeStage +export interface ComputeStage { /** * 着色器源码,将由 {@link GPUDevice.createShaderModule} 生成 {@link GPUShaderModule} 。 diff --git a/src/data/IGPUReadPixels.ts b/src/data/IGPUReadPixels.ts deleted file mode 100644 index cd82c4d..0000000 --- a/src/data/IGPUReadPixels.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { TextureLike, ReadPixels } from "@feng3d/render-api"; - -/** - * 读取GPU纹理像素 - */ -export interface IGPUReadPixels extends ReadPixels -{ - /** - * GPU纹理 - */ - texture: TextureLike, -} \ No newline at end of file diff --git a/src/data/IGPUStencilFaceState.ts b/src/data/IGPUStencilFaceState.ts deleted file mode 100644 index e84619f..0000000 --- a/src/data/IGPUStencilFaceState.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * {@link GPUStencilFaceState} - * - * @see https://www.orillusion.com/zh/webgpu.html#dictdef-gpustencilfacestate - */ -export interface IGPUStencilFaceState -{ - /** - * 在测试片元与 depthStencilAttachment 模板值时使用的 GPUCompareFunction。 - * - * 默认为 "always"。 - */ - readonly compare?: GPUCompareFunction; - - /** - * 如果片元模板比较测试(由 compare 描述)失败,则执行的 GPUStencilOperation。 - * - * 默认为 "keep"。 - */ - readonly failOp?: GPUStencilOperation; - - /** - * 如果由 depthCompare 描述的片元深度比较失败,则执行的 GPUStencilOperation。 - * - * 默认为 "keep"。 - */ - readonly depthFailOp?: GPUStencilOperation; - - /** - * 如果片元模板比较测试通过,则执行由compare描述的GPUStencilOperation。 - * - * 默认为 "keep"。 - */ - readonly passOp?: GPUStencilOperation; -} \ No newline at end of file diff --git a/src/data/IGPUMultisampleState.ts b/src/data/MultisampleState.ts similarity index 80% rename from src/data/IGPUMultisampleState.ts rename to src/data/MultisampleState.ts index e71c5d4..c3a38cf 100644 --- a/src/data/IGPUMultisampleState.ts +++ b/src/data/MultisampleState.ts @@ -5,16 +5,20 @@ import { RenderPassDescriptor } from "@feng3d/render-api"; * * 多重采样次数将由 {@link RenderPassDescriptor.sampleCount} 覆盖。 */ -export interface IGPUMultisampleState +export interface MultisampleState { /** * Mask determining which samples are written to. + * + * 默认为 0xFFFFFFFF 。 */ readonly mask?: GPUSampleMask; /** * When `true` indicates that a fragment's alpha channel should be used to generate a sample * coverage mask. + * + * 默认为 `false` 。 */ readonly alphaToCoverageEnabled?: boolean; } \ No newline at end of file diff --git a/src/data/IGPURenderBundle.ts b/src/data/RenderBundle.ts similarity index 89% rename from src/data/IGPURenderBundle.ts rename to src/data/RenderBundle.ts index bd7d200..8e46846 100644 --- a/src/data/IGPURenderBundle.ts +++ b/src/data/RenderBundle.ts @@ -7,7 +7,7 @@ import { RenderObject } from "@feng3d/render-api"; * * {@link GPUDevice.createRenderBundleEncoder} */ -export interface IGPURenderBundle +export interface RenderBundle { /** * 数据类型。 @@ -17,7 +17,7 @@ export interface IGPURenderBundle /** * GPU渲染捆绑编码器描述。 */ - readonly descriptor?: IGPURenderBundleEncoderDescriptor + readonly descriptor?: RenderBundleDescriptor /** * GPU渲染对象列表。 @@ -34,7 +34,7 @@ export interface IGPURenderBundle * * 'colorFormats' | 'depthStencilFormat' | 'sampleCount' 都将从GPU渲染通道中自动获取。 */ -export interface IGPURenderBundleEncoderDescriptor +export interface RenderBundleDescriptor { /** * If `true`, indicates that the render bundle does not modify the depth component of the diff --git a/src/data/IGPUTimestampQuery.ts b/src/data/TimestampQuery.ts similarity index 86% rename from src/data/IGPUTimestampQuery.ts rename to src/data/TimestampQuery.ts index 3a821f2..3d3feb8 100644 --- a/src/data/IGPUTimestampQuery.ts +++ b/src/data/TimestampQuery.ts @@ -1,7 +1,7 @@ /** * 查询通道运行消耗时长(单位为纳秒)。 */ -export interface GPUTimestampQuery +export interface TimestampQuery { /** * (单位为纳秒) diff --git a/src/data/IGPUExternalTexture.ts b/src/data/VideoTexture.ts similarity index 82% rename from src/data/IGPUExternalTexture.ts rename to src/data/VideoTexture.ts index 234bc6d..ec17a53 100644 --- a/src/data/IGPUExternalTexture.ts +++ b/src/data/VideoTexture.ts @@ -1,11 +1,11 @@ /** - * 外部纹理。 - * + * 视频纹理,WebGPU外部纹理。 + * * @see GPUExternalTexture * @see GPUExternalTextureDescriptor * @see GPUDevice.importExternalTexture */ -export interface IGPUExternalTexture +export interface VideoTexture { /** * The initial value of {@link GPUObjectBase#label|GPUObjectBase.label}. @@ -16,9 +16,7 @@ export interface IGPUExternalTexture * The video source to import the external texture from. Source size is determined as described * by the external source dimensions table. */ - readonly source: - | HTMLVideoElement - | VideoFrame; + readonly source: HTMLVideoElement | VideoFrame; /** * The color space the image contents of {@link GPUExternalTextureDescriptor#source} will be diff --git a/src/data/IGPUWorkgroups.ts b/src/data/Workgroups.ts similarity index 85% rename from src/data/IGPUWorkgroups.ts rename to src/data/Workgroups.ts index 5a64b75..5120883 100644 --- a/src/data/IGPUWorkgroups.ts +++ b/src/data/Workgroups.ts @@ -1,9 +1,9 @@ /** - * 分配的工作组。 + * WebGPU分配的工作组。 * * {@link GPUComputePassEncoder.dispatchWorkgroups} */ -export interface GPUWorkgroups +export interface Workgroups { /** * X的维度工作组数量。 diff --git a/src/data/polyfills/CanvasContext.ts b/src/data/polyfills/CanvasContext.ts index b65c3b8..80691ad 100644 --- a/src/data/polyfills/CanvasContext.ts +++ b/src/data/polyfills/CanvasContext.ts @@ -1,5 +1,5 @@ import { CanvasContext } from "@feng3d/render-api"; -import { GPU_CanvasConfiguration } from "../GPU_CanvasConfiguration"; +import { CanvasConfiguration } from "../CanvasConfiguration"; declare module "@feng3d/render-api" { @@ -10,8 +10,8 @@ declare module "@feng3d/render-api" export interface CanvasContext { /** - * 画布配置。默认有引擎自动设置。 + * WebGPU画布配置。默认有引擎自动设置。 */ - configuration?: GPU_CanvasConfiguration; + configuration?: CanvasConfiguration; } } diff --git a/src/data/polyfills/CommandEncoder.ts b/src/data/polyfills/CommandEncoder.ts index 477fb31..8a57f46 100644 --- a/src/data/polyfills/CommandEncoder.ts +++ b/src/data/polyfills/CommandEncoder.ts @@ -1,10 +1,10 @@ import { } from "@feng3d/render-api"; -import { GPUComputePass } from "../GPUComputePass"; +import { ComputePass } from "../ComputePass"; declare module "@feng3d/render-api" { export interface PassEncoderMap { - GPUComputePass: GPUComputePass; + GPUComputePass: ComputePass; } } diff --git a/src/data/IGPUOcclusionQuery.ts b/src/data/polyfills/OcclusionQuery.ts similarity index 100% rename from src/data/IGPUOcclusionQuery.ts rename to src/data/polyfills/OcclusionQuery.ts diff --git a/src/data/IGPUPrimitiveState.ts b/src/data/polyfills/PrimitiveState.ts similarity index 100% rename from src/data/IGPUPrimitiveState.ts rename to src/data/polyfills/PrimitiveState.ts diff --git a/src/data/polyfills/ReadPixels.ts b/src/data/polyfills/ReadPixels.ts new file mode 100644 index 0000000..9d3a606 --- /dev/null +++ b/src/data/polyfills/ReadPixels.ts @@ -0,0 +1,12 @@ +import { TextureLike } from "@feng3d/render-api"; + +declare module "@feng3d/render-api" +{ + export interface ReadPixels + { + /** + * GPU纹理 + */ + texture: TextureLike, + } +} diff --git a/src/data/IGPURenderObject.ts b/src/data/polyfills/RenderObject.ts similarity index 97% rename from src/data/IGPURenderObject.ts rename to src/data/polyfills/RenderObject.ts index 3994f5d..cc62ea0 100644 --- a/src/data/IGPURenderObject.ts +++ b/src/data/polyfills/RenderObject.ts @@ -1,5 +1,5 @@ import { DrawIndexed, DrawVertex, Viewport } from "@feng3d/render-api"; -import { } from "./polyfills/Uniforms"; +import { } from "./Uniforms"; declare module "@feng3d/render-api" { diff --git a/src/data/IGPURenderPass.ts b/src/data/polyfills/RenderPass.ts similarity index 79% rename from src/data/IGPURenderPass.ts rename to src/data/polyfills/RenderPass.ts index 83e764a..594c1b1 100644 --- a/src/data/IGPURenderPass.ts +++ b/src/data/polyfills/RenderPass.ts @@ -1,7 +1,7 @@ import { RenderPass, RenderPassDescriptor } from "@feng3d/render-api"; -import { } from "./IGPUOcclusionQuery"; -import { IGPURenderBundle } from "./IGPURenderBundle"; -import { GPUTimestampQuery } from "./IGPUTimestampQuery"; +import { } from "./OcclusionQuery"; +import { RenderBundle } from "../RenderBundle"; +import { TimestampQuery } from "../TimestampQuery"; declare module "@feng3d/render-api" { @@ -26,11 +26,11 @@ declare module "@feng3d/render-api" * * 如果需要查询通道运行消耗时长,需要为该属性赋值,如 `pass.timestampQuery = {};`。WebGPU渲染完成后引擎自动填充结果到属性`elapsedNs`。 */ - timestampQuery?: GPUTimestampQuery; + timestampQuery?: TimestampQuery; } export interface RenderPassObjectMap { - IGPURenderBundle: IGPURenderBundle; + RenderBundle: RenderBundle; } } diff --git a/src/data/IGPURenderPassColorAttachment.ts b/src/data/polyfills/RenderPassColorAttachment.ts similarity index 100% rename from src/data/IGPURenderPassColorAttachment.ts rename to src/data/polyfills/RenderPassColorAttachment.ts diff --git a/src/data/IGPURenderPassDepthStencilAttachment.ts b/src/data/polyfills/RenderPassDepthStencilAttachment.ts similarity index 100% rename from src/data/IGPURenderPassDepthStencilAttachment.ts rename to src/data/polyfills/RenderPassDepthStencilAttachment.ts diff --git a/src/data/IGPURenderPassDescriptor.ts b/src/data/polyfills/RenderPassDescriptor.ts similarity index 100% rename from src/data/IGPURenderPassDescriptor.ts rename to src/data/polyfills/RenderPassDescriptor.ts diff --git a/src/data/IGPURenderPipeline.ts b/src/data/polyfills/RenderPipeline.ts similarity index 97% rename from src/data/IGPURenderPipeline.ts rename to src/data/polyfills/RenderPipeline.ts index 02f55ea..fbace27 100644 --- a/src/data/IGPURenderPipeline.ts +++ b/src/data/polyfills/RenderPipeline.ts @@ -1,6 +1,6 @@ import { BlendState,DepthStencilState } from "@feng3d/render-api"; -import { IGPUMultisampleState } from "./IGPUMultisampleState"; +import { MultisampleState } from "../MultisampleState"; declare module "@feng3d/render-api" { @@ -14,7 +14,7 @@ declare module "@feng3d/render-api" /** * 多重采样阶段描述。 */ - readonly multisample?: IGPUMultisampleState; + readonly multisample?: MultisampleState; } /** diff --git a/src/data/IGPUTexture.ts b/src/data/polyfills/Texture.ts similarity index 100% rename from src/data/IGPUTexture.ts rename to src/data/polyfills/Texture.ts diff --git a/src/data/IGPUTextureView.ts b/src/data/polyfills/TextureView.ts similarity index 100% rename from src/data/IGPUTextureView.ts rename to src/data/polyfills/TextureView.ts diff --git a/src/data/polyfills/Uniforms.ts b/src/data/polyfills/Uniforms.ts index baaa981..b15c12c 100644 --- a/src/data/polyfills/Uniforms.ts +++ b/src/data/polyfills/Uniforms.ts @@ -1,5 +1,5 @@ import { Sampler } from "@feng3d/render-api"; -import { IGPUExternalTexture } from "../IGPUExternalTexture"; +import { VideoTexture } from "../VideoTexture"; declare module "@feng3d/render-api" { @@ -7,6 +7,6 @@ declare module "@feng3d/render-api" { Sampler: Sampler; TextureView: TextureView; - IGPUExternalTexture: IGPUExternalTexture; + VideoTexture: VideoTexture; } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index ff5f916..7954364 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,24 +1,25 @@ export * from "./WebGPU"; -export * from "./data/GPU_ComputePipeline"; -export * from "./data/GPUComputeObject"; -export * from "./data/GPUComputePass"; -export * from "./data/IGPUOcclusionQuery"; -export * from "./data/IGPUPrimitiveState"; -export * from "./data/IGPUReadPixels"; -export * from "./data/IGPURenderBundle"; -export * from "./data/IGPURenderObject"; -export * from "./data/IGPURenderPass"; -export * from "./data/IGPURenderPassColorAttachment"; -export * from "./data/IGPURenderPassDepthStencilAttachment"; -export * from "./data/IGPURenderPassDescriptor"; -export * from "./data/IGPURenderPipeline"; -export * from "./data/IGPUTexture"; -export * from "./data/IGPUTextureView"; -export * from "./data/IGPUTimestampQuery"; +export * from "./data/ComputeObject"; +export * from "./data/ComputePass"; +export * from "./data/ComputePipeline"; +export * from "./data/polyfills/Texture"; +export * from "./data/polyfills/TextureView"; +export * from "./data/RenderBundle"; +export * from "./data/TimestampQuery"; + export * from "./data/polyfills/Buffer"; export * from "./data/polyfills/CanvasContext"; export * from "./data/polyfills/CommandEncoder"; +export * from "./data/polyfills/OcclusionQuery"; +export * from "./data/polyfills/PrimitiveState"; +export * from "./data/polyfills/ReadPixels"; +export * from "./data/polyfills/RenderObject"; +export * from "./data/polyfills/RenderPass"; +export * from "./data/polyfills/RenderPassColorAttachment"; +export * from "./data/polyfills/RenderPassDepthStencilAttachment"; +export * from "./data/polyfills/RenderPassDescriptor"; +export * from "./data/polyfills/RenderPipeline"; export * from "./data/polyfills/Uniforms"; export * from "./caches/getIGPUBuffer"; diff --git a/src/internal/IGPUBindGroupDescriptor.ts b/src/internal/IGPUBindGroupDescriptor.ts deleted file mode 100644 index 8d1e062..0000000 --- a/src/internal/IGPUBindGroupDescriptor.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { BufferBinding, IUniformType, Sampler, TextureView } from "@feng3d/render-api"; -import { IGPUExternalTexture } from "../data/IGPUExternalTexture"; - -/** - * GPU 绑定组。 - * - * @see GPUBindGroupDescriptor - * @see GPUDevice.createBindGroup - */ -export interface IGPUBindGroupDescriptor -{ - /** - * The initial value of {@link GPUObjectBase#label|GPUObjectBase.label}. - */ - label?: string; - - /** - * The {@link IGPUBindGroupLayoutDescriptor} the entries of this bind group will conform to. - */ - layout: GPUBindGroupLayoutDescriptor; - - /** - * A list of entries describing the resources to expose to the shader for each binding - * described by the {@link GPUBindGroupDescriptor#layout}. - * - * {@link GPUBindGroupEntry} - */ - entries: IGPUBindGroupEntry[]; -} - -/** - * 绑定资源入口,指定资源绑定的位置。 - * - * @see GPUBindGroupEntry - */ -export interface IGPUBindGroupEntry -{ - binding: GPUIndex32; - - /** - * The resource to bind, which may be a {@link GPUSampler}, {@link GPUTextureView}, - * {@link GPUExternalTexture}, or {@link GPUBufferBinding}. - */ - resource: IGPUBindingResource; -} - -export type IGPUBindingResource = Sampler | TextureView | IGPUExternalTexture | IUniformType; diff --git a/src/internal/IGPUSetBindGroup.ts b/src/internal/IGPUSetBindGroup.ts deleted file mode 100644 index 17f6bb8..0000000 --- a/src/internal/IGPUSetBindGroup.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IGPUBindGroupDescriptor } from "./IGPUBindGroupDescriptor"; - -/** - * GPU渲染时使用的绑定组。 - * - * {@link GPUBindingCommandsMixin.setBindGroup} - */ -export interface IGPUSetBindGroup -{ - /** - * GPU绑定组。 - * - * Bind group to use for subsequent render or compute commands. - */ - bindGroup: IGPUBindGroupDescriptor; - - /** - * Array containing buffer offsets in bytes for each entry in `bindGroup` marked as {@link GPUBindGroupLayoutEntry#buffer}.{@link GPUBufferBindingLayout#hasDynamicOffset}.--> - */ - dynamicOffsets?: number[]; -} diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 14178d1..4ed449f 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -16,15 +16,17 @@ import { IGPUShader } from "../caches/getIGPUPipelineLayout"; import { getIGPUSetBindGroups } from "../caches/getIGPUSetBindGroups"; import { getNGPURenderPipeline } from "../caches/getNGPURenderPipeline"; import { getRealGPUBindGroup } from "../const"; -import { GPUComputeObject } from "../data/GPUComputeObject"; -import { GPUComputePass } from "../data/GPUComputePass"; -import { GPU_ComputePipeline } from "../data/GPU_ComputePipeline"; -import { } from "../data/IGPUOcclusionQuery"; -import { IGPURenderBundle } from "../data/IGPURenderBundle"; -import { GPUWorkgroups } from "../data/IGPUWorkgroups"; +import { ComputeObject } from "../data/ComputeObject"; +import { ComputePass } from "../data/ComputePass"; +import { ComputePipeline } from "../data/ComputePipeline"; +import { Workgroups } from "../data/Workgroups"; +import { } from "../data/polyfills/OcclusionQuery"; +import "../data/polyfills/RenderObject"; +import "../data/polyfills/RenderPass"; +import { RenderBundle } from "../data/RenderBundle"; import { GPUQueue_submit } from "../eventnames"; -import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; import { getIGPUSetIndexBuffer } from "../internal/getIGPUSetIndexBuffer"; +import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; export class RunWebGPU @@ -143,7 +145,7 @@ export class RunWebGPU * @param commandEncoder 命令编码器。 * @param computePass 计算通道。 */ - protected runComputePass(device: GPUDevice, commandEncoder: GPUCommandEncoder, computePass: GPUComputePass) + protected runComputePass(device: GPUDevice, commandEncoder: GPUCommandEncoder, computePass: ComputePass) { const descriptor: GPUComputePassDescriptor = {}; // 处理时间戳查询 @@ -160,7 +162,7 @@ export class RunWebGPU timestampQuery.resolve(device, commandEncoder, computePass); } - protected runComputeObjects(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObjects: GPUComputeObject[]) + protected runComputeObjects(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObjects: ComputeObject[]) { computeObjects.forEach((computeObject) => { @@ -219,9 +221,9 @@ export class RunWebGPU passEncoder.endOcclusionQuery(); } - protected runRenderBundle(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IGPURenderPassFormat, renderBundleObject: IGPURenderBundle) + protected runRenderBundle(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IGPURenderPassFormat, renderBundleObject: RenderBundle) { - const renderBundleMap: ChainMap<[IGPURenderBundle, string], GPURenderBundle> = device["_renderBundleMap"] = device["_renderBundleMap"] || new ChainMap(); + const renderBundleMap: ChainMap<[RenderBundle, string], GPURenderBundle> = device["_renderBundleMap"] = device["_renderBundleMap"] || new ChainMap(); // let gpuRenderBundle: GPURenderBundle = renderBundleMap.get([renderBundleObject, renderPassFormat._key]); if (!gpuRenderBundle) @@ -256,7 +258,7 @@ export class RunWebGPU * @param passEncoder 计算通道编码器。 * @param computeObject 计算对象。 */ - protected runComputeObject(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObject: GPUComputeObject) + protected runComputeObject(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObject: ComputeObject) { const { pipeline: material, uniforms: bindingResources, workgroups } = computeObject; @@ -269,7 +271,7 @@ export class RunWebGPU this.runWorkgroups(passEncoder, workgroups); } - protected runComputePipeline(device: GPUDevice, passEncoder: GPUComputePassEncoder, material: GPU_ComputePipeline) + protected runComputePipeline(device: GPUDevice, passEncoder: GPUComputePassEncoder, material: ComputePipeline) { const gpuComputePipeline = getIGPUComputePipeline(material); @@ -283,7 +285,7 @@ export class RunWebGPU * @param passEncoder 计算通道编码器。 * @param workgroups 计算工作组。 */ - protected runWorkgroups(passEncoder: GPUComputePassEncoder, workgroups?: GPUWorkgroups) + protected runWorkgroups(passEncoder: GPUComputePassEncoder, workgroups?: Workgroups) { const { workgroupCountX, workgroupCountY, workgroupCountZ } = workgroups; passEncoder.dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ); -- Gitee From 35091c3b8fa35fee7eda1607244124e881015cc4 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 12 Mar 2025 21:53:43 +0800 Subject: [PATCH 037/214] =?UTF-8?q?refactor(internal):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E5=86=85=E9=83=A8=E6=8E=A5=E5=8F=A3=E5=92=8C=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重命名和调整内部接口,以提高代码一致性和可读性 - 更新缓存系统,移除不必要的中间对象 - 优化渲染管线和缓冲区相关代码 - 调整类型定义,以更好地匹配 WebGPU API --- src/caches/getGPUPipelineLayout.ts | 4 +- src/caches/getGPURenderPassDescriptor.ts | 4 +- src/caches/getGPURenderPassFormat.ts | 6 +-- src/caches/getGPURenderPipeline.ts | 6 +-- src/caches/getGPUTexture.ts | 6 +-- src/caches/getIGPUBuffer.ts | 19 +--------- src/caches/getIGPUPipelineLayout.ts | 8 ++-- src/caches/getIGPUSetBindGroups.ts | 4 +- src/caches/getNGPURenderPipeline.ts | 27 +++++++------- src/caches/getWGSLReflectInfo.ts | 4 +- src/internal/IGPUIndexBuffer.ts | 37 ------------------- ...reMultisample.ts => MultisampleTexture.ts} | 2 +- ...NGPUFragmentState.ts => NFragmentState.ts} | 2 +- src/internal/NGPUVertexBuffer.ts | 6 +-- ...PURenderPipeline.ts => NRenderPipeline.ts} | 10 ++--- ...criptor.ts => PipelineLayoutDescriptor.ts} | 12 +++--- ...enderPassFormat.ts => RenderPassFormat.ts} | 2 +- src/internal/getIGPUSetIndexBuffer.ts | 14 ------- src/runs/RunWebGPU.ts | 35 ++++++++++-------- src/runs/RunWebGPUCommandCache.ts | 8 ++-- 20 files changed, 76 insertions(+), 140 deletions(-) delete mode 100644 src/internal/IGPUIndexBuffer.ts rename src/internal/{IGPUTextureMultisample.ts => MultisampleTexture.ts} (86%) rename src/internal/{NGPUFragmentState.ts => NFragmentState.ts} (88%) rename src/internal/{NGPURenderPipeline.ts => NRenderPipeline.ts} (71%) rename src/internal/{IGPUPipelineLayoutDescriptor.ts => PipelineLayoutDescriptor.ts} (58%) rename src/internal/{IGPURenderPassFormat.ts => RenderPassFormat.ts} (89%) delete mode 100644 src/internal/getIGPUSetIndexBuffer.ts diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 5157124..bf3eb1e 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,7 +1,7 @@ -import { IGPUPipelineLayoutDescriptor } from "../internal/IGPUPipelineLayoutDescriptor"; +import { PipelineLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; -export function getGPUPipelineLayout(device: GPUDevice, layout: IGPUPipelineLayoutDescriptor) +export function getGPUPipelineLayout(device: GPUDevice, layout: PipelineLayoutDescriptor) { const bindGroupLayouts = layout.bindGroupLayouts.map((v) => { diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index f559248..c135cdb 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -2,7 +2,7 @@ import { anyEmitter } from "@feng3d/event"; import { CanvasTexture, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUTexture_resize } from "../eventnames"; -import { IGPUTextureMultisample } from "../internal/IGPUTextureMultisample"; +import { MultisampleTexture } from "../internal/MultisampleTexture"; import { NGPURenderPassColorAttachment } from "../internal/internal"; import { getGPUTextureFormat } from "./getGPUTextureFormat"; import { getGPUTextureView } from "./getGPUTextureView"; @@ -241,7 +241,7 @@ function getMultisampleTextureView(texture: TextureLike, sampleCount: 4) // 新增用于解决多重采样的纹理 const size = getIGPUTextureLikeSize(texture); const format = getGPUTextureFormat(texture); - const multisampleTexture: IGPUTextureMultisample = { + const multisampleTexture: MultisampleTexture = { label: "自动生成多重采样的纹理", size, sampleCount, diff --git a/src/caches/getGPURenderPassFormat.ts b/src/caches/getGPURenderPassFormat.ts index 214ed7b..f05e297 100644 --- a/src/caches/getGPURenderPassFormat.ts +++ b/src/caches/getGPURenderPassFormat.ts @@ -1,6 +1,6 @@ import { RenderPassDescriptor } from "@feng3d/render-api"; import { getGPUTextureFormat } from "../caches/getGPUTextureFormat"; -import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; +import { IRenderPassFormat } from "../internal/RenderPassFormat"; /** * 获取渲染通道格式。 @@ -8,9 +8,9 @@ import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; * @param descriptor 渲染通道描述。 * @returns */ -export function getGPURenderPassFormat(descriptor: RenderPassDescriptor): IGPURenderPassFormat +export function getGPURenderPassFormat(descriptor: RenderPassDescriptor): IRenderPassFormat { - let gpuRenderPassFormat: IGPURenderPassFormat = descriptor[_RenderPassFormat]; + let gpuRenderPassFormat: IRenderPassFormat = descriptor[_RenderPassFormat]; if (gpuRenderPassFormat) return gpuRenderPassFormat; const colorAttachmentTextureFormats = descriptor.colorAttachments.map((v) => getGPUTextureFormat(v.view.texture)); diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index 2845320..a13560f 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -1,9 +1,9 @@ -import { NGPURenderPipeline } from "../internal/NGPURenderPipeline"; +import { NRenderPipeline } from "../internal/NRenderPipeline"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; import { getGPUShaderModule } from "./getGPUShaderModule"; import { getIGPUPipelineLayout } from "./getIGPUPipelineLayout"; -export function getGPURenderPipeline(device: GPUDevice, renderPipeline: NGPURenderPipeline) +export function getGPURenderPipeline(device: GPUDevice, renderPipeline: NRenderPipeline) { let pipeline = pipelineMap.get(renderPipeline); if (pipeline) return pipeline; @@ -38,4 +38,4 @@ export function getGPURenderPipeline(device: GPUDevice, renderPipeline: NGPURend return pipeline; } -const pipelineMap = new Map(); +const pipelineMap = new Map(); diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index e7bd982..1584ff9 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,8 +1,8 @@ import { anyEmitter } from "@feng3d/event"; -import { TextureLike, TextureSize, Texture, TextureDataSource, TextureImageSource, TextureSource, CanvasTexture } from "@feng3d/render-api"; +import { CanvasTexture, Texture, TextureDataSource, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; -import { IGPUTextureMultisample } from "../internal/IGPUTextureMultisample"; +import { MultisampleTexture } from "../internal/MultisampleTexture"; import { generateMipmap } from "../utils/generate-mipmap"; import { getGPUCanvasContext } from "./getGPUCanvasContext"; import { getGPUTextureDimension } from "./getGPUTextureDimension"; @@ -39,7 +39,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC // 创建纹理 const createTexture = () => { - const { format, sampleCount, dimension, viewFormats } = texture as IGPUTextureMultisample; + const { format, sampleCount, dimension, viewFormats } = texture as MultisampleTexture; let { label, mipLevelCount } = texture; const size = texture.size; diff --git a/src/caches/getIGPUBuffer.ts b/src/caches/getIGPUBuffer.ts index 52c72cc..d75f71a 100644 --- a/src/caches/getIGPUBuffer.ts +++ b/src/caches/getIGPUBuffer.ts @@ -1,4 +1,4 @@ -import { Buffer, IVertexDataTypes, TypedArray, UnReadonly } from "@feng3d/render-api"; +import { Buffer, TypedArray } from "@feng3d/render-api"; export function getIGPUBuffer(bufferSource: TypedArray) { @@ -16,20 +16,3 @@ export function getIGPUBuffer(bufferSource: TypedArray) return gpuBuffer; } -export function getIGPUVertexBuffer(data: IVertexDataTypes) -{ - const buffer = getIGPUBuffer(data); - (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); - - return buffer; -} -let autoVertexIndex = 0; - -export function getIGPUIndexBuffer(data: Uint16Array | Uint32Array) -{ - const buffer = getIGPUBuffer(data); - (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); - - return buffer; -} -let autoIndex = 0; \ No newline at end of file diff --git a/src/caches/getIGPUPipelineLayout.ts b/src/caches/getIGPUPipelineLayout.ts index 2c97182..f7d2a6d 100644 --- a/src/caches/getIGPUPipelineLayout.ts +++ b/src/caches/getIGPUPipelineLayout.ts @@ -1,4 +1,4 @@ -import { IGPUBindGroupLayoutDescriptor, IGPUPipelineLayoutDescriptor } from "../internal/IGPUPipelineLayoutDescriptor"; +import { BindGroupLayoutDescriptor, PipelineLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { getIGPUBindGroupLayoutEntryMap, IGPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; export type IGPUShader = { readonly vertex?: string, readonly fragment?: string, readonly compute?: string }; @@ -14,7 +14,7 @@ export function getIGPUShaderKey(shader: IGPUShader) * @param shader GPU管线。 * @returns 管线布局。 */ -export function getIGPUPipelineLayout(shader: IGPUShader): IGPUPipelineLayoutDescriptor +export function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor { const shaderKey = getIGPUShaderKey(shader); @@ -44,7 +44,7 @@ export function getIGPUPipelineLayout(shader: IGPUShader): IGPUPipelineLayoutDes } // - const bindGroupLayouts: IGPUBindGroupLayoutDescriptor[] = []; + const bindGroupLayouts: BindGroupLayoutDescriptor[] = []; for (const resourceName in entryMap) { const bindGroupLayoutEntry = entryMap[resourceName]; @@ -108,4 +108,4 @@ function mergeBindGroupLayouts(entryMap: IGPUBindGroupLayoutEntryMap, entryMap1: return entryMap; } -const gpuPipelineLayoutMap: { [key: string]: IGPUPipelineLayoutDescriptor } = {}; +const gpuPipelineLayoutMap: { [key: string]: PipelineLayoutDescriptor } = {}; diff --git a/src/caches/getIGPUSetBindGroups.ts b/src/caches/getIGPUSetBindGroups.ts index 59d8132..b31734b 100644 --- a/src/caches/getIGPUSetBindGroups.ts +++ b/src/caches/getIGPUSetBindGroups.ts @@ -2,7 +2,7 @@ import { watcher } from "@feng3d/watcher"; import { BufferBinding, Uniforms } from "@feng3d/render-api"; import { getIGPUPipelineLayout, getIGPUShaderKey, IGPUShader } from "../caches/getIGPUPipelineLayout"; -import { IGPUBindGroupLayoutDescriptor } from "../internal/IGPUPipelineLayoutDescriptor"; +import { BindGroupLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { ChainMap } from "../utils/ChainMap"; import { getBufferBindingInfo, IBufferBindingInfo } from "../utils/getBufferBindingInfo"; import { updateBufferBinding } from "../utils/updateBufferBinding"; @@ -31,7 +31,7 @@ export function getIGPUSetBindGroups(shader: IGPUShader, bindingResources: Unifo const bindGroupsMap = new ChainMap<[string, Uniforms], IGPUSetBindGroup[]>(); -function getIGPUSetBindGroup(bindGroupLayout: IGPUBindGroupLayoutDescriptor, bindingResources: Uniforms): IGPUSetBindGroup +function getIGPUSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, bindingResources: Uniforms): IGPUSetBindGroup { const map: ChainMap, IGPUSetBindGroup> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); const subBindingResources = bindGroupLayout.entryNames.map((v) => bindingResources[v]); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index aa055d6..e615cf2 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -4,11 +4,10 @@ import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; import { gPartial } from "@feng3d/polyfill"; import { MultisampleState } from "../data/MultisampleState"; -import { getIGPUSetIndexBuffer } from "../internal/getIGPUSetIndexBuffer"; -import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; -import { NGPUFragmentState } from "../internal/NGPUFragmentState"; -import { NGPURenderPipeline } from "../internal/NGPURenderPipeline"; -import { NGPUVertexBuffer } from "../internal/NGPUVertexBuffer"; +import { IRenderPassFormat } from "../internal/RenderPassFormat"; +import { NFragmentState } from "../internal/NFragmentState"; +import { NRenderPipeline } from "../internal/NRenderPipeline"; +import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; import { NGPUVertexState } from "../internal/NGPUVertexState"; import { ChainMap } from "../utils/ChainMap"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; @@ -21,9 +20,9 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPassFormat: IGPURenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) +export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPassFormat: IRenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { - const indexFormat = indices ? getIGPUSetIndexBuffer(indices).indexFormat : undefined; + const indexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; let result = renderPipelineMap.get([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); if (result) return result; @@ -50,7 +49,7 @@ export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPass const blendConstantColor = BlendState.getBlendConstantColor(renderPipeline.fragment?.targets?.[0]?.blend); // - const material: NGPURenderPipeline = { + const material: NRenderPipeline = { label, primitive: gpuPrimitive, vertex: vertexStateResult.gpuVertexState, @@ -85,11 +84,11 @@ const renderPipelineMap = new ChainMap< /** * GPU渲染管线描述。 */ - material: NGPURenderPipeline; + material: NRenderPipeline; /** * GPU渲染时使用的顶点缓冲区列表。 */ - vertexBuffers: NGPUVertexBuffer[]; + vertexBuffers: NVertexBuffer[]; /** * 版本号 */ @@ -266,7 +265,7 @@ function getNGPUVertexState(vertexState: VertexState, vertices: VertexAttributes const vertexStateMap = new ChainMap<[VertexState, VertexAttributes], { gpuVertexState: NGPUVertexState; - vertexBuffers: NGPUVertexBuffer[]; + vertexBuffers: NVertexBuffer[]; /** * 版本号,用于版本控制。 */ @@ -284,7 +283,7 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) { const vertexBufferLayouts: GPUVertexBufferLayout[] = []; - const vertexBuffers: NGPUVertexBuffer[] = []; + const vertexBuffers: NVertexBuffer[] = []; const map: WeakMap = new WeakMap(); @@ -368,7 +367,7 @@ function getNGPUFragmentState(fragmentState: FragmentState, colorAttachments: re const colorAttachmentsKey = colorAttachments.toString(); - let gpuFragmentState: NGPUFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); + let gpuFragmentState: NFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); if (gpuFragmentState) return gpuFragmentState; const code = fragmentState.code; @@ -431,7 +430,7 @@ function getNGPUFragmentState(fragmentState: FragmentState, colorAttachments: re return gpuFragmentState; } -const fragmentStateMap = new ChainMap<[FragmentState, string], NGPUFragmentState>(); +const fragmentStateMap = new ChainMap<[FragmentState, string], NFragmentState>(); function getGPUBlendState(blend?: BlendState): GPUBlendState { diff --git a/src/caches/getWGSLReflectInfo.ts b/src/caches/getWGSLReflectInfo.ts index 55814ec..f497252 100644 --- a/src/caches/getWGSLReflectInfo.ts +++ b/src/caches/getWGSLReflectInfo.ts @@ -1,5 +1,5 @@ import { ResourceType, TemplateInfo, WgslReflect } from "wgsl_reflect"; -import { IGPUBindGroupLayoutEntry } from "../internal/IGPUPipelineLayoutDescriptor"; +import { BindGroupLayoutEntry } from "../internal/PipelineLayoutDescriptor"; import { DepthTextureType, ExternalSampledTextureType, MultisampledTextureType, TextureType } from "../types/TextureType"; /** @@ -19,7 +19,7 @@ export function getWGSLReflectInfo(code: string): WgslReflect } const reflectMap: { [code: string]: WgslReflect } = {}; -export type IGPUBindGroupLayoutEntryMap = { [name: string]: IGPUBindGroupLayoutEntry; }; +export type IGPUBindGroupLayoutEntryMap = { [name: string]: BindGroupLayoutEntry; }; export function getIGPUBindGroupLayoutEntryMap(code: string): IGPUBindGroupLayoutEntryMap { diff --git a/src/internal/IGPUIndexBuffer.ts b/src/internal/IGPUIndexBuffer.ts deleted file mode 100644 index 6d4bf14..0000000 --- a/src/internal/IGPUIndexBuffer.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Buffer } from "@feng3d/render-api"; - -/** - * GPU渲染时使用的索引缓冲区。 - * - * {@link GPURenderCommandsMixin.setIndexBuffer} - */ -export interface IGPUSetIndexBuffer -{ - /** - * Buffer containing index data to use for subsequent drawing commands. - * - * 顶点索引缓冲区,包含提供给后续绘制命令使用的顶点索引数据。 - */ - buffer: Buffer; - - /** - * Format of the index data contained in `buffer`. - * - * 缓冲区中提供的顶点索引数据格式。 - */ - indexFormat: GPUIndexFormat; - - /** - * Offset in bytes into `buffer` where the index data begins. Defaults to `0`. - * - * 索引数据在缓冲区中的起始偏移值。默认为 `0` 。 - */ - offset?: number; - - /** - * Size in bytes of the index data in `buffer`. Defaults to the size of the buffer minus the offset. - * - * 索引数据在缓冲区中所占字节尺寸。默认为缓冲区尺寸减去起始偏移值。 - */ - size?: number; -} diff --git a/src/internal/IGPUTextureMultisample.ts b/src/internal/MultisampleTexture.ts similarity index 86% rename from src/internal/IGPUTextureMultisample.ts rename to src/internal/MultisampleTexture.ts index 5c67ae6..ea10b00 100644 --- a/src/internal/IGPUTextureMultisample.ts +++ b/src/internal/MultisampleTexture.ts @@ -3,7 +3,7 @@ import { Texture } from "@feng3d/render-api"; /** * 多重采样纹理,一般只在渲染通道中需要解决多重采样时使用。 */ -export interface IGPUTextureMultisample extends Texture +export interface MultisampleTexture extends Texture { /** * The sample count of the texture. A {@link GPUTextureDescriptor#sampleCount} > `1` indicates diff --git a/src/internal/NGPUFragmentState.ts b/src/internal/NFragmentState.ts similarity index 88% rename from src/internal/NGPUFragmentState.ts rename to src/internal/NFragmentState.ts index 1ee8727..361f839 100644 --- a/src/internal/NGPUFragmentState.ts +++ b/src/internal/NFragmentState.ts @@ -1,7 +1,7 @@ /** * 内部对象。 */ -export interface NGPUFragmentState +export interface NFragmentState { readonly code: string; readonly entryPoint: string; diff --git a/src/internal/NGPUVertexBuffer.ts b/src/internal/NGPUVertexBuffer.ts index 86338a4..77fed53 100644 --- a/src/internal/NGPUVertexBuffer.ts +++ b/src/internal/NGPUVertexBuffer.ts @@ -1,4 +1,4 @@ -import { IVertexDataTypes } from "@feng3d/render-api"; +import { VertexDataTypes } from "@feng3d/render-api"; /** * Sets the current vertex buffer for the given slot. @@ -7,14 +7,14 @@ import { IVertexDataTypes } from "@feng3d/render-api"; * * {@link GPURenderCommandsMixin.setVertexBuffer} */ -export interface NGPUVertexBuffer +export interface NVertexBuffer { /** * Buffer containing vertex data to use for subsequent drawing commands. * * GPU缓冲区,包含后续绘制命令所包含的顶点数据的 */ - data: IVertexDataTypes; + data: VertexDataTypes; /** * Offset in bytes into `buffer` where the vertex data begins. Defaults to `0`. diff --git a/src/internal/NGPURenderPipeline.ts b/src/internal/NRenderPipeline.ts similarity index 71% rename from src/internal/NGPURenderPipeline.ts rename to src/internal/NRenderPipeline.ts index f10bafb..41f7557 100644 --- a/src/internal/NGPURenderPipeline.ts +++ b/src/internal/NRenderPipeline.ts @@ -1,16 +1,16 @@ -import { IColor } from "@feng3d/render-api"; -import { NGPUFragmentState } from "./NGPUFragmentState"; +import { Color } from "@feng3d/render-api"; +import { NFragmentState } from "./NFragmentState"; import { NGPUVertexState } from "./NGPUVertexState"; /** * 内部对象。 */ -export interface NGPURenderPipeline +export interface NRenderPipeline { readonly label: string; readonly primitive: GPUPrimitiveState; readonly vertex: NGPUVertexState - readonly fragment: NGPUFragmentState, + readonly fragment: NFragmentState, readonly depthStencil: GPUDepthStencilState, readonly multisample: GPUMultisampleState, @@ -22,5 +22,5 @@ export interface NGPURenderPipeline /** * 当混合系数用到了混合常量值时设置混合常量值。 */ - readonly blendConstantColor: IColor; + readonly blendConstantColor: Color; } \ No newline at end of file diff --git a/src/internal/IGPUPipelineLayoutDescriptor.ts b/src/internal/PipelineLayoutDescriptor.ts similarity index 58% rename from src/internal/IGPUPipelineLayoutDescriptor.ts rename to src/internal/PipelineLayoutDescriptor.ts index e6d4427..96d2c9f 100644 --- a/src/internal/IGPUPipelineLayoutDescriptor.ts +++ b/src/internal/PipelineLayoutDescriptor.ts @@ -9,23 +9,25 @@ import { VariableInfo } from "wgsl_reflect"; * * {@link GPUPipelineLayout} */ -export interface IGPUPipelineLayoutDescriptor extends Omit +export interface PipelineLayoutDescriptor { + label?: string; /** * A list of {@link GPUBindGroupLayout}s the pipeline will use. Each element corresponds to a * @group attribute in the {@link GPUShaderModule}, with the `N`th element corresponding with * `@group(N)`. */ - bindGroupLayouts: IGPUBindGroupLayoutDescriptor[]; + bindGroupLayouts: BindGroupLayoutDescriptor[]; } -export interface IGPUBindGroupLayoutDescriptor extends GPUBindGroupLayoutDescriptor +export interface BindGroupLayoutDescriptor { - entries: IGPUBindGroupLayoutEntry[]; + label?: string; + entries: BindGroupLayoutEntry[]; entryNames: string[], } -export interface IGPUBindGroupLayoutEntry extends GPUBindGroupLayoutEntry +export interface BindGroupLayoutEntry extends GPUBindGroupLayoutEntry { variableInfo: VariableInfo; } \ No newline at end of file diff --git a/src/internal/IGPURenderPassFormat.ts b/src/internal/RenderPassFormat.ts similarity index 89% rename from src/internal/IGPURenderPassFormat.ts rename to src/internal/RenderPassFormat.ts index 65a5fa2..9a6da2f 100644 --- a/src/internal/IGPURenderPassFormat.ts +++ b/src/internal/RenderPassFormat.ts @@ -1,4 +1,4 @@ -export interface IGPURenderPassFormat +export interface IRenderPassFormat { readonly attachmentSize: { readonly width: number, readonly height: number } readonly colorFormats: readonly GPUTextureFormat[], diff --git a/src/internal/getIGPUSetIndexBuffer.ts b/src/internal/getIGPUSetIndexBuffer.ts deleted file mode 100644 index 5160a8b..0000000 --- a/src/internal/getIGPUSetIndexBuffer.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { getIGPUIndexBuffer } from "../caches/getIGPUBuffer"; -import { IGPUSetIndexBuffer } from "./IGPUIndexBuffer"; - -export function getIGPUSetIndexBuffer(index: Uint16Array | Uint32Array) -{ - const indexBuffer: IGPUSetIndexBuffer = index["_IGPUIndexBuffer"] = index["_IGPUIndexBuffer"] || { - buffer: getIGPUIndexBuffer(index), - indexFormat: index.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", - offset: index.byteOffset, - size: index.byteLength, - }; - - return indexBuffer; -} diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 4ed449f..bd06d50 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, Uniforms, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { Buffer, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, Uniforms, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -10,7 +10,7 @@ import { getGPURenderPassFormat } from "../caches/getGPURenderPassFormat"; import { getGPURenderPipeline } from "../caches/getGPURenderPipeline"; import { getGPURenderTimestampQuery } from "../caches/getGPURenderTimestampQuery"; import { getGPUTexture } from "../caches/getGPUTexture"; -import { getIGPUVertexBuffer } from "../caches/getIGPUBuffer"; +import { getIGPUBuffer } from "../caches/getIGPUBuffer"; import { getIGPUComputePipeline } from "../caches/getIGPUComputePipeline"; import { IGPUShader } from "../caches/getIGPUPipelineLayout"; import { getIGPUSetBindGroups } from "../caches/getIGPUSetBindGroups"; @@ -19,14 +19,13 @@ import { getRealGPUBindGroup } from "../const"; import { ComputeObject } from "../data/ComputeObject"; import { ComputePass } from "../data/ComputePass"; import { ComputePipeline } from "../data/ComputePipeline"; -import { Workgroups } from "../data/Workgroups"; import { } from "../data/polyfills/OcclusionQuery"; import "../data/polyfills/RenderObject"; import "../data/polyfills/RenderPass"; import { RenderBundle } from "../data/RenderBundle"; +import { Workgroups } from "../data/Workgroups"; import { GPUQueue_submit } from "../eventnames"; -import { getIGPUSetIndexBuffer } from "../internal/getIGPUSetIndexBuffer"; -import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; +import { IRenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; export class RunWebGPU @@ -109,7 +108,7 @@ export class RunWebGPU timestampQuery.resolve(device, commandEncoder, renderPass); } - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IGPURenderPassFormat, renderObjects?: readonly IRenderPassObject[]) + protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: readonly IRenderPassObject[]) { if (!renderObjects) return; // @@ -211,7 +210,7 @@ export class RunWebGPU ); } - protected runRenderOcclusionQueryObject(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IGPURenderPassFormat, renderOcclusionQueryObject: OcclusionQuery) + protected runRenderOcclusionQueryObject(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderOcclusionQueryObject: OcclusionQuery) { passEncoder.beginOcclusionQuery(renderOcclusionQueryObject._queryIndex); renderOcclusionQueryObject.renderObjects.forEach((renderObject) => @@ -221,7 +220,7 @@ export class RunWebGPU passEncoder.endOcclusionQuery(); } - protected runRenderBundle(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IGPURenderPassFormat, renderBundleObject: RenderBundle) + protected runRenderBundle(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderBundleObject: RenderBundle) { const renderBundleMap: ChainMap<[RenderBundle, string], GPURenderBundle> = device["_renderBundleMap"] = device["_renderBundleMap"] || new ChainMap(); // @@ -242,7 +241,7 @@ export class RunWebGPU passEncoder.executeBundles([gpuRenderBundle]); } - protected runRenderBundleObjects(device: GPUDevice, passEncoder: GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObjects?: readonly RenderObject[]) + protected runRenderBundleObjects(device: GPUDevice, passEncoder: GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: readonly RenderObject[]) { // renderObjects.forEach((element) => @@ -299,7 +298,7 @@ export class RunWebGPU * @param renderObject 渲染对象。 * @param renderPass 渲染通道。 */ - protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: RenderObject) + protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, renderObject: RenderObject) { const { viewport, scissorRect, pipeline, uniforms: bindingResources, geometry } = renderObject; @@ -334,7 +333,7 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { // const renderPipelineResult = getNGPURenderPipeline(material, renderPassFormat, primitive, vertices, indices); @@ -431,14 +430,16 @@ export class RunWebGPU }); } - protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const renderPipeline = getNGPURenderPipeline(material, renderPassFormat, primitive, vertices, indices); // renderPipeline.vertexBuffers?.forEach((vertexBuffer, index) => { - const buffer = getIGPUVertexBuffer(vertexBuffer.data); + const buffer = getIGPUBuffer(vertexBuffer.data); + (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); + const gBuffer = getGPUBuffer(device, buffer); passEncoder.setVertexBuffer(index, gBuffer, vertexBuffer.offset, vertexBuffer.size); @@ -449,13 +450,13 @@ export class RunWebGPU { if (!indices) return; - const indexBuffer = getIGPUSetIndexBuffer(indices); + const buffer = getIGPUBuffer(indices); + (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); - const { buffer, indexFormat, offset, size } = indexBuffer; const gBuffer = getGPUBuffer(device, buffer); // - passEncoder.setIndexBuffer(gBuffer, indexFormat, offset, size); + passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); } protected runDrawVertex(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, drawVertex: DrawVertex) @@ -471,3 +472,5 @@ export class RunWebGPU } } +let autoIndex = 0; +let autoVertexIndex = 0; \ No newline at end of file diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/runs/RunWebGPUCommandCache.ts index 2e809e3..655c866 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/runs/RunWebGPUCommandCache.ts @@ -2,7 +2,7 @@ import { IRenderPassObject, RenderObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; -import { IGPURenderPassFormat } from "../internal/IGPURenderPassFormat"; +import { IRenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; import { RunWebGPU } from "./RunWebGPU"; @@ -11,7 +11,7 @@ import { RunWebGPU } from "./RunWebGPU"; */ export class RunWebGPUCommandCache extends RunWebGPU { - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IGPURenderPassFormat, renderObjects?: IRenderPassObject[]) + protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: IRenderPassObject[]) { const map: ChainMap<[string, IRenderPassObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); let caches = map.get([renderPassFormat._key, renderObjects]); @@ -47,7 +47,7 @@ export class RunWebGPUCommandCache extends RunWebGPU runCommands(passEncoder, caches); } - protected runRenderBundleObjects(device: GPUDevice, bundleEncoder: GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObjects?: RenderObject[]) + protected runRenderBundleObjects(device: GPUDevice, bundleEncoder: GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: RenderObject[]) { const map: ChainMap<[string, RenderObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); let caches = map.get([renderPassFormat._key, renderObjects]); @@ -86,7 +86,7 @@ export class RunWebGPUCommandCache extends RunWebGPU runCommands(bundleEncoder, { ...caches, commands }); } - protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IGPURenderPassFormat, renderObject: RenderObject) + protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, renderObject: RenderObject) { const map: ChainMap<[string, RenderObject], Array> = device["_IGPURenderObjectCommandMap"] = device["_IGPURenderObjectCommandMap"] || new ChainMap(); const _commands = passEncoder["_commands"] as any[]; -- Gitee From d418ac0544361cf792b78aa3e1962df58975159a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 13 Mar 2025 13:22:36 +0800 Subject: [PATCH 038/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E5=8C=BA=E7=BB=91=E5=AE=9A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 IBufferBindingInfo 接口移至 @feng3d/render-api - 重命名 IBufferBindingInfo 为 BufferBindingInfo - 更新相关函数和文件的引用 --- src/caches/getIGPUSetBindGroups.ts | 6 +++--- src/utils/getBufferBindingInfo.ts | 16 ++-------------- src/utils/updateBufferBinding.ts | 5 ++--- 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/caches/getIGPUSetBindGroups.ts b/src/caches/getIGPUSetBindGroups.ts index b31734b..26958e0 100644 --- a/src/caches/getIGPUSetBindGroups.ts +++ b/src/caches/getIGPUSetBindGroups.ts @@ -1,10 +1,10 @@ import { watcher } from "@feng3d/watcher"; -import { BufferBinding, Uniforms } from "@feng3d/render-api"; +import { BufferBinding, BufferBindingInfo, Uniforms } from "@feng3d/render-api"; import { getIGPUPipelineLayout, getIGPUShaderKey, IGPUShader } from "../caches/getIGPUPipelineLayout"; import { BindGroupLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { ChainMap } from "../utils/ChainMap"; -import { getBufferBindingInfo, IBufferBindingInfo } from "../utils/getBufferBindingInfo"; +import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; import { updateBufferBinding } from "../utils/updateBufferBinding"; import { getIGPUBuffer } from "./getIGPUBuffer"; import { IGPUBindGroupDescriptor, IGPUBindGroupEntry } from "./getGPUBindGroup"; @@ -62,7 +62,7 @@ function getIGPUSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, binding if (entry1.buffer) { const bufferBinding = ((typeof bindingResource === "number") ? [bindingResource] : bindingResource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 - const bufferBindingInfo: IBufferBindingInfo = variableInfo["_bufferBindingInfo"] ||= getBufferBindingInfo(variableInfo.type); + const bufferBindingInfo: BufferBindingInfo = variableInfo["_bufferBindingInfo"] ||= getBufferBindingInfo(variableInfo.type); // 更新缓冲区绑定的数据。 updateBufferBinding(resourceName, bufferBindingInfo, bufferBinding); // diff --git a/src/utils/getBufferBindingInfo.ts b/src/utils/getBufferBindingInfo.ts index 90ed7b3..821ba5b 100644 --- a/src/utils/getBufferBindingInfo.ts +++ b/src/utils/getBufferBindingInfo.ts @@ -1,3 +1,4 @@ +import { BufferBindingInfo } from "@feng3d/render-api"; import { ArrayInfo, StructInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; /** @@ -9,7 +10,7 @@ import { ArrayInfo, StructInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; * @param bufferBindingInfo 缓冲区绑定信息。 * @returns */ -export function getBufferBindingInfo(type: TypeInfo, paths: string[] = [], offset = 0, bufferBindingInfo: IBufferBindingInfo = { size: type.size, items: [] }) +export function getBufferBindingInfo(type: TypeInfo, paths: string[] = [], offset = 0, bufferBindingInfo: BufferBindingInfo = { size: type.size, items: [] }) { if (type.isStruct) { @@ -118,16 +119,3 @@ const templateFormatDataCls: { [key: string]: DataCls } = { type DataCls = Float32ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Int16ArrayConstructor; -/** - * 缓冲区绑定信息。 - */ -export interface IBufferBindingInfo -{ - size: number; - items: { - paths: string[]; - offset: number; - size: number; - Cls: DataCls; - }[] -} diff --git a/src/utils/updateBufferBinding.ts b/src/utils/updateBufferBinding.ts index ca209a4..e3bd4e9 100644 --- a/src/utils/updateBufferBinding.ts +++ b/src/utils/updateBufferBinding.ts @@ -1,9 +1,8 @@ -import { BufferBinding, UnReadonly } from "@feng3d/render-api"; +import { BufferBinding, BufferBindingInfo, UnReadonly } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { VariableInfo } from "wgsl_reflect"; import { getIGPUBuffer } from "../caches/getIGPUBuffer"; -import { IBufferBindingInfo } from "./getBufferBindingInfo"; /** * 初始化缓冲区绑定。 @@ -12,7 +11,7 @@ import { IBufferBindingInfo } from "./getBufferBindingInfo"; * @param uniformData * @returns */ -export function updateBufferBinding(resourceName: string, bufferBindingInfo: IBufferBindingInfo, uniformData: BufferBinding) +export function updateBufferBinding(resourceName: string, bufferBindingInfo: BufferBindingInfo, uniformData: BufferBinding) { if (uniformData["_variableInfo"] !== undefined) { -- Gitee From 6cedcfe1caa7e2759b5266d246491acc66e6a1bf Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 13 Mar 2025 16:09:17 +0800 Subject: [PATCH 039/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E7=BB=84=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重写 getGPUBindGroup 函数,移除 IGPUBindGroupDescriptor 接口 - 删除 getGPUBufferBinding 函数,直接在 getGPUBindGroup 中处理缓冲区绑定 - 更新相关接口和类型名称,简化代码结构 - 优化绑定组缓存逻辑,提高性能 --- src/caches/getGPUBindGroup.ts | 27 ++++++++++++++++++++------- src/caches/getGPUBufferBinding.ts | 18 ------------------ src/caches/getGPUTexture.ts | 4 ++-- src/caches/getIGPUSetBindGroups.ts | 20 ++++++++++---------- 4 files changed, 32 insertions(+), 37 deletions(-) delete mode 100644 src/caches/getGPUBufferBinding.ts diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 8781bf6..1560f42 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -5,13 +5,14 @@ import { getRealGPUBindGroup } from "../const"; import { VideoTexture } from "../data/VideoTexture"; import { GPUTextureView_destroy, IGPUSampler_changed } from "../eventnames"; import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; -import { getGPUBufferBinding } from "./getGPUBufferBinding"; +import { getGPUBuffer } from "./getGPUBuffer"; import { getGPUSampler } from "./getGPUSampler"; import { getGPUTextureView } from "./getGPUTextureView"; +import { getIGPUBuffer } from "./getIGPUBuffer"; -export function getGPUBindGroup(device: GPUDevice, bindGroup: IGPUBindGroupDescriptor) +export function getGPUBindGroup(device: GPUDevice, bindGroup: BindGroupDescriptor) { - const bindGroupMap: WeakMap = device["_bindGroupMap"] = device["_bindGroupMap"] || new WeakMap(); + const bindGroupMap: WeakMap = device["_bindGroupMap"] = device["_bindGroupMap"] || new WeakMap(); let gBindGroup = bindGroupMap.get(bindGroup); if (gBindGroup) return gBindGroup; @@ -46,7 +47,19 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: IGPUBindGroupDescr { updateResource = () => { - entry.resource = getGPUBufferBinding(device, v.resource as BufferBinding); + const resource = v.resource as BufferBinding; + // + const b = getIGPUBuffer(resource.bufferView); + const buffer = getGPUBuffer(device, b); + + const offset = resource.bufferView.byteOffset; + const size = resource.bufferView.byteLength; + + entry.resource = { + buffer, + offset, + size, + }; }; } else if ((v.resource as TextureView).texture) @@ -129,7 +142,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: IGPUBindGroupDescr * @see GPUBindGroupDescriptor * @see GPUDevice.createBindGroup */ -export interface IGPUBindGroupDescriptor +export interface BindGroupDescriptor { /** * The initial value of {@link GPUObjectBase#label|GPUObjectBase.label}. @@ -147,7 +160,7 @@ export interface IGPUBindGroupDescriptor * * {@link GPUBindGroupEntry} */ - entries: IGPUBindGroupEntry[]; + entries: BindGroupEntry[]; } /** @@ -155,7 +168,7 @@ export interface IGPUBindGroupDescriptor * * @see GPUBindGroupEntry */ -export interface IGPUBindGroupEntry +export interface BindGroupEntry { binding: GPUIndex32; diff --git a/src/caches/getGPUBufferBinding.ts b/src/caches/getGPUBufferBinding.ts deleted file mode 100644 index 7415f85..0000000 --- a/src/caches/getGPUBufferBinding.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { BufferBinding } from "@feng3d/render-api"; -import { getGPUBuffer } from "./getGPUBuffer"; -import { getIGPUBuffer } from "./getIGPUBuffer"; - -export function getGPUBufferBinding(device: GPUDevice, resource: BufferBinding): GPUBufferBinding -{ - const b = getIGPUBuffer(resource.bufferView); - const buffer = getGPUBuffer(device, b); - - const offset = resource.bufferView.byteOffset; - const size = resource.bufferView.byteLength; - - return { - buffer, - offset, - size, - }; -} diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 1584ff9..f466f24 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -20,7 +20,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC let gpuTexture: GPUTexture; if ("context" in textureLike) { - const canvasTexture = textureLike as CanvasTexture; + const canvasTexture = textureLike; const context = getGPUCanvasContext(device, canvasTexture.context); gpuTexture = context.getCurrentTexture(); @@ -248,4 +248,4 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC } let autoIndex = 0; -const _GPUTextureMap = "_GPUTextureMap"; \ No newline at end of file +const _GPUTextureMap = "_GPUTextureMap"; diff --git a/src/caches/getIGPUSetBindGroups.ts b/src/caches/getIGPUSetBindGroups.ts index 26958e0..e2a58b8 100644 --- a/src/caches/getIGPUSetBindGroups.ts +++ b/src/caches/getIGPUSetBindGroups.ts @@ -7,7 +7,7 @@ import { ChainMap } from "../utils/ChainMap"; import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; import { updateBufferBinding } from "../utils/updateBufferBinding"; import { getIGPUBuffer } from "./getIGPUBuffer"; -import { IGPUBindGroupDescriptor, IGPUBindGroupEntry } from "./getGPUBindGroup"; +import { BindGroupDescriptor, BindGroupEntry } from "./getGPUBindGroup"; export function getIGPUSetBindGroups(shader: IGPUShader, bindingResources: Uniforms) { @@ -23,22 +23,22 @@ export function getIGPUSetBindGroups(shader: IGPUShader, bindingResources: Unifo const layout = getIGPUPipelineLayout(shader); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { - gpuSetBindGroups[group] = getIGPUSetBindGroup(bindGroupLayout, bindingResources); + gpuSetBindGroups[group] = getSetBindGroup(bindGroupLayout, bindingResources); }); return gpuSetBindGroups; } -const bindGroupsMap = new ChainMap<[string, Uniforms], IGPUSetBindGroup[]>(); +const bindGroupsMap = new ChainMap<[string, Uniforms], SetBindGroup[]>(); -function getIGPUSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, bindingResources: Uniforms): IGPUSetBindGroup +function getSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, bindingResources: Uniforms): SetBindGroup { - const map: ChainMap, IGPUSetBindGroup> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); + const map: ChainMap, SetBindGroup> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); const subBindingResources = bindGroupLayout.entryNames.map((v) => bindingResources[v]); - let setBindGroup: IGPUSetBindGroup = map.get(subBindingResources); + let setBindGroup: SetBindGroup = map.get(subBindingResources); if (setBindGroup) return setBindGroup; - const entries: IGPUBindGroupEntry[] = []; + const entries: BindGroupEntry[] = []; setBindGroup = { bindGroup: { layout: bindGroupLayout, entries } }; map.set(subBindingResources, setBindGroup); @@ -47,7 +47,7 @@ function getIGPUSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, binding { const { variableInfo, binding } = entry1; // - const entry: IGPUBindGroupEntry = { binding, resource: null }; + const entry: BindGroupEntry = { binding, resource: null }; entries.push(entry); @@ -90,14 +90,14 @@ function getIGPUSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, binding * * {@link GPUBindingCommandsMixin.setBindGroup} */ -interface IGPUSetBindGroup +interface SetBindGroup { /** * GPU绑定组。 * * Bind group to use for subsequent render or compute commands. */ - bindGroup: IGPUBindGroupDescriptor; + bindGroup: BindGroupDescriptor; /** * Array containing buffer offsets in bytes for each entry in `bindGroup` marked as {@link GPUBindGroupLayoutEntry#buffer}.{@link GPUBufferBindingLayout#hasDynamicOffset}.--> -- Gitee From f6438bd8aac1841aaeff44b340cdac84157af98b Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 13 Mar 2025 20:33:46 +0800 Subject: [PATCH 040/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 Vue Reactivity 模块以增强响应式处理 - 优化 getGPUCanvasContext 函数,使用 computed 和 reactive 改进配置更新逻辑 - 调整 getGPUComputePipeline 和 getGPUTexture 函数以适应新逻辑 - 移除未使用的 getIGPUComputePipeline 函数 - 简化 RunWebGPU 类中的 runComputePipeline 方法 --- package.json | 3 ++- src/caches/getGPUCanvasContext.ts | 38 ++++++++++++++++++++-------- src/caches/getGPUComputePipeline.ts | 6 ++--- src/caches/getGPUTexture.ts | 2 +- src/caches/getIGPUComputePipeline.ts | 19 -------------- src/runs/RunWebGPU.ts | 7 ++--- 6 files changed, 36 insertions(+), 39 deletions(-) delete mode 100644 src/caches/getIGPUComputePipeline.ts diff --git a/package.json b/package.json index a4391f6..8b4cfde 100644 --- a/package.json +++ b/package.json @@ -58,9 +58,10 @@ "vitest": "^0.32.2" }, "dependencies": { - "@feng3d/render-api": "0.0.2", "@feng3d/event": "^0.8.4", + "@feng3d/render-api": "0.0.2", "@feng3d/watcher": "^0.8.11", + "@vue/reactivity": "^3.5.13", "@webgpu/types": "0.1.49", "stats.js": "^0.17.0", "wgsl_reflect": "^1.0.16" diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index 3637463..10a3e53 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -1,17 +1,39 @@ import { CanvasContext } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import "../data/polyfills/CanvasContext"; +import { computed, ComputedRef, reactive } from "@vue/reactivity"; export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) { - let gpuCanvasContext = canvasContextMap[context.canvasId]; - if (gpuCanvasContext) return gpuCanvasContext; + let result = canvasContextMap[context.canvasId]; + if (result) return result; const canvas = document.getElementById(context.canvasId) as HTMLCanvasElement; - gpuCanvasContext = canvas.getContext("webgpu"); + const gpuCanvasContext = canvas.getContext("webgpu"); - canvasContextMap[context.canvasId] = gpuCanvasContext; + result = computed(() => + { + // 监听 + const ro = reactive(context); + const configuration = ro.configuration; + if (configuration) + { + configuration.format; + configuration.usage; + configuration.viewFormats?.forEach(() => { }); + configuration.colorSpace; + configuration.toneMapping?.mode; + configuration.alphaMode; + } + + // 执行 + updateConfigure(); + + return gpuCanvasContext; + }); + + canvasContextMap[context.canvasId] = result; const updateConfigure = () => { @@ -38,11 +60,7 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) }); }; - updateConfigure(); - - watcher.watchobject(context, { configuration: { usage: undefined, format: undefined, colorSpace: undefined, toneMapping: { mode: undefined }, alphaMode: undefined } }, updateConfigure); - - return gpuCanvasContext; + return result; } -const canvasContextMap: { [canvasId: string]: GPUCanvasContext } = {}; +const canvasContextMap: { [canvasId: string]: ComputedRef } = {}; diff --git a/src/caches/getGPUComputePipeline.ts b/src/caches/getGPUComputePipeline.ts index dd8515b..856b618 100644 --- a/src/caches/getGPUComputePipeline.ts +++ b/src/caches/getGPUComputePipeline.ts @@ -30,15 +30,15 @@ export function getGPUComputePipeline(device: GPUDevice, computePipeline: Comput } // 从GPU管线中获取管线布局。 - const gpuPipelineLayout = getIGPUPipelineLayout({ compute: computePipeline.compute.code }); + const gpuPipelineLayout = getIGPUPipelineLayout({ compute: computeStage.code }); const layout = getGPUPipelineLayout(device, gpuPipelineLayout); pipeline = device.createComputePipeline({ layout, compute: { - ...computePipeline.compute, - module: getGPUShaderModule(device, computePipeline.compute.code), + ...computeStage, + module: getGPUShaderModule(device, computeStage.code), }, }); computePipelineMap.set(computePipeline, pipeline); diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index f466f24..3fa8fa1 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -21,7 +21,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC if ("context" in textureLike) { const canvasTexture = textureLike; - const context = getGPUCanvasContext(device, canvasTexture.context); + const context = getGPUCanvasContext(device, canvasTexture.context).value; gpuTexture = context.getCurrentTexture(); diff --git a/src/caches/getIGPUComputePipeline.ts b/src/caches/getIGPUComputePipeline.ts deleted file mode 100644 index 9e4faad..0000000 --- a/src/caches/getIGPUComputePipeline.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { UnReadonly } from "@feng3d/render-api"; -import { ComputePipeline } from "../data/ComputePipeline"; -import { ComputeStage } from "../data/ComputeStage"; -import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; - -/** - * 从渲染管线描述、渲染通道描述以及完整的顶点属性数据映射获得完整的渲染管线描述以及顶点缓冲区数组。 - *获取完整的计算管线描述。 - * - * @param computePipeline 计算管线描述。 - * @returns 完整的计算管线描述。 - */ -export function getIGPUComputePipeline(computePipeline: ComputePipeline): ComputePipeline -{ - - - return computePipeline; -} - diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index bd06d50..fe0ea93 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -11,7 +11,6 @@ import { getGPURenderPipeline } from "../caches/getGPURenderPipeline"; import { getGPURenderTimestampQuery } from "../caches/getGPURenderTimestampQuery"; import { getGPUTexture } from "../caches/getGPUTexture"; import { getIGPUBuffer } from "../caches/getIGPUBuffer"; -import { getIGPUComputePipeline } from "../caches/getIGPUComputePipeline"; import { IGPUShader } from "../caches/getIGPUPipelineLayout"; import { getIGPUSetBindGroups } from "../caches/getIGPUSetBindGroups"; import { getNGPURenderPipeline } from "../caches/getNGPURenderPipeline"; @@ -270,11 +269,9 @@ export class RunWebGPU this.runWorkgroups(passEncoder, workgroups); } - protected runComputePipeline(device: GPUDevice, passEncoder: GPUComputePassEncoder, material: ComputePipeline) + protected runComputePipeline(device: GPUDevice, passEncoder: GPUComputePassEncoder, pipeline: ComputePipeline) { - const gpuComputePipeline = getIGPUComputePipeline(material); - - const computePipeline = getGPUComputePipeline(device, gpuComputePipeline); + const computePipeline = getGPUComputePipeline(device, pipeline); passEncoder.setPipeline(computePipeline); } -- Gitee From ccf3f2685dc2ca99b6b9df5389538e6ab3f0f495 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 13 Mar 2025 22:15:03 +0800 Subject: [PATCH 041/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=94=BB=E5=B8=83=E9=85=8D=E7=BD=AE=E5=92=8C=E7=BA=B9=E7=90=86?= =?UTF-8?q?=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 CanvasConfiguration 接口,将属性标记为只读 - 优化 getGPUCanvasContext 和 getGPUTexture 函数的实现 - 移除未使用的 stats.js 依赖 - 在 index.ts 中导出 export 模块 --- .../src/webgpu/RenderObjectChanges/index.ts | 2 +- examples/src/webgpu/blending/index.ts | 4 +-- package.json | 1 - src/caches/getGPUCanvasContext.ts | 26 +++++++++---------- src/caches/getGPUTexture.ts | 2 +- src/data/CanvasConfiguration.ts | 14 +++++----- src/data/polyfills/CanvasContext.ts | 2 +- src/export.ts | 9 +++++++ src/index.ts | 2 ++ 9 files changed, 36 insertions(+), 26 deletions(-) create mode 100644 src/export.ts diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index 2ff32d8..dc95b4d 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -29,7 +29,7 @@ const init = async (canvas: HTMLCanvasElement) => } ` }, }, - geometry:{ + geometry: { vertices: { position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 }, diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 7becf26..0e1cd0e 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -3,7 +3,7 @@ import { mat4 } from "wgpu-matrix"; import texturedQuadWGSL from "./texturedQuad.wgsl"; import { BlendComponent, CanvasContext, IRenderPassObject, RenderObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, TextureView, Uniforms } from "@feng3d/render-api"; -import { WebGPU } from "@feng3d/webgpu"; +import { reactive, WebGPU } from "@feng3d/webgpu"; declare module "@feng3d/render-api" { @@ -469,7 +469,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const { srcTexture, dstTexture, srcBindGroup, dstBindGroup } = textureSets[settings.textureSet === "premultiplied alpha" ? 0 : 1]; - context.configuration.alphaMode = settings.alphaMode; + reactive(context.configuration).alphaMode = settings.alphaMode; // Apply the clearValue, pre-multiplying or not it based on the settings. { diff --git a/package.json b/package.json index 8b4cfde..91efc3e 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "@feng3d/watcher": "^0.8.11", "@vue/reactivity": "^3.5.13", "@webgpu/types": "0.1.49", - "stats.js": "^0.17.0", "wgsl_reflect": "^1.0.16" } } diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index 10a3e53..046777d 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -1,12 +1,11 @@ import { CanvasContext } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; -import "../data/polyfills/CanvasContext"; import { computed, ComputedRef, reactive } from "@vue/reactivity"; +import "../data/polyfills/CanvasContext"; export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) { let result = canvasContextMap[context.canvasId]; - if (result) return result; + if (result) return result.value; const canvas = document.getElementById(context.canvasId) as HTMLCanvasElement; @@ -38,29 +37,28 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) const updateConfigure = () => { // - context.configuration = context.configuration || {}; - const format = (context.configuration as any).format = context.configuration.format || navigator.gpu.getPreferredCanvasFormat(); - - let usage = 0; + const configuration = context.configuration || {}; - if (context.configuration.usage) - { - usage = context.configuration.usage; - } + const format = configuration.format || navigator.gpu.getPreferredCanvasFormat(); // 附加上 GPUTextureUsage.RENDER_ATTACHMENT - usage = usage | GPUTextureUsage.RENDER_ATTACHMENT; + const usage = (configuration.usage ?? 0) + | GPUTextureUsage.COPY_SRC + | GPUTextureUsage.COPY_DST + | GPUTextureUsage.TEXTURE_BINDING + | GPUTextureUsage.STORAGE_BINDING + | GPUTextureUsage.RENDER_ATTACHMENT; // gpuCanvasContext.configure({ - ...context.configuration, + ...configuration, device, usage, format, }); }; - return result; + return result.value; } const canvasContextMap: { [canvasId: string]: ComputedRef } = {}; diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 3fa8fa1..f466f24 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -21,7 +21,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC if ("context" in textureLike) { const canvasTexture = textureLike; - const context = getGPUCanvasContext(device, canvasTexture.context).value; + const context = getGPUCanvasContext(device, canvasTexture.context); gpuTexture = context.getCurrentTexture(); diff --git a/src/data/CanvasConfiguration.ts b/src/data/CanvasConfiguration.ts index 14885a2..36c77ad 100644 --- a/src/data/CanvasConfiguration.ts +++ b/src/data/CanvasConfiguration.ts @@ -13,7 +13,7 @@ export interface CanvasConfiguration * when setting a custom usage if you wish to use textures returned by * {@link GPUCanvasContext#getCurrentTexture} as color targets for a render pass. */ - usage?: GPUTextureUsageFlags; + readonly usage?: GPUTextureUsageFlags; /** * The format that textures returned by {@link GPUCanvasContext#getCurrentTexture} will have. @@ -21,7 +21,7 @@ export interface CanvasConfiguration * * 默认 `navigator.gpu.getPreferredCanvasFormat()` 。 */ - format?: GPUTextureFormat; + readonly format?: GPUTextureFormat; /** * Determines the effect that alpha values will have on the content of textures returned by @@ -29,21 +29,23 @@ export interface CanvasConfiguration * * 默认 'premultiplied' 。 */ - alphaMode?: GPUCanvasAlphaMode; + readonly alphaMode?: GPUCanvasAlphaMode; /** * The formats that views created from textures returned by * {@link GPUCanvasContext#getCurrentTexture} may use. */ - viewFormats?: GPUTextureFormat[]; + readonly viewFormats?: GPUTextureFormat[]; + /** * The color space that values written into textures returned by * {@link GPUCanvasContext#getCurrentTexture} should be displayed with. */ - colorSpace?: PredefinedColorSpace; + readonly colorSpace?: PredefinedColorSpace; + /** * The tone mapping determines how the content of textures returned by * {@link GPUCanvasContext#getCurrentTexture} are to be displayed. */ - toneMapping?: GPUCanvasToneMapping; + readonly toneMapping?: GPUCanvasToneMapping; } \ No newline at end of file diff --git a/src/data/polyfills/CanvasContext.ts b/src/data/polyfills/CanvasContext.ts index 80691ad..108eb97 100644 --- a/src/data/polyfills/CanvasContext.ts +++ b/src/data/polyfills/CanvasContext.ts @@ -12,6 +12,6 @@ declare module "@feng3d/render-api" /** * WebGPU画布配置。默认有引擎自动设置。 */ - configuration?: CanvasConfiguration; + readonly configuration?: CanvasConfiguration; } } diff --git a/src/export.ts b/src/export.ts new file mode 100644 index 0000000..b066afc --- /dev/null +++ b/src/export.ts @@ -0,0 +1,9 @@ +import { UnReadonly } from "@feng3d/render-api"; +import { Reactive, reactive as vueReactive } from "@vue/reactivity"; + +/** + * Vue响应式。 + * + * 额外把只读属性去掉(引擎希望原始数据只用于访问,不直接修改,通过修改响应式数据来触发引擎更新逻辑并间接修改原始数据)。 + */ +export const reactive: (target: T) => Reactive> = vueReactive; diff --git a/src/index.ts b/src/index.ts index 7954364..a0dbcd7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,3 +32,5 @@ export * as internal from "./internal"; export * from "./utils/ChainMap"; export * from "./utils/getOffscreenCanvasId"; +// 导出 +export * from "./export"; -- Gitee From c999140fc3d5c0d8281984181e2b5860dc165c2c Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 13 Mar 2025 23:30:20 +0800 Subject: [PATCH 042/214] =?UTF-8?q?refactor(src):=20=E8=B0=83=E6=95=B4=20g?= =?UTF-8?q?etGPUCanvasContext=20=E5=87=BD=E6=95=B0=E4=B8=AD=E7=9A=84=20rea?= =?UTF-8?q?ctive=20=E8=B0=83=E7=94=A8=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 reactive 调用移至函数开头,以优化性能 - 调整代码结构,提高可读性 --- src/caches/getGPUCanvasContext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index 046777d..b472aff 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -11,10 +11,10 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) const gpuCanvasContext = canvas.getContext("webgpu"); + const ro = reactive(context); result = computed(() => { // 监听 - const ro = reactive(context); const configuration = ro.configuration; if (configuration) { -- Gitee From fdab28c68e3f56b3e5c700e085333033685edfdd Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 13 Mar 2025 23:34:01 +0800 Subject: [PATCH 043/214] =?UTF-8?q?feat(core):=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E5=8C=BA=E6=95=B0=E6=8D=AE=E7=9A=84=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E5=BC=8F=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 reactive 函数,将缓冲区对象转换为响应式对象 - 在写入缓冲区数据时,使用响应式对象的属性进行操作 - 优化缓冲区数据更新逻辑,提高渲染性能 --- .../src/webgpu/textRenderingMsdf/index.ts | 5 +- .../src/webgpu/textRenderingMsdf/msdfText.ts | 6 +- src/caches/getGPUBuffer.ts | 119 ++++++++++-------- src/index.ts | 5 +- src/{export.ts => reactivity.ts} | 7 +- src/utils/updateBufferBinding.ts | 5 +- 6 files changed, 80 insertions(+), 67 deletions(-) rename src/{export.ts => reactivity.ts} (54%) diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index ba8f96d..cb5d9af 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -1,7 +1,7 @@ import { mat4, vec3 } from "wgpu-matrix"; import { IRenderPassObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; +import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; import basicVertWGSL from "../../shaders/basic.vert.wgsl"; import vertexPositionColorWGSL from "../../shaders/vertexPositionColor.frag.wgsl"; @@ -9,7 +9,6 @@ import vertexPositionColorWGSL from "../../shaders/vertexPositionColor.frag.wgsl import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; import { MsdfTextRenderer } from "./msdfText"; - const init = async (canvas: HTMLCanvasElement) => { const devicePixelRatio = window.devicePixelRatio || 1; @@ -248,7 +247,7 @@ setBlendConstant().`, dataOffset: transformationMatrix.byteOffset, size: transformationMatrix.byteLength }); - buffer.writeBuffers = writeBuffers; + reactive(buffer).writeBuffers = writeBuffers; const renderObjects: IRenderPassObject[] = []; diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index d467dcb..16fe4e3 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -3,7 +3,7 @@ import { mat4, Mat4 } from "wgpu-matrix"; import msdfTextWGSL from "./msdfText.wgsl"; import { IRenderPassObject, RenderPipeline, Sampler, Texture, Uniforms } from "@feng3d/render-api"; -import { getIGPUBuffer, RenderBundle } from "@feng3d/webgpu"; +import { getIGPUBuffer, reactive, RenderBundle } from "@feng3d/webgpu"; // The kerning map stores a spare map of character ID pairs with an associated // X offset that should be applied to the character spacing when the second @@ -112,7 +112,7 @@ export class MsdfText dataOffset: 0, size: this.bufferArray.length }); - buffer.writeBuffers = writeBuffers; + reactive(buffer).writeBuffers = writeBuffers; } return this.renderBundle; @@ -443,7 +443,7 @@ export class MsdfTextRenderer writeBuffers.push({ data: this.cameraUniformBuffer, }); - buffer.writeBuffers = writeBuffers; + reactive(buffer).writeBuffers = writeBuffers; } render(renderObjects: IRenderPassObject[], ...text: MsdfText[]) diff --git a/src/caches/getGPUBuffer.ts b/src/caches/getGPUBuffer.ts index 1226ce4..c7c31f5 100644 --- a/src/caches/getGPUBuffer.ts +++ b/src/caches/getGPUBuffer.ts @@ -1,5 +1,6 @@ import { Buffer, UnReadonly } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; +import { computed, ComputedRef, effect, reactive } from "../reactivity"; /** * 除了GPU与CPU数据交换的`MAP_READ`与`MAP_WRITE`除外。 @@ -26,10 +27,10 @@ const defaultGPUBufferUsage = 0 */ export function getGPUBuffer(device: GPUDevice, buffer: Buffer) { - const gBufferMap: WeakMap = device["_gBufferMap"] = device["_gBufferMap"] || new WeakMap(); + const gBufferMap: WeakMap> = device["_gBufferMap"] = device["_gBufferMap"] || new WeakMap>(); - let gBuffer: GPUBuffer = gBufferMap.get(buffer); - if (gBuffer) return gBuffer; + let result = gBufferMap.get(buffer); + if (result) return result.value; const size = buffer.size; console.assert(size && (size % 4 === 0), `初始化缓冲区时必须设置缓冲区尺寸且必须为4的倍数!`); @@ -42,7 +43,7 @@ export function getGPUBuffer(device: GPUDevice, buffer: Buffer) // 初始化时存在数据,则使用map方式上传第一次数据。 const mappedAtCreation = buffer.data !== undefined; - gBuffer = device.createBuffer({ label, size, usage, mappedAtCreation }); + const gBuffer = device.createBuffer({ label, size, usage, mappedAtCreation }); if (mappedAtCreation) { @@ -62,63 +63,72 @@ export function getGPUBuffer(device: GPUDevice, buffer: Buffer) const writeBuffer = () => { // 处理数据写入GPU缓冲 - if (buffer.writeBuffers) + if (!buffer.writeBuffers) return; + buffer.writeBuffers.forEach((writeBuffer) => { - buffer.writeBuffers.forEach((v) => + const bufferOffset = writeBuffer.bufferOffset ?? 0; + const data = writeBuffer.data; + const dataOffset = writeBuffer.dataOffset ?? 0; + const size = writeBuffer.size; + + let arrayBuffer: ArrayBuffer; + let dataOffsetByte: number; + let sizeByte: number; + if (ArrayBuffer.isView(data)) { - const bufferData = v; - - let bufferOffset = 0; - let dataOffset = 0; - bufferOffset = bufferData.bufferOffset ?? bufferOffset; - const data = bufferData.data; - dataOffset = bufferData.dataOffset ?? dataOffset; - const size = bufferData.size; - - let arrayBuffer: ArrayBuffer; - let dataOffsetByte: number; - let sizeByte: number; - if (ArrayBuffer.isView(data)) - { - const bytesPerElement = (data as Uint8Array).BYTES_PER_ELEMENT; - - arrayBuffer = data.buffer; - dataOffsetByte = data.byteOffset + bytesPerElement * dataOffset; - sizeByte = size ? (bytesPerElement * size) : data.byteLength; - } - else - { - arrayBuffer = data; - dataOffsetByte = dataOffset ?? 0; - sizeByte = size ?? (data.byteLength - dataOffsetByte); - } - - // 防止给出数据不够的情况 - console.assert(sizeByte <= arrayBuffer.byteLength - dataOffsetByte, `上传的尺寸超出数据范围!`); - - console.assert(sizeByte % 4 === 0, `写入数据长度不是4的倍数!`); - - // - device.queue.writeBuffer( - gBuffer, - bufferOffset, - arrayBuffer, - dataOffsetByte, - sizeByte, - ); - }); - buffer.writeBuffers = null; - } + const bytesPerElement = (data as Uint8Array).BYTES_PER_ELEMENT; + + arrayBuffer = data.buffer; + dataOffsetByte = data.byteOffset + bytesPerElement * dataOffset; + sizeByte = size ? (bytesPerElement * size) : data.byteLength; + } + else + { + arrayBuffer = data; + dataOffsetByte = dataOffset ?? 0; + sizeByte = size ?? (data.byteLength - dataOffsetByte); + } + + // 防止给出数据不够的情况 + console.assert(sizeByte <= arrayBuffer.byteLength - dataOffsetByte, `上传的尺寸超出数据范围!`); + + console.assert(sizeByte % 4 === 0, `写入数据长度不是4的倍数!`); + + // + device.queue.writeBuffer( + gBuffer, + bufferOffset, + arrayBuffer, + dataOffsetByte, + sizeByte, + ); + }); + rb.writeBuffers = null; }; - writeBuffer(); - watcher.watch(buffer, "writeBuffers", writeBuffer); + const rb = reactive(buffer); + // 处理数据写入GPU缓冲 + result = computed(() => + { + // 监听 + rb.writeBuffers?.forEach(() => { }); + + // 执行 + writeBuffer(); + + return gBuffer; + }); + + // 这行是不是可以删掉? + effect(() =>{ + result.value; + }) const dataChange = () => { const writeBuffers = buffer.writeBuffers || []; writeBuffers.push({ data: buffer.data }); - buffer.writeBuffers = writeBuffers; + rb.writeBuffers = writeBuffers; }; watcher.watch(buffer, "data", dataChange); @@ -133,12 +143,11 @@ export function getGPUBuffer(device: GPUDevice, buffer: Buffer) gBufferMap.delete(buffer); // - watcher.unwatch(buffer, "writeBuffers", writeBuffer); watcher.unwatch(buffer, "data", dataChange); }; })(gBuffer.destroy); - gBufferMap.set(buffer, gBuffer); + gBufferMap.set(buffer, result); - return gBuffer; + return result.value; } diff --git a/src/index.ts b/src/index.ts index a0dbcd7..de74b04 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,5 +32,6 @@ export * as internal from "./internal"; export * from "./utils/ChainMap"; export * from "./utils/getOffscreenCanvasId"; -// 导出 -export * from "./export"; +// 导出反应式相关功能 +export * from "./reactivity"; + diff --git a/src/export.ts b/src/reactivity.ts similarity index 54% rename from src/export.ts rename to src/reactivity.ts index b066afc..a6b45bc 100644 --- a/src/export.ts +++ b/src/reactivity.ts @@ -1,9 +1,12 @@ import { UnReadonly } from "@feng3d/render-api"; -import { Reactive, reactive as vueReactive } from "@vue/reactivity"; +import { reactive as vueReactive } from "@vue/reactivity"; + +export { computed, type ComputedRef, effect } from "@vue/reactivity"; /** * Vue响应式。 * * 额外把只读属性去掉(引擎希望原始数据只用于访问,不直接修改,通过修改响应式数据来触发引擎更新逻辑并间接修改原始数据)。 */ -export const reactive: (target: T) => Reactive> = vueReactive; +export const reactive: (target: T) => UnReadonly = vueReactive as any; + diff --git a/src/utils/updateBufferBinding.ts b/src/utils/updateBufferBinding.ts index e3bd4e9..f6bcba8 100644 --- a/src/utils/updateBufferBinding.ts +++ b/src/utils/updateBufferBinding.ts @@ -3,6 +3,7 @@ import { watcher } from "@feng3d/watcher"; import { VariableInfo } from "wgsl_reflect"; import { getIGPUBuffer } from "../caches/getIGPUBuffer"; +import { reactive } from "../reactivity"; /** * 初始化缓冲区绑定。 @@ -52,7 +53,7 @@ export function updateBufferBinding(resourceName: string, bufferBindingInfo: Buf console.warn(`没有找到 统一块变量属性 ${paths.join(".")} 的值!`); } -return; + return; } } @@ -72,7 +73,7 @@ return; const writeBuffers = buffer.writeBuffers ?? []; writeBuffers.push({ bufferOffset: offset + itemInfoOffset, data: data.buffer, dataOffset: data.byteOffset, size: Math.min(itemInfoSize, data.byteLength) }); - buffer.writeBuffers = writeBuffers; + reactive(buffer).writeBuffers = writeBuffers; }; update(); -- Gitee From 1afc15b1afcb639d363eeb54bfb344f409f0ed23 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 13 Mar 2025 23:39:51 +0800 Subject: [PATCH 044/214] =?UTF-8?q?refactor(webgpu):=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20reactive=20=E5=87=BD=E6=95=B0=E5=8C=85=E8=A3=85=20GPUBuffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在多个地方,将 buffer.writeBuffers 替换为 reactive(buffer).writeBuffers。这种改动利用了 reactive 函数来增强数据的响应性,可能为未来的数据处理带来便利。 --- examples/src/webgpu/skinnedMesh/index.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 1682ca3..93ff7ac 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -8,7 +8,7 @@ import { gridIndices } from "./gridData"; import { createSkinnedGridBuffers, createSkinnedGridRenderPipeline } from "./gridUtils"; import { IPassEncoder, RenderPass, RenderPassDescriptor, Texture, Uniforms, RenderObject } from "@feng3d/render-api"; -import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; +import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -154,7 +154,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => data: new Uint32Array([RenderMode[settings.renderMode]]), }); - buffer.writeBuffers = writeBuffers; + reactive(buffer).writeBuffers = writeBuffers; }); // Determine whether the mesh is static or whether skinning is activated gui.add(settings, "skinMode", ["ON", "OFF"]).onChange(() => @@ -180,7 +180,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => bufferOffset: 4, data: new Uint32Array([SkinMode[settings.skinMode]]), }); - buffer.writeBuffers = writeBuffers; + reactive(buffer).writeBuffers = writeBuffers; }); const animFolder = gui.addFolder("Animation Settings"); animFolder.add(settings, "angle", 0.05, 0.5).step(0.05); @@ -384,7 +384,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => data: gridBoneCollection.bindPosesInv[i] }); } - buffer.writeBuffers = writeBuffers; + reactive(buffer).writeBuffers = writeBuffers; // A map that maps a joint index to the original matrix transformation of a bone const origMatrices = new Map(); @@ -458,7 +458,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => dataOffset: modelMatrix.byteOffset, size: modelMatrix.byteLength }); - buffer.writeBuffers = writeBuffers; + reactive(buffer).writeBuffers = writeBuffers; // Write to skinned grid bone uniform buffer const buffer0 = getIGPUBuffer(skinnedGridJointUniformBuffer); @@ -470,7 +470,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => data: gridBoneCollection.transforms[i] }); } - buffer0.writeBuffers = writeBuffers0; + reactive(buffer0).writeBuffers = writeBuffers0; // Update node matrixes for (const scene of whaleScene.scenes) -- Gitee From 18e079b2e61f0e8043066c0e8cb5c1e030bb962c Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 00:48:21 +0800 Subject: [PATCH 045/214] =?UTF-8?q?refactor(webgpu):=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20reactive=20=E5=87=BD=E6=95=B0=E5=A4=84=E7=90=86=20GPU=20?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在多个示例中,将 getIGPUBuffer 替换为 reactive(getIGPUBuffer) - 此更改旨在利用 reactive 函数的响应式特性,提高代码的灵活性和性能 - 受影响的主要文件包括: - bitonicSort/index.ts - cornell/common.ts - cornell/radiosity.ts - deferredRendering/index.ts - imageBlur/index.ts - multipleCanvases/index.ts - particles/index.ts - renderBundles/index.ts - samplerParameters/index.ts - shadowMapping/index.ts - skinnedMesh/glbUtils.ts --- examples/src/webgpu/bitonicSort/index.ts | 6 ++--- examples/src/webgpu/cornell/common.ts | 4 +-- examples/src/webgpu/cornell/radiosity.ts | 4 +-- .../src/webgpu/deferredRendering/index.ts | 14 +++++----- examples/src/webgpu/imageBlur/index.ts | 4 +-- examples/src/webgpu/multipleCanvases/index.ts | 6 ++--- examples/src/webgpu/particles/index.ts | 8 +++--- examples/src/webgpu/renderBundles/index.ts | 4 +-- .../src/webgpu/samplerParameters/index.ts | 26 +++++++++---------- examples/src/webgpu/shadowMapping/index.ts | 8 +++--- examples/src/webgpu/skinnedMesh/glbUtils.ts | 4 +-- 11 files changed, 44 insertions(+), 44 deletions(-) diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index fcbf677..0a694b5 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,6 +1,6 @@ import { Buffer, BufferBinding, CommandEncoder, RenderPassDescriptor, Submit, Uniforms } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { ComputePipeline, getIGPUBuffer, ComputePass, TimestampQuery, WebGPU } from "@feng3d/webgpu"; +import { ComputePipeline, getIGPUBuffer, ComputePass, TimestampQuery, WebGPU, reactive } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats.js"; @@ -707,7 +707,7 @@ async function init( let iGPUBuffer = getIGPUBuffer(elementsInputBuffer.bufferView); let writeBuffers = iGPUBuffer.writeBuffers || []; writeBuffers.push({ data: elements }); - iGPUBuffer.writeBuffers = writeBuffers; + reactive(iGPUBuffer).writeBuffers = writeBuffers; const dims = new Float32Array([ settings["Grid Width"], @@ -722,7 +722,7 @@ async function init( writeBuffers = iGPUBuffer.writeBuffers || []; writeBuffers.push({ data: dims }); writeBuffers.push({ bufferOffset: 8, data: stepDetails }); - iGPUBuffer.writeBuffers = writeBuffers; + reactive(iGPUBuffer).writeBuffers = writeBuffers; const commandEncoder: CommandEncoder = { passEncoders: [] }; const submit: Submit = { commandEncoders: [commandEncoder] }; diff --git a/examples/src/webgpu/cornell/common.ts b/examples/src/webgpu/cornell/common.ts index b02e3d6..c4c9ffc 100644 --- a/examples/src/webgpu/cornell/common.ts +++ b/examples/src/webgpu/cornell/common.ts @@ -1,5 +1,5 @@ import { Uniforms } from "@feng3d/render-api"; -import { getIGPUBuffer } from "@feng3d/webgpu"; +import { getIGPUBuffer, reactive } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; import commonWGSL from "./common.wgsl"; @@ -77,7 +77,7 @@ export default class Common uniformDataU32[33] = 0xffffffff * Math.random(); uniformDataU32[34] = 0xffffffff * Math.random(); - getIGPUBuffer(this.uniformBuffer).writeBuffers = [{ data: uniformDataF32 }]; + reactive(getIGPUBuffer(this.uniformBuffer)).writeBuffers = [{ data: uniformDataF32 }]; this.frame++; } diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index 1bbf97c..38bff0c 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -1,5 +1,5 @@ import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; -import { ComputePipeline, getIGPUBuffer } from "@feng3d/webgpu"; +import { ComputePipeline, getIGPUBuffer, reactive } from "@feng3d/webgpu"; import Common from "./common"; import radiosityWGSL from "./radiosity.wgsl"; @@ -169,6 +169,6 @@ export default class Radiosity uniformDataF32[4] = this.scene.lightCenter[0]; uniformDataF32[5] = this.scene.lightCenter[1]; uniformDataF32[6] = this.scene.lightCenter[2]; - getIGPUBuffer(this.uniformBuffer).writeBuffers = [{ data: uniformDataF32 }]; + reactive(getIGPUBuffer(this.uniformBuffer)).writeBuffers = [{ data: uniformDataF32 }]; } } diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index e2f44d5..0b16dec 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -11,7 +11,7 @@ import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU } from "@feng3d/webgpu"; +import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU, reactive } from "@feng3d/webgpu"; const kMaxNumLights = 1024; const lightExtentMin = vec3.fromValues(-50, -30, -50); @@ -169,7 +169,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } else { - getIGPUBuffer(configUniformBuffer).writeBuffers = [{ data: new Uint32Array([settings.numLights]) }]; + reactive(getIGPUBuffer(configUniformBuffer)).writeBuffers = [{ data: new Uint32Array([settings.numLights]) }]; } }); @@ -229,7 +229,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const lightExtentData = new Float32Array(8); lightExtentData.set(lightExtentMin, 0); lightExtentData.set(lightExtentMax, 4); - getIGPUBuffer(lightExtentBuffer).writeBuffers = [{ data: lightExtentData }]; + reactive(getIGPUBuffer(lightExtentBuffer)).writeBuffers = [{ data: lightExtentData }]; const lightUpdateComputePipeline: ComputePipeline = { compute: { @@ -283,7 +283,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } else { - getIGPUBuffer(cameraUniformBuffer).writeBuffers = [{ data: cameraMatrixData }]; + reactive(getIGPUBuffer(cameraUniformBuffer)).writeBuffers = [{ data: cameraMatrixData }]; } const modelData = modelMatrix as Float32Array; if (getIGPUBuffer(modelUniformBuffer).writeBuffers) @@ -292,7 +292,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } else { - getIGPUBuffer(modelUniformBuffer).writeBuffers = [{ data: modelData }]; + reactive(getIGPUBuffer(modelUniformBuffer)).writeBuffers = [{ data: modelData }]; } const invertTransposeModelMatrix = mat4.invert(modelMatrix); mat4.transpose(invertTransposeModelMatrix, invertTransposeModelMatrix); @@ -303,7 +303,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } else { - getIGPUBuffer(modelUniformBuffer).writeBuffers = [{ bufferOffset: 64, data: normalModelData }]; + reactive(getIGPUBuffer(modelUniformBuffer)).writeBuffers = [{ bufferOffset: 64, data: normalModelData }]; } // Rotates the camera around the origin based on time. @@ -397,7 +397,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } else { - getIGPUBuffer(cameraUniformBuffer).writeBuffers = [{ data: cameraViewProj }]; + reactive(getIGPUBuffer(cameraUniformBuffer)).writeBuffers = [{ data: cameraViewProj }]; } const submit: Submit = { diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 410af05..3ea07b0 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -4,7 +4,7 @@ import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgs import blurWGSL from "./blur.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; -import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU } from "@feng3d/webgpu"; +import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU, reactive } from "@feng3d/webgpu"; // Contants from the blur.wgsl shader. const tileDim = 128; @@ -119,7 +119,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } else { - getIGPUBuffer(blurParamsBuffer).writeBuffers = [{ data: new Uint32Array([settings.filterSize, blockDim]) }]; + reactive(getIGPUBuffer(blurParamsBuffer)).writeBuffers = [{ data: new Uint32Array([settings.filterSize, blockDim]) }]; } needUpdateEncoder = true; }; diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index 2856e97..18d015b 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,5 +1,5 @@ import { CanvasContext, IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; +import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; @@ -114,7 +114,7 @@ const init = async () => `, }; - const pipeline: RenderPipeline = { + const pipeline: RenderPipeline = { label: "our hardcoded red triangle pipeline", vertex: { ...module, @@ -309,7 +309,7 @@ const init = async () => writeBuffers.push({ data: uniformValues, }); - buffer.writeBuffers = writeBuffers; + reactive(buffer).writeBuffers = writeBuffers; // make a render pass encoder to encode render specific commands passEncoders.push({ diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index 9307b26..e68569d 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -8,7 +8,7 @@ import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU } from "@feng3d/webgpu"; +import { ComputePass, ComputePipeline, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; const numParticles = 50000; const particlePositionOffset = 0; @@ -163,7 +163,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const probabilityMapUBOBuffer = new Uint8Array(probabilityMapUBOBufferSize); const bufferA = new Uint8Array(textureWidth * textureHeight * 4); const bufferB = new Uint8Array(textureWidth * textureHeight * 4); - getIGPUBuffer(probabilityMapUBOBuffer).writeBuffers = [{ data: new Int32Array([textureWidth]) }]; + reactive(getIGPUBuffer(probabilityMapUBOBuffer)).writeBuffers = [{ data: new Int32Array([textureWidth]) }]; const passEncoders: ComputePass[] = []; @@ -301,7 +301,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => function frame() { - getIGPUBuffer(simulationUBOBuffer).writeBuffers = [{ + reactive(getIGPUBuffer(simulationUBOBuffer)).writeBuffers = [{ data: new Float32Array([ simulationParams.simulate ? simulationParams.deltaTime : 0.0, 0.0, @@ -320,7 +320,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => mat4.multiply(projection, view, mvp); // prettier-ignore - getIGPUBuffer(uniformBuffer).writeBuffers = [{ + reactive(getIGPUBuffer(uniformBuffer)).writeBuffers = [{ data: new Float32Array([ // modelViewProjectionMatrix mvp[0], mvp[1], mvp[2], mvp[3], diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index ad1bb1d..7eb7450 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,5 +1,5 @@ import { CanvasContext, IRenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { RenderBundle, WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; +import { RenderBundle, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats-js"; @@ -310,7 +310,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => const transformationMatrix = getTransformationMatrix(); - getIGPUBuffer(uniformBuffer).writeBuffers = [{ data: transformationMatrix }]; + reactive(getIGPUBuffer(uniformBuffer)).writeBuffers = [{ data: transformationMatrix }]; let renderObjects: IRenderPassObject[] = []; if (settings.useRenderBundles) diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index 87cf3e5..2aa050d 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import { IRenderPassObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, TextureSource, Uniforms } from "@feng3d/render-api"; -import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; +import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; import showTextureWGSL from "./showTexture.wgsl"; import texturedSquareWGSL from "./texturedSquare.wgsl"; @@ -57,7 +57,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } else { - getIGPUBuffer(bufConfig).writeBuffers = [{ bufferOffset: 64, data }]; + reactive(getIGPUBuffer(bufConfig)).writeBuffers = [{ bufferOffset: 64, data }]; } }; @@ -289,7 +289,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => [0, 0, -kCameraDist] ); const bufConfig = new Uint8Array(128); - getIGPUBuffer(bufConfig).writeBuffers = [{ data: viewProj }]; + reactive(getIGPUBuffer(bufConfig)).writeBuffers = [{ data: viewProj }]; const bufMatrices = kMatrices; @@ -320,10 +320,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push( { - viewport: {isYup: false, x: vpX, y: vpY, width: kViewportSize, height: kViewportSize, minDepth: 0, maxDepth: 1 }, + viewport: { isYup: false, x: vpX, y: vpY, width: kViewportSize, height: kViewportSize, minDepth: 0, maxDepth: 1 }, pipeline: texturedSquarePipeline, uniforms: bindingResources0, - geometry:{ + geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } } } @@ -336,40 +336,40 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const kLastViewport = (kViewportGridSize - 1) * kViewportGridStride + 1; renderObjects.push( { - viewport: {isYup: false, x: kLastViewport, y: kLastViewport, width: 32, height: 32, minDepth: 0, maxDepth: 1 }, + viewport: { isYup: false, x: kLastViewport, y: kLastViewport, width: 32, height: 32, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - geometry:{ + geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } } } ); renderObjects.push( { - viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport, width: 16, height: 16, minDepth: 0, maxDepth: 1 }, + viewport: { isYup: false, x: kLastViewport + 32, y: kLastViewport, width: 16, height: 16, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - geometry:{ + geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } } } ); renderObjects.push( { - viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 16, width: 8, height: 8, minDepth: 0, maxDepth: 1 }, + viewport: { isYup: false, x: kLastViewport + 32, y: kLastViewport + 16, width: 8, height: 8, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - geometry:{ + geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } } } ); renderObjects.push( { - viewport: {isYup: false, x: kLastViewport + 32, y: kLastViewport + 24, width: 4, height: 4, minDepth: 0, maxDepth: 1 }, + viewport: { isYup: false, x: kLastViewport + 32, y: kLastViewport + 24, width: 4, height: 4, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, uniforms: bindingResources1, - geometry:{ + geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } } } diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index d46fb20..68ec0db 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -1,5 +1,5 @@ import { RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { WebGPU, getIGPUBuffer } from "@feng3d/webgpu"; +import { WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; import { mesh } from "../../meshes/stanfordDragon"; @@ -173,14 +173,14 @@ const init = async (canvas: HTMLCanvasElement) => const lightMatrixData = lightViewProjMatrix as Float32Array; const cameraMatrixData = viewProjMatrix as Float32Array; const lightData = lightPosition as Float32Array; - getIGPUBuffer(sceneUniformBuffer).writeBuffers = [ + reactive(getIGPUBuffer(sceneUniformBuffer)).writeBuffers = [ { bufferOffset: 0, data: lightMatrixData }, { bufferOffset: 64, data: cameraMatrixData }, { bufferOffset: 128, data: lightData }, ]; const modelData = modelMatrix as Float32Array; - getIGPUBuffer(modelUniformBuffer).writeBuffers = [{ data: modelData }]; + reactive(getIGPUBuffer(modelUniformBuffer)).writeBuffers = [{ data: modelData }]; } // Rotates the camera around the origin based on time. @@ -260,7 +260,7 @@ const init = async (canvas: HTMLCanvasElement) => const cameraViewProj = getCameraViewProjMatrix(); const writeBuffers = getIGPUBuffer(sceneUniformBuffer).writeBuffers || []; writeBuffers.push({ bufferOffset: 64, data: cameraViewProj }); - getIGPUBuffer(sceneUniformBuffer).writeBuffers = writeBuffers; + reactive(getIGPUBuffer(sceneUniformBuffer)).writeBuffers = writeBuffers; webgpu.submit(submit); diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 6c246da..15d687d 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -2,7 +2,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; import { Buffer, FragmentState, IDraw, PrimitiveState, RenderObject, RenderPipeline, Uniforms, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; -import { getIGPUBuffer } from "@feng3d/webgpu"; +import { getIGPUBuffer, reactive } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models // Modified from Will Usher code found at this link https://www.willusher.io/graphics/2023/05/16/0-to-gltf-first-mesh @@ -800,7 +800,7 @@ export class GLTFSkin }); } - gpuBuffer.writeBuffers = writeBuffers; + reactive(gpuBuffer).writeBuffers = writeBuffers; } } -- Gitee From 13792b8615b01d9d06ebbc62a54dc5f0842ec788 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 09:04:59 +0800 Subject: [PATCH 046/214] =?UTF-8?q?refactor(bindGroup):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E7=BB=91=E5=AE=9A=E7=BB=84=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 getIGPUSetBindGroups 函数,直接在 getGPUBindGroup 中处理绑定组布局和资源 - 优化 BindGroupLayoutDescriptor 接口,移除冗余的 label 属性 - 重构 getGPUBindGroup 函数,使用新的 BindGroupLayoutDescriptor 和 Uniforms 类型 - 更新 RunWebGPU 类中的 runBindingResources 方法,适应新的绑定组逻辑 --- src/caches/getGPUBindGroup.ts | 74 ++++++++++++++-- src/caches/getIGPUPipelineLayout.ts | 7 +- src/caches/getIGPUSetBindGroups.ts | 106 ----------------------- src/internal/PipelineLayoutDescriptor.ts | 3 + src/runs/RunWebGPU.ts | 23 ++--- 5 files changed, 85 insertions(+), 128 deletions(-) delete mode 100644 src/caches/getIGPUSetBindGroups.ts diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 1560f42..9e3009e 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BufferBinding, CanvasTexture, Sampler, TextureView, UniformType } from "@feng3d/render-api"; +import { BufferBinding, BufferBindingInfo, CanvasTexture, Sampler, TextureView, Uniforms, UniformType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; import { VideoTexture } from "../data/VideoTexture"; @@ -9,12 +9,18 @@ import { getGPUBuffer } from "./getGPUBuffer"; import { getGPUSampler } from "./getGPUSampler"; import { getGPUTextureView } from "./getGPUTextureView"; import { getIGPUBuffer } from "./getIGPUBuffer"; +import { BindGroupLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; +import { ChainMap } from "../utils/ChainMap"; +import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; +import { updateBufferBinding } from "../utils/updateBufferBinding"; -export function getGPUBindGroup(device: GPUDevice, bindGroup: BindGroupDescriptor) +export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: BindGroupLayoutDescriptor, bindingResources: Uniforms) { + const bindGroupDescriptor = getSetBindGroup(bindGroupLayout, bindingResources); + const bindGroupMap: WeakMap = device["_bindGroupMap"] = device["_bindGroupMap"] || new WeakMap(); - let gBindGroup = bindGroupMap.get(bindGroup); + let gBindGroup = bindGroupMap.get(bindGroupDescriptor); if (gBindGroup) return gBindGroup; // 总是更新函数列表。 @@ -22,9 +28,9 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: BindGroupDescripto // 执行一次函数列表 const onceUpdateFuncs: (() => void)[] = []; - const layout = getGPUBindGroupLayout(device, bindGroup.layout); + const layout = getGPUBindGroupLayout(device, bindGroupDescriptor.layout); - const entries = bindGroup.entries.map((v) => + const entries = bindGroupDescriptor.entries.map((v) => { const entry: GPUBindGroupEntry = { binding: v.binding, resource: null }; @@ -116,7 +122,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroup: BindGroupDescripto gBindGroup = device.createBindGroup({ layout, entries }); - bindGroupMap.set(bindGroup, gBindGroup); + bindGroupMap.set(bindGroupDescriptor, gBindGroup); // 设置更新外部纹理/画布纹理视图 if (awaysUpdateFuncs.length > 0) @@ -180,3 +186,59 @@ export interface BindGroupEntry } export type BindingResource = Sampler | TextureView | VideoTexture | UniformType; + + +function getSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, bindingResources: Uniforms) +{ + const map: ChainMap, BindGroupDescriptor> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); + const subBindingResources = bindGroupLayout.entryNames.map((v) => bindingResources[v]); + let bindGroupDescriptor = map.get(subBindingResources); + if (bindGroupDescriptor) return bindGroupDescriptor; + + const entries: BindGroupEntry[] = []; + bindGroupDescriptor = { layout: bindGroupLayout, entries }; + map.set(subBindingResources, bindGroupDescriptor); + + // + bindGroupLayout.entries.forEach((entry1) => + { + const { variableInfo, binding } = entry1; + // + const entry: BindGroupEntry = { binding, resource: null }; + + entries.push(entry); + + const resourceName = variableInfo.name; + + const updateResource = () => + { + const bindingResource = bindingResources[resourceName]; + console.assert(!!bindingResource, `在绑定资源中没有找到 ${resourceName} 。`); + + // + if (entry1.buffer) + { + const bufferBinding = ((typeof bindingResource === "number") ? [bindingResource] : bindingResource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 + const bufferBindingInfo: BufferBindingInfo = variableInfo["_bufferBindingInfo"] ||= getBufferBindingInfo(variableInfo.type); + // 更新缓冲区绑定的数据。 + updateBufferBinding(resourceName, bufferBindingInfo, bufferBinding); + // + const buffer = getIGPUBuffer(bufferBinding.bufferView); + (buffer as any).label = buffer.label || (`BufferBinding ${variableInfo.name}`); + // + entry.resource = bufferBinding; + } + else + { + entry.resource = bindingResource; + } + }; + + // + updateResource(); + watcher.watch(bindingResources, resourceName, updateResource); + }); + + return bindGroupDescriptor; +} + diff --git a/src/caches/getIGPUPipelineLayout.ts b/src/caches/getIGPUPipelineLayout.ts index f7d2a6d..3034c92 100644 --- a/src/caches/getIGPUPipelineLayout.ts +++ b/src/caches/getIGPUPipelineLayout.ts @@ -3,11 +3,6 @@ import { getIGPUBindGroupLayoutEntryMap, IGPUBindGroupLayoutEntryMap } from "./g export type IGPUShader = { readonly vertex?: string, readonly fragment?: string, readonly compute?: string }; -export function getIGPUShaderKey(shader: IGPUShader) -{ - return shader.vertex + shader.fragment + shader.compute; -} - /** * 从GPU管线中获取管线布局。 * @@ -16,7 +11,7 @@ export function getIGPUShaderKey(shader: IGPUShader) */ export function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor { - const shaderKey = getIGPUShaderKey(shader); + const shaderKey = shader.vertex + shader.fragment + shader.compute; // let gpuPipelineLayout = gpuPipelineLayoutMap[shaderKey]; diff --git a/src/caches/getIGPUSetBindGroups.ts b/src/caches/getIGPUSetBindGroups.ts deleted file mode 100644 index e2a58b8..0000000 --- a/src/caches/getIGPUSetBindGroups.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { watcher } from "@feng3d/watcher"; - -import { BufferBinding, BufferBindingInfo, Uniforms } from "@feng3d/render-api"; -import { getIGPUPipelineLayout, getIGPUShaderKey, IGPUShader } from "../caches/getIGPUPipelineLayout"; -import { BindGroupLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; -import { ChainMap } from "../utils/ChainMap"; -import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; -import { updateBufferBinding } from "../utils/updateBufferBinding"; -import { getIGPUBuffer } from "./getIGPUBuffer"; -import { BindGroupDescriptor, BindGroupEntry } from "./getGPUBindGroup"; - -export function getIGPUSetBindGroups(shader: IGPUShader, bindingResources: Uniforms) -{ - const shaderKey = getIGPUShaderKey(shader); - // - let gpuSetBindGroups = bindGroupsMap.get([shaderKey, bindingResources]); - if (gpuSetBindGroups) return gpuSetBindGroups; - - gpuSetBindGroups = []; - bindGroupsMap.set([shaderKey, bindingResources], gpuSetBindGroups); - - // - const layout = getIGPUPipelineLayout(shader); - layout.bindGroupLayouts.forEach((bindGroupLayout, group) => - { - gpuSetBindGroups[group] = getSetBindGroup(bindGroupLayout, bindingResources); - }); - - return gpuSetBindGroups; -} - -const bindGroupsMap = new ChainMap<[string, Uniforms], SetBindGroup[]>(); - -function getSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, bindingResources: Uniforms): SetBindGroup -{ - const map: ChainMap, SetBindGroup> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); - const subBindingResources = bindGroupLayout.entryNames.map((v) => bindingResources[v]); - let setBindGroup: SetBindGroup = map.get(subBindingResources); - if (setBindGroup) return setBindGroup; - - const entries: BindGroupEntry[] = []; - setBindGroup = { bindGroup: { layout: bindGroupLayout, entries } }; - map.set(subBindingResources, setBindGroup); - - // - bindGroupLayout.entries.forEach((entry1) => - { - const { variableInfo, binding } = entry1; - // - const entry: BindGroupEntry = { binding, resource: null }; - - entries.push(entry); - - const resourceName = variableInfo.name; - - const updateResource = () => - { - const bindingResource = bindingResources[resourceName]; - console.assert(!!bindingResource, `在绑定资源中没有找到 ${resourceName} 。`); - - // - if (entry1.buffer) - { - const bufferBinding = ((typeof bindingResource === "number") ? [bindingResource] : bindingResource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 - const bufferBindingInfo: BufferBindingInfo = variableInfo["_bufferBindingInfo"] ||= getBufferBindingInfo(variableInfo.type); - // 更新缓冲区绑定的数据。 - updateBufferBinding(resourceName, bufferBindingInfo, bufferBinding); - // - const buffer = getIGPUBuffer(bufferBinding.bufferView); - (buffer as any).label = buffer.label || (`BufferBinding ${variableInfo.name}`); - // - entry.resource = bufferBinding; - } - else - { - entry.resource = bindingResource; - } - }; - - // - updateResource(); - watcher.watch(bindingResources, resourceName, updateResource); - }); - - return setBindGroup; -} - -/** - * GPU渲染时使用的绑定组。 - * - * {@link GPUBindingCommandsMixin.setBindGroup} - */ -interface SetBindGroup -{ - /** - * GPU绑定组。 - * - * Bind group to use for subsequent render or compute commands. - */ - bindGroup: BindGroupDescriptor; - - /** - * Array containing buffer offsets in bytes for each entry in `bindGroup` marked as {@link GPUBindGroupLayoutEntry#buffer}.{@link GPUBufferBindingLayout#hasDynamicOffset}.--> - */ - dynamicOffsets?: number[]; -} diff --git a/src/internal/PipelineLayoutDescriptor.ts b/src/internal/PipelineLayoutDescriptor.ts index 96d2c9f..ca2376c 100644 --- a/src/internal/PipelineLayoutDescriptor.ts +++ b/src/internal/PipelineLayoutDescriptor.ts @@ -20,6 +20,9 @@ export interface PipelineLayoutDescriptor bindGroupLayouts: BindGroupLayoutDescriptor[]; } +/** + * {@link GPUBindGroupLayoutDescriptor} + */ export interface BindGroupLayoutDescriptor { label?: string; diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index fe0ea93..40bf04f 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,7 +1,8 @@ import { anyEmitter } from "@feng3d/event"; -import { Buffer, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, Uniforms, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { Buffer, BufferBinding, BufferBindingInfo, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, Uniforms, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; -import { getGPUBindGroup } from "../caches/getGPUBindGroup"; +import { watcher } from "@feng3d/watcher"; +import { BindGroupDescriptor, BindGroupEntry, getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; import { getGPUComputePipeline } from "../caches/getGPUComputePipeline"; import { getGPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; @@ -11,8 +12,7 @@ import { getGPURenderPipeline } from "../caches/getGPURenderPipeline"; import { getGPURenderTimestampQuery } from "../caches/getGPURenderTimestampQuery"; import { getGPUTexture } from "../caches/getGPUTexture"; import { getIGPUBuffer } from "../caches/getIGPUBuffer"; -import { IGPUShader } from "../caches/getIGPUPipelineLayout"; -import { getIGPUSetBindGroups } from "../caches/getIGPUSetBindGroups"; +import { getIGPUPipelineLayout, IGPUShader } from "../caches/getIGPUPipelineLayout"; import { getNGPURenderPipeline } from "../caches/getNGPURenderPipeline"; import { getRealGPUBindGroup } from "../const"; import { ComputeObject } from "../data/ComputeObject"; @@ -24,8 +24,11 @@ import "../data/polyfills/RenderPass"; import { RenderBundle } from "../data/RenderBundle"; import { Workgroups } from "../data/Workgroups"; import { GPUQueue_submit } from "../eventnames"; +import { BindGroupLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { IRenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; +import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; +import { updateBufferBinding } from "../utils/updateBufferBinding"; export class RunWebGPU { @@ -418,12 +421,11 @@ export class RunWebGPU protected runBindingResources(device: GPUDevice, passEncoder: GPUBindingCommandsMixin, shader: IGPUShader, bindingResources: Uniforms) { // 计算 bindGroups - const setBindGroups = getIGPUSetBindGroups(shader, bindingResources); - - setBindGroups?.forEach((setBindGroup, index) => + const layout = getIGPUPipelineLayout(shader); + layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { - const gpuBindGroup = getGPUBindGroup(device, setBindGroup.bindGroup)[getRealGPUBindGroup](); - passEncoder.setBindGroup(index, gpuBindGroup, setBindGroup.dynamicOffsets); + const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); + passEncoder.setBindGroup(group, gpuBindGroup); }); } @@ -470,4 +472,5 @@ export class RunWebGPU } let autoIndex = 0; -let autoVertexIndex = 0; \ No newline at end of file +let autoVertexIndex = 0; + -- Gitee From 6feabd9b5ea7b88f23a99a56a7f69b413b8ce61c Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 09:07:40 +0800 Subject: [PATCH 047/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E7=BC=93=E5=AD=98=E5=92=8C?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 getNGPURenderPipeline 函数,将结果对象中的 material 属性重命名为 pipeline - 更新 RunWebGPU 类中的 runRenderPipeline 方法,使用新的 pipeline 属性 - 调整相关类型定义和注释,以适应新的命名 --- src/caches/getNGPURenderPipeline.ts | 4 ++-- src/runs/RunWebGPU.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index e615cf2..f32da9a 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -60,7 +60,7 @@ export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPass blendConstantColor, }; - result = { _version: 0, material, vertexBuffers: vertexStateResult.vertexBuffers }; + result = { _version: 0, pipeline: material, vertexBuffers: vertexStateResult.vertexBuffers }; renderPipelineMap.set([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat], result); // 监听管线变化 @@ -84,7 +84,7 @@ const renderPipelineMap = new ChainMap< /** * GPU渲染管线描述。 */ - material: NRenderPipeline; + pipeline: NRenderPipeline; /** * GPU渲染时使用的顶点缓冲区列表。 */ diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 40bf04f..431a972 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -333,12 +333,12 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { // - const renderPipelineResult = getNGPURenderPipeline(material, renderPassFormat, primitive, vertices, indices); + const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); - const nPipeline = renderPipelineResult.material; + const nPipeline = renderPipelineResult.pipeline; const gpuRenderPipeline = getGPURenderPipeline(device, nPipeline); -- Gitee From edca268859a85e859a980c3ba5186670a8da67be Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 10:16:42 +0800 Subject: [PATCH 048/214] =?UTF-8?q?refactor(caches):=20=E6=95=B4=E5=90=88?= =?UTF-8?q?=20getIGPUPipelineLayout=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 getIGPUPipelineLayout 从独立文件移动到 getGPUPipelineLayout.ts 中 - 优化了 GPU 管线布局的生成逻辑 - 移除了冗余的代码和文件 - 调整了相关文件的引用路径 --- src/caches/getGPUComputePipeline.ts | 7 +- src/caches/getGPUPipelineLayout.ts | 111 +++++++++++++++++++++++++++- src/caches/getGPURenderPipeline.ts | 4 +- src/caches/getIGPUPipelineLayout.ts | 106 -------------------------- src/runs/RunWebGPU.ts | 2 +- 5 files changed, 113 insertions(+), 117 deletions(-) delete mode 100644 src/caches/getIGPUPipelineLayout.ts diff --git a/src/caches/getGPUComputePipeline.ts b/src/caches/getGPUComputePipeline.ts index 856b618..f8927b6 100644 --- a/src/caches/getGPUComputePipeline.ts +++ b/src/caches/getGPUComputePipeline.ts @@ -1,10 +1,9 @@ import { UnReadonly } from "@feng3d/render-api"; import { ComputePipeline } from "../data/ComputePipeline"; +import { ComputeStage } from "../data/ComputeStage"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; import { getGPUShaderModule } from "./getGPUShaderModule"; -import { getIGPUPipelineLayout } from "./getIGPUPipelineLayout"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; -import { ComputeStage } from "../data/ComputeStage"; export function getGPUComputePipeline(device: GPUDevice, computePipeline: ComputePipeline) { @@ -30,9 +29,7 @@ export function getGPUComputePipeline(device: GPUDevice, computePipeline: Comput } // 从GPU管线中获取管线布局。 - const gpuPipelineLayout = getIGPUPipelineLayout({ compute: computeStage.code }); - - const layout = getGPUPipelineLayout(device, gpuPipelineLayout); + const layout = getGPUPipelineLayout(device, { compute: computeStage.code }); pipeline = device.createComputePipeline({ layout, diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index bf3eb1e..2a8653b 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,8 +1,11 @@ -import { PipelineLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; +import { BindGroupLayoutDescriptor, PipelineLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; +import { getIGPUBindGroupLayoutEntryMap, IGPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; -export function getGPUPipelineLayout(device: GPUDevice, layout: PipelineLayoutDescriptor) +export function getGPUPipelineLayout(device: GPUDevice, shader: IGPUShader) { + const layout = getIGPUPipelineLayout(shader); + const bindGroupLayouts = layout.bindGroupLayouts.map((v) => { const gBindGroupLayout = getGPUBindGroupLayout(device, v); @@ -15,3 +18,107 @@ export function getGPUPipelineLayout(device: GPUDevice, layout: PipelineLayoutDe return gPipelineLayout; } + +export type IGPUShader = { readonly vertex?: string, readonly fragment?: string, readonly compute?: string }; + +/** + * 从GPU管线中获取管线布局。 + * + * @param shader GPU管线。 + * @returns 管线布局。 + */ +export function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor +{ + const shaderKey = shader.vertex + shader.fragment + shader.compute; + + // + let gpuPipelineLayout = gpuPipelineLayoutMap[shaderKey]; + if (gpuPipelineLayout) return gpuPipelineLayout; + + const vertexCode = shader.vertex; + const fragmentCode = shader.fragment; + const computeCode = shader.compute; + + let entryMap: IGPUBindGroupLayoutEntryMap = {}; + if (vertexCode) + { + const vertexEntryMap = getIGPUBindGroupLayoutEntryMap(vertexCode); + entryMap = mergeBindGroupLayouts(entryMap, vertexEntryMap); + } + if (fragmentCode && fragmentCode !== vertexCode) + { + const fragmentEntryMap = getIGPUBindGroupLayoutEntryMap(fragmentCode); + entryMap = mergeBindGroupLayouts(entryMap, fragmentEntryMap); + } + if (computeCode && computeCode !== vertexCode && computeCode !== fragmentCode) + { + const computeEntryMap = getIGPUBindGroupLayoutEntryMap(computeCode); + entryMap = mergeBindGroupLayouts(entryMap, computeEntryMap); + } + + // + const bindGroupLayouts: BindGroupLayoutDescriptor[] = []; + for (const resourceName in entryMap) + { + const bindGroupLayoutEntry = entryMap[resourceName]; + const { group, binding } = bindGroupLayoutEntry.variableInfo; + // + const bindGroupLayout = bindGroupLayouts[group] = bindGroupLayouts[group] || { entries: [], entryNames: [] }; + + // 检测相同位置是否存在多个定义 + if (bindGroupLayout.entries[binding]) + { + // 存在重复定义时,判断是否兼容 + const preEntry = bindGroupLayout.entries[binding]; + console.error(`在管线中 @group(${group}) @binding(${binding}) 处存在多个定义 ${preEntry.variableInfo.name} ${resourceName} 。`); + } + + // + bindGroupLayout.entries[binding] = bindGroupLayoutEntry; + bindGroupLayout.entryNames.push(resourceName); + } + + // 排除 undefined 元素。 + for (let i = 0; i < bindGroupLayouts.length; i++) + { + const entries = bindGroupLayouts[i].entries as GPUBindGroupLayoutEntry[]; + for (let i = entries.length - 1; i >= 0; i--) + { + if (!entries[i]) + { + entries.splice(i, 1); + } + } + } + + // + gpuPipelineLayout = gpuPipelineLayoutMap[shaderKey] = { bindGroupLayouts }; + + return gpuPipelineLayout; +} + +function mergeBindGroupLayouts(entryMap: IGPUBindGroupLayoutEntryMap, entryMap1: IGPUBindGroupLayoutEntryMap): IGPUBindGroupLayoutEntryMap +{ + for (const resourceName in entryMap1) + { + // 检测相同名称是否被定义在多个地方 + if (entryMap[resourceName]) + { + const preEntry = entryMap[resourceName].variableInfo; + const currentEntry = entryMap1[resourceName].variableInfo; + + if (preEntry.group !== currentEntry.group + || preEntry.binding !== currentEntry.binding + || preEntry.resourceType !== currentEntry.resourceType + ) + { + console.warn(`分别在 着色器 @group(${preEntry.group}) @binding(${preEntry.binding}) 与 @group(${currentEntry.group}) @binding(${currentEntry.binding}) 处存在相同名称的变量 ${currentEntry.name} 。`); + } + } + entryMap[resourceName] = entryMap1[resourceName]; + } + + return entryMap; +} + +const gpuPipelineLayoutMap: { [key: string]: PipelineLayoutDescriptor } = {}; diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index a13560f..154854e 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -1,7 +1,6 @@ import { NRenderPipeline } from "../internal/NRenderPipeline"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; import { getGPUShaderModule } from "./getGPUShaderModule"; -import { getIGPUPipelineLayout } from "./getIGPUPipelineLayout"; export function getGPURenderPipeline(device: GPUDevice, renderPipeline: NRenderPipeline) { @@ -9,8 +8,7 @@ export function getGPURenderPipeline(device: GPUDevice, renderPipeline: NRenderP if (pipeline) return pipeline; // 从GPU管线中获取管线布局。 - const gpuPipelineLayout = getIGPUPipelineLayout({ vertex: renderPipeline.vertex.code, fragment: renderPipeline.fragment?.code }); - const layout = getGPUPipelineLayout(device, gpuPipelineLayout); + const layout = getGPUPipelineLayout(device, { vertex: renderPipeline.vertex.code, fragment: renderPipeline.fragment?.code }); const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { layout, diff --git a/src/caches/getIGPUPipelineLayout.ts b/src/caches/getIGPUPipelineLayout.ts deleted file mode 100644 index 3034c92..0000000 --- a/src/caches/getIGPUPipelineLayout.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { BindGroupLayoutDescriptor, PipelineLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; -import { getIGPUBindGroupLayoutEntryMap, IGPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; - -export type IGPUShader = { readonly vertex?: string, readonly fragment?: string, readonly compute?: string }; - -/** - * 从GPU管线中获取管线布局。 - * - * @param shader GPU管线。 - * @returns 管线布局。 - */ -export function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor -{ - const shaderKey = shader.vertex + shader.fragment + shader.compute; - - // - let gpuPipelineLayout = gpuPipelineLayoutMap[shaderKey]; - if (gpuPipelineLayout) return gpuPipelineLayout; - - const vertexCode = shader.vertex; - const fragmentCode = shader.fragment; - const computeCode = shader.compute; - - let entryMap: IGPUBindGroupLayoutEntryMap = {}; - if (vertexCode) - { - const vertexEntryMap = getIGPUBindGroupLayoutEntryMap(vertexCode); - entryMap = mergeBindGroupLayouts(entryMap, vertexEntryMap); - } - if (fragmentCode && fragmentCode !== vertexCode) - { - const fragmentEntryMap = getIGPUBindGroupLayoutEntryMap(fragmentCode); - entryMap = mergeBindGroupLayouts(entryMap, fragmentEntryMap); - } - if (computeCode && computeCode !== vertexCode && computeCode !== fragmentCode) - { - const computeEntryMap = getIGPUBindGroupLayoutEntryMap(computeCode); - entryMap = mergeBindGroupLayouts(entryMap, computeEntryMap); - } - - // - const bindGroupLayouts: BindGroupLayoutDescriptor[] = []; - for (const resourceName in entryMap) - { - const bindGroupLayoutEntry = entryMap[resourceName]; - const { group, binding } = bindGroupLayoutEntry.variableInfo; - // - const bindGroupLayout = bindGroupLayouts[group] = bindGroupLayouts[group] || { entries: [], entryNames: [] }; - - // 检测相同位置是否存在多个定义 - if (bindGroupLayout.entries[binding]) - { - // 存在重复定义时,判断是否兼容 - const preEntry = bindGroupLayout.entries[binding]; - console.error(`在管线中 @group(${group}) @binding(${binding}) 处存在多个定义 ${preEntry.variableInfo.name} ${resourceName} 。`); - } - - // - bindGroupLayout.entries[binding] = bindGroupLayoutEntry; - bindGroupLayout.entryNames.push(resourceName); - } - - // 排除 undefined 元素。 - for (let i = 0; i < bindGroupLayouts.length; i++) - { - const entries = bindGroupLayouts[i].entries as GPUBindGroupLayoutEntry[]; - for (let i = entries.length - 1; i >= 0; i--) - { - if (!entries[i]) - { - entries.splice(i, 1); - } - } - } - - // - gpuPipelineLayout = gpuPipelineLayoutMap[shaderKey] = { bindGroupLayouts }; - - return gpuPipelineLayout; -} - -function mergeBindGroupLayouts(entryMap: IGPUBindGroupLayoutEntryMap, entryMap1: IGPUBindGroupLayoutEntryMap): IGPUBindGroupLayoutEntryMap -{ - for (const resourceName in entryMap1) - { - // 检测相同名称是否被定义在多个地方 - if (entryMap[resourceName]) - { - const preEntry = entryMap[resourceName].variableInfo; - const currentEntry = entryMap1[resourceName].variableInfo; - - if (preEntry.group !== currentEntry.group - || preEntry.binding !== currentEntry.binding - || preEntry.resourceType !== currentEntry.resourceType - ) - { - console.warn(`分别在 着色器 @group(${preEntry.group}) @binding(${preEntry.binding}) 与 @group(${currentEntry.group}) @binding(${currentEntry.binding}) 处存在相同名称的变量 ${currentEntry.name} 。`); - } - } - entryMap[resourceName] = entryMap1[resourceName]; - } - - return entryMap; -} - -const gpuPipelineLayoutMap: { [key: string]: PipelineLayoutDescriptor } = {}; diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 431a972..004260a 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -12,7 +12,6 @@ import { getGPURenderPipeline } from "../caches/getGPURenderPipeline"; import { getGPURenderTimestampQuery } from "../caches/getGPURenderTimestampQuery"; import { getGPUTexture } from "../caches/getGPUTexture"; import { getIGPUBuffer } from "../caches/getIGPUBuffer"; -import { getIGPUPipelineLayout, IGPUShader } from "../caches/getIGPUPipelineLayout"; import { getNGPURenderPipeline } from "../caches/getNGPURenderPipeline"; import { getRealGPUBindGroup } from "../const"; import { ComputeObject } from "../data/ComputeObject"; @@ -29,6 +28,7 @@ import { IRenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; import { updateBufferBinding } from "../utils/updateBufferBinding"; +import { IGPUShader, getIGPUPipelineLayout } from "../caches/getGPUPipelineLayout"; export class RunWebGPU { -- Gitee From 336ca38f95e3888530cdf9220623773aea5f8682 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 14:50:16 +0800 Subject: [PATCH 049/214] =?UTF-8?q?feat(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=AE=A1=E7=BA=BF=E5=B8=83=E5=B1=80=E5=92=8C=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E7=BB=84=E5=B8=83=E5=B1=80=E7=9A=84=E7=BC=93=E5=AD=98=E4=B8=8E?= =?UTF-8?q?=E5=A4=8D=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 getGPUPipelineLayout 中增加缓存逻辑,复用相同的管线布局 - 在 getIGPUPipelineLayout 中增加缓存逻辑,复用相同的绑定组布局 - 在 BindGroupLayoutDescriptor 和 PipelineLayoutDescriptor 中添加 key 属性,用于缓存 - 在 RunWebGPU 中使用 getGPUPipelineLayout 替代 getIGPUPipelineLayout - 在 vite.config.js 中添加 __DEV__ 定义,用于控制缓存日志输出 --- examples/vite.config.js | 3 ++ src/caches/getGPUPipelineLayout.ts | 52 +++++++++++++++++++++--- src/caches/getWGSLReflectInfo.ts | 16 +++++--- src/global.ts | 8 ++++ src/index.ts | 2 + src/internal/PipelineLayoutDescriptor.ts | 4 ++ src/runs/RunWebGPU.ts | 12 ++---- vite.config.js | 3 ++ 8 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 src/global.ts diff --git a/examples/vite.config.js b/examples/vite.config.js index 9ca1560..27979c3 100644 --- a/examples/vite.config.js +++ b/examples/vite.config.js @@ -4,6 +4,9 @@ import { resolve } from "path"; import { defineConfig } from "vite"; export default defineConfig({ + define: { + __DEV__: process.env.NODE_ENV === 'development' ? true : false + }, publicDir: "resources", build: { rollupOptions: { diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 2a8653b..9443ee8 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -2,8 +2,22 @@ import { BindGroupLayoutDescriptor, PipelineLayoutDescriptor } from "../internal import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; import { getIGPUBindGroupLayoutEntryMap, IGPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; -export function getGPUPipelineLayout(device: GPUDevice, shader: IGPUShader) +declare global { + interface GPUPipelineLayout + { + bindGroupLayouts: BindGroupLayoutDescriptor[]; + } +} + +export function getGPUPipelineLayout(device: GPUDevice, shader: IGPUShader): GPUPipelineLayout +{ + const shaderKey = shader.vertex + shader.fragment + shader.compute; + + // + let gpuPipelineLayout = gpuPipelineLayoutMap0[shaderKey]; + if (gpuPipelineLayout) return gpuPipelineLayout; + const layout = getIGPUPipelineLayout(shader); const bindGroupLayouts = layout.bindGroupLayouts.map((v) => @@ -15,9 +29,12 @@ export function getGPUPipelineLayout(device: GPUDevice, shader: IGPUShader) const gPipelineLayout = device.createPipelineLayout({ bindGroupLayouts, }); + gPipelineLayout.bindGroupLayouts = layout.bindGroupLayouts; + gpuPipelineLayoutMap0[shaderKey] = gPipelineLayout; return gPipelineLayout; } +const gpuPipelineLayoutMap0: { [key: string]: GPUPipelineLayout } = {}; export type IGPUShader = { readonly vertex?: string, readonly fragment?: string, readonly compute?: string }; @@ -27,7 +44,7 @@ export type IGPUShader = { readonly vertex?: string, readonly fragment?: string, * @param shader GPU管线。 * @returns 管线布局。 */ -export function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor +function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor { const shaderKey = shader.vertex + shader.fragment + shader.compute; @@ -63,7 +80,7 @@ export function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescrip const bindGroupLayoutEntry = entryMap[resourceName]; const { group, binding } = bindGroupLayoutEntry.variableInfo; // - const bindGroupLayout = bindGroupLayouts[group] = bindGroupLayouts[group] || { entries: [], entryNames: [] }; + const bindGroupLayout = bindGroupLayouts[group] = bindGroupLayouts[group] || { entries: [], entryNames: [], key: "" }; // 检测相同位置是否存在多个定义 if (bindGroupLayout.entries[binding]) @@ -81,7 +98,8 @@ export function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescrip // 排除 undefined 元素。 for (let i = 0; i < bindGroupLayouts.length; i++) { - const entries = bindGroupLayouts[i].entries as GPUBindGroupLayoutEntry[]; + const bindGroupLayout = bindGroupLayouts[i]; + const entries = bindGroupLayout.entries as GPUBindGroupLayoutEntry[]; for (let i = entries.length - 1; i >= 0; i--) { if (!entries[i]) @@ -89,14 +107,36 @@ export function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescrip entries.splice(i, 1); } } + bindGroupLayout.key = bindGroupLayout.entries.map((v) => v.key).join(","); + // 相同的布局只保留一个。 + if (__DEV__) + { + if (bindGroupLayoutMap[bindGroupLayout.key]) + { + console.log(`命中相同的布局 ${bindGroupLayout.key},公用绑定组布局对象。`); + } + } + bindGroupLayouts[i] = bindGroupLayoutMap[bindGroupLayout.key] = bindGroupLayoutMap[bindGroupLayout.key] || bindGroupLayout; } - // - gpuPipelineLayout = gpuPipelineLayoutMap[shaderKey] = { bindGroupLayouts }; + const pipelineLayoutKey = bindGroupLayouts.map((v, i) => `[${i} ,${v.key}]`).join(","); + // 相同的布局只保留一个。 + if (__DEV__) + { + if (pipelineLayoutDescriptorMap[pipelineLayoutKey]) + { + console.log(`命中相同的布局 ${pipelineLayoutKey},公用管线布局对象。`); + } + } + gpuPipelineLayout = gpuPipelineLayoutMap[shaderKey] = pipelineLayoutDescriptorMap[pipelineLayoutKey] + = pipelineLayoutDescriptorMap[pipelineLayoutKey] || { bindGroupLayouts, key: pipelineLayoutKey }; return gpuPipelineLayout; } +const bindGroupLayoutMap: { [key: string]: BindGroupLayoutDescriptor } = {}; +const pipelineLayoutDescriptorMap: { [key: string]: PipelineLayoutDescriptor } = {}; + function mergeBindGroupLayouts(entryMap: IGPUBindGroupLayoutEntryMap, entryMap1: IGPUBindGroupLayoutEntryMap): IGPUBindGroupLayoutEntryMap { for (const resourceName in entryMap1) diff --git a/src/caches/getWGSLReflectInfo.ts b/src/caches/getWGSLReflectInfo.ts index f497252..01ceefc 100644 --- a/src/caches/getWGSLReflectInfo.ts +++ b/src/caches/getWGSLReflectInfo.ts @@ -41,6 +41,7 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): IGPUBindGroupLayou entryMap[name] = { variableInfo: uniform, visibility: Visibility_ALL, binding, buffer: layout, + key: `[${binding}, buffer, ${layout.type} , ${layout.minBindingSize}]`, }; } @@ -60,7 +61,8 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): IGPUBindGroupLayou entryMap[name] = { variableInfo: storage, - visibility: type === "storage" ? Visibility_FRAGMENT_COMPUTE : Visibility_ALL, binding, buffer: layout + visibility: type === "storage" ? Visibility_FRAGMENT_COMPUTE : Visibility_ALL, binding, buffer: layout, + key: `[${binding}, buffer, ${layout.type}]`, }; } else if (storage.resourceType === ResourceType.StorageTexture) @@ -82,7 +84,8 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): IGPUBindGroupLayou entryMap[name] = { variableInfo: storage, - visibility: Visibility_FRAGMENT_COMPUTE, binding, storageTexture: layout + visibility: Visibility_FRAGMENT_COMPUTE, binding, storageTexture: layout, + key: `[${binding}, storageTexture, ${layout.access}, ${layout.format}, ${layout.viewDimension}]`, }; } else @@ -103,7 +106,8 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): IGPUBindGroupLayou { entryMap[name] = { variableInfo: texture, - visibility: Visibility_ALL, binding, externalTexture: {} + visibility: Visibility_ALL, binding, externalTexture: {}, + key: `[${binding}, externalTexture]`, }; } else @@ -151,7 +155,8 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): IGPUBindGroupLayou entryMap[name] = { variableInfo: texture, - visibility: Visibility_ALL, binding, texture: layout + visibility: Visibility_ALL, binding, texture: layout, + key: `[${binding}, texture, ${layout.sampleType}, ${layout.viewDimension}, ${layout.multisampled}]`, }; } } @@ -169,7 +174,8 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): IGPUBindGroupLayou entryMap[name] = { variableInfo: sampler, - visibility: Visibility_ALL, binding, sampler: layout + visibility: Visibility_ALL, binding, sampler: layout, + key: `[${binding}, sampler, ${layout.type}]`, }; } diff --git a/src/global.ts b/src/global.ts new file mode 100644 index 0000000..0777368 --- /dev/null +++ b/src/global.ts @@ -0,0 +1,8 @@ +export { }; +declare global +{ + /** + * 是否为开发模式。 + */ + var __DEV__: boolean; +} diff --git a/src/index.ts b/src/index.ts index de74b04..b7752dd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -35,3 +35,5 @@ export * from "./utils/getOffscreenCanvasId"; // 导出反应式相关功能 export * from "./reactivity"; +import "./global" + diff --git a/src/internal/PipelineLayoutDescriptor.ts b/src/internal/PipelineLayoutDescriptor.ts index ca2376c..da4ae32 100644 --- a/src/internal/PipelineLayoutDescriptor.ts +++ b/src/internal/PipelineLayoutDescriptor.ts @@ -18,6 +18,8 @@ export interface PipelineLayoutDescriptor * `@group(N)`. */ bindGroupLayouts: BindGroupLayoutDescriptor[]; + + key: string; } /** @@ -28,9 +30,11 @@ export interface BindGroupLayoutDescriptor label?: string; entries: BindGroupLayoutEntry[]; entryNames: string[], + key: string, } export interface BindGroupLayoutEntry extends GPUBindGroupLayoutEntry { variableInfo: VariableInfo; + key: string; } \ No newline at end of file diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 004260a..6ddd69a 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,10 +1,10 @@ import { anyEmitter } from "@feng3d/event"; -import { Buffer, BufferBinding, BufferBindingInfo, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, Uniforms, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { Buffer, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, Uniforms, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; -import { BindGroupDescriptor, BindGroupEntry, getGPUBindGroup } from "../caches/getGPUBindGroup"; +import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; import { getGPUComputePipeline } from "../caches/getGPUComputePipeline"; +import { getGPUPipelineLayout, IGPUShader } from "../caches/getGPUPipelineLayout"; import { getGPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; import { getGPURenderPassDescriptor } from "../caches/getGPURenderPassDescriptor"; import { getGPURenderPassFormat } from "../caches/getGPURenderPassFormat"; @@ -23,12 +23,8 @@ import "../data/polyfills/RenderPass"; import { RenderBundle } from "../data/RenderBundle"; import { Workgroups } from "../data/Workgroups"; import { GPUQueue_submit } from "../eventnames"; -import { BindGroupLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { IRenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; -import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; -import { updateBufferBinding } from "../utils/updateBufferBinding"; -import { IGPUShader, getIGPUPipelineLayout } from "../caches/getGPUPipelineLayout"; export class RunWebGPU { @@ -421,7 +417,7 @@ export class RunWebGPU protected runBindingResources(device: GPUDevice, passEncoder: GPUBindingCommandsMixin, shader: IGPUShader, bindingResources: Uniforms) { // 计算 bindGroups - const layout = getIGPUPipelineLayout(shader); + const layout = getGPUPipelineLayout(device, shader); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); diff --git a/vite.config.js b/vite.config.js index e51dbba..711ba2a 100644 --- a/vite.config.js +++ b/vite.config.js @@ -9,6 +9,9 @@ const external = pkg.standalone ? [] : Object.keys(pkg.dependencies || []); const globals = () => namespace; export default defineConfig({ + define: { + __DEV__: process.env.NODE_ENV === 'development' ? true : false + }, publicDir: false, build: { lib: { -- Gitee From 2d43c4f7983100e967c39d4f9352c8e20c26987f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 15:09:09 +0800 Subject: [PATCH 050/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20GPU=20=E7=AE=A1=E7=BA=BF=E5=B8=83=E5=B1=80=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新类型名称:IGPUBindGroupLayoutEntryMap -> GPUBindGroupLayoutEntryMap - 移除冗余的 BindGroupLayoutEntry 类型定义 - 优化了 getGPUPipelineLayout 和 getWGSLReflectInfo 文件中的相关代码 --- src/caches/getGPUPipelineLayout.ts | 6 +++--- src/caches/getWGSLReflectInfo.ts | 12 +++++------- src/internal/PipelineLayoutDescriptor.ts | 18 ++++++++++++++---- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 9443ee8..a96f390 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,6 +1,6 @@ import { BindGroupLayoutDescriptor, PipelineLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; -import { getIGPUBindGroupLayoutEntryMap, IGPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; +import { getIGPUBindGroupLayoutEntryMap, GPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; declare global { @@ -56,7 +56,7 @@ function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor const fragmentCode = shader.fragment; const computeCode = shader.compute; - let entryMap: IGPUBindGroupLayoutEntryMap = {}; + let entryMap: GPUBindGroupLayoutEntryMap = {}; if (vertexCode) { const vertexEntryMap = getIGPUBindGroupLayoutEntryMap(vertexCode); @@ -137,7 +137,7 @@ function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor const bindGroupLayoutMap: { [key: string]: BindGroupLayoutDescriptor } = {}; const pipelineLayoutDescriptorMap: { [key: string]: PipelineLayoutDescriptor } = {}; -function mergeBindGroupLayouts(entryMap: IGPUBindGroupLayoutEntryMap, entryMap1: IGPUBindGroupLayoutEntryMap): IGPUBindGroupLayoutEntryMap +function mergeBindGroupLayouts(entryMap: GPUBindGroupLayoutEntryMap, entryMap1: GPUBindGroupLayoutEntryMap): GPUBindGroupLayoutEntryMap { for (const resourceName in entryMap1) { diff --git a/src/caches/getWGSLReflectInfo.ts b/src/caches/getWGSLReflectInfo.ts index 01ceefc..14799ff 100644 --- a/src/caches/getWGSLReflectInfo.ts +++ b/src/caches/getWGSLReflectInfo.ts @@ -1,5 +1,4 @@ import { ResourceType, TemplateInfo, WgslReflect } from "wgsl_reflect"; -import { BindGroupLayoutEntry } from "../internal/PipelineLayoutDescriptor"; import { DepthTextureType, ExternalSampledTextureType, MultisampledTextureType, TextureType } from "../types/TextureType"; /** @@ -19,16 +18,15 @@ export function getWGSLReflectInfo(code: string): WgslReflect } const reflectMap: { [code: string]: WgslReflect } = {}; -export type IGPUBindGroupLayoutEntryMap = { [name: string]: BindGroupLayoutEntry; }; +export type GPUBindGroupLayoutEntryMap = { [name: string]: GPUBindGroupLayoutEntry; }; -export function getIGPUBindGroupLayoutEntryMap(code: string): IGPUBindGroupLayoutEntryMap +export function getIGPUBindGroupLayoutEntryMap(code: string): GPUBindGroupLayoutEntryMap { if (shaderLayoutMap[code]) return shaderLayoutMap[code]; - const reflect = getWGSLReflectInfo(code); - - const entryMap: IGPUBindGroupLayoutEntryMap = shaderLayoutMap[code] = {}; + const entryMap: GPUBindGroupLayoutEntryMap = shaderLayoutMap[code] = {}; + const reflect = getWGSLReflectInfo(code); for (const uniform of reflect.uniforms) { const { binding, name } = uniform; @@ -182,7 +180,7 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): IGPUBindGroupLayou return entryMap; } -const shaderLayoutMap: { [code: string]: IGPUBindGroupLayoutEntryMap } = {}; +const shaderLayoutMap: { [code: string]: GPUBindGroupLayoutEntryMap } = {}; /** * 片段与计算着色器可见。 diff --git a/src/internal/PipelineLayoutDescriptor.ts b/src/internal/PipelineLayoutDescriptor.ts index da4ae32..1ab4e62 100644 --- a/src/internal/PipelineLayoutDescriptor.ts +++ b/src/internal/PipelineLayoutDescriptor.ts @@ -28,13 +28,23 @@ export interface PipelineLayoutDescriptor export interface BindGroupLayoutDescriptor { label?: string; - entries: BindGroupLayoutEntry[]; + entries: GPUBindGroupLayoutEntry[]; entryNames: string[], key: string, } -export interface BindGroupLayoutEntry extends GPUBindGroupLayoutEntry +declare global { - variableInfo: VariableInfo; - key: string; + interface GPUBindGroupLayoutEntry + { + /** + * 绑定资源变量信息。 + */ + variableInfo: VariableInfo; + + /** + * 用于判断布局信息是否相同的标识。 + */ + key: string; + } } \ No newline at end of file -- Gitee From 48ae1a99d7e88cca313de9fa5a6b4b55ca8a54b6 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 15:26:43 +0800 Subject: [PATCH 051/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20GPU=20=E7=AE=A1=E7=BA=BF=E5=B8=83=E5=B1=80=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了不必要的 shaderKey 计算和 gpuPipelineLayoutMap 使用 - 优化了 PipelineLayoutDescriptor 的创建和复用逻辑 - 添加了 GPUBindGroupLayoutDescriptor 接口的补充定义 --- src/caches/getGPUPipelineLayout.ts | 11 ++--------- src/internal/PipelineLayoutDescriptor.ts | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index a96f390..a0032e5 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -26,6 +26,7 @@ export function getGPUPipelineLayout(device: GPUDevice, shader: IGPUShader): GPU return gBindGroupLayout; }); + const gPipelineLayout = device.createPipelineLayout({ bindGroupLayouts, }); @@ -46,12 +47,6 @@ export type IGPUShader = { readonly vertex?: string, readonly fragment?: string, */ function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor { - const shaderKey = shader.vertex + shader.fragment + shader.compute; - - // - let gpuPipelineLayout = gpuPipelineLayoutMap[shaderKey]; - if (gpuPipelineLayout) return gpuPipelineLayout; - const vertexCode = shader.vertex; const fragmentCode = shader.fragment; const computeCode = shader.compute; @@ -128,7 +123,7 @@ function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor console.log(`命中相同的布局 ${pipelineLayoutKey},公用管线布局对象。`); } } - gpuPipelineLayout = gpuPipelineLayoutMap[shaderKey] = pipelineLayoutDescriptorMap[pipelineLayoutKey] + const gpuPipelineLayout: PipelineLayoutDescriptor = pipelineLayoutDescriptorMap[pipelineLayoutKey] = pipelineLayoutDescriptorMap[pipelineLayoutKey] || { bindGroupLayouts, key: pipelineLayoutKey }; return gpuPipelineLayout; @@ -160,5 +155,3 @@ function mergeBindGroupLayouts(entryMap: GPUBindGroupLayoutEntryMap, entryMap1: return entryMap; } - -const gpuPipelineLayoutMap: { [key: string]: PipelineLayoutDescriptor } = {}; diff --git a/src/internal/PipelineLayoutDescriptor.ts b/src/internal/PipelineLayoutDescriptor.ts index 1ab4e62..542191a 100644 --- a/src/internal/PipelineLayoutDescriptor.ts +++ b/src/internal/PipelineLayoutDescriptor.ts @@ -35,15 +35,36 @@ export interface BindGroupLayoutDescriptor declare global { + interface GPUBindGroupLayoutDescriptor + { + /** + * 绑定组变量名称列表。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + entryNames?: string[], + + /** + * 用于判断布局信息是否相同的标识。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + key?: string, + } + interface GPUBindGroupLayoutEntry { /** * 绑定资源变量信息。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 */ variableInfo: VariableInfo; /** * 用于判断布局信息是否相同的标识。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 */ key: string; } -- Gitee From f5f08eb9a2b8c8fb295204ae3ed1804e8da72a84 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 15:39:39 +0800 Subject: [PATCH 052/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E7=BB=84=E5=92=8C=E7=AE=A1=E9=81=93=E5=B8=83?= =?UTF-8?q?=E5=B1=80=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 getGPUBindGroup 函数,使用 GPUBindGroupLayoutDescriptor 替代 BindGroupLayoutDescriptor - 更新 getGPUPipelineLayout 函数,使用 GPUBindGroupLayoutDescriptor 替代 BindGroupLayoutDescriptor - 移除 BindGroupLayoutDescriptor 接口中的 entryNames 属性 - 优化绑定组和管道布局的生成逻辑 --- src/caches/getGPUBindGroup.ts | 9 ++++----- src/caches/getGPUPipelineLayout.ts | 15 +++++++-------- src/internal/PipelineLayoutDescriptor.ts | 20 +------------------- 3 files changed, 12 insertions(+), 32 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 9e3009e..d32e70a 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -9,12 +9,11 @@ import { getGPUBuffer } from "./getGPUBuffer"; import { getGPUSampler } from "./getGPUSampler"; import { getGPUTextureView } from "./getGPUTextureView"; import { getIGPUBuffer } from "./getIGPUBuffer"; -import { BindGroupLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { ChainMap } from "../utils/ChainMap"; import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; import { updateBufferBinding } from "../utils/updateBufferBinding"; -export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: BindGroupLayoutDescriptor, bindingResources: Uniforms) +export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayoutDescriptor, bindingResources: Uniforms) { const bindGroupDescriptor = getSetBindGroup(bindGroupLayout, bindingResources); @@ -188,10 +187,10 @@ export interface BindGroupEntry export type BindingResource = Sampler | TextureView | VideoTexture | UniformType; -function getSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, bindingResources: Uniforms) +function getSetBindGroup(bindGroupLayout: GPUBindGroupLayoutDescriptor, bindingResources: Uniforms) { const map: ChainMap, BindGroupDescriptor> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); - const subBindingResources = bindGroupLayout.entryNames.map((v) => bindingResources[v]); + const subBindingResources = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map(v=>v.variableInfo.name).map((v) => bindingResources[v]); let bindGroupDescriptor = map.get(subBindingResources); if (bindGroupDescriptor) return bindGroupDescriptor; @@ -200,7 +199,7 @@ function getSetBindGroup(bindGroupLayout: BindGroupLayoutDescriptor, bindingReso map.set(subBindingResources, bindGroupDescriptor); // - bindGroupLayout.entries.forEach((entry1) => + (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).forEach((entry1) => { const { variableInfo, binding } = entry1; // diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index a0032e5..15f1125 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,4 +1,4 @@ -import { BindGroupLayoutDescriptor, PipelineLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; +import { PipelineLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; import { getIGPUBindGroupLayoutEntryMap, GPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; @@ -6,7 +6,7 @@ declare global { interface GPUPipelineLayout { - bindGroupLayouts: BindGroupLayoutDescriptor[]; + bindGroupLayouts: GPUBindGroupLayoutDescriptor[]; } } @@ -69,25 +69,24 @@ function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor } // - const bindGroupLayouts: BindGroupLayoutDescriptor[] = []; + const bindGroupLayouts: GPUBindGroupLayoutDescriptor[] = []; for (const resourceName in entryMap) { const bindGroupLayoutEntry = entryMap[resourceName]; const { group, binding } = bindGroupLayoutEntry.variableInfo; // - const bindGroupLayout = bindGroupLayouts[group] = bindGroupLayouts[group] || { entries: [], entryNames: [], key: "" }; + const bindGroupLayout = bindGroupLayouts[group] = bindGroupLayouts[group] || { entries: [], key: "" }; // 检测相同位置是否存在多个定义 if (bindGroupLayout.entries[binding]) { // 存在重复定义时,判断是否兼容 const preEntry = bindGroupLayout.entries[binding]; - console.error(`在管线中 @group(${group}) @binding(${binding}) 处存在多个定义 ${preEntry.variableInfo.name} ${resourceName} 。`); + console.error(`在管线中 @group(${group}) @binding(${binding}) 处存在多个定义 ${preEntry.variableInfo.name} ${resourceName} !`); } // bindGroupLayout.entries[binding] = bindGroupLayoutEntry; - bindGroupLayout.entryNames.push(resourceName); } // 排除 undefined 元素。 @@ -102,7 +101,7 @@ function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor entries.splice(i, 1); } } - bindGroupLayout.key = bindGroupLayout.entries.map((v) => v.key).join(","); + bindGroupLayout.key = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map((v) => v.key).join(","); // 相同的布局只保留一个。 if (__DEV__) { @@ -129,7 +128,7 @@ function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor return gpuPipelineLayout; } -const bindGroupLayoutMap: { [key: string]: BindGroupLayoutDescriptor } = {}; +const bindGroupLayoutMap: { [key: string]: GPUBindGroupLayoutDescriptor } = {}; const pipelineLayoutDescriptorMap: { [key: string]: PipelineLayoutDescriptor } = {}; function mergeBindGroupLayouts(entryMap: GPUBindGroupLayoutEntryMap, entryMap1: GPUBindGroupLayoutEntryMap): GPUBindGroupLayoutEntryMap diff --git a/src/internal/PipelineLayoutDescriptor.ts b/src/internal/PipelineLayoutDescriptor.ts index 542191a..6bf3f79 100644 --- a/src/internal/PipelineLayoutDescriptor.ts +++ b/src/internal/PipelineLayoutDescriptor.ts @@ -17,33 +17,15 @@ export interface PipelineLayoutDescriptor * @group attribute in the {@link GPUShaderModule}, with the `N`th element corresponding with * `@group(N)`. */ - bindGroupLayouts: BindGroupLayoutDescriptor[]; + bindGroupLayouts: GPUBindGroupLayoutDescriptor[]; key: string; } -/** - * {@link GPUBindGroupLayoutDescriptor} - */ -export interface BindGroupLayoutDescriptor -{ - label?: string; - entries: GPUBindGroupLayoutEntry[]; - entryNames: string[], - key: string, -} - declare global { interface GPUBindGroupLayoutDescriptor { - /** - * 绑定组变量名称列表。 - * - * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 - */ - entryNames?: string[], - /** * 用于判断布局信息是否相同的标识。 * -- Gitee From efcedf02352e245fdd38944164691ccf33013222 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 16:03:23 +0800 Subject: [PATCH 053/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=AE=A1=E7=BA=BF=E5=B8=83=E5=B1=80=E5=92=8C=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E7=BB=84=E5=B8=83=E5=B1=80=E7=9A=84=E7=94=9F=E6=88=90=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 getGPUBindGroup 函数,使用 GPUBindGroupLayout 替代 GPUBindGroupLayoutDescriptor - 重构 getGPUPipelineLayout 函数,优化绑定组布局的生成和处理 - 更新相关类型定义,增加 GPUBindGroupLayoutDescriptor 和 GPUBindGroupLayoutEntry 的定义 - 移除 PipelineLayoutDescriptor 文件中的冗余定义 --- src/caches/getGPUBindGroup.ts | 4 +- src/caches/getGPUPipelineLayout.ts | 116 ++++++++++++++--------- src/caches/getWGSLReflectInfo.ts | 31 +++++- src/internal/PipelineLayoutDescriptor.ts | 65 ++++--------- 4 files changed, 124 insertions(+), 92 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index d32e70a..90e40db 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -13,7 +13,7 @@ import { ChainMap } from "../utils/ChainMap"; import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; import { updateBufferBinding } from "../utils/updateBufferBinding"; -export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayoutDescriptor, bindingResources: Uniforms) +export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: Uniforms) { const bindGroupDescriptor = getSetBindGroup(bindGroupLayout, bindingResources); @@ -187,7 +187,7 @@ export interface BindGroupEntry export type BindingResource = Sampler | TextureView | VideoTexture | UniformType; -function getSetBindGroup(bindGroupLayout: GPUBindGroupLayoutDescriptor, bindingResources: Uniforms) +function getSetBindGroup(bindGroupLayout: GPUBindGroupLayout, bindingResources: Uniforms) { const map: ChainMap, BindGroupDescriptor> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); const subBindingResources = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map(v=>v.variableInfo.name).map((v) => bindingResources[v]); diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 15f1125..2de1225 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,4 +1,4 @@ -import { PipelineLayoutDescriptor } from "../internal/PipelineLayoutDescriptor"; +import { VariableInfo } from "wgsl_reflect"; import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; import { getIGPUBindGroupLayoutEntryMap, GPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; @@ -6,7 +6,49 @@ declare global { interface GPUPipelineLayout { - bindGroupLayouts: GPUBindGroupLayoutDescriptor[]; + /** + * 绑定组布局列表。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + bindGroupLayouts: GPUBindGroupLayout[]; + } + + interface GPUBindGroupLayout + { + /** + * 绑定组布局的入口列表。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + entries: GPUBindGroupLayoutEntry[]; + } + + interface GPUBindGroupLayoutDescriptor + { + /** + * 用于判断布局信息是否相同的标识。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + key?: string, + } + + interface GPUBindGroupLayoutEntry + { + /** + * 绑定资源变量信息。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + variableInfo: VariableInfo; + + /** + * 用于判断布局信息是否相同的标识。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + key: string; } } @@ -18,22 +60,11 @@ export function getGPUPipelineLayout(device: GPUDevice, shader: IGPUShader): GPU let gpuPipelineLayout = gpuPipelineLayoutMap0[shaderKey]; if (gpuPipelineLayout) return gpuPipelineLayout; - const layout = getIGPUPipelineLayout(shader); - - const bindGroupLayouts = layout.bindGroupLayouts.map((v) => - { - const gBindGroupLayout = getGPUBindGroupLayout(device, v); - - return gBindGroupLayout; - }); + const layout = getIGPUPipelineLayout(device, shader); - const gPipelineLayout = device.createPipelineLayout({ - bindGroupLayouts, - }); - gPipelineLayout.bindGroupLayouts = layout.bindGroupLayouts; - gpuPipelineLayoutMap0[shaderKey] = gPipelineLayout; + gpuPipelineLayoutMap0[shaderKey] = layout; - return gPipelineLayout; + return layout; } const gpuPipelineLayoutMap0: { [key: string]: GPUPipelineLayout } = {}; @@ -45,7 +76,7 @@ export type IGPUShader = { readonly vertex?: string, readonly fragment?: string, * @param shader GPU管线。 * @returns 管线布局。 */ -function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor +function getIGPUPipelineLayout(device: GPUDevice, shader: IGPUShader) { const vertexCode = shader.vertex; const fragmentCode = shader.fragment; @@ -68,52 +99,47 @@ function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor entryMap = mergeBindGroupLayouts(entryMap, computeEntryMap); } - // - const bindGroupLayouts: GPUBindGroupLayoutDescriptor[] = []; + // 绑定组布局描述列表。 + const bindGroupLayoutDescriptors: GPUBindGroupLayoutDescriptor[] = []; for (const resourceName in entryMap) { const bindGroupLayoutEntry = entryMap[resourceName]; const { group, binding } = bindGroupLayoutEntry.variableInfo; // - const bindGroupLayout = bindGroupLayouts[group] = bindGroupLayouts[group] || { entries: [], key: "" }; + const bindGroupLayoutDescriptor = bindGroupLayoutDescriptors[group] = bindGroupLayoutDescriptors[group] || { entries: [], key: "" }; // 检测相同位置是否存在多个定义 - if (bindGroupLayout.entries[binding]) + if (bindGroupLayoutDescriptor.entries[binding]) { // 存在重复定义时,判断是否兼容 - const preEntry = bindGroupLayout.entries[binding]; + const preEntry = bindGroupLayoutDescriptor.entries[binding]; console.error(`在管线中 @group(${group}) @binding(${binding}) 处存在多个定义 ${preEntry.variableInfo.name} ${resourceName} !`); } // - bindGroupLayout.entries[binding] = bindGroupLayoutEntry; + bindGroupLayoutDescriptor.entries[binding] = bindGroupLayoutEntry; } - // 排除 undefined 元素。 - for (let i = 0; i < bindGroupLayouts.length; i++) + // + const bindGroupLayouts = bindGroupLayoutDescriptors.map((descriptor) => { - const bindGroupLayout = bindGroupLayouts[i]; - const entries = bindGroupLayout.entries as GPUBindGroupLayoutEntry[]; - for (let i = entries.length - 1; i >= 0; i--) - { - if (!entries[i]) - { - entries.splice(i, 1); - } - } - bindGroupLayout.key = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map((v) => v.key).join(","); + // 排除 undefined 元素。 + const entries = (descriptor.entries as GPUBindGroupLayoutEntry[]).filter((v) => !!v); + const key = entries.map((v) => v.key).join(","); // 相同的布局只保留一个。 if (__DEV__) { - if (bindGroupLayoutMap[bindGroupLayout.key]) + if (bindGroupLayoutMap[key]) { - console.log(`命中相同的布局 ${bindGroupLayout.key},公用绑定组布局对象。`); + console.log(`命中相同的布局 ${key},公用绑定组布局对象。`); } } - bindGroupLayouts[i] = bindGroupLayoutMap[bindGroupLayout.key] = bindGroupLayoutMap[bindGroupLayout.key] || bindGroupLayout; - } + const bindGroupLayout: GPUBindGroupLayout = bindGroupLayoutMap[key] = bindGroupLayoutMap[key] || getGPUBindGroupLayout(device, { entries }); + bindGroupLayout.entries = entries; + return bindGroupLayout; + }); - const pipelineLayoutKey = bindGroupLayouts.map((v, i) => `[${i} ,${v.key}]`).join(","); + const pipelineLayoutKey = bindGroupLayoutDescriptors.map((v, i) => `[${i} ,${v.key}]`).join(","); // 相同的布局只保留一个。 if (__DEV__) { @@ -122,14 +148,16 @@ function getIGPUPipelineLayout(shader: IGPUShader): PipelineLayoutDescriptor console.log(`命中相同的布局 ${pipelineLayoutKey},公用管线布局对象。`); } } - const gpuPipelineLayout: PipelineLayoutDescriptor = pipelineLayoutDescriptorMap[pipelineLayoutKey] - = pipelineLayoutDescriptorMap[pipelineLayoutKey] || { bindGroupLayouts, key: pipelineLayoutKey }; + const gpuPipelineLayout: GPUPipelineLayout = pipelineLayoutDescriptorMap[pipelineLayoutKey] = pipelineLayoutDescriptorMap[pipelineLayoutKey] || device.createPipelineLayout({ + bindGroupLayouts, + }); + gpuPipelineLayout.bindGroupLayouts = bindGroupLayouts; return gpuPipelineLayout; } -const bindGroupLayoutMap: { [key: string]: GPUBindGroupLayoutDescriptor } = {}; -const pipelineLayoutDescriptorMap: { [key: string]: PipelineLayoutDescriptor } = {}; +const bindGroupLayoutMap: { [key: string]: GPUBindGroupLayout } = {}; +const pipelineLayoutDescriptorMap: { [key: string]: GPUPipelineLayout } = {}; function mergeBindGroupLayouts(entryMap: GPUBindGroupLayoutEntryMap, entryMap1: GPUBindGroupLayoutEntryMap): GPUBindGroupLayoutEntryMap { diff --git a/src/caches/getWGSLReflectInfo.ts b/src/caches/getWGSLReflectInfo.ts index 14799ff..200ba37 100644 --- a/src/caches/getWGSLReflectInfo.ts +++ b/src/caches/getWGSLReflectInfo.ts @@ -1,5 +1,34 @@ -import { ResourceType, TemplateInfo, WgslReflect } from "wgsl_reflect"; +import { ResourceType, TemplateInfo, VariableInfo, WgslReflect } from "wgsl_reflect"; import { DepthTextureType, ExternalSampledTextureType, MultisampledTextureType, TextureType } from "../types/TextureType"; +declare global +{ + interface GPUBindGroupLayoutDescriptor + { + /** + * 用于判断布局信息是否相同的标识。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + key?: string, + } + + interface GPUBindGroupLayoutEntry + { + /** + * 绑定资源变量信息。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + variableInfo: VariableInfo; + + /** + * 用于判断布局信息是否相同的标识。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + key: string; + } +} /** * 从WebGPU着色器代码中获取反射信息。 diff --git a/src/internal/PipelineLayoutDescriptor.ts b/src/internal/PipelineLayoutDescriptor.ts index 6bf3f79..a5e0978 100644 --- a/src/internal/PipelineLayoutDescriptor.ts +++ b/src/internal/PipelineLayoutDescriptor.ts @@ -1,53 +1,28 @@ import { VariableInfo } from "wgsl_reflect"; -/** - * GPU管线布局描述。 - * - * {@link GPUPipelineLayoutDescriptor} - * - * {@link GPUDevice.createPipelineLayout} - * - * {@link GPUPipelineLayout} - */ -export interface PipelineLayoutDescriptor -{ - label?: string; - /** - * A list of {@link GPUBindGroupLayout}s the pipeline will use. Each element corresponds to a - * @group attribute in the {@link GPUShaderModule}, with the `N`th element corresponding with - * `@group(N)`. - */ - bindGroupLayouts: GPUBindGroupLayoutDescriptor[]; +// /** +// * GPU管线布局描述。 +// * +// * {@link GPUPipelineLayoutDescriptor} +// * +// * {@link GPUDevice.createPipelineLayout} +// * +// * {@link GPUPipelineLayout} +// */ +// export interface PipelineLayoutDescriptor +// { +// label?: string; +// /** +// * A list of {@link GPUBindGroupLayout}s the pipeline will use. Each element corresponds to a +// * @group attribute in the {@link GPUShaderModule}, with the `N`th element corresponding with +// * `@group(N)`. +// */ +// bindGroupLayouts: GPUBindGroupLayoutDescriptor[]; - key: string; -} +// key: string; +// } declare global { - interface GPUBindGroupLayoutDescriptor - { - /** - * 用于判断布局信息是否相同的标识。 - * - * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 - */ - key?: string, - } - - interface GPUBindGroupLayoutEntry - { - /** - * 绑定资源变量信息。 - * - * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 - */ - variableInfo: VariableInfo; - /** - * 用于判断布局信息是否相同的标识。 - * - * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 - */ - key: string; - } } \ No newline at end of file -- Gitee From 221ff82946532388553e0935ce6deff737054392 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 16:30:44 +0800 Subject: [PATCH 054/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E7=BB=84=E5=92=8C=E7=AE=A1=E9=81=93=E5=B8=83?= =?UTF-8?q?=E5=B1=80=E7=9A=84=E5=88=9B=E5=BB=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 getGPUBindGroupLayout 函数,直接在 getGPUPipelineLayout 中创建绑定组布局 - 优化绑定组布局描述符的生成逻辑,移除不必要的 key 属性 - 更新 getGPUBindGroup 函数,使用新的绑定组布局逻辑 - 调整 getWGSLReflectInfo 函数,改进绑定组布局的键值生成 --- src/caches/getGPUBindGroup.ts | 13 ++++----- src/caches/getGPUBindGroupLayout.ts | 15 ----------- src/caches/getGPUPipelineLayout.ts | 17 +++++------- src/caches/getWGSLReflectInfo.ts | 41 +++++------------------------ 4 files changed, 18 insertions(+), 68 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 90e40db..2b5c939 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -4,14 +4,13 @@ import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; import { VideoTexture } from "../data/VideoTexture"; import { GPUTextureView_destroy, IGPUSampler_changed } from "../eventnames"; -import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; +import { ChainMap } from "../utils/ChainMap"; +import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; +import { updateBufferBinding } from "../utils/updateBufferBinding"; import { getGPUBuffer } from "./getGPUBuffer"; import { getGPUSampler } from "./getGPUSampler"; import { getGPUTextureView } from "./getGPUTextureView"; import { getIGPUBuffer } from "./getIGPUBuffer"; -import { ChainMap } from "../utils/ChainMap"; -import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; -import { updateBufferBinding } from "../utils/updateBufferBinding"; export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: Uniforms) { @@ -27,8 +26,6 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup // 执行一次函数列表 const onceUpdateFuncs: (() => void)[] = []; - const layout = getGPUBindGroupLayout(device, bindGroupDescriptor.layout); - const entries = bindGroupDescriptor.entries.map((v) => { const entry: GPUBindGroupEntry = { binding: v.binding, resource: null }; @@ -119,7 +116,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup { onceUpdateFuncs.forEach((v) => v()); - gBindGroup = device.createBindGroup({ layout, entries }); + gBindGroup = device.createBindGroup({ layout: bindGroupLayout, entries }); bindGroupMap.set(bindGroupDescriptor, gBindGroup); @@ -190,7 +187,7 @@ export type BindingResource = Sampler | TextureView | VideoTexture | UniformType function getSetBindGroup(bindGroupLayout: GPUBindGroupLayout, bindingResources: Uniforms) { const map: ChainMap, BindGroupDescriptor> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); - const subBindingResources = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map(v=>v.variableInfo.name).map((v) => bindingResources[v]); + const subBindingResources = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map(v => v.variableInfo.name).map((v) => bindingResources[v]); let bindGroupDescriptor = map.get(subBindingResources); if (bindGroupDescriptor) return bindGroupDescriptor; diff --git a/src/caches/getGPUBindGroupLayout.ts b/src/caches/getGPUBindGroupLayout.ts index 783017c..e69de29 100644 --- a/src/caches/getGPUBindGroupLayout.ts +++ b/src/caches/getGPUBindGroupLayout.ts @@ -1,15 +0,0 @@ -export function getGPUBindGroupLayout(device: GPUDevice, layout: GPUBindGroupLayoutDescriptor) -{ - let gpuBindGroupLayout = bindGroupLayoutMap.get(layout); - - if (gpuBindGroupLayout) return gpuBindGroupLayout; - - // - gpuBindGroupLayout = device.createBindGroupLayout(layout); - - bindGroupLayoutMap.set(layout, gpuBindGroupLayout); - - return gpuBindGroupLayout; -} - -const bindGroupLayoutMap = new WeakMap(); diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 2de1225..fca7f42 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,5 +1,4 @@ import { VariableInfo } from "wgsl_reflect"; -import { getGPUBindGroupLayout } from "./getGPUBindGroupLayout"; import { getIGPUBindGroupLayoutEntryMap, GPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; declare global @@ -22,16 +21,13 @@ declare global * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 */ entries: GPUBindGroupLayoutEntry[]; - } - interface GPUBindGroupLayoutDescriptor - { /** * 用于判断布局信息是否相同的标识。 * * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 */ - key?: string, + key: string, } interface GPUBindGroupLayoutEntry @@ -106,7 +102,7 @@ function getIGPUPipelineLayout(device: GPUDevice, shader: IGPUShader) const bindGroupLayoutEntry = entryMap[resourceName]; const { group, binding } = bindGroupLayoutEntry.variableInfo; // - const bindGroupLayoutDescriptor = bindGroupLayoutDescriptors[group] = bindGroupLayoutDescriptors[group] || { entries: [], key: "" }; + const bindGroupLayoutDescriptor = bindGroupLayoutDescriptors[group] = bindGroupLayoutDescriptors[group] || { entries: [] }; // 检测相同位置是否存在多个定义 if (bindGroupLayoutDescriptor.entries[binding]) @@ -120,7 +116,7 @@ function getIGPUPipelineLayout(device: GPUDevice, shader: IGPUShader) bindGroupLayoutDescriptor.entries[binding] = bindGroupLayoutEntry; } - // + // 绑定组布局列表。 const bindGroupLayouts = bindGroupLayoutDescriptors.map((descriptor) => { // 排除 undefined 元素。 @@ -134,13 +130,14 @@ function getIGPUPipelineLayout(device: GPUDevice, shader: IGPUShader) console.log(`命中相同的布局 ${key},公用绑定组布局对象。`); } } - const bindGroupLayout: GPUBindGroupLayout = bindGroupLayoutMap[key] = bindGroupLayoutMap[key] || getGPUBindGroupLayout(device, { entries }); + const bindGroupLayout: GPUBindGroupLayout = bindGroupLayoutMap[key] = bindGroupLayoutMap[key] || device.createBindGroupLayout({ entries, label: key }); bindGroupLayout.entries = entries; + bindGroupLayout.key = key; return bindGroupLayout; }); - const pipelineLayoutKey = bindGroupLayoutDescriptors.map((v, i) => `[${i} ,${v.key}]`).join(","); - // 相同的布局只保留一个。 + // 管线布局描述标识符。 + const pipelineLayoutKey = bindGroupLayouts.map((v, i) => `[${i}: ${v.key}]`).join(","); if (__DEV__) { if (pipelineLayoutDescriptorMap[pipelineLayoutKey]) diff --git a/src/caches/getWGSLReflectInfo.ts b/src/caches/getWGSLReflectInfo.ts index 200ba37..f9d7251 100644 --- a/src/caches/getWGSLReflectInfo.ts +++ b/src/caches/getWGSLReflectInfo.ts @@ -1,34 +1,5 @@ import { ResourceType, TemplateInfo, VariableInfo, WgslReflect } from "wgsl_reflect"; import { DepthTextureType, ExternalSampledTextureType, MultisampledTextureType, TextureType } from "../types/TextureType"; -declare global -{ - interface GPUBindGroupLayoutDescriptor - { - /** - * 用于判断布局信息是否相同的标识。 - * - * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 - */ - key?: string, - } - - interface GPUBindGroupLayoutEntry - { - /** - * 绑定资源变量信息。 - * - * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 - */ - variableInfo: VariableInfo; - - /** - * 用于判断布局信息是否相同的标识。 - * - * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 - */ - key: string; - } -} /** * 从WebGPU着色器代码中获取反射信息。 @@ -68,7 +39,7 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): GPUBindGroupLayout entryMap[name] = { variableInfo: uniform, visibility: Visibility_ALL, binding, buffer: layout, - key: `[${binding}, buffer, ${layout.type} , ${layout.minBindingSize}]`, + key: `[${binding}, ${name}, buffer, ${layout.type} , ${layout.minBindingSize}]`, }; } @@ -89,7 +60,7 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): GPUBindGroupLayout entryMap[name] = { variableInfo: storage, visibility: type === "storage" ? Visibility_FRAGMENT_COMPUTE : Visibility_ALL, binding, buffer: layout, - key: `[${binding}, buffer, ${layout.type}]`, + key: `[${binding}, ${name}, buffer, ${layout.type}]`, }; } else if (storage.resourceType === ResourceType.StorageTexture) @@ -112,7 +83,7 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): GPUBindGroupLayout entryMap[name] = { variableInfo: storage, visibility: Visibility_FRAGMENT_COMPUTE, binding, storageTexture: layout, - key: `[${binding}, storageTexture, ${layout.access}, ${layout.format}, ${layout.viewDimension}]`, + key: `[${binding}, ${name}, storageTexture, ${layout.access}, ${layout.format}, ${layout.viewDimension}]`, }; } else @@ -134,7 +105,7 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): GPUBindGroupLayout entryMap[name] = { variableInfo: texture, visibility: Visibility_ALL, binding, externalTexture: {}, - key: `[${binding}, externalTexture]`, + key: `[${binding}, ${name}, externalTexture]`, }; } else @@ -183,7 +154,7 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): GPUBindGroupLayout entryMap[name] = { variableInfo: texture, visibility: Visibility_ALL, binding, texture: layout, - key: `[${binding}, texture, ${layout.sampleType}, ${layout.viewDimension}, ${layout.multisampled}]`, + key: `[${binding}, ${name}, texture, ${layout.sampleType}, ${layout.viewDimension}, ${layout.multisampled}]`, }; } } @@ -202,7 +173,7 @@ export function getIGPUBindGroupLayoutEntryMap(code: string): GPUBindGroupLayout entryMap[name] = { variableInfo: sampler, visibility: Visibility_ALL, binding, sampler: layout, - key: `[${binding}, sampler, ${layout.type}]`, + key: `[${binding}, ${name}, sampler, ${layout.type}]`, }; } -- Gitee From be4159f02485ad2e18f3c6cf78be8ef0aa7f320f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 18:02:00 +0800 Subject: [PATCH 055/214] =?UTF-8?q?refactor(bindings):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E7=BB=91=E5=AE=9A=E8=B5=84=E6=BA=90=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=92=8C=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 Uniforms 重命名为 BindingResources,以更准确地反映其用途 - 更新了多个文件中的类型引用和接口定义 - 调整了部分函数签名,以适应新的绑定资源类型 --- .../src/webgpu/bitonicSort/bitonicDisplay.ts | 6 +++--- examples/src/webgpu/bitonicSort/index.ts | 4 ++-- examples/src/webgpu/bitonicSort/utils.ts | 4 ++-- examples/src/webgpu/blending/index.ts | 16 ++++++++------- examples/src/webgpu/cornell/common.ts | 6 +++--- examples/src/webgpu/cornell/radiosity.ts | 4 ++-- examples/src/webgpu/cornell/rasterizer.ts | 4 ++-- examples/src/webgpu/cornell/raytracer.ts | 4 ++-- examples/src/webgpu/cornell/tonemapper.ts | 4 ++-- .../src/webgpu/deferredRendering/index.ts | 12 +++++------ examples/src/webgpu/gameOfLife/index.ts | 10 +++++----- examples/src/webgpu/imageBlur/index.ts | 20 +++++++++---------- examples/src/webgpu/multipleCanvases/index.ts | 6 +++--- examples/src/webgpu/normalMap/index.ts | 4 ++-- examples/src/webgpu/particles/index.ts | 8 ++++---- examples/src/webgpu/renderBundles/index.ts | 12 +++++------ .../src/webgpu/resizeObserverHDDPI/index.ts | 4 ++-- examples/src/webgpu/reversedZ/index.ts | 6 +++--- .../src/webgpu/samplerParameters/index.ts | 8 ++++---- examples/src/webgpu/shadowMapping/index.ts | 8 ++++---- examples/src/webgpu/skinnedMesh/glbUtils.ts | 10 +++++----- examples/src/webgpu/skinnedMesh/index.ts | 10 +++++----- .../src/webgpu/textRenderingMsdf/index.ts | 6 +++--- .../src/webgpu/textRenderingMsdf/msdfText.ts | 10 +++++----- .../webgpu/volumeRenderingTexture3D/index.ts | 4 ++-- examples/src/webgpu/wireframe/index.ts | 12 +++++------ src/WebGPUStep.ts | 4 ++-- src/caches/getGPUBindGroup.ts | 11 ++++------ src/caches/getGPURenderOcclusionQuery.ts | 4 ++-- src/data/ComputeObject.ts | 4 ++-- src/data/polyfills/Uniforms.ts | 2 +- src/runs/RunWebGPU.ts | 8 ++++---- src/runs/RunWebGPUCommandCache.ts | 6 +++--- 33 files changed, 120 insertions(+), 121 deletions(-) diff --git a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts index 5c2f8bd..d79c7d0 100644 --- a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts +++ b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts @@ -1,4 +1,4 @@ -import { BufferBinding, CommandEncoder, RenderPassDescriptor, Uniforms } from "@feng3d/render-api"; +import { BindingResources, BufferBinding, CommandEncoder, RenderPassDescriptor } from "@feng3d/render-api"; import bitonicDisplay from "./bitonicDisplay.frag.wgsl"; import { Base2DRendererClass } from "./utils"; @@ -12,11 +12,11 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass { switchBindGroup: (name: string) => void; setArguments: (args: BitonicDisplayRenderArgs) => void; - computeBGDescript: Uniforms; + computeBGDescript: BindingResources; constructor( renderPassDescriptor: RenderPassDescriptor, - computeBGDescript: Uniforms, + computeBGDescript: BindingResources, label: string ) { diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 0a694b5..fea455c 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,4 +1,4 @@ -import { Buffer, BufferBinding, CommandEncoder, RenderPassDescriptor, Submit, Uniforms } from "@feng3d/render-api"; +import { Buffer, BufferBinding, CommandEncoder, RenderPassDescriptor, Submit, BindingResources } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { ComputePipeline, getIGPUBuffer, ComputePass, TimestampQuery, WebGPU, reactive } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -283,7 +283,7 @@ async function init( bufferView: new Float32Array(4), }; - const computeBGCluster: Uniforms = { + const computeBGCluster: BindingResources = { input_data: elementsInputBuffer, data: elementsInputBuffer, output_data: elementsOutputBuffer, diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index d1ebecc..48a71b6 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Uniforms } from "@feng3d/render-api"; +import { BindingResources, CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline } from "@feng3d/render-api"; const fullscreenTexturedQuad = ` @@ -51,7 +51,7 @@ export abstract class Base2DRendererClass commandEncoder: CommandEncoder, renderPassDescriptor: RenderPassDescriptor, pipeline: RenderPipeline, - bindingResources?: Uniforms + bindingResources?: BindingResources ) { const passEncoder: RenderPass = { diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 0e1cd0e..7533225 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import texturedQuadWGSL from "./texturedQuad.wgsl"; -import { BlendComponent, CanvasContext, IRenderPassObject, RenderObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, TextureView, Uniforms } from "@feng3d/render-api"; +import { BindingResources, BlendComponent, CanvasContext, RenderObject, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureView } from "@feng3d/render-api"; import { reactive, WebGPU } from "@feng3d/webgpu"; declare module "@feng3d/render-api" @@ -167,25 +167,25 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const srcUniform = { matrix: new Float32Array(16) }; const dstUniform = { matrix: new Float32Array(16) }; - const srcBindGroupUnpremultipliedAlpha: Uniforms = { + const srcBindGroupUnpremultipliedAlpha: BindingResources = { ourSampler: sampler, ourTexture: { texture: srcTextureUnpremultipliedAlpha }, uni: srcUniform, }; - const dstBindGroupUnpremultipliedAlpha: Uniforms = { + const dstBindGroupUnpremultipliedAlpha: BindingResources = { ourSampler: sampler, ourTexture: { texture: dstTextureUnpremultipliedAlpha }, uni: dstUniform, }; - const srcBindGroupPremultipliedAlpha: Uniforms = { + const srcBindGroupPremultipliedAlpha: BindingResources = { ourSampler: sampler, ourTexture: { texture: srcTexturePremultipliedAlpha }, uni: srcUniform, }; - const dstBindGroupPremultipliedAlpha: Uniforms = { + const dstBindGroupPremultipliedAlpha: BindingResources = { ourSampler: sampler, ourTexture: { texture: dstTexturePremultipliedAlpha }, uni: dstUniform, @@ -482,7 +482,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } function updateUniforms( - uniforms: Uniforms, + uniforms: { + matrix: Float32Array; + }, canvas: HTMLCanvasElement, texture: Texture ) @@ -523,7 +525,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; - const renderObjects: IRenderPassObject[] = [ + const renderObjects: RenderPassObject[] = [ ro, ro1, ]; diff --git a/examples/src/webgpu/cornell/common.ts b/examples/src/webgpu/cornell/common.ts index c4c9ffc..bb07684 100644 --- a/examples/src/webgpu/cornell/common.ts +++ b/examples/src/webgpu/cornell/common.ts @@ -1,4 +1,4 @@ -import { Uniforms } from "@feng3d/render-api"; +import { BindingResources } from "@feng3d/render-api"; import { getIGPUBuffer, reactive } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -13,7 +13,7 @@ export default class Common readonly wgsl = commonWGSL; /** The common uniform buffer bind group and layout */ readonly uniforms: { - bindGroup: Uniforms; + bindGroup: BindingResources; }; private readonly uniformBuffer: Uint8Array; @@ -27,7 +27,7 @@ export default class Common + 4 * 16 // inv_mvp + 4 * 4); - const bindGroup: Uniforms = { + const bindGroup: BindingResources = { common_uniforms: { bufferView: this.uniformBuffer, }, diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index 38bff0c..6027579 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; +import { BindingResources, CommandEncoder, IPassEncoder, Texture } from "@feng3d/render-api"; import { ComputePipeline, getIGPUBuffer, reactive } from "@feng3d/webgpu"; import Common from "./common"; @@ -39,7 +39,7 @@ export default class Radiosity private readonly scene: Scene; private readonly radiosityPipeline: ComputePipeline; private readonly accumulationToLightmapPipeline: ComputePipeline; - private readonly bindGroup: Uniforms; + private readonly bindGroup: BindingResources; private readonly accumulationBuffer: Uint8Array; private readonly uniformBuffer: Uint8Array; diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index deeb746..c6d25eb 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Texture, Uniforms } from "@feng3d/render-api"; +import { BindingResources, CommandEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Texture } from "@feng3d/render-api"; import Common from "./common"; import Radiosity from "./radiosity"; @@ -14,7 +14,7 @@ export default class Rasterizer private readonly scene: Scene; private readonly renderPassDescriptor: RenderPassDescriptor; private readonly pipeline: RenderPipeline; - private readonly bindGroup: Uniforms; + private readonly bindGroup: BindingResources; constructor( common: Common, diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index c32d73e..193d74e 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -1,4 +1,4 @@ -import { CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; +import { BindingResources, CommandEncoder, IPassEncoder, Texture } from "@feng3d/render-api"; import { ComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -13,7 +13,7 @@ export default class Raytracer private readonly common: Common; private readonly framebuffer: Texture; private readonly material: ComputePipeline; - private readonly bindGroup: Uniforms; + private readonly bindGroup: BindingResources; private readonly kWorkgroupSizeX = 16; private readonly kWorkgroupSizeY = 16; diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index 2658e78..5124cf2 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -1,4 +1,4 @@ -import { CanvasTexture, CommandEncoder, IPassEncoder, Texture, Uniforms } from "@feng3d/render-api"; +import { BindingResources, CanvasTexture, CommandEncoder, IPassEncoder, Texture } from "@feng3d/render-api"; import { ComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -10,7 +10,7 @@ import tonemapperWGSL from "./tonemapper.wgsl"; */ export default class Tonemapper { - private readonly bindGroup: Uniforms; + private readonly bindGroup: BindingResources; private readonly material: ComputePipeline; private readonly width: number; private readonly height: number; diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 0b16dec..b1adf54 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -10,8 +10,8 @@ import lightUpdate from "./lightUpdate.wgsl"; import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU, reactive } from "@feng3d/webgpu"; +import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; +import { ComputePass, ComputePipeline, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; const kMaxNumLights = 1024; const lightExtentMin = vec3.fromValues(-50, -30, -50); @@ -177,7 +177,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const cameraUniformBuffer = new Uint8Array(4 * 16); - const sceneUniformBindGroup: Uniforms = { + const sceneUniformBindGroup: BindingResources = { uniforms: { bufferView: modelUniformBuffer, }, @@ -186,7 +186,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const gBufferTexturesBindGroup: Uniforms = { + const gBufferTexturesBindGroup: BindingResources = { gBufferPosition: gBufferTextureViews[0], gBufferNormal: gBufferTextureViews[1], gBufferAlbedo: gBufferTextureViews[2], @@ -236,7 +236,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => code: lightUpdate, }, }; - const lightsBufferBindGroup: Uniforms = { + const lightsBufferBindGroup: BindingResources = { lightsBuffer: { bufferView: lightsBuffer, }, @@ -244,7 +244,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => bufferView: configUniformBuffer, }, }; - const lightsBufferComputeBindGroup: Uniforms = { + const lightsBufferComputeBindGroup: BindingResources = { lightsBuffer: { bufferView: lightsBuffer, }, diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 50a2826..089c2cf 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -4,8 +4,8 @@ import computeWGSL from "./compute.wgsl"; import fragWGSL from "./frag.wgsl"; import vertWGSL from "./vert.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; -import { ComputePipeline, ComputePass, WebGPU } from "@feng3d/webgpu"; +import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; +import { ComputePass, ComputePipeline, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -74,13 +74,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cell: { data: buffer1, format: "uint32", stepMode: "instance" } }; - const bindGroup0: Uniforms = { + const bindGroup0: BindingResources = { size: { bufferView: sizeBuffer }, current: { bufferView: buffer0 }, next: { bufferView: buffer1 }, }; - const bindGroup1: Uniforms = { + const bindGroup1: BindingResources = { size: { bufferView: sizeBuffer }, current: { bufferView: buffer1 }, next: { bufferView: buffer0 }, @@ -95,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const uniformBindGroup: Uniforms = { + const uniformBindGroup: BindingResources = { size: { bufferView: sizeBuffer, offset: 0, diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 3ea07b0..43d783a 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -3,8 +3,8 @@ import { GUI } from "dat.gui"; import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgsl"; import blurWGSL from "./blur.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; -import { ComputePipeline, getIGPUBuffer, ComputePass, WebGPU, reactive } from "@feng3d/webgpu"; +import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture } from "@feng3d/render-api"; +import { ComputePass, ComputePipeline, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; // Contants from the blur.wgsl shader. const tileDim = 128; @@ -66,14 +66,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const blurParamsBuffer = new Uint8Array(8); - const computeConstants: Uniforms = { + const computeConstants: BindingResources = { samp: sampler, params: { bufferView: blurParamsBuffer, }, }; - const computeBindGroup0: Uniforms = { + const computeBindGroup0: BindingResources = { inputTex: { texture: cubeTexture1 }, outputTex: { texture: textures[0] }, flip: { @@ -81,7 +81,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; - const computeBindGroup1: Uniforms = { + const computeBindGroup1: BindingResources = { inputTex: { texture: textures[0] }, outputTex: { texture: textures[1] }, flip: { @@ -89,7 +89,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const computeBindGroup2: Uniforms = { + const computeBindGroup2: BindingResources = { inputTex: { texture: textures[1] }, outputTex: { texture: textures[0] }, flip: { @@ -97,7 +97,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; - const showResultBindGroup1: Uniforms = { + const showResultBindGroup1: BindingResources = { mySampler: sampler, myTexture: { texture: textures[1] }, }; @@ -163,15 +163,15 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ] }; - const bindingResources0: Uniforms = { + const bindingResources0: BindingResources = { ...computeConstants, ...computeBindGroup0, }; - const bindingResources1: Uniforms = { + const bindingResources1: BindingResources = { ...computeConstants, ...computeBindGroup1, }; - const bindingResources2: Uniforms = { + const bindingResources2: BindingResources = { ...computeConstants, ...computeBindGroup2, }; diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index 18d015b..1de4b9f 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,4 +1,4 @@ -import { CanvasContext, IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, CanvasContext, IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; @@ -169,7 +169,7 @@ const init = async () => worldViewProjectionMatrixValue: Float32Array; worldMatrixValue: Float32Array; uniformValues: Float32Array; - bindGroup: Uniforms; + bindGroup: BindingResources; rotation: number; model: Model; renderPassDescriptor?: RenderPassDescriptor @@ -221,7 +221,7 @@ const init = async () => colorValue.set(randColor()); // Make a bind group for this uniform - const bindGroup: Uniforms = { + const bindGroup: BindingResources = { uni: { bufferView: uniformValues, worldViewProjectionMatrix: undefined, diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index 5b06cfc..9898289 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, BindingResources } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -164,7 +164,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => depthLayers: undefined, }; - const bindingResources: Uniforms = { + const bindingResources: BindingResources = { spaceTransform, mapInfo, // Texture bindGroups and bindGroupLayout diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index e68569d..f031e35 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -7,7 +7,7 @@ import particleWGSL from "./particle.wgsl"; import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; -import { RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { ComputePass, ComputePipeline, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; const numParticles = 50000; @@ -74,7 +74,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => + 0; const uniformBuffer = new Uint8Array(uniformBufferSize); - const uniformBindGroup: Uniforms = { + const uniformBindGroup: BindingResources = { render_params: { bufferView: uniformBuffer, }, @@ -179,7 +179,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { const levelWidth = textureWidth >> level; const levelHeight = textureHeight >> level; - const probabilityMapBindGroup: Uniforms = { + const probabilityMapBindGroup: BindingResources = { ubo: { bufferView: probabilityMapUBOBuffer }, buf_in: { bufferView: level & 1 ? bufferA : bufferB }, buf_out: { bufferView: level & 1 ? bufferB : bufferA }, @@ -250,7 +250,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => code: simulateWGSL, }, }; - const computeBindGroup: Uniforms = { + const computeBindGroup: BindingResources = { sim_params: { bufferView: simulationUBOBuffer, }, diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 7eb7450..523a64c 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,4 +1,4 @@ -import { CanvasContext, IRenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, CanvasContext, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { RenderBundle, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -15,7 +15,7 @@ interface Renderable vertexAttributes: VertexAttributes; indices: Uint16Array; indexCount: number; - bindGroup?: Uniforms; + bindGroup?: BindingResources; } const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => @@ -130,11 +130,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => function createSphereBindGroup1( texture: Texture, transform: Float32Array - ): Uniforms + ): BindingResources { const uniformBuffer = new Float32Array(transform); - const bindGroup: Uniforms = { + const bindGroup: BindingResources = { modelMatrix: { bufferView: uniformBuffer, }, @@ -211,7 +211,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => ); const modelViewProjectionMatrix = mat4.create(); - const frameBindGroup: Uniforms = { + const frameBindGroup: BindingResources = { uniforms: { bufferView: uniformBuffer, }, @@ -312,7 +312,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => reactive(getIGPUBuffer(uniformBuffer)).writeBuffers = [{ data: transformationMatrix }]; - let renderObjects: IRenderPassObject[] = []; + let renderObjects: RenderPassObject[] = []; if (settings.useRenderBundles) { // Executing a bundle is equivalent to calling all of the commands encoded diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index d446017..ccf3c67 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -1,7 +1,7 @@ import { GUI } from "dat.gui"; import checkerWGSL from "./checker.wgsl"; -import { RenderPassDescriptor, RenderPipeline, Submit, Uniforms } from "@feng3d/render-api"; +import { BindingResources, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement) => @@ -21,7 +21,7 @@ const init = async (canvas: HTMLCanvasElement) => size: undefined, }; - const bindGroup: Uniforms = { + const bindGroup: BindingResources = { uni, }; diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index d63623d..40caf8c 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -10,7 +10,7 @@ import vertexDepthPrePassWGSL from "./vertexDepthPrePass.wgsl"; import vertexPrecisionErrorPassWGSL from "./vertexPrecisionErrorPass.wgsl"; import vertexTextureQuadWGSL from "./vertexTextureQuad.wgsl"; -import { CanvasContext, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, CanvasContext, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; // Two planes close to each other for depth precision test @@ -259,7 +259,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => textureQuadPassLoadDescriptor, ]; - const depthTextureBindGroup: Uniforms = { + const depthTextureBindGroup: BindingResources = { depthTexture: { texture: depthTexture }, }; @@ -301,7 +301,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewProjectionMatrix: cameraMatrixReversedDepthBuffer, }; - const uniformBindGroups: Uniforms[] = [ + const uniformBindGroups: BindingResources[] = [ { uniforms, camera: camera0, diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index 2aa050d..a54829f 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -1,7 +1,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; -import { IRenderPassObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, TextureSource, Uniforms } from "@feng3d/render-api"; +import { BindingResources, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureSource } from "@feng3d/render-api"; import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; import showTextureWGSL from "./showTexture.wgsl"; @@ -302,9 +302,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ], }; - const renderObjects: IRenderPassObject[] = []; + const renderObjects: RenderPassObject[] = []; - const bindingResources0: Uniforms = { + const bindingResources0: BindingResources = { config: { bufferView: bufConfig }, matrices: { bufferView: bufMatrices }, samp: null, // 帧更新中设置 @@ -330,7 +330,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ); } - const bindingResources1: Uniforms = { + const bindingResources1: BindingResources = { tex: { texture: checkerboard }, }; const kLastViewport = (kViewportGridSize - 1) * kViewportGridStride + 1; diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 68ec0db..49a3bf1 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -114,13 +114,13 @@ const init = async (canvas: HTMLCanvasElement) => // Rounded to the nearest multiple of 16. const sceneUniformBuffer = new Uint8Array(2 * 4 * 16 + 4 * 4); - const sceneBindGroupForShadow: Uniforms = { + const sceneBindGroupForShadow: BindingResources = { scene: { bufferView: sceneUniformBuffer, }, }; - const sceneBindGroupForRender: Uniforms = { + const sceneBindGroupForRender: BindingResources = { scene: { bufferView: sceneUniformBuffer, }, @@ -130,7 +130,7 @@ const init = async (canvas: HTMLCanvasElement) => }, }; - const modelBindGroup: Uniforms = { + const modelBindGroup: BindingResources = { model: { bufferView: modelUniformBuffer, }, diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 15d687d..5f7a697 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { Buffer, FragmentState, IDraw, PrimitiveState, RenderObject, RenderPipeline, Uniforms, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; +import { BindingResources, Buffer, FragmentState, IDraw, PrimitiveState, RenderObject, RenderPipeline, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { getIGPUBuffer, reactive } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -441,7 +441,7 @@ export class GLTFPrimitive this.renderPipeline = rpDescript; } - render(renderObjects: RenderObject[], bindingResources: Uniforms) + render(renderObjects: RenderObject[], bindingResources: BindingResources) { let draw: IDraw; if (this.indices) @@ -509,7 +509,7 @@ export class GLTFMesh } } - render(renderObjects: RenderObject[], bindingResources: Uniforms) + render(renderObjects: RenderObject[], bindingResources: BindingResources) { // We take a pretty simple approach to start. Just loop through all the primitives and // call their individual draw methods @@ -664,7 +664,7 @@ export class GLTFNode } renderDrawables( - renderObjects: RenderObject[], bindingResources: Uniforms + renderObjects: RenderObject[], bindingResources: BindingResources ) { if (this.drawables !== undefined) @@ -733,7 +733,7 @@ export class GLTFSkin // [5, 2, 3] means our joint info is at nodes 5, 2, and 3 joints: number[]; // Bind Group for this skin's uniform buffer - skinBindGroup: Uniforms; + skinBindGroup: BindingResources; // Static bindGroupLayout shared across all skins // In a larger shader with more properties, certain bind groups // would likely have to be combined due to device limitations in the number of bind groups diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 93ff7ac..b2dc4fd 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -7,7 +7,7 @@ import gridWGSL from "./grid.wgsl"; import { gridIndices } from "./gridData"; import { createSkinnedGridBuffers, createSkinnedGridRenderPipeline } from "./gridUtils"; -import { IPassEncoder, RenderPass, RenderPassDescriptor, Texture, Uniforms, RenderObject } from "@feng3d/render-api"; +import { BindingResources, IPassEncoder, RenderObject, RenderPass, RenderPassDescriptor, Texture } from "@feng3d/render-api"; import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -193,7 +193,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const cameraBuffer = new Float32Array(48); - const cameraBGCluster: Uniforms = { + const cameraBGCluster: BindingResources = { camera_uniforms: { bufferView: cameraBuffer, } @@ -201,7 +201,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const generalUniformsBuffer = new Uint32Array(2); - const generalUniformsBGCLuster: Uniforms = { + const generalUniformsBGCLuster: BindingResources = { general_uniforms: { bufferView: generalUniformsBuffer, }, @@ -227,7 +227,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Buffer for our uniforms, joints, and inverse bind matrices const skinnedGridJointUniformBuffer = new Uint8Array(MAT4X4_BYTES * 5); const skinnedGridInverseBindUniformBuffer = new Uint8Array(MAT4X4_BYTES * 5); - const skinnedGridBoneBGCluster: Uniforms = { + const skinnedGridBoneBGCluster: BindingResources = { joint_matrices: { bufferView: skinnedGridJointUniformBuffer }, inverse_bind_matrices: { bufferView: skinnedGridInverseBindUniformBuffer }, }; @@ -488,7 +488,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => if (settings.object === "Whale") { const renderObjects: RenderObject[] = []; - const bindingResources: Uniforms = { + const bindingResources: BindingResources = { ...cameraBGCluster, ...generalUniformsBGCLuster, }; diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index cb5d9af..dc1e6db 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { IRenderPassObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, Uniforms, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, RenderPassDescriptor, RenderPassObject, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; import basicVertWGSL from "../../shaders/basic.vert.wgsl"; @@ -162,7 +162,7 @@ setBlendConstant().`, const uniformBuffer = new Float32Array(16); - const uniformBindGroup: Uniforms = { + const uniformBindGroup: BindingResources = { uniforms: { bufferView: uniformBuffer }, }; @@ -249,7 +249,7 @@ setBlendConstant().`, }); reactive(buffer).writeBuffers = writeBuffers; - const renderObjects: IRenderPassObject[] = []; + const renderObjects: RenderPassObject[] = []; renderObjects.push({ pipeline: pipeline, diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index 16fe4e3..303bbea 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -2,7 +2,7 @@ import { mat4, Mat4 } from "wgpu-matrix"; import msdfTextWGSL from "./msdfText.wgsl"; -import { IRenderPassObject, RenderPipeline, Sampler, Texture, Uniforms } from "@feng3d/render-api"; +import { BindingResources, RenderPassObject, RenderPipeline, Sampler, Texture } from "@feng3d/render-api"; import { getIGPUBuffer, reactive, RenderBundle } from "@feng3d/webgpu"; // The kerning map stores a spare map of character ID pairs with an associated @@ -33,7 +33,7 @@ export class MsdfFont defaultChar: MsdfChar; constructor( public material: RenderPipeline, - public bindGroup: Uniforms, + public bindGroup: BindingResources, public lineHeight: number, public chars: { [x: number]: MsdfChar }, public kernings: KerningMap @@ -253,7 +253,7 @@ export class MsdfTextRenderer const pageTextures = await Promise.all(pagePromises); - const bindGroup: Uniforms = { + const bindGroup: BindingResources = { fontTexture: { texture: pageTextures[0] }, fontSampler: this.sampler, chars: { bufferView: charsArray } @@ -330,7 +330,7 @@ export class MsdfTextRenderer ); } - const bindGroup: Uniforms = { + const bindGroup: BindingResources = { camera: { bufferView: this.cameraUniformBuffer }, text: { bufferView: textBuffer }, }; @@ -446,7 +446,7 @@ export class MsdfTextRenderer reactive(buffer).writeBuffers = writeBuffers; } - render(renderObjects: IRenderPassObject[], ...text: MsdfText[]) + render(renderObjects: RenderPassObject[], ...text: MsdfText[]) { const renderBundles = text.map((t) => t.getRenderBundle()); diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index ac7cd18..7f7ba41 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import volumeWGSL from "./volume.wgsl"; -import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, Uniforms } from "@feng3d/render-api"; +import { BindingResources, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const gui = new GUI(); @@ -91,7 +91,7 @@ const init = async (canvas: HTMLCanvasElement) => maxAnisotropy: 16, }; - const uniformBindGroup: Uniforms = { + const uniformBindGroup: BindingResources = { uniforms: uniformBuffer, mySampler: sampler, myTexture: { texture: volumeTexture }, diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 78ca8f4..ea44e94 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, RenderPipeline, Submit, Uniforms, PrimitiveState, RenderObject, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, PrimitiveState, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -131,8 +131,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => thickness: number; alphaThreshold: number; }; - litBindGroup: Uniforms; - wireframeBindGroups: Uniforms[]; + litBindGroup: BindingResources; + wireframeBindGroups: BindingResources[]; model: Model; }; @@ -155,7 +155,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const model = randElement(models); // Make a bind group for this uniform - const litBindGroup: Uniforms = { + const litBindGroup: BindingResources = { uni: uniformBuffer, }; @@ -177,14 +177,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // We're creating 2 bindGroups, one for each pipeline. // We could create just one since they are identical. To do // so we'd have to manually create a bindGroupLayout. - const wireframeBindGroup: Uniforms = { + const wireframeBindGroup: BindingResources = { uni: uniformBuffer, positions: { bufferView: model.vertices }, indices: { bufferView: model.indices }, line: lineUniformBuffer, }; - const barycentricCoordinatesBasedWireframeBindGroup: Uniforms = { + const barycentricCoordinatesBasedWireframeBindGroup: BindingResources = { uni: uniformBuffer, positions: { bufferView: model.vertices }, indices: { bufferView: model.indices }, diff --git a/src/WebGPUStep.ts b/src/WebGPUStep.ts index a78a38f..03bea60 100644 --- a/src/WebGPUStep.ts +++ b/src/WebGPUStep.ts @@ -1,4 +1,4 @@ -import { CopyBufferToBuffer, CopyTextureToTexture, IRenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, Submit } from "@feng3d/render-api"; +import { CopyBufferToBuffer, CopyTextureToTexture, RenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, Submit } from "@feng3d/render-api"; import { GPUComputeObject } from "./data/IGPUComputeObject"; import { GPUComputePass } from "./data/IGPUComputePass"; @@ -35,7 +35,7 @@ export class WebGPUStep renderObject(renderObject: RenderObject) { - (this._currentRenderPassEncoder.renderObjects as IRenderPassObject[]).push(renderObject); + (this._currentRenderPassEncoder.renderObjects as RenderPassObject[]).push(renderObject); } computePass() diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 2b5c939..cff91ef 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BufferBinding, BufferBindingInfo, CanvasTexture, Sampler, TextureView, Uniforms, UniformType } from "@feng3d/render-api"; +import { BufferBinding, BufferBindingInfo, CanvasTexture, Sampler, TextureView, BindingResources, BindingResource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; import { VideoTexture } from "../data/VideoTexture"; @@ -12,7 +12,7 @@ import { getGPUSampler } from "./getGPUSampler"; import { getGPUTextureView } from "./getGPUTextureView"; import { getIGPUBuffer } from "./getIGPUBuffer"; -export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: Uniforms) +export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) { const bindGroupDescriptor = getSetBindGroup(bindGroupLayout, bindingResources); @@ -178,13 +178,10 @@ export interface BindGroupEntry * The resource to bind, which may be a {@link GPUSampler}, {@link GPUTextureView}, * {@link GPUExternalTexture}, or {@link GPUBufferBinding}. */ - resource: BindingResource; + resource: Sampler | TextureView | VideoTexture | BindingResource; } -export type BindingResource = Sampler | TextureView | VideoTexture | UniformType; - - -function getSetBindGroup(bindGroupLayout: GPUBindGroupLayout, bindingResources: Uniforms) +function getSetBindGroup(bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) { const map: ChainMap, BindGroupDescriptor> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); const subBindingResources = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map(v => v.variableInfo.name).map((v) => bindingResources[v]); diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index 154befc..bc02deb 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -1,10 +1,10 @@ import { anyEmitter } from "@feng3d/event"; -import { IRenderPassObject, OcclusionQuery, RenderPass } from "@feng3d/render-api"; +import { RenderPassObject, OcclusionQuery, RenderPass } from "@feng3d/render-api"; import { } from "../data/polyfills/OcclusionQuery"; import { GPUQueue_submit } from "../eventnames"; -export function getGPURenderOcclusionQuery(renderObjects?: readonly IRenderPassObject[]): GPURenderOcclusionQuery +export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassObject[]): GPURenderOcclusionQuery { if (!renderObjects) return defautRenderOcclusionQuery; let renderOcclusionQuery: GPURenderOcclusionQuery = renderObjects["_GPURenderOcclusionQuery"]; diff --git a/src/data/ComputeObject.ts b/src/data/ComputeObject.ts index b87dfc8..2056664 100644 --- a/src/data/ComputeObject.ts +++ b/src/data/ComputeObject.ts @@ -1,4 +1,4 @@ -import { Uniforms } from "@feng3d/render-api"; +import { BindingResources } from "@feng3d/render-api"; import { ComputePipeline } from "./ComputePipeline"; import { Workgroups } from "./Workgroups"; @@ -21,7 +21,7 @@ export interface ComputeObject /** * 绑定资源。包含数值、纹理、采样、外部纹理。 */ - readonly uniforms?: Uniforms; + readonly uniforms?: BindingResources; /** * {@link GPUComputePassEncoder.dispatchWorkgroups} diff --git a/src/data/polyfills/Uniforms.ts b/src/data/polyfills/Uniforms.ts index b15c12c..7c02868 100644 --- a/src/data/polyfills/Uniforms.ts +++ b/src/data/polyfills/Uniforms.ts @@ -3,7 +3,7 @@ import { VideoTexture } from "../VideoTexture"; declare module "@feng3d/render-api" { - export interface UniformTypeMap + export interface BindingResourceTypeMap { Sampler: Sampler; TextureView: TextureView; diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 6ddd69a..ec2b5c7 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { Buffer, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, IRenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, Uniforms, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { Buffer, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, RenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, BindingResources, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -106,7 +106,7 @@ export class RunWebGPU timestampQuery.resolve(device, commandEncoder, renderPass); } - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: readonly IRenderPassObject[]) + protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: readonly RenderPassObject[]) { if (!renderObjects) return; // @@ -130,7 +130,7 @@ export class RunWebGPU } else { - throw `未处理 ${(element as IRenderPassObject).__type__} 类型的渲染通道对象!`; + throw `未处理 ${(element as RenderPassObject).__type__} 类型的渲染通道对象!`; } }); } @@ -414,7 +414,7 @@ export class RunWebGPU } } - protected runBindingResources(device: GPUDevice, passEncoder: GPUBindingCommandsMixin, shader: IGPUShader, bindingResources: Uniforms) + protected runBindingResources(device: GPUDevice, passEncoder: GPUBindingCommandsMixin, shader: IGPUShader, bindingResources: BindingResources) { // 计算 bindGroups const layout = getGPUPipelineLayout(device, shader); diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/runs/RunWebGPUCommandCache.ts index 655c866..3afec93 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/runs/RunWebGPUCommandCache.ts @@ -1,4 +1,4 @@ -import { IRenderPassObject, RenderObject } from "@feng3d/render-api"; +import { RenderPassObject, RenderObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { getRealGPUBindGroup } from "../const"; @@ -11,9 +11,9 @@ import { RunWebGPU } from "./RunWebGPU"; */ export class RunWebGPUCommandCache extends RunWebGPU { - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: IRenderPassObject[]) + protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: RenderPassObject[]) { - const map: ChainMap<[string, IRenderPassObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); + const map: ChainMap<[string, RenderPassObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); let caches = map.get([renderPassFormat._key, renderObjects]); if (!caches) { -- Gitee From d4fa1a2fa7b2d945482d86d34d68693fdbbcffc5 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 18:18:53 +0800 Subject: [PATCH 056/214] =?UTF-8?q?refactor(webgpu):=20=E5=B0=86=20Buffer?= =?UTF-8?q?=20=E7=B1=BB=E5=9E=8B=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20GBu?= =?UTF-8?q?ffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重命名了以下内容: - 将 Buffer 类型重命名为 GBuffer - 更新了相关文件中的导入和使用 - 删除了原 Buffer 类型的定义文件 这个改动旨在统一 GPU 相关的缓冲区类型,避免混淆。 --- examples/src/webgpu/bitonicSort/index.ts | 8 ++++---- examples/src/webgpu/skinnedMesh/glbUtils.ts | 6 +++--- package.json | 1 - src/WebGPU.ts | 4 ++-- src/caches/getGPUBuffer.ts | 8 ++++---- src/caches/getIGPUBuffer.ts | 4 ++-- src/data/polyfills/{Buffer.ts => GBuffer.ts} | 2 +- src/index.ts | 2 +- src/runs/RunWebGPU.ts | 4 ++-- 9 files changed, 19 insertions(+), 20 deletions(-) rename src/data/polyfills/{Buffer.ts => GBuffer.ts} (95%) diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index fea455c..36aab99 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,6 +1,6 @@ -import { Buffer, BufferBinding, CommandEncoder, RenderPassDescriptor, Submit, BindingResources } from "@feng3d/render-api"; +import { BindingResources, BufferBinding, CommandEncoder, GBuffer, RenderPassDescriptor, Submit } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { ComputePipeline, getIGPUBuffer, ComputePass, TimestampQuery, WebGPU, reactive } from "@feng3d/webgpu"; +import { ComputePass, ComputePipeline, TimestampQuery, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats.js"; @@ -262,7 +262,7 @@ async function init( const elementsOutputBuffer: BufferBinding = { bufferView: new Uint8Array(elementsBufferSize) }; - const elementsStagingBuffer: Buffer = { + const elementsStagingBuffer: GBuffer = { size: elementsBufferSize, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, }; @@ -272,7 +272,7 @@ async function init( const atomicSwapsOutputBuffer: BufferBinding = { bufferView: new Uint32Array(1) }; - const atomicSwapsStagingBuffer: Buffer = { + const atomicSwapsStagingBuffer: GBuffer = { size: Uint32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, }; diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 5f7a697..094baaf 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { BindingResources, Buffer, FragmentState, IDraw, PrimitiveState, RenderObject, RenderPipeline, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; +import { BindingResources, FragmentState, GBuffer, IDraw, PrimitiveState, RenderObject, RenderPipeline, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { getIGPUBuffer, reactive } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -245,7 +245,7 @@ export class GLTFBufferView byteStride: number; view: Uint8Array; needsUpload: boolean; - gpuBuffer: Buffer; + gpuBuffer: GBuffer; usage: number; constructor(buffer: GLTFBuffer, view: BufferView) { @@ -285,7 +285,7 @@ export class GLTFBufferView upload() { // Note: must align to 4 byte size when mapped at creation is true - const buf: Buffer = { + const buf: GBuffer = { size: alignTo(this.view.byteLength, 4), usage: this.usage, data: this.view, diff --git a/package.json b/package.json index 91efc3e..150099a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "@feng3d/event": "^0.8.4", "@feng3d/render-api": "0.0.2", "@feng3d/watcher": "^0.8.11", - "@vue/reactivity": "^3.5.13", "@webgpu/types": "0.1.49", "wgsl_reflect": "^1.0.16" } diff --git a/src/WebGPU.ts b/src/WebGPU.ts index 9b1634a..5acfc6b 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,4 +1,4 @@ -import { Buffer, ReadPixels, Submit, TextureLike } from "@feng3d/render-api"; +import { GBuffer, ReadPixels, Submit, TextureLike } from "@feng3d/render-api"; import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUTexture } from "./caches/getGPUTexture"; import { getIGPUTextureLikeSize } from "./caches/getIGPUTextureSize"; @@ -149,7 +149,7 @@ export class WebGPU * @param size 读取字节数量。 * @returns CPU数据缓冲区。 */ - async readBuffer(buffer: Buffer, offset?: GPUSize64, size?: GPUSize64) + async readBuffer(buffer: GBuffer, offset?: GPUSize64, size?: GPUSize64) { const gpuBuffer = getGPUBuffer(this.device, buffer); await gpuBuffer.mapAsync(GPUMapMode.READ); diff --git a/src/caches/getGPUBuffer.ts b/src/caches/getGPUBuffer.ts index c7c31f5..a3df932 100644 --- a/src/caches/getGPUBuffer.ts +++ b/src/caches/getGPUBuffer.ts @@ -1,4 +1,4 @@ -import { Buffer, UnReadonly } from "@feng3d/render-api"; +import { GBuffer, UnReadonly } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { computed, ComputedRef, effect, reactive } from "../reactivity"; @@ -25,9 +25,9 @@ const defaultGPUBufferUsage = 0 * @param buffer * @returns */ -export function getGPUBuffer(device: GPUDevice, buffer: Buffer) +export function getGPUBuffer(device: GPUDevice, buffer: GBuffer) { - const gBufferMap: WeakMap> = device["_gBufferMap"] = device["_gBufferMap"] || new WeakMap>(); + const gBufferMap: WeakMap> = device["_gBufferMap"] = device["_gBufferMap"] || new WeakMap>(); let result = gBufferMap.get(buffer); if (result) return result.value; @@ -35,7 +35,7 @@ export function getGPUBuffer(device: GPUDevice, buffer: Buffer) const size = buffer.size; console.assert(size && (size % 4 === 0), `初始化缓冲区时必须设置缓冲区尺寸且必须为4的倍数!`); - (buffer as UnReadonly).usage = buffer.usage ?? defaultGPUBufferUsage; + (buffer as UnReadonly).usage = buffer.usage ?? defaultGPUBufferUsage; const label = buffer.label; const usage = buffer.usage; diff --git a/src/caches/getIGPUBuffer.ts b/src/caches/getIGPUBuffer.ts index d75f71a..5dd022a 100644 --- a/src/caches/getIGPUBuffer.ts +++ b/src/caches/getIGPUBuffer.ts @@ -1,4 +1,4 @@ -import { Buffer, TypedArray } from "@feng3d/render-api"; +import { GBuffer, TypedArray } from "@feng3d/render-api"; export function getIGPUBuffer(bufferSource: TypedArray) { @@ -8,7 +8,7 @@ export function getIGPUBuffer(bufferSource: TypedArray) arrayBuffer = (bufferSource as ArrayBufferView).buffer; } - const gpuBuffer: Buffer = arrayBuffer["_IGPUBuffer"] = arrayBuffer["_IGPUBuffer"] || { + const gpuBuffer: GBuffer = arrayBuffer["_IGPUBuffer"] = arrayBuffer["_IGPUBuffer"] || { size: Math.ceil(arrayBuffer.byteLength / 4) * 4, data: arrayBuffer, }; diff --git a/src/data/polyfills/Buffer.ts b/src/data/polyfills/GBuffer.ts similarity index 95% rename from src/data/polyfills/Buffer.ts rename to src/data/polyfills/GBuffer.ts index 7864d95..71aa2d3 100644 --- a/src/data/polyfills/Buffer.ts +++ b/src/data/polyfills/GBuffer.ts @@ -8,7 +8,7 @@ declare module "@feng3d/render-api" * {@link GPUBufferDescriptor} * {@link GPUBuffer} */ - export interface Buffer + export interface GBuffer { /** * The allowed usages for the buffer. diff --git a/src/index.ts b/src/index.ts index b7752dd..e6f7998 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,7 +8,7 @@ export * from "./data/polyfills/TextureView"; export * from "./data/RenderBundle"; export * from "./data/TimestampQuery"; -export * from "./data/polyfills/Buffer"; +export * from "./data/polyfills/GBuffer"; export * from "./data/polyfills/CanvasContext"; export * from "./data/polyfills/CommandEncoder"; export * from "./data/polyfills/OcclusionQuery"; diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index ec2b5c7..d26bea3 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { Buffer, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, IIndicesDataTypes, RenderPassObject, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPipeline, ScissorRect, Submit, BindingResources, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { BindingResources, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -446,7 +446,7 @@ export class RunWebGPU if (!indices) return; const buffer = getIGPUBuffer(indices); - (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); + (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); const gBuffer = getGPUBuffer(device, buffer); -- Gitee From eb18d7a3a0e09b83e8017220d3eff516b40d1556 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 18:23:40 +0800 Subject: [PATCH 057/214] =?UTF-8?q?refactor(webgpu):=20=E5=B0=86=20RenderO?= =?UTF-8?q?bject=20=E4=B8=AD=E7=9A=84=20uniforms=20=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20bindingResources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改了多个示例文件中的 RenderObject 结构,将 uniforms 属性统一重命名为 bindingResources,以更好地反映其作为绑定资源组的角色。这一变更可以提高代码的可读性和一致性。 --- examples/src/webgpu/RenderObjectChanges/index.ts | 2 +- examples/src/webgpu/a-buffer/index.ts | 6 +++--- examples/src/webgpu/animometer/index.ts | 4 ++-- examples/src/webgpu/bitonicSort/utils.ts | 2 +- examples/src/webgpu/blending/index.ts | 4 ++-- examples/src/webgpu/cameras/index.ts | 2 +- examples/src/webgpu/cornell/rasterizer.ts | 2 +- examples/src/webgpu/cubemap/index.ts | 4 ++-- examples/src/webgpu/deferredRendering/index.ts | 6 +++--- examples/src/webgpu/fractalCube/index.ts | 4 ++-- examples/src/webgpu/gameOfLife/index.ts | 2 +- examples/src/webgpu/helloTriangle/index.ts | 2 +- examples/src/webgpu/imageBlur/index.ts | 2 +- examples/src/webgpu/instancedCube/index.ts | 2 +- examples/src/webgpu/multipleCanvases/index.ts | 2 +- examples/src/webgpu/normalMap/index.ts | 2 +- examples/src/webgpu/occlusionQuery/index.ts | 6 +++--- examples/src/webgpu/particles/index.ts | 2 +- examples/src/webgpu/points/index.ts | 2 +- examples/src/webgpu/renderBundles/index.ts | 2 +- examples/src/webgpu/resizeObserverHDDPI/index.ts | 2 +- examples/src/webgpu/reversedZ/index.ts | 10 +++++----- examples/src/webgpu/rotatingCube/index.ts | 2 +- examples/src/webgpu/samplerParameters/index.ts | 10 +++++----- examples/src/webgpu/shadowMapping/index.ts | 4 ++-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 2 +- examples/src/webgpu/skinnedMesh/index.ts | 2 +- examples/src/webgpu/textRenderingMsdf/index.ts | 2 +- examples/src/webgpu/textRenderingMsdf/msdfText.ts | 2 +- examples/src/webgpu/texturedCube/index.ts | 2 +- examples/src/webgpu/timestampQuery/index.ts | 2 +- examples/src/webgpu/transparentCanvas/index.ts | 2 +- examples/src/webgpu/twoCubes/index.ts | 4 ++-- examples/src/webgpu/videoUploading/index.ts | 2 +- examples/src/webgpu/volumeRenderingTexture3D/index.ts | 2 +- examples/src/webgpu/wireframe/index.ts | 4 ++-- examples/src/webgpu/worker/worker.ts | 2 +- src/runs/RunWebGPU.ts | 2 +- 38 files changed, 59 insertions(+), 59 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index dc95b4d..e45415b 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -36,7 +36,7 @@ const init = async (canvas: HTMLCanvasElement) => indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 }, - uniforms: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 + bindingResources: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 }; const submit: Submit = { // 一次GPU提交 diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 8dae440..865ddfd 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -278,7 +278,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: opaquePassDescriptor, renderObjects: [{ pipeline: opaquePipeline, - uniforms: bindingResources, + bindingResources: bindingResources, geometry: { primitive: { topology: "triangle-list", @@ -316,7 +316,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { scissorRect: { x: scissorX, y: scissorY, width: scissorWidth, height: scissorHeight }, pipeline: translucentPipeline, - uniforms: { + bindingResources: { ...bindingResources, sliceInfo: sliceInfoBuffer[slice], }, @@ -342,7 +342,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { scissorRect: { x: scissorX, y: scissorY, width: scissorWidth, height: scissorHeight }, pipeline: compositePipeline, - uniforms: { + bindingResources: { ...bindingResources, sliceInfo: sliceInfoBuffer[slice] }, diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index 0fa6136..760a2ce 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -55,7 +55,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: RenderObject = { pipeline: pipeline, - uniforms: {}, + bindingResources: {}, geometry: { primitive: { frontFace: "ccw", @@ -95,7 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { renderObjects0[i] = { ...renderObject, - uniforms: { + bindingResources: { time, uniforms: { bufferView: new Float32Array(uniformBuffer.buffer, i * alignedUniformBytes, 5), diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index 48a71b6..51986ae 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -58,7 +58,7 @@ export abstract class Base2DRendererClass descriptor: renderPassDescriptor, renderObjects: [{ pipeline: pipeline, - uniforms: bindingResources, + bindingResources: bindingResources, geometry: { primitive: { topology: "triangle-list", diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 7533225..fa5c74b 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -511,7 +511,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const ro: RenderObject = { pipeline: dstPipeline, - uniforms: dstBindGroup, + bindingResources: dstBindGroup, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6 }, } @@ -519,7 +519,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const ro1: RenderObject = { pipeline: srcPipeline, - uniforms: srcBindGroup, + bindingResources: srcBindGroup, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6 }, } diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index d3fa1a2..7e1b638 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -94,7 +94,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: RenderObject = { pipeline: pipeline, - uniforms: bindingResources, + bindingResources: bindingResources, geometry:{ primitive: { topology: "triangle-list", diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index c6d25eb..d882be6 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -76,7 +76,7 @@ export default class Rasterizer descriptor: this.renderPassDescriptor, renderObjects: [{ pipeline: this.pipeline, - uniforms: { + bindingResources: { ...this.common.uniforms.bindGroup, ...this.bindGroup, }, diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index c59c937..a20a367 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -123,7 +123,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleCubemapWGSL }, }, - uniforms: { + bindingResources: { uniforms: { modelViewProjectionMatrix: new Float32Array(16) }, @@ -146,7 +146,7 @@ const init = async (canvas: HTMLCanvasElement) => { updateTransformationMatrix(); - (renderObject.uniforms.uniforms as BufferBinding).modelViewProjectionMatrix = modelViewProjectionMatrix; + (renderObject.bindingResources.uniforms as BufferBinding).modelViewProjectionMatrix = modelViewProjectionMatrix; const data: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index b1adf54..f2292cc 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -328,7 +328,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { pipeline: writeGBuffersPipeline, - uniforms: { + bindingResources: { ...sceneUniformBindGroup, }, geometry: { @@ -360,7 +360,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { pipeline: gBuffersDebugViewPipeline, - uniforms: { + bindingResources: { ...gBufferTexturesBindGroup, }, geometry: { @@ -376,7 +376,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { pipeline: deferredRenderPipeline, - uniforms: { + bindingResources: { ...gBufferTexturesBindGroup, ...lightsBufferBindGroup, }, diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 35b72d9..03e97b7 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -90,7 +90,7 @@ const init = async (canvas: HTMLCanvasElement) => }, draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }, - uniforms: { + bindingResources: { uniforms: { modelViewProjectionMatrix: new Float32Array(16) }, @@ -110,7 +110,7 @@ const init = async (canvas: HTMLCanvasElement) => { const transformationMatrix = getTransformationMatrix(); - (renderObject.uniforms.uniforms as BufferBinding).modelViewProjectionMatrix = transformationMatrix; + (renderObject.bindingResources.uniforms as BufferBinding).modelViewProjectionMatrix = transformationMatrix; const data: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 089c2cf..9e09a54 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -134,7 +134,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [ { pipeline: renderPipeline, - uniforms: uniformBindGroup, + bindingResources: uniformBindGroup, geometry: { primitive: { topology: "triangle-strip", diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 2c94fab..d9037e7 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement) => indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 }, - uniforms: { color: [1, 0, 0, 0] }, // Uniform 颜色值。 + bindingResources: { color: [1, 0, 0, 0] }, // Uniform 颜色值。 }] }, ] diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 43d783a..49e93c2 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -144,7 +144,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: renderPassDescriptor, renderObjects: [{ pipeline: fullscreenQuadPipeline1, - uniforms: showResultBindGroup1, + bindingResources: showResultBindGroup1, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, }, diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 5df30fb..318275d 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -115,7 +115,7 @@ const init = async (canvas: HTMLCanvasElement) => }, draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: numInstances } }, - uniforms: { + bindingResources: { uniforms: { modelViewProjectionMatrix: mvpMatricesData }, diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index 1de4b9f..252e1fb 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -316,7 +316,7 @@ const init = async () => descriptor: renderPassDescriptor, renderObjects: [{ pipeline: pipeline, - uniforms: bindGroup, + bindingResources: bindGroup, geometry: { primitive: { cullFace: "back", diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index 9898289..cddef77 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -318,7 +318,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: renderPassDescriptor, renderObjects: [{ pipeline: texturedCubePipeline, - uniforms: bindingResourcesList[currentSurfaceBindGroup], + bindingResources: bindingResourcesList[currentSurfaceBindGroup], // * position : float32x3 // * normal : float32x3 // * uv : float32x2 diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 049a4f8..27c10ef 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -136,7 +136,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => indices, draw: { __type__: "DrawIndexed", indexCount: indices.length }, }, - uniforms: { + bindingResources: { uni: { bufferView: undefined, }, @@ -147,7 +147,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { const ro: RenderObject = { ...renderObject, - uniforms: { + bindingResources: { uni: { bufferView: v.uniformBuffer, }, @@ -224,7 +224,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => mat4.transpose(mat4.inverse(world), worldInverseTranspose); mat4.multiply(viewProjection, world, worldViewProjection); - const buffer = (renderObjects[i].uniforms.uni as BufferBinding).bufferView; + const buffer = (renderObjects[i].bindingResources.uni as BufferBinding).bufferView; getIGPUBuffer(buffer).data = uniformValues.slice(); } ); diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index f031e35..e88ae9e 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -290,7 +290,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: renderPassDescriptor, renderObjects: [{ pipeline: renderPipeline, - uniforms: { ...uniformBindGroup }, + bindingResources: { ...uniformBindGroup }, geometry: { vertices: { ...particlesVertices, ...quadVertices }, draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: numParticles, firstVertex: 0, firstInstance: 0 }, diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 507dc5b..cd80ed0 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -199,7 +199,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => descriptor: renderPassDescriptor, renderObjects: [{ pipeline: pipeline, - uniforms: bindingResources, + bindingResources: bindingResources, geometry: { vertices, draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 523a64c..f24a8b9 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -251,7 +251,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => { renderable.renderObject = { pipeline: pipeline, - uniforms: { ...frameBindGroup, ...renderable.bindGroup }, + bindingResources: { ...frameBindGroup, ...renderable.bindGroup }, geometry: { primitive: { // Backface culling since the sphere is solid piece of geometry. diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index ccf3c67..56a583a 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -105,7 +105,7 @@ return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); descriptor: renderPassDescriptor, renderObjects: [{ pipeline: pipeline, - uniforms: bindGroup, + bindingResources: bindGroup, geometry:{ draw: { __type__: "DrawVertex", vertexCount: 3 }, } diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 40caf8c..30b38ba 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -367,7 +367,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: colorPassPipelines[m], - uniforms: { ...uniformBindGroups[m] }, + bindingResources: { ...uniformBindGroups[m] }, geometry: { primitive: { cullFace: "back", @@ -394,7 +394,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], - uniforms: { ...uniformBindGroups[m] }, + bindingResources: { ...uniformBindGroups[m] }, geometry: { primitive: { cullFace: "back", @@ -416,7 +416,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: precisionPassPipelines[m], - uniforms: { ...uniformBindGroups[m], ...depthTextureBindGroup }, + bindingResources: { ...uniformBindGroups[m], ...depthTextureBindGroup }, geometry: { primitive: { cullFace: "back", @@ -443,7 +443,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], - uniforms: { ...uniformBindGroups[m] }, + bindingResources: { ...uniformBindGroups[m] }, geometry: { primitive: { cullFace: "back", @@ -459,7 +459,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: textureQuadPassPipline, - uniforms: { ...depthTextureBindGroup }, + bindingResources: { ...depthTextureBindGroup }, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, } diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index 9e2960b..dfa1356 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -47,7 +47,7 @@ const init = async (canvas: HTMLCanvasElement) => }, draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }, - uniforms: { + bindingResources: { uniforms, }, }; diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index a54829f..c9cd2ff 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -322,7 +322,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: vpX, y: vpY, width: kViewportSize, height: kViewportSize, minDepth: 0, maxDepth: 1 }, pipeline: texturedSquarePipeline, - uniforms: bindingResources0, + bindingResources: bindingResources0, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } } @@ -338,7 +338,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: kLastViewport, y: kLastViewport, width: 32, height: 32, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, - uniforms: bindingResources1, + bindingResources: bindingResources1, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } } @@ -348,7 +348,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: kLastViewport + 32, y: kLastViewport, width: 16, height: 16, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, - uniforms: bindingResources1, + bindingResources: bindingResources1, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } } @@ -358,7 +358,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: kLastViewport + 32, y: kLastViewport + 16, width: 8, height: 8, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, - uniforms: bindingResources1, + bindingResources: bindingResources1, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } } @@ -368,7 +368,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { viewport: { isYup: false, x: kLastViewport + 32, y: kLastViewport + 24, width: 4, height: 4, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, - uniforms: bindingResources1, + bindingResources: bindingResources1, geometry: { draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } } diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 49a3bf1..2cefada 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -219,7 +219,7 @@ const init = async (canvas: HTMLCanvasElement) => renderObjects: [ { pipeline: shadowPipeline, - uniforms: { + bindingResources: { ...sceneBindGroupForShadow, ...modelBindGroup, }, @@ -237,7 +237,7 @@ const init = async (canvas: HTMLCanvasElement) => renderObjects: [ { pipeline: pipeline, - uniforms: { + bindingResources: { ...sceneBindGroupForRender, ...modelBindGroup, }, diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 094baaf..051fe9a 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -469,7 +469,7 @@ export class GLTFPrimitive const renderObject: RenderObject = { pipeline: this.renderPipeline, - uniforms: bindingResources, + bindingResources: bindingResources, //if skin do something with bone bind group geometry: { primitive, diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index b2dc4fd..90918d1 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -510,7 +510,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // data at ./gridData.ts const renderObject: RenderObject = { pipeline: skinnedGridPipeline, - uniforms: { + bindingResources: { ...cameraBGCluster, ...generalUniformsBGCLuster, ...skinnedGridBoneBGCluster, diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index dc1e6db..784e87b 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -253,7 +253,7 @@ setBlendConstant().`, renderObjects.push({ pipeline: pipeline, - uniforms: uniformBindGroup, + bindingResources: uniformBindGroup, geometry: { primitive: { // Backface culling since the cube is solid piece of geometry. diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index 303bbea..f2e1358 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -340,7 +340,7 @@ export class MsdfTextRenderer renderObjects: [ { pipeline: font.material, - uniforms: { + bindingResources: { ...font.bindGroup, ...bindGroup, }, diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index 4814798..23b40d1 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -56,7 +56,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleTextureMixColorWGSL }, }, - uniforms: { + bindingResources: { uniforms, mySampler: sampler, myTexture: { texture: cubeTexture }, diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 9b70a63..355f6ac 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -103,7 +103,7 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: RenderObject = { pipeline: pipeline, - uniforms: { + bindingResources: { uniforms, }, geometry: { diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index bb82e63..5b25b29 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -102,7 +102,7 @@ const init = async (canvas: HTMLCanvasElement) => descriptor: renderPassDescriptor, renderObjects: [{ pipeline: pipeline, - uniforms: uniformBindGroup, + bindingResources: uniformBindGroup, geometry: { primitive: { topology: "triangle-list", diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index 46a5e94..a755785 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -46,7 +46,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, }, - uniforms: { + bindingResources: { uniforms, }, geometry: { @@ -68,7 +68,7 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject1: RenderObject = { ...renderObject, - uniforms: { + bindingResources: { uniforms: uniforms1, }, }; diff --git a/examples/src/webgpu/videoUploading/index.ts b/examples/src/webgpu/videoUploading/index.ts index 24fbd17..7464efe 100644 --- a/examples/src/webgpu/videoUploading/index.ts +++ b/examples/src/webgpu/videoUploading/index.ts @@ -41,7 +41,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: fullscreenTexturedQuadWGSL }, fragment: { code: sampleExternalTextureWGSL }, }, - uniforms: { + bindingResources: { mySampler: sampler, myTexture: { source: video, diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index 7f7ba41..a72bd21 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -158,7 +158,7 @@ const init = async (canvas: HTMLCanvasElement) => descriptor: renderPassDescriptor, renderObjects: [{ pipeline, - uniforms: uniformBindGroup, + bindingResources: uniformBindGroup, geometry: { primitive: { topology: "triangle-list", diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index ea44e94..b70e46f 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -319,7 +319,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { renderObjects.push({ pipeline: litPipeline, - uniforms: litBindGroup, + bindingResources: litBindGroup, geometry: { primitive: { cullFace: "back", @@ -350,7 +350,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { renderObjects.push({ pipeline, - uniforms: wireframeBindGroups[bindGroupNdx], + bindingResources: wireframeBindGroups[bindGroupNdx], geometry: { primitive, draw: { __type__: "DrawVertex", vertexCount: indices.length * countMult }, diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index f90e5d3..2d19f2d 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -147,7 +147,7 @@ async function init(canvas: OffscreenCanvas) descriptor: renderPassDescriptor, renderObjects: [{ pipeline, - uniforms: uniformBindGroup, + bindingResources: uniformBindGroup, geometry: { primitive: { topology: "triangle-list", diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index d26bea3..4abeef6 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -296,7 +296,7 @@ export class RunWebGPU */ protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, renderObject: RenderObject) { - const { viewport, scissorRect, pipeline, uniforms: bindingResources, geometry } = renderObject; + const { viewport, scissorRect, pipeline, bindingResources: bindingResources, geometry } = renderObject; const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; -- Gitee From dc93e038eb149546383b145324b493ea875b2925 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 18:49:12 +0800 Subject: [PATCH 058/214] =?UTF-8?q?refactor(caches):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=9C=AA=E4=BD=BF=E7=94=A8=E7=9A=84=E7=BA=B9=E7=90=86=E5=B0=BA?= =?UTF-8?q?=E5=AF=B8=E8=AE=A1=E7=AE=97=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 getIGPUTextureSourceSize 函数 - 保留了 getIGPUTextureLikeSize 函数 --- src/caches/getIGPUTextureSize.ts | 34 -------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/caches/getIGPUTextureSize.ts b/src/caches/getIGPUTextureSize.ts index 2d3b27e..f611282 100644 --- a/src/caches/getIGPUTextureSize.ts +++ b/src/caches/getIGPUTextureSize.ts @@ -17,38 +17,4 @@ export function getIGPUTextureLikeSize(texture: TextureLike) } return texture.size; -} - -export function getIGPUTextureSourceSize(source?: TextureImageSource[]): TextureSize -{ - if (!source) return undefined; - - let width: number; - let height: number; - let maxDepthOrArrayLayers = 0; - - for (let i = 0; i < source.length; i++) - { - const element = source[i]; - // 获取mipLevel为0的资源尺寸。 - if (!element.mipLevel) - { - const copySize = element.size || TextureImageSource.getTexImageSourceSize(element.image); - if (width || height) - { - console.assert(width === copySize[0] && height === copySize[1], `纹理资源中提供的尺寸不正确!`); - } - else - { - width = copySize[0]; - height = copySize[1]; - } - - maxDepthOrArrayLayers = Math.max(maxDepthOrArrayLayers, element.textureOrigin?.[2] || 0); - } - } - - console.assert(width > 0 && height > 0, `没有从纹理资源中找到合适的尺寸!`); - - return [width, height, maxDepthOrArrayLayers + 1]; // 总深度比最大深度大1 } \ No newline at end of file -- Gitee From 36a05e32b45772f4e1cd65443173920f1a70b25c Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 22:48:53 +0800 Subject: [PATCH 059/214] =?UTF-8?q?refactor(types):=20=E5=B0=86=20TextureT?= =?UTF-8?q?ype.ts=20=E4=B8=AD=E7=9A=84=E5=AF=BC=E5=87=BA=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E5=B1=80=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 TextureDimensionality 和 TextureArrayed 的导出改为局部导出 - 优化了类型定义,使代码更加简洁 --- src/types/TextureType.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/types/TextureType.ts b/src/types/TextureType.ts index 62b2a03..f3d26cf 100644 --- a/src/types/TextureType.ts +++ b/src/types/TextureType.ts @@ -1,27 +1,27 @@ /** * 纹理维度。 */ -export const TextureDimensionality = { +const TextureDimensionality = { "1D": "1D", "2D": "2D", "3D": "3D", Cube: "Cube", }; -export type TextureDimensionality = keyof typeof TextureDimensionality; +type TextureDimensionality = keyof typeof TextureDimensionality; /** * 纹理为是否数组。 */ -export const TextureArrayed = { +const TextureArrayed = { No: false, Yes: true, }; -export type TextureArrayed = keyof typeof TextureArrayed; +type TextureArrayed = keyof typeof TextureArrayed; /** * 纹理第二类型,描述纹理维度以及是否为数组。 */ -export type TextureSecondType = [TextureDimensionality, TextureArrayed, GPUTextureViewDimension]; +type TextureSecondType = [TextureDimensionality, TextureArrayed, GPUTextureViewDimension]; /** * 采样纹理类型。 -- Gitee From f23fe16f6dc8357e8357b925dae139fb6d208b26 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 23:03:21 +0800 Subject: [PATCH 060/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E5=91=BD?= =?UTF-8?q?=E5=90=8D=20getIGPUBuffer=20=E4=B8=BA=20getGBuffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在多个示例文件中将 getIGPUBuffer 函数重命名为 getGBuffer - 更新了相关的导入语句和函数调用 - 此修改统一了缓冲区获取函数的命名,提高了代码的一致性和可读性 --- examples/src/webgpu/a-buffer/index.ts | 6 ++-- examples/src/webgpu/bitonicSort/index.ts | 10 +++--- examples/src/webgpu/cornell/common.ts | 4 +-- examples/src/webgpu/cornell/radiosity.ts | 4 +-- .../src/webgpu/deferredRendering/index.ts | 36 +++++++++---------- examples/src/webgpu/imageBlur/index.ts | 8 ++--- examples/src/webgpu/multipleCanvases/index.ts | 4 +-- examples/src/webgpu/occlusionQuery/index.ts | 4 +-- examples/src/webgpu/particles/index.ts | 8 ++--- examples/src/webgpu/renderBundles/index.ts | 4 +-- .../src/webgpu/samplerParameters/index.ts | 10 +++--- examples/src/webgpu/shadowMapping/index.ts | 10 +++--- examples/src/webgpu/skinnedMesh/glbUtils.ts | 4 +-- examples/src/webgpu/skinnedMesh/index.ts | 12 +++---- .../src/webgpu/textRenderingMsdf/index.ts | 4 +-- .../src/webgpu/textRenderingMsdf/msdfText.ts | 6 ++-- src/caches/getGPUBindGroup.ts | 6 ++-- src/caches/getIGPUBuffer.ts | 2 +- src/runs/RunWebGPU.ts | 6 ++-- src/utils/updateBufferBinding.ts | 4 +-- 20 files changed, 76 insertions(+), 76 deletions(-) diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 865ddfd..525023c 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -1,5 +1,5 @@ import { BufferBinding, CanvasContext, IPassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; +import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -296,8 +296,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // initialize the heads buffer passEncoders.push({ __type__: "CopyBufferToBuffer", - source: getIGPUBuffer(headsInitBuffer), - destination: getIGPUBuffer(headsBuffer.bufferView), + source: getGBuffer(headsInitBuffer), + destination: getGBuffer(headsBuffer.bufferView), }); const scissorX = 0; diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 36aab99..ae9ef6c 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,6 +1,6 @@ import { BindingResources, BufferBinding, CommandEncoder, GBuffer, RenderPassDescriptor, Submit } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { ComputePass, ComputePipeline, TimestampQuery, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; +import { ComputePass, ComputePipeline, TimestampQuery, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats.js"; @@ -704,7 +704,7 @@ async function init( { // Write elements buffer - let iGPUBuffer = getIGPUBuffer(elementsInputBuffer.bufferView); + let iGPUBuffer = getGBuffer(elementsInputBuffer.bufferView); let writeBuffers = iGPUBuffer.writeBuffers || []; writeBuffers.push({ data: elements }); reactive(iGPUBuffer).writeBuffers = writeBuffers; @@ -718,7 +718,7 @@ async function init( settings["Next Swap Span"], ]); - iGPUBuffer = getIGPUBuffer(computeUniformsBuffer.bufferView); + iGPUBuffer = getGBuffer(computeUniformsBuffer.bufferView); writeBuffers = iGPUBuffer.writeBuffers || []; writeBuffers.push({ data: dims }); writeBuffers.push({ bufferOffset: 8, data: stepDetails }); @@ -796,7 +796,7 @@ async function init( commandEncoder.passEncoders.push( { __type__: "CopyBufferToBuffer", - source: getIGPUBuffer(elementsOutputBuffer.bufferView), + source: getGBuffer(elementsOutputBuffer.bufferView), sourceOffset: 0, destination: elementsStagingBuffer, destinationOffset: 0, @@ -804,7 +804,7 @@ async function init( }, { __type__: "CopyBufferToBuffer", - source: getIGPUBuffer(atomicSwapsOutputBuffer.bufferView), + source: getGBuffer(atomicSwapsOutputBuffer.bufferView), sourceOffset: 0, destination: atomicSwapsStagingBuffer, destinationOffset: 0, diff --git a/examples/src/webgpu/cornell/common.ts b/examples/src/webgpu/cornell/common.ts index bb07684..d1e845b 100644 --- a/examples/src/webgpu/cornell/common.ts +++ b/examples/src/webgpu/cornell/common.ts @@ -1,5 +1,5 @@ import { BindingResources } from "@feng3d/render-api"; -import { getIGPUBuffer, reactive } from "@feng3d/webgpu"; +import { getGBuffer, reactive } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; import commonWGSL from "./common.wgsl"; @@ -77,7 +77,7 @@ export default class Common uniformDataU32[33] = 0xffffffff * Math.random(); uniformDataU32[34] = 0xffffffff * Math.random(); - reactive(getIGPUBuffer(this.uniformBuffer)).writeBuffers = [{ data: uniformDataF32 }]; + reactive(getGBuffer(this.uniformBuffer)).writeBuffers = [{ data: uniformDataF32 }]; this.frame++; } diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index 6027579..fbaadc1 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -1,5 +1,5 @@ import { BindingResources, CommandEncoder, IPassEncoder, Texture } from "@feng3d/render-api"; -import { ComputePipeline, getIGPUBuffer, reactive } from "@feng3d/webgpu"; +import { ComputePipeline, getGBuffer, reactive } from "@feng3d/webgpu"; import Common from "./common"; import radiosityWGSL from "./radiosity.wgsl"; @@ -169,6 +169,6 @@ export default class Radiosity uniformDataF32[4] = this.scene.lightCenter[0]; uniformDataF32[5] = this.scene.lightCenter[1]; uniformDataF32[6] = this.scene.lightCenter[2]; - reactive(getIGPUBuffer(this.uniformBuffer)).writeBuffers = [{ data: uniformDataF32 }]; + reactive(getGBuffer(this.uniformBuffer)).writeBuffers = [{ data: uniformDataF32 }]; } } diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index f2292cc..9439598 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -11,7 +11,7 @@ import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; -import { ComputePass, ComputePipeline, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; +import { ComputePass, ComputePipeline, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; const kMaxNumLights = 1024; const lightExtentMin = vec3.fromValues(-50, -30, -50); @@ -163,13 +163,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => .step(1) .onChange(() => { - if (getIGPUBuffer(configUniformBuffer).writeBuffers) + if (getGBuffer(configUniformBuffer).writeBuffers) { - getIGPUBuffer(configUniformBuffer).writeBuffers.push({ data: new Uint32Array([settings.numLights]) }); + getGBuffer(configUniformBuffer).writeBuffers.push({ data: new Uint32Array([settings.numLights]) }); } else { - reactive(getIGPUBuffer(configUniformBuffer)).writeBuffers = [{ data: new Uint32Array([settings.numLights]) }]; + reactive(getGBuffer(configUniformBuffer)).writeBuffers = [{ data: new Uint32Array([settings.numLights]) }]; } }); @@ -223,13 +223,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => tmpVec4[3] = 20.0; lightData.set(tmpVec4, offset + 4); } - getIGPUBuffer(lightsBuffer).data = lightData; + getGBuffer(lightsBuffer).data = lightData; const lightExtentBuffer = new Uint8Array(4 * 8); const lightExtentData = new Float32Array(8); lightExtentData.set(lightExtentMin, 0); lightExtentData.set(lightExtentMax, 4); - reactive(getIGPUBuffer(lightExtentBuffer)).writeBuffers = [{ data: lightExtentData }]; + reactive(getGBuffer(lightExtentBuffer)).writeBuffers = [{ data: lightExtentData }]; const lightUpdateComputePipeline: ComputePipeline = { compute: { @@ -277,33 +277,33 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const modelMatrix = mat4.translation([0, -45, 0]); const cameraMatrixData = viewProjMatrix as Float32Array; - if (getIGPUBuffer(cameraUniformBuffer).writeBuffers) + if (getGBuffer(cameraUniformBuffer).writeBuffers) { - getIGPUBuffer(cameraUniformBuffer).writeBuffers.push({ data: cameraMatrixData }); + getGBuffer(cameraUniformBuffer).writeBuffers.push({ data: cameraMatrixData }); } else { - reactive(getIGPUBuffer(cameraUniformBuffer)).writeBuffers = [{ data: cameraMatrixData }]; + reactive(getGBuffer(cameraUniformBuffer)).writeBuffers = [{ data: cameraMatrixData }]; } const modelData = modelMatrix as Float32Array; - if (getIGPUBuffer(modelUniformBuffer).writeBuffers) + if (getGBuffer(modelUniformBuffer).writeBuffers) { - getIGPUBuffer(modelUniformBuffer).writeBuffers.push({ data: modelData }); + getGBuffer(modelUniformBuffer).writeBuffers.push({ data: modelData }); } else { - reactive(getIGPUBuffer(modelUniformBuffer)).writeBuffers = [{ data: modelData }]; + reactive(getGBuffer(modelUniformBuffer)).writeBuffers = [{ data: modelData }]; } const invertTransposeModelMatrix = mat4.invert(modelMatrix); mat4.transpose(invertTransposeModelMatrix, invertTransposeModelMatrix); const normalModelData = invertTransposeModelMatrix as Float32Array; - if (getIGPUBuffer(modelUniformBuffer).writeBuffers) + if (getGBuffer(modelUniformBuffer).writeBuffers) { - getIGPUBuffer(modelUniformBuffer).writeBuffers.push({ bufferOffset: 64, data: normalModelData }); + getGBuffer(modelUniformBuffer).writeBuffers.push({ bufferOffset: 64, data: normalModelData }); } else { - reactive(getIGPUBuffer(modelUniformBuffer)).writeBuffers = [{ bufferOffset: 64, data: normalModelData }]; + reactive(getGBuffer(modelUniformBuffer)).writeBuffers = [{ bufferOffset: 64, data: normalModelData }]; } // Rotates the camera around the origin based on time. @@ -391,13 +391,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => function frame() { const cameraViewProj = getCameraViewProjMatrix(); - if (getIGPUBuffer(cameraUniformBuffer).writeBuffers) + if (getGBuffer(cameraUniformBuffer).writeBuffers) { - getIGPUBuffer(cameraUniformBuffer).writeBuffers.push({ data: cameraViewProj }); + getGBuffer(cameraUniformBuffer).writeBuffers.push({ data: cameraViewProj }); } else { - reactive(getIGPUBuffer(cameraUniformBuffer)).writeBuffers = [{ data: cameraViewProj }]; + reactive(getGBuffer(cameraUniformBuffer)).writeBuffers = [{ data: cameraViewProj }]; } const submit: Submit = { diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 49e93c2..1af547f 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -4,7 +4,7 @@ import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgs import blurWGSL from "./blur.wgsl"; import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture } from "@feng3d/render-api"; -import { ComputePass, ComputePipeline, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; +import { ComputePass, ComputePipeline, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; // Contants from the blur.wgsl shader. const tileDim = 128; @@ -113,13 +113,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const updateSettings = () => { blockDim = tileDim - (settings.filterSize - 1); - if (getIGPUBuffer(blurParamsBuffer).writeBuffers) + if (getGBuffer(blurParamsBuffer).writeBuffers) { - getIGPUBuffer(blurParamsBuffer).writeBuffers.push({ data: new Uint32Array([settings.filterSize, blockDim]) }); + getGBuffer(blurParamsBuffer).writeBuffers.push({ data: new Uint32Array([settings.filterSize, blockDim]) }); } else { - reactive(getIGPUBuffer(blurParamsBuffer)).writeBuffers = [{ data: new Uint32Array([settings.filterSize, blockDim]) }]; + reactive(getGBuffer(blurParamsBuffer)).writeBuffers = [{ data: new Uint32Array([settings.filterSize, blockDim]) }]; } needUpdateEncoder = true; }; diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index 252e1fb..1c1f192 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,5 +1,5 @@ import { BindingResources, CanvasContext, IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; +import { getGBuffer, reactive, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; @@ -304,7 +304,7 @@ const init = async () => mat3.fromMat4(world, worldMatrixValue); // Upload our uniform values. - const buffer = getIGPUBuffer(uniformValues); + const buffer = getGBuffer(uniformValues); const writeBuffers = buffer.writeBuffers || []; writeBuffers.push({ data: uniformValues, diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 27c10ef..7a57132 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -1,6 +1,6 @@ import { BufferBinding, OcclusionQuery, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { getIGPUBuffer, WebGPU } from "@feng3d/webgpu"; +import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; @@ -225,7 +225,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => mat4.multiply(viewProjection, world, worldViewProjection); const buffer = (renderObjects[i].bindingResources.uni as BufferBinding).bufferView; - getIGPUBuffer(buffer).data = uniformValues.slice(); + getGBuffer(buffer).data = uniformValues.slice(); } ); diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index e88ae9e..19d90cd 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -8,7 +8,7 @@ import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { ComputePass, ComputePipeline, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; +import { ComputePass, ComputePipeline, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; const numParticles = 50000; const particlePositionOffset = 0; @@ -163,7 +163,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const probabilityMapUBOBuffer = new Uint8Array(probabilityMapUBOBufferSize); const bufferA = new Uint8Array(textureWidth * textureHeight * 4); const bufferB = new Uint8Array(textureWidth * textureHeight * 4); - reactive(getIGPUBuffer(probabilityMapUBOBuffer)).writeBuffers = [{ data: new Int32Array([textureWidth]) }]; + reactive(getGBuffer(probabilityMapUBOBuffer)).writeBuffers = [{ data: new Int32Array([textureWidth]) }]; const passEncoders: ComputePass[] = []; @@ -301,7 +301,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => function frame() { - reactive(getIGPUBuffer(simulationUBOBuffer)).writeBuffers = [{ + reactive(getGBuffer(simulationUBOBuffer)).writeBuffers = [{ data: new Float32Array([ simulationParams.simulate ? simulationParams.deltaTime : 0.0, 0.0, @@ -320,7 +320,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => mat4.multiply(projection, view, mvp); // prettier-ignore - reactive(getIGPUBuffer(uniformBuffer)).writeBuffers = [{ + reactive(getGBuffer(uniformBuffer)).writeBuffers = [{ data: new Float32Array([ // modelViewProjectionMatrix mvp[0], mvp[1], mvp[2], mvp[3], diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index f24a8b9..e35b824 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,5 +1,5 @@ import { BindingResources, CanvasContext, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { RenderBundle, WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; +import { RenderBundle, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats-js"; @@ -310,7 +310,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => const transformationMatrix = getTransformationMatrix(); - reactive(getIGPUBuffer(uniformBuffer)).writeBuffers = [{ data: transformationMatrix }]; + reactive(getGBuffer(uniformBuffer)).writeBuffers = [{ data: transformationMatrix }]; let renderObjects: RenderPassObject[] = []; if (settings.useRenderBundles) diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index c9cd2ff..fcbc25f 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import { BindingResources, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureSource } from "@feng3d/render-api"; -import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; +import { getGBuffer, reactive, WebGPU } from "@feng3d/webgpu"; import showTextureWGSL from "./showTexture.wgsl"; import texturedSquareWGSL from "./texturedSquare.wgsl"; @@ -51,13 +51,13 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => Number(config.highlightFlange), ]); - if (getIGPUBuffer(bufConfig).writeBuffers) + if (getGBuffer(bufConfig).writeBuffers) { - getIGPUBuffer(bufConfig).writeBuffers.push({ bufferOffset: 64, data }); + getGBuffer(bufConfig).writeBuffers.push({ bufferOffset: 64, data }); } else { - reactive(getIGPUBuffer(bufConfig)).writeBuffers = [{ bufferOffset: 64, data }]; + reactive(getGBuffer(bufConfig)).writeBuffers = [{ bufferOffset: 64, data }]; } }; @@ -289,7 +289,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => [0, 0, -kCameraDist] ); const bufConfig = new Uint8Array(128); - reactive(getIGPUBuffer(bufConfig)).writeBuffers = [{ data: viewProj }]; + reactive(getGBuffer(bufConfig)).writeBuffers = [{ data: viewProj }]; const bufMatrices = kMatrices; diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 2cefada..537fbbb 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -1,5 +1,5 @@ import { BindingResources, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { WebGPU, getIGPUBuffer, reactive } from "@feng3d/webgpu"; +import { WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; import { mesh } from "../../meshes/stanfordDragon"; @@ -173,14 +173,14 @@ const init = async (canvas: HTMLCanvasElement) => const lightMatrixData = lightViewProjMatrix as Float32Array; const cameraMatrixData = viewProjMatrix as Float32Array; const lightData = lightPosition as Float32Array; - reactive(getIGPUBuffer(sceneUniformBuffer)).writeBuffers = [ + reactive(getGBuffer(sceneUniformBuffer)).writeBuffers = [ { bufferOffset: 0, data: lightMatrixData }, { bufferOffset: 64, data: cameraMatrixData }, { bufferOffset: 128, data: lightData }, ]; const modelData = modelMatrix as Float32Array; - reactive(getIGPUBuffer(modelUniformBuffer)).writeBuffers = [{ data: modelData }]; + reactive(getGBuffer(modelUniformBuffer)).writeBuffers = [{ data: modelData }]; } // Rotates the camera around the origin based on time. @@ -258,9 +258,9 @@ const init = async (canvas: HTMLCanvasElement) => function frame() { const cameraViewProj = getCameraViewProjMatrix(); - const writeBuffers = getIGPUBuffer(sceneUniformBuffer).writeBuffers || []; + const writeBuffers = getGBuffer(sceneUniformBuffer).writeBuffers || []; writeBuffers.push({ bufferOffset: 64, data: cameraViewProj }); - reactive(getIGPUBuffer(sceneUniformBuffer)).writeBuffers = writeBuffers; + reactive(getGBuffer(sceneUniformBuffer)).writeBuffers = writeBuffers; webgpu.submit(submit); diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 051fe9a..501c194 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -2,7 +2,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; import { BindingResources, FragmentState, GBuffer, IDraw, PrimitiveState, RenderObject, RenderPipeline, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; -import { getIGPUBuffer, reactive } from "@feng3d/webgpu"; +import { getGBuffer, reactive } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models // Modified from Will Usher code found at this link https://www.willusher.io/graphics/2023/05/16/0-to-gltf-first-mesh @@ -782,7 +782,7 @@ export class GLTFSkin const globalWorldInverse = mat4.inverse( nodes[currentNodeIndex].worldMatrix ); - const gpuBuffer = getIGPUBuffer(this.jointMatricesUniformBuffer); + const gpuBuffer = getGBuffer(this.jointMatricesUniformBuffer); const writeBuffers = gpuBuffer.writeBuffers || []; for (let j = 0; j < this.joints.length; j++) diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 90918d1..513a44c 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -8,7 +8,7 @@ import { gridIndices } from "./gridData"; import { createSkinnedGridBuffers, createSkinnedGridRenderPipeline } from "./gridUtils"; import { BindingResources, IPassEncoder, RenderObject, RenderPass, RenderPassDescriptor, Texture } from "@feng3d/render-api"; -import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; +import { getGBuffer, reactive, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { @@ -147,7 +147,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => .add(settings, "renderMode", ["NORMAL", "JOINTS", "WEIGHTS"]) .onChange(() => { - const buffer = getIGPUBuffer(generalUniformsBuffer); + const buffer = getGBuffer(generalUniformsBuffer); const writeBuffers = buffer.writeBuffers || []; writeBuffers.push({ @@ -174,7 +174,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => settings.cameraZ = -14.6; } } - const buffer = getIGPUBuffer(generalUniformsBuffer); + const buffer = getGBuffer(generalUniformsBuffer); const writeBuffers = buffer.writeBuffers || []; writeBuffers.push({ bufferOffset: 4, @@ -374,7 +374,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Create bones of the skinned grid and write the inverse bind positions to // the skinned grid's inverse bind matrix array - const buffer = getIGPUBuffer(skinnedGridInverseBindUniformBuffer); + const buffer = getGBuffer(skinnedGridInverseBindUniformBuffer); const writeBuffers = buffer.writeBuffers || []; const gridBoneCollection = createBoneCollection(5); for (let i = 0; i < gridBoneCollection.bindPosesInv.length; i++) @@ -438,7 +438,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => animSkinnedGrid(gridBoneCollection.transforms, angle); // Write to mvp to camera buffer - const buffer = getIGPUBuffer(cameraBuffer); + const buffer = getGBuffer(cameraBuffer); const writeBuffers = buffer.writeBuffers || []; writeBuffers.push({ bufferOffset: 0, @@ -461,7 +461,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => reactive(buffer).writeBuffers = writeBuffers; // Write to skinned grid bone uniform buffer - const buffer0 = getIGPUBuffer(skinnedGridJointUniformBuffer); + const buffer0 = getGBuffer(skinnedGridJointUniformBuffer); const writeBuffers0 = buffer0.writeBuffers || []; for (let i = 0; i < gridBoneCollection.transforms.length; i++) { diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index 784e87b..d188c82 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -1,7 +1,7 @@ import { mat4, vec3 } from "wgpu-matrix"; import { BindingResources, RenderPassDescriptor, RenderPassObject, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { getIGPUBuffer, reactive, WebGPU } from "@feng3d/webgpu"; +import { getGBuffer, reactive, WebGPU } from "@feng3d/webgpu"; import basicVertWGSL from "../../shaders/basic.vert.wgsl"; import vertexPositionColorWGSL from "../../shaders/vertexPositionColor.frag.wgsl"; @@ -240,7 +240,7 @@ setBlendConstant().`, { const transformationMatrix = getTransformationMatrix(); - const buffer = getIGPUBuffer(uniformBuffer); + const buffer = getGBuffer(uniformBuffer); const writeBuffers = buffer.writeBuffers || []; writeBuffers.push({ data: transformationMatrix.buffer, diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index f2e1358..de6dd37 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -3,7 +3,7 @@ import { mat4, Mat4 } from "wgpu-matrix"; import msdfTextWGSL from "./msdfText.wgsl"; import { BindingResources, RenderPassObject, RenderPipeline, Sampler, Texture } from "@feng3d/render-api"; -import { getIGPUBuffer, reactive, RenderBundle } from "@feng3d/webgpu"; +import { getGBuffer, reactive, RenderBundle } from "@feng3d/webgpu"; // The kerning map stores a spare map of character ID pairs with an associated // X offset that should be applied to the character spacing when the second @@ -104,7 +104,7 @@ export class MsdfText if (this.bufferArrayDirty) { this.bufferArrayDirty = false; - const buffer = getIGPUBuffer(this.textBuffer); + const buffer = getGBuffer(this.textBuffer); const writeBuffers = buffer.writeBuffers || []; writeBuffers.push({ bufferOffset: 0, @@ -438,7 +438,7 @@ export class MsdfTextRenderer this.cameraUniformBuffer.set(projection, 0); this.cameraUniformBuffer.set(view, 16); - const buffer = getIGPUBuffer(this.cameraUniformBuffer); + const buffer = getGBuffer(this.cameraUniformBuffer); const writeBuffers = buffer.writeBuffers || []; writeBuffers.push({ data: this.cameraUniformBuffer, diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index cff91ef..8608f71 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -10,7 +10,7 @@ import { updateBufferBinding } from "../utils/updateBufferBinding"; import { getGPUBuffer } from "./getGPUBuffer"; import { getGPUSampler } from "./getGPUSampler"; import { getGPUTextureView } from "./getGPUTextureView"; -import { getIGPUBuffer } from "./getIGPUBuffer"; +import { getGBuffer } from "./getIGPUBuffer"; export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) { @@ -51,7 +51,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup { const resource = v.resource as BufferBinding; // - const b = getIGPUBuffer(resource.bufferView); + const b = getGBuffer(resource.bufferView); const buffer = getGPUBuffer(device, b); const offset = resource.bufferView.byteOffset; @@ -216,7 +216,7 @@ function getSetBindGroup(bindGroupLayout: GPUBindGroupLayout, bindingResources: // 更新缓冲区绑定的数据。 updateBufferBinding(resourceName, bufferBindingInfo, bufferBinding); // - const buffer = getIGPUBuffer(bufferBinding.bufferView); + const buffer = getGBuffer(bufferBinding.bufferView); (buffer as any).label = buffer.label || (`BufferBinding ${variableInfo.name}`); // entry.resource = bufferBinding; diff --git a/src/caches/getIGPUBuffer.ts b/src/caches/getIGPUBuffer.ts index 5dd022a..e279824 100644 --- a/src/caches/getIGPUBuffer.ts +++ b/src/caches/getIGPUBuffer.ts @@ -1,6 +1,6 @@ import { GBuffer, TypedArray } from "@feng3d/render-api"; -export function getIGPUBuffer(bufferSource: TypedArray) +export function getGBuffer(bufferSource: TypedArray) { let arrayBuffer = bufferSource as ArrayBuffer; if ((bufferSource as ArrayBufferView).buffer) diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 4abeef6..84a2350 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -11,7 +11,7 @@ import { getGPURenderPassFormat } from "../caches/getGPURenderPassFormat"; import { getGPURenderPipeline } from "../caches/getGPURenderPipeline"; import { getGPURenderTimestampQuery } from "../caches/getGPURenderTimestampQuery"; import { getGPUTexture } from "../caches/getGPUTexture"; -import { getIGPUBuffer } from "../caches/getIGPUBuffer"; +import { getGBuffer } from "../caches/getIGPUBuffer"; import { getNGPURenderPipeline } from "../caches/getNGPURenderPipeline"; import { getRealGPUBindGroup } from "../const"; import { ComputeObject } from "../data/ComputeObject"; @@ -432,7 +432,7 @@ export class RunWebGPU // renderPipeline.vertexBuffers?.forEach((vertexBuffer, index) => { - const buffer = getIGPUBuffer(vertexBuffer.data); + const buffer = getGBuffer(vertexBuffer.data); (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); const gBuffer = getGPUBuffer(device, buffer); @@ -445,7 +445,7 @@ export class RunWebGPU { if (!indices) return; - const buffer = getIGPUBuffer(indices); + const buffer = getGBuffer(indices); (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); const gBuffer = getGPUBuffer(device, buffer); diff --git a/src/utils/updateBufferBinding.ts b/src/utils/updateBufferBinding.ts index f6bcba8..20ffa26 100644 --- a/src/utils/updateBufferBinding.ts +++ b/src/utils/updateBufferBinding.ts @@ -2,7 +2,7 @@ import { BufferBinding, BufferBindingInfo, UnReadonly } from "@feng3d/render-api import { watcher } from "@feng3d/watcher"; import { VariableInfo } from "wgsl_reflect"; -import { getIGPUBuffer } from "../caches/getIGPUBuffer"; +import { getGBuffer } from "../caches/getIGPUBuffer"; import { reactive } from "../reactivity"; /** @@ -34,7 +34,7 @@ export function updateBufferBinding(resourceName: string, bufferBindingInfo: Buf (uniformData as UnReadonly).bufferView = new Uint8Array(size); } - const buffer = getIGPUBuffer(uniformData.bufferView); + const buffer = getGBuffer(uniformData.bufferView); const offset = uniformData.bufferView.byteOffset; for (let i = 0; i < bufferBindingInfo.items.length; i++) -- Gitee From 5d27a66da07c5eb945dca5c8e80956bb224a863d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 23:10:09 +0800 Subject: [PATCH 061/214] =?UTF-8?q?refactor(examples):=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E5=AF=BC=E5=85=A5=E8=AF=AD=E5=8F=A5=E5=92=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化了多个示例项目中的导入语句 - 移除了重复导入的 reactive 模块 - 调整了导入顺序,将本地模块放在了外部模块之后 - 删除了未使用的 global.ts 文件 - 移除了 index.ts 中的重复导出 - 删除了 reactivity.ts 文件,统一了 reactive 相关的导入 --- examples/src/webgpu/bitonicSort/index.ts | 4 ++-- examples/src/webgpu/blending/index.ts | 4 ++-- examples/src/webgpu/cornell/common.ts | 4 ++-- examples/src/webgpu/cornell/radiosity.ts | 4 ++-- examples/src/webgpu/deferredRendering/index.ts | 4 ++-- examples/src/webgpu/imageBlur/index.ts | 4 ++-- examples/src/webgpu/multipleCanvases/index.ts | 4 ++-- examples/src/webgpu/particles/index.ts | 4 ++-- examples/src/webgpu/renderBundles/index.ts | 4 ++-- examples/src/webgpu/samplerParameters/index.ts | 4 ++-- examples/src/webgpu/shadowMapping/index.ts | 4 ++-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 4 ++-- examples/src/webgpu/skinnedMesh/index.ts | 4 ++-- examples/src/webgpu/textRenderingMsdf/index.ts | 4 ++-- examples/src/webgpu/textRenderingMsdf/msdfText.ts | 4 ++-- src/caches/getGPUBuffer.ts | 3 +-- src/global.ts | 8 -------- src/index.ts | 5 ----- src/reactivity.ts | 12 ------------ src/utils/updateBufferBinding.ts | 3 +-- 20 files changed, 32 insertions(+), 59 deletions(-) delete mode 100644 src/global.ts delete mode 100644 src/reactivity.ts diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index ae9ef6c..fb5d2b5 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,6 +1,6 @@ -import { BindingResources, BufferBinding, CommandEncoder, GBuffer, RenderPassDescriptor, Submit } from "@feng3d/render-api"; +import { BindingResources, BufferBinding, CommandEncoder, GBuffer, RenderPassDescriptor, Submit, reactive } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { ComputePass, ComputePipeline, TimestampQuery, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; +import { ComputePass, ComputePipeline, TimestampQuery, WebGPU, getGBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats.js"; diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index fa5c74b..07a5e5c 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -2,8 +2,8 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import texturedQuadWGSL from "./texturedQuad.wgsl"; -import { BindingResources, BlendComponent, CanvasContext, RenderObject, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureView } from "@feng3d/render-api"; -import { reactive, WebGPU } from "@feng3d/webgpu"; +import { BindingResources, BlendComponent, CanvasContext, reactive, RenderObject, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureView } from "@feng3d/render-api"; +import { WebGPU } from "@feng3d/webgpu"; declare module "@feng3d/render-api" { diff --git a/examples/src/webgpu/cornell/common.ts b/examples/src/webgpu/cornell/common.ts index d1e845b..2fbaad9 100644 --- a/examples/src/webgpu/cornell/common.ts +++ b/examples/src/webgpu/cornell/common.ts @@ -1,5 +1,5 @@ -import { BindingResources } from "@feng3d/render-api"; -import { getGBuffer, reactive } from "@feng3d/webgpu"; +import { BindingResources, reactive } from "@feng3d/render-api"; +import { getGBuffer } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; import commonWGSL from "./common.wgsl"; diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index fbaadc1..3d5d2e6 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -1,5 +1,5 @@ -import { BindingResources, CommandEncoder, IPassEncoder, Texture } from "@feng3d/render-api"; -import { ComputePipeline, getGBuffer, reactive } from "@feng3d/webgpu"; +import { BindingResources, CommandEncoder, IPassEncoder, reactive, Texture } from "@feng3d/render-api"; +import { ComputePipeline, getGBuffer } from "@feng3d/webgpu"; import Common from "./common"; import radiosityWGSL from "./radiosity.wgsl"; diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 9439598..abeb041 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -10,8 +10,8 @@ import lightUpdate from "./lightUpdate.wgsl"; import vertexTextureQuad from "./vertexTextureQuad.wgsl"; import vertexWriteGBuffers from "./vertexWriteGBuffers.wgsl"; -import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; -import { ComputePass, ComputePipeline, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; +import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes, reactive } from "@feng3d/render-api"; +import { ComputePass, ComputePipeline, WebGPU, getGBuffer } from "@feng3d/webgpu"; const kMaxNumLights = 1024; const lightExtentMin = vec3.fromValues(-50, -30, -50); diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 1af547f..b4743cb 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -3,8 +3,8 @@ import { GUI } from "dat.gui"; import fullscreenTexturedQuadWGSL from "../../shaders/fullscreenTexturedQuad.wgsl"; import blurWGSL from "./blur.wgsl"; -import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture } from "@feng3d/render-api"; -import { ComputePass, ComputePipeline, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; +import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, reactive } from "@feng3d/render-api"; +import { ComputePass, ComputePipeline, WebGPU, getGBuffer } from "@feng3d/webgpu"; // Contants from the blur.wgsl shader. const tileDim = 128; diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index 1c1f192..75ef515 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,5 +1,5 @@ -import { BindingResources, CanvasContext, IPassEncoder, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; -import { getGBuffer, reactive, WebGPU } from "@feng3d/webgpu"; +import { BindingResources, CanvasContext, IPassEncoder, reactive, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; +import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index 19d90cd..f4dd629 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -7,8 +7,8 @@ import particleWGSL from "./particle.wgsl"; import probabilityMapWGSL from "./probabilityMap.wgsl"; import simulateWGSL from "./simulate.wgsl"; -import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { ComputePass, ComputePipeline, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; +import { BindingResources, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes, reactive } from "@feng3d/render-api"; +import { ComputePass, ComputePipeline, WebGPU, getGBuffer } from "@feng3d/webgpu"; const numParticles = 50000; const particlePositionOffset = 0; diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index e35b824..b7eb7a5 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -1,5 +1,5 @@ -import { BindingResources, CanvasContext, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { RenderBundle, WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; +import { BindingResources, CanvasContext, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, VertexAttributes, reactive } from "@feng3d/render-api"; +import { RenderBundle, WebGPU, getGBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats-js"; diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index fcbc25f..9fcb6ec 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -1,8 +1,8 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; -import { BindingResources, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureSource } from "@feng3d/render-api"; -import { getGBuffer, reactive, WebGPU } from "@feng3d/webgpu"; +import { BindingResources, reactive, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureSource } from "@feng3d/render-api"; +import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import showTextureWGSL from "./showTexture.wgsl"; import texturedSquareWGSL from "./texturedSquare.wgsl"; diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 537fbbb..87b2bf3 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -1,5 +1,5 @@ -import { BindingResources, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { WebGPU, getGBuffer, reactive } from "@feng3d/webgpu"; +import { BindingResources, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes, reactive } from "@feng3d/render-api"; +import { WebGPU, getGBuffer } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; import { mesh } from "../../meshes/stanfordDragon"; diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 501c194..235b786 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,8 +1,8 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { BindingResources, FragmentState, GBuffer, IDraw, PrimitiveState, RenderObject, RenderPipeline, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; -import { getGBuffer, reactive } from "@feng3d/webgpu"; +import { BindingResources, FragmentState, GBuffer, IDraw, PrimitiveState, reactive, RenderObject, RenderPipeline, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; +import { getGBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models // Modified from Will Usher code found at this link https://www.willusher.io/graphics/2023/05/16/0-to-gltf-first-mesh diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 513a44c..9857e74 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -7,8 +7,8 @@ import gridWGSL from "./grid.wgsl"; import { gridIndices } from "./gridData"; import { createSkinnedGridBuffers, createSkinnedGridRenderPipeline } from "./gridUtils"; -import { BindingResources, IPassEncoder, RenderObject, RenderPass, RenderPassDescriptor, Texture } from "@feng3d/render-api"; -import { getGBuffer, reactive, WebGPU } from "@feng3d/webgpu"; +import { BindingResources, IPassEncoder, reactive, RenderObject, RenderPass, RenderPassDescriptor, Texture } from "@feng3d/render-api"; +import { getGBuffer, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => { diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index d188c82..515d3e8 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -1,7 +1,7 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { BindingResources, RenderPassDescriptor, RenderPassObject, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; -import { getGBuffer, reactive, WebGPU } from "@feng3d/webgpu"; +import { BindingResources, reactive, RenderPassDescriptor, RenderPassObject, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; +import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import basicVertWGSL from "../../shaders/basic.vert.wgsl"; import vertexPositionColorWGSL from "../../shaders/vertexPositionColor.frag.wgsl"; diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index de6dd37..9d90cff 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -2,8 +2,8 @@ import { mat4, Mat4 } from "wgpu-matrix"; import msdfTextWGSL from "./msdfText.wgsl"; -import { BindingResources, RenderPassObject, RenderPipeline, Sampler, Texture } from "@feng3d/render-api"; -import { getGBuffer, reactive, RenderBundle } from "@feng3d/webgpu"; +import { BindingResources, reactive, RenderPassObject, RenderPipeline, Sampler, Texture } from "@feng3d/render-api"; +import { getGBuffer, RenderBundle } from "@feng3d/webgpu"; // The kerning map stores a spare map of character ID pairs with an associated // X offset that should be applied to the character spacing when the second diff --git a/src/caches/getGPUBuffer.ts b/src/caches/getGPUBuffer.ts index a3df932..b6dbc67 100644 --- a/src/caches/getGPUBuffer.ts +++ b/src/caches/getGPUBuffer.ts @@ -1,6 +1,5 @@ -import { GBuffer, UnReadonly } from "@feng3d/render-api"; +import { computed, ComputedRef, effect, GBuffer, reactive, UnReadonly } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { computed, ComputedRef, effect, reactive } from "../reactivity"; /** * 除了GPU与CPU数据交换的`MAP_READ`与`MAP_WRITE`除外。 diff --git a/src/global.ts b/src/global.ts deleted file mode 100644 index 0777368..0000000 --- a/src/global.ts +++ /dev/null @@ -1,8 +0,0 @@ -export { }; -declare global -{ - /** - * 是否为开发模式。 - */ - var __DEV__: boolean; -} diff --git a/src/index.ts b/src/index.ts index e6f7998..6d895d4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,8 +32,3 @@ export * as internal from "./internal"; export * from "./utils/ChainMap"; export * from "./utils/getOffscreenCanvasId"; -// 导出反应式相关功能 -export * from "./reactivity"; - -import "./global" - diff --git a/src/reactivity.ts b/src/reactivity.ts deleted file mode 100644 index a6b45bc..0000000 --- a/src/reactivity.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { UnReadonly } from "@feng3d/render-api"; -import { reactive as vueReactive } from "@vue/reactivity"; - -export { computed, type ComputedRef, effect } from "@vue/reactivity"; - -/** - * Vue响应式。 - * - * 额外把只读属性去掉(引擎希望原始数据只用于访问,不直接修改,通过修改响应式数据来触发引擎更新逻辑并间接修改原始数据)。 - */ -export const reactive: (target: T) => UnReadonly = vueReactive as any; - diff --git a/src/utils/updateBufferBinding.ts b/src/utils/updateBufferBinding.ts index 20ffa26..8ffbfa2 100644 --- a/src/utils/updateBufferBinding.ts +++ b/src/utils/updateBufferBinding.ts @@ -1,9 +1,8 @@ -import { BufferBinding, BufferBindingInfo, UnReadonly } from "@feng3d/render-api"; +import { BufferBinding, BufferBindingInfo, reactive, UnReadonly } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { VariableInfo } from "wgsl_reflect"; import { getGBuffer } from "../caches/getIGPUBuffer"; -import { reactive } from "../reactivity"; /** * 初始化缓冲区绑定。 -- Gitee From 10b22ff817fda31fd369e6b47a696fb1dc276b92 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 23:35:40 +0800 Subject: [PATCH 062/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=88=B3=E6=9F=A5=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除对 watcher 的依赖,改为使用回调函数处理查询结果 - 优化了 bitonicSort 和 PerfCounter 示例中的时间戳查询逻辑 - 修改了 TimestampQuery 接口,增加了回调函数类型属性 - 调整了 getGPURenderTimestampQuery 函数,支持新的查询结果回调 --- examples/src/webgpu/bitonicSort/index.ts | 52 +++++++++---------- .../src/webgpu/timestampQuery/PerfCounter.ts | 10 ++-- examples/src/webgpu/timestampQuery/index.ts | 41 +++++++-------- src/caches/getGPURenderTimestampQuery.ts | 12 +++-- src/data/TimestampQuery.ts | 12 +++-- 5 files changed, 65 insertions(+), 62 deletions(-) diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index fb5d2b5..8620649 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,5 +1,4 @@ import { BindingResources, BufferBinding, CommandEncoder, GBuffer, RenderPassDescriptor, Submit, reactive } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; import { ComputePass, ComputePipeline, TimestampQuery, WebGPU, getGBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import Stats from "stats.js"; @@ -103,32 +102,33 @@ async function init( const maxInvocationsX = webgpu.device.limits.maxComputeWorkgroupSizeX; // Handle timestamp query stuff - const querySet: TimestampQuery = {}; - watcher.watch(querySet, "elapsedNs", () => - { - // Calculate new step, sort, and average sort times - const newStepTime = querySet.elapsedNs / 1000000; - const newSortTime = settings.sortTime + newStepTime; - // Apply calculated times to settings object as both number and 'ms' appended string - settings.stepTime = newStepTime; - settings.sortTime = newSortTime; - stepTimeController.setValue(`${newStepTime.toFixed(5)}ms`); - sortTimeController.setValue(`${newSortTime.toFixed(5)}ms`); - // Calculate new average sort upon end of final execution step of a full bitonic sort. - if (highestBlockHeight === settings["Total Elements"] * 2) + const querySet: TimestampQuery = { + onQuery: (elapsedNs) => { - // Lock off access to this larger if block..not best architected solution but eh - highestBlockHeight *= 2; - settings.configToCompleteSwapsMap[settings.configKey].time - += newSortTime; - const averageSortTime - = settings.configToCompleteSwapsMap[settings.configKey].time - / settings.configToCompleteSwapsMap[settings.configKey].sorts; - averageSortTimeController.setValue( - `${averageSortTime.toFixed(5)}ms` - ); - } - }, undefined, false); + // Calculate new step, sort, and average sort times + const newStepTime = elapsedNs / 1000000; + const newSortTime = settings.sortTime + newStepTime; + // Apply calculated times to settings object as both number and 'ms' appended string + settings.stepTime = newStepTime; + settings.sortTime = newSortTime; + stepTimeController.setValue(`${newStepTime.toFixed(5)}ms`); + sortTimeController.setValue(`${newSortTime.toFixed(5)}ms`); + // Calculate new average sort upon end of final execution step of a full bitonic sort. + if (highestBlockHeight === settings["Total Elements"] * 2) + { + // Lock off access to this larger if block..not best architected solution but eh + highestBlockHeight *= 2; + settings.configToCompleteSwapsMap[settings.configKey].time + += newSortTime; + const averageSortTime + = settings.configToCompleteSwapsMap[settings.configKey].time + / settings.configToCompleteSwapsMap[settings.configKey].sorts; + averageSortTimeController.setValue( + `${averageSortTime.toFixed(5)}ms` + ); + } + }, + }; const totalElementOptions = []; const maxElements = maxInvocationsX * 32; diff --git a/examples/src/webgpu/timestampQuery/PerfCounter.ts b/examples/src/webgpu/timestampQuery/PerfCounter.ts index 4756462..1500ccd 100644 --- a/examples/src/webgpu/timestampQuery/PerfCounter.ts +++ b/examples/src/webgpu/timestampQuery/PerfCounter.ts @@ -6,30 +6,30 @@ export default class PerfCounter accumulatedSq: number; constructor() -{ + { this.sampleCount = 0; this.accumulated = 0; this.accumulatedSq = 0; } addSample(value: number) -{ + { this.sampleCount += 1; this.accumulated += value; this.accumulatedSq += value * value; } getAverage(): number -{ + { return this.sampleCount === 0 ? 0 : this.accumulated / this.sampleCount; } getStddev(): number -{ + { if (this.sampleCount === 0) return 0; const avg = this.getAverage(); const variance = this.accumulatedSq / this.sampleCount - avg * avg; -return Math.sqrt(Math.max(0.0, variance)); + return Math.sqrt(Math.max(0.0, variance)); } } diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 355f6ac..3743e76 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -8,39 +8,34 @@ import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cub import basicVertWGSL from "../../shaders/basic.vert.wgsl"; import fragmentWGSL from "../../shaders/black.frag.wgsl"; -import { watcher } from "@feng3d/watcher"; import PerfCounter from "./PerfCounter"; const init = async (canvas: HTMLCanvasElement) => { + const renderPassDurationCounter = new PerfCounter(); // GPU-side timer and the CPU-side counter where we accumulate statistics: // NB: Look for 'timestampQueryManager' in this file to locate parts of this // snippets that are related to timestamps. Most of the logic is in // TimestampQueryManager.ts. - const timestampQuery: TimestampQuery = {}; - // const timestampQueryManager = new TimestampQueryManager(device); - const renderPassDurationCounter = new PerfCounter(); - - watcher.watch(timestampQuery, "isSupports", () => - { - if (!timestampQuery.isSupports) + const timestampQuery: TimestampQuery = { + onSupports: (isSupports: boolean) => { - perfDisplay.innerHTML = "Timestamp queries are not supported"; + if (!isSupports) + { + perfDisplay.innerHTML = "Timestamp queries are not supported"; + } + }, + onQuery: (elapsedNs: number) => + { + // Show the last successfully downloaded elapsed time. + // Convert from nanoseconds to milliseconds: + const elapsedMs = Number(elapsedNs) * 1e-6; + renderPassDurationCounter.addSample(elapsedMs); + perfDisplay.innerHTML = `Render Pass duration: ${renderPassDurationCounter + .getAverage() + .toFixed(3)} ms ± ${renderPassDurationCounter.getStddev().toFixed(3)} ms`; } - }); - - // 监听结果。 - watcher.watch(timestampQuery, "elapsedNs", () => - { - // Show the last successfully downloaded elapsed time. - const elapsedNs = timestampQuery.elapsedNs; - // Convert from nanoseconds to milliseconds: - const elapsedMs = Number(elapsedNs) * 1e-6; - renderPassDurationCounter.addSample(elapsedMs); - perfDisplay.innerHTML = `Render Pass duration: ${renderPassDurationCounter - .getAverage() - .toFixed(3)} ms ± ${renderPassDurationCounter.getStddev().toFixed(3)} ms`; - }); + }; // const devicePixelRatio = window.devicePixelRatio || 1; diff --git a/src/caches/getGPURenderTimestampQuery.ts b/src/caches/getGPURenderTimestampQuery.ts index 3584401..c1f2b92 100644 --- a/src/caches/getGPURenderTimestampQuery.ts +++ b/src/caches/getGPURenderTimestampQuery.ts @@ -9,10 +9,14 @@ export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: T if (!timestampQuery) return defautGPURenderTimestampQuery; let renderTimestampQuery: GPURenderTimestampQuery = timestampQuery["_GPURenderTimestampQuery"]; if (renderTimestampQuery) return renderTimestampQuery; - + // 判断是否支持 `timestamp-query` - timestampQuery.isSupports = device.features.has(`timestamp-query`); - if (!timestampQuery.isSupports) + if (timestampQuery["isSupports"] === undefined) + { + timestampQuery["isSupports"] = device.features.has(`timestamp-query`); + timestampQuery.onSupports?.(timestampQuery["isSupports"]); + } + if (!timestampQuery["isSupports"]) { console.warn(`WebGPU未开启或者不支持 timestamp-query 特性,请确认 WebGPU.init 初始化参数是否正确!`); @@ -98,7 +102,7 @@ export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: T // (see spec https://gpuweb.github.io/gpuweb/#timestamp) if (elapsedNs >= 0) { - timestampQuery.elapsedNs = elapsedNs; + timestampQuery.onQuery(elapsedNs); } resultBuf.unmap(); diff --git a/src/data/TimestampQuery.ts b/src/data/TimestampQuery.ts index 3d3feb8..adfb6d9 100644 --- a/src/data/TimestampQuery.ts +++ b/src/data/TimestampQuery.ts @@ -4,12 +4,16 @@ export interface TimestampQuery { /** - * (单位为纳秒) + * 是否支持该特性时将调用此回调函数。 + * + * @param isSupports 当前WebGPU是否支持该特性。 */ - elapsedNs?: number; + onSupports?(isSupports: boolean): void; /** - * 当前WebGPU是否支持该特性。 + * 获得结果时将调用此回调函数。 + * + * @param elapsedNs 通道运行消耗时长(单位为纳秒) */ - isSupports?: boolean; + onQuery?(elapsedNs: number): void; } \ No newline at end of file -- Gitee From 0aaff47e7a6ee1559a573290b3d56e53eac052e9 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 23:55:37 +0800 Subject: [PATCH 063/214] =?UTF-8?q?refactor(occlusionquery):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20occlusionquery=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 occlusionquery 对象中的 _queryIndex 属性 - 新增 getQueryIndex 方法获取查询索引 - 更新 RunWebGPU 和 RunWebGPUCommandCache 中的 occlusionquery 相关逻辑 - 优化 occlusionquery 的初始化和结果获取流程 --- src/caches/getGPURenderOcclusionQuery.ts | 14 +++++++++----- src/data/polyfills/OcclusionQuery.ts | 7 ------- src/runs/RunWebGPU.ts | 14 ++++++++------ src/runs/RunWebGPUCommandCache.ts | 7 ++++--- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index bc02deb..3c7a03f 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -18,8 +18,6 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb return defautRenderOcclusionQuery; } - occlusionQueryObjects.forEach((v, i) => { v._queryIndex = i; }); - let occlusionQuerySet: GPUQuerySet; let resolveBuf: GPUBuffer; let resultBuf: GPUBuffer; @@ -37,6 +35,11 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb occlusionQuerySet = renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: occlusionQueryObjects.length }); }; + const getQueryIndex = (occlusionQuery: OcclusionQuery) => + { + return occlusionQueryObjects.indexOf(occlusionQuery); + }; + /** * 查询结果。 * @@ -93,15 +96,16 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb anyEmitter.on(device.queue, GPUQueue_submit, getOcclusionQueryResult); }; - renderObjects["_GPURenderOcclusionQuery"] = renderOcclusionQuery = { init, resolve }; + renderObjects["_GPURenderOcclusionQuery"] = renderOcclusionQuery = { init, resolve, getQueryIndex }; return renderOcclusionQuery; } -interface GPURenderOcclusionQuery +export interface GPURenderOcclusionQuery { init: (device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor) => void + getQueryIndex: (occlusionQuery: OcclusionQuery) => number; resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass) => void } -const defautRenderOcclusionQuery = { init: () => { }, resolve: () => { } }; \ No newline at end of file +const defautRenderOcclusionQuery = { init: () => { }, getQueryIndex: () => 0, resolve: () => { } }; \ No newline at end of file diff --git a/src/data/polyfills/OcclusionQuery.ts b/src/data/polyfills/OcclusionQuery.ts index 19141e7..348b49c 100644 --- a/src/data/polyfills/OcclusionQuery.ts +++ b/src/data/polyfills/OcclusionQuery.ts @@ -4,13 +4,6 @@ declare module "@feng3d/render-api" { export interface OcclusionQuery { - /** - * 临时变量, 执行过程中由引擎自动填充 - * - * @internal - */ - _queryIndex?: GPUSize32; - _version?: number; } } diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 84a2350..ae631f6 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -5,7 +5,7 @@ import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; import { getGPUComputePipeline } from "../caches/getGPUComputePipeline"; import { getGPUPipelineLayout, IGPUShader } from "../caches/getGPUPipelineLayout"; -import { getGPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; +import { getGPURenderOcclusionQuery, GPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; import { getGPURenderPassDescriptor } from "../caches/getGPURenderPassDescriptor"; import { getGPURenderPassFormat } from "../caches/getGPURenderPassFormat"; import { getGPURenderPipeline } from "../caches/getGPURenderPipeline"; @@ -95,7 +95,7 @@ export class RunWebGPU const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); - this.runRenderPassObjects(device, passEncoder, renderPassFormat, renderObjects); + this.runRenderPassObjects(device, passEncoder, renderPassFormat, renderObjects, occlusionQuery); passEncoder.end(); @@ -106,7 +106,7 @@ export class RunWebGPU timestampQuery.resolve(device, commandEncoder, renderPass); } - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: readonly RenderPassObject[]) + protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects: readonly RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { if (!renderObjects) return; // @@ -126,7 +126,7 @@ export class RunWebGPU } else if (element.__type__ === "OcclusionQuery") { - this.runRenderOcclusionQueryObject(device, passEncoder, renderPassFormat, element); + this.runRenderOcclusionQueryObject(device, passEncoder, renderPassFormat, element, occlusionQuery); } else { @@ -208,13 +208,15 @@ export class RunWebGPU ); } - protected runRenderOcclusionQueryObject(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderOcclusionQueryObject: OcclusionQuery) + protected runRenderOcclusionQueryObject(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderOcclusionQueryObject: OcclusionQuery, occlusionQuery: GPURenderOcclusionQuery) { - passEncoder.beginOcclusionQuery(renderOcclusionQueryObject._queryIndex); + passEncoder.beginOcclusionQuery(occlusionQuery.getQueryIndex(renderOcclusionQueryObject)); + renderOcclusionQueryObject.renderObjects.forEach((renderObject) => { this.runRenderObject(device, passEncoder, renderPassFormat, renderObject); }); + passEncoder.endOcclusionQuery(); } diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/runs/RunWebGPUCommandCache.ts index 3afec93..e017b26 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/runs/RunWebGPUCommandCache.ts @@ -1,6 +1,7 @@ -import { RenderPassObject, RenderObject } from "@feng3d/render-api"; +import { RenderObject, RenderPassObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; +import { GPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; import { getRealGPUBindGroup } from "../const"; import { IRenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; @@ -11,7 +12,7 @@ import { RunWebGPU } from "./RunWebGPU"; */ export class RunWebGPUCommandCache extends RunWebGPU { - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: RenderPassObject[]) + protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { const map: ChainMap<[string, RenderPassObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); let caches = map.get([renderPassFormat._key, renderObjects]); @@ -21,7 +22,7 @@ export class RunWebGPUCommandCache extends RunWebGPU const renderPassRecord = new GPURenderPassRecord(); const commands = renderPassRecord["_commands"] = []; - super.runRenderPassObjects(device, renderPassRecord, renderPassFormat, renderObjects); + super.runRenderPassObjects(device, renderPassRecord, renderPassFormat, renderObjects, occlusionQuery); // 排除无效命令 paichuWuxiaoCommands(renderPassFormat.attachmentSize, commands); -- Gitee From 90ba6eace7a868872e4bff4622faff5207bfc2b9 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 14 Mar 2025 23:59:00 +0800 Subject: [PATCH 064/214] =?UTF-8?q?refactor(data):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=9C=AA=E4=BD=BF=E7=94=A8=E7=9A=84=20OcclusionQuery=20polyfil?= =?UTF-8?q?l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 src/data/polyfills/OcclusionQuery.ts 文件 - 移除了相关文件中对 OcclusionQuery polyfill 的引用 - 调整了部分代码以适应移除后的变化 此次重构优化了项目结构,移除了不必要的 polyfill 文件,提高了代码的可维护性。 --- src/caches/getGPURenderOcclusionQuery.ts | 1 - src/data/polyfills/OcclusionQuery.ts | 10 ---------- src/data/polyfills/RenderPass.ts | 3 +-- src/index.ts | 1 - src/runs/RunWebGPU.ts | 1 - src/runs/RunWebGPUCommandCache.ts | 25 ++---------------------- 6 files changed, 3 insertions(+), 38 deletions(-) delete mode 100644 src/data/polyfills/OcclusionQuery.ts diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index 3c7a03f..3ad8c1f 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -1,7 +1,6 @@ import { anyEmitter } from "@feng3d/event"; import { RenderPassObject, OcclusionQuery, RenderPass } from "@feng3d/render-api"; -import { } from "../data/polyfills/OcclusionQuery"; import { GPUQueue_submit } from "../eventnames"; export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassObject[]): GPURenderOcclusionQuery diff --git a/src/data/polyfills/OcclusionQuery.ts b/src/data/polyfills/OcclusionQuery.ts deleted file mode 100644 index 348b49c..0000000 --- a/src/data/polyfills/OcclusionQuery.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { OcclusionQuery } from "@feng3d/render-api"; - -declare module "@feng3d/render-api" -{ - export interface OcclusionQuery - { - _version?: number; - } -} - diff --git a/src/data/polyfills/RenderPass.ts b/src/data/polyfills/RenderPass.ts index 594c1b1..57c716e 100644 --- a/src/data/polyfills/RenderPass.ts +++ b/src/data/polyfills/RenderPass.ts @@ -1,5 +1,4 @@ -import { RenderPass, RenderPassDescriptor } from "@feng3d/render-api"; -import { } from "./OcclusionQuery"; +import { OcclusionQuery } from "@feng3d/render-api"; import { RenderBundle } from "../RenderBundle"; import { TimestampQuery } from "../TimestampQuery"; diff --git a/src/index.ts b/src/index.ts index 6d895d4..5efb4ec 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,7 +11,6 @@ export * from "./data/TimestampQuery"; export * from "./data/polyfills/GBuffer"; export * from "./data/polyfills/CanvasContext"; export * from "./data/polyfills/CommandEncoder"; -export * from "./data/polyfills/OcclusionQuery"; export * from "./data/polyfills/PrimitiveState"; export * from "./data/polyfills/ReadPixels"; export * from "./data/polyfills/RenderObject"; diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index ae631f6..c0f810f 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -17,7 +17,6 @@ import { getRealGPUBindGroup } from "../const"; import { ComputeObject } from "../data/ComputeObject"; import { ComputePass } from "../data/ComputePass"; import { ComputePipeline } from "../data/ComputePipeline"; -import { } from "../data/polyfills/OcclusionQuery"; import "../data/polyfills/RenderObject"; import "../data/polyfills/RenderPass"; import { RenderBundle } from "../data/RenderBundle"; diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/runs/RunWebGPUCommandCache.ts index e017b26..87fd08c 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/runs/RunWebGPUCommandCache.ts @@ -39,9 +39,9 @@ export class RunWebGPUCommandCache extends RunWebGPU { map.delete([renderPassFormat._key, renderObjects]); // - renderObjects.forEach((v) => { watcher.unwatch(v, "_version", onchanged); }); + renderObjects.forEach((v) => { watcher.unwatch(v, "_version" as any, onchanged); }); }; - renderObjects.forEach((v) => { watcher.watch(v, "_version", onchanged); }); + renderObjects.forEach((v) => { watcher.watch(v, "_version" as any, onchanged); }); } // 执行命令 @@ -118,27 +118,6 @@ export class RunWebGPUCommandCache extends RunWebGPU } } -class GPURenderBundleRecord implements GPURenderBundleEncoder -{ - __brand: "GPURenderBundleEncoder"; - label: string; - // - setPipeline(...args: any): undefined { this["_commands"].push(["setPipeline", args]); } - setVertexBuffer(...args: any): undefined { this["_commands"].push(["setVertexBuffer", args]); } - setIndexBuffer(...args: any): undefined { this["_commands"].push(["setIndexBuffer", args]); } - setBindGroup(...args: any): undefined { this["_commands"].push(["setBindGroup", args]); } - draw(...args: any): undefined { this["_commands"].push(["draw", args]); } - drawIndexed(...args: any): undefined { this["_commands"].push(["drawIndexed", args]); } - drawIndirect(...args: any): undefined { this["_commands"].push(["drawIndirect", args]); } - drawIndexedIndirect(...args: any): undefined { this["_commands"].push(["drawIndexedIndirect", args]); } - // - finish(...args: any): undefined { this["_commands"].push(["finish", args]); } - // - pushDebugGroup(...args: any): undefined { this["_commands"].push(["pushDebugGroup", args]); } - popDebugGroup(...args: any): undefined { this["_commands"].push(["popDebugGroup", args]); } - insertDebugMarker(...args: any): undefined { this["_commands"].push(["insertDebugMarker", args]); } -} - class GPURenderPassRecord implements GPURenderPassEncoder { __brand: "GPURenderPassEncoder" = "GPURenderPassEncoder"; -- Gitee From 970b3050114407aa6e3b927fe4bde2824de69313 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 15 Mar 2025 00:26:28 +0800 Subject: [PATCH 065/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=81=AE=E6=8C=A1=E6=9F=A5=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 renderPass.occlusionQueryResults 属性 - 新增 renderPass.onOcclusionQuery 回调函数 - 优化 occlusion query 结果处理流程 - 修复 examples 中的 occlusion query 示例 --- examples/src/webgpu/occlusionQuery/index.ts | 19 ++++++-------- src/caches/getGPURenderOcclusionQuery.ts | 29 ++++++++++++--------- src/data/polyfills/RenderPass.ts | 4 ++- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 7a57132..0b7872d 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -162,8 +162,15 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderPass: RenderPass = { descriptor: renderPassDescriptor, - // renderObjects: renderObjects, renderObjects: occlusionQueryObjects, + onOcclusionQuery(_occlusionQuerys, results) + { + const visible = objectInfos + .filter((_, i) => results[i]) + .map(({ id }) => id) + .join(""); + info.textContent = `visible: ${visible}`; + }, }; const submit: Submit = { @@ -231,16 +238,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => webgpu.submit(submit); - // 监听查询结果。 - watcher.watch(renderPass, "occlusionQueryResults", () => - { - const visible = objectInfos - .filter((_, i) => renderPass.occlusionQueryResults[i].result.result) - .map(({ id }) => id) - .join(""); - info.textContent = `visible: ${visible}`; - }); - requestAnimationFrame(render); } requestAnimationFrame(render); diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index 3ad8c1f..c9b5fed 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -9,8 +9,8 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb let renderOcclusionQuery: GPURenderOcclusionQuery = renderObjects["_GPURenderOcclusionQuery"]; if (renderOcclusionQuery) return renderOcclusionQuery; - const occlusionQueryObjects: OcclusionQuery[] = renderObjects.filter((cv) => cv.__type__ === "OcclusionQuery") as any; - if (occlusionQueryObjects.length === 0) + const occlusionQuerys: OcclusionQuery[] = renderObjects.filter((cv) => cv.__type__ === "OcclusionQuery") as any; + if (occlusionQuerys.length === 0) { renderObjects["_GPURenderOcclusionQuery"] = defautRenderOcclusionQuery; @@ -31,12 +31,12 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb */ const init = (device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor) => { - occlusionQuerySet = renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: occlusionQueryObjects.length }); + occlusionQuerySet = renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: occlusionQuerys.length }); }; const getQueryIndex = (occlusionQuery: OcclusionQuery) => { - return occlusionQueryObjects.indexOf(occlusionQuery); + return occlusionQuerys.indexOf(occlusionQuery); }; /** @@ -51,11 +51,11 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb resolveBuf = resolveBuf || device.createBuffer({ label: "resolveBuffer", // Query results are 64bit unsigned integers. - size: occlusionQueryObjects.length * BigUint64Array.BYTES_PER_ELEMENT, + size: occlusionQuerys.length * BigUint64Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC, }); - commandEncoder.resolveQuerySet(occlusionQuerySet, 0, occlusionQueryObjects.length, resolveBuf, 0); + commandEncoder.resolveQuerySet(occlusionQuerySet, 0, occlusionQuerys.length, resolveBuf, 0); resultBuf = resultBuf || device.createBuffer({ label: "resultBuffer", @@ -74,16 +74,21 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb { resultBuf.mapAsync(GPUMapMode.READ).then(() => { - const results = new BigUint64Array(resultBuf.getMappedRange()); + const bigUint64Array = new BigUint64Array(resultBuf.getMappedRange()); - occlusionQueryObjects.forEach((v, i) => + const results = bigUint64Array.reduce((pv: boolean[], cv) => { - v.result = { result: Number(results[i]) }; - }); - + pv.push(!!cv); + return pv; + }, []); resultBuf.unmap(); - renderPass.occlusionQueryResults = occlusionQueryObjects.concat(); + occlusionQuerys.forEach((v, i) => + { + v.onQuery?.(results[i]); + }); + + renderPass.onOcclusionQuery?.(occlusionQuerys, results); // anyEmitter.off(device.queue, GPUQueue_submit, getOcclusionQueryResult); diff --git a/src/data/polyfills/RenderPass.ts b/src/data/polyfills/RenderPass.ts index 57c716e..06380c7 100644 --- a/src/data/polyfills/RenderPass.ts +++ b/src/data/polyfills/RenderPass.ts @@ -17,8 +17,10 @@ declare module "@feng3d/render-api" * 渲染不被遮挡查询结果。具体数据保存在各子项的"result"属性中。 * * 当提交WebGPU后自动获取结果后填充该属性。 + * + * @param results 是否被渲染。true表示被渲染,false表示未被渲染。 */ - occlusionQueryResults?: OcclusionQuery[]; + onOcclusionQuery?(occlusionQuerys: OcclusionQuery[], results: boolean[]): void; /** * 查询通道运行消耗时长(单位为纳秒)。 -- Gitee From a0f94d51dd5fdb3e9b12b34fbccd701619fcc454 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 15 Mar 2025 00:42:12 +0800 Subject: [PATCH 066/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20occlusion=20query=20=E7=BB=93=E6=9E=9C=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 occlusion query 结果转换为 number 类型,而不是 boolean - 移除了 RenderPass 接口中未使用的 onOcclusionQuery 方法 --- src/caches/getGPURenderOcclusionQuery.ts | 4 ++-- src/data/polyfills/RenderPass.ts | 9 --------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index c9b5fed..efb8f05 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -76,9 +76,9 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb { const bigUint64Array = new BigUint64Array(resultBuf.getMappedRange()); - const results = bigUint64Array.reduce((pv: boolean[], cv) => + const results = bigUint64Array.reduce((pv: number[], cv) => { - pv.push(!!cv); + pv.push(Number(cv)); return pv; }, []); resultBuf.unmap(); diff --git a/src/data/polyfills/RenderPass.ts b/src/data/polyfills/RenderPass.ts index 06380c7..1e659e8 100644 --- a/src/data/polyfills/RenderPass.ts +++ b/src/data/polyfills/RenderPass.ts @@ -13,15 +13,6 @@ declare module "@feng3d/render-api" */ export interface RenderPass { - /** - * 渲染不被遮挡查询结果。具体数据保存在各子项的"result"属性中。 - * - * 当提交WebGPU后自动获取结果后填充该属性。 - * - * @param results 是否被渲染。true表示被渲染,false表示未被渲染。 - */ - onOcclusionQuery?(occlusionQuerys: OcclusionQuery[], results: boolean[]): void; - /** * 查询通道运行消耗时长(单位为纳秒)。 * -- Gitee From 264691a52a504284a552f4d4e6291d3f3f5ac09e Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 15 Mar 2025 17:18:15 +0800 Subject: [PATCH 067/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20getGPUBindGroup=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 BindGroupDescriptor 类型,直接使用 BindingResources 作为缓存键 - 重新设计了 bindGroup 的生成逻辑,提高了性能和可维护性 - 优化了资源更新机制,支持更灵活的资源类型 - 删除了未使用的 occlusionQuery 示例代码 --- examples/src/webgpu/occlusionQuery/index.ts | 2 - src/caches/getGPUBindGroup.ts | 108 ++++++-------------- 2 files changed, 31 insertions(+), 79 deletions(-) diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 0b7872d..3707ce0 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -1,12 +1,10 @@ import { BufferBinding, OcclusionQuery, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import solidColorLitWGSL from "./solidColorLit.wgsl"; - const info = document.querySelector("#info"); const init = async (canvas: HTMLCanvasElement, gui: GUI) => diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 8608f71..80d8f3c 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,24 +1,23 @@ import { anyEmitter } from "@feng3d/event"; -import { BufferBinding, BufferBindingInfo, CanvasTexture, Sampler, TextureView, BindingResources, BindingResource } from "@feng3d/render-api"; +import { BindingResource, BindingResources, BufferBinding, BufferBindingInfo, CanvasTexture, Sampler, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; +import { ResourceType } from "wgsl_reflect"; import { getRealGPUBindGroup } from "../const"; import { VideoTexture } from "../data/VideoTexture"; import { GPUTextureView_destroy, IGPUSampler_changed } from "../eventnames"; -import { ChainMap } from "../utils/ChainMap"; -import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; -import { updateBufferBinding } from "../utils/updateBufferBinding"; +import { ExternalSampledTextureType } from "../types/TextureType"; import { getGPUBuffer } from "./getGPUBuffer"; import { getGPUSampler } from "./getGPUSampler"; import { getGPUTextureView } from "./getGPUTextureView"; import { getGBuffer } from "./getIGPUBuffer"; +import { updateBufferBinding } from "../utils/updateBufferBinding"; +import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) { - const bindGroupDescriptor = getSetBindGroup(bindGroupLayout, bindingResources); - - const bindGroupMap: WeakMap = device["_bindGroupMap"] = device["_bindGroupMap"] || new WeakMap(); + const bindGroupMap: WeakMap = bindGroupLayout["_bindGroupMap"] = bindGroupLayout["_bindGroupMap"] || new WeakMap(); - let gBindGroup = bindGroupMap.get(bindGroupDescriptor); + let gBindGroup = bindGroupMap.get(bindingResources); if (gBindGroup) return gBindGroup; // 总是更新函数列表。 @@ -26,9 +25,11 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup // 执行一次函数列表 const onceUpdateFuncs: (() => void)[] = []; - const entries = bindGroupDescriptor.entries.map((v) => + const entries = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map((v) => { - const entry: GPUBindGroupEntry = { binding: v.binding, resource: null }; + const { name, type, resourceType, binding } = v.variableInfo; + + const entry: GPUBindGroupEntry = { binding, resource: null }; // 更新资源函数。 let updateResource: () => void; @@ -45,14 +46,22 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup }; // - if ((v.resource as BufferBinding).bufferView) + if (resourceType === ResourceType.Uniform || resourceType === ResourceType.Storage) { updateResource = () => { - const resource = v.resource as BufferBinding; + const resource = bindingResources[name] as BufferBinding; + + const bufferBinding = ((typeof resource === "number") ? [resource] : resource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 + const bufferBindingInfo: BufferBindingInfo = type["_bufferBindingInfo"] = type["_bufferBindingInfo"] || getBufferBindingInfo(type); + // 更新缓冲区绑定的数据。 + updateBufferBinding(name, bufferBindingInfo, bufferBinding); + // + const gbuffer = getGBuffer(bufferBinding.bufferView); + (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); // const b = getGBuffer(resource.bufferView); - const buffer = getGPUBuffer(device, b); + const buffer = getGPUBuffer(device, gbuffer); const offset = resource.bufferView.byteOffset; const size = resource.bufferView.byteLength; @@ -64,25 +73,25 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup }; }; } - else if ((v.resource as TextureView).texture) + else if (resourceType === ResourceType.Texture) { updateResource = () => { - entry.resource = getGPUTextureView(device, v.resource as TextureView); + entry.resource = getGPUTextureView(device, bindingResources[name] as TextureView); anyEmitter.once(entry.resource, GPUTextureView_destroy, onResourceChanged); }; - if (((v.resource as TextureView).texture as CanvasTexture).context) + if (((bindingResources[name] as TextureView).texture as CanvasTexture).context) { awaysUpdateFuncs.push(updateResource); } } - else if ((v.resource as VideoTexture).source) + else if (ExternalSampledTextureType[type.name]) // 判断是否为外部纹理 { updateResource = () => { - entry.resource = device.importExternalTexture(v.resource as VideoTexture); + entry.resource = device.importExternalTexture(bindingResources[name] as VideoTexture); }; awaysUpdateFuncs.push(updateResource); @@ -91,15 +100,15 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup { updateResource = () => { - entry.resource = getGPUSampler(device, v.resource as Sampler); - anyEmitter.once(v.resource as Sampler, IGPUSampler_changed, onResourceChanged); + entry.resource = getGPUSampler(device, bindingResources[name] as Sampler); + anyEmitter.once(bindingResources[name] as Sampler, IGPUSampler_changed, onResourceChanged); }; } updateResource(); // 监听绑定资源发生改变 - watcher.watch(v, "resource", onResourceChanged); + watcher.watch(bindingResources, name, onResourceChanged); return entry; }); @@ -118,7 +127,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup gBindGroup = device.createBindGroup({ layout: bindGroupLayout, entries }); - bindGroupMap.set(bindGroupDescriptor, gBindGroup); + bindGroupMap.set(bindingResources, gBindGroup); // 设置更新外部纹理/画布纹理视图 if (awaysUpdateFuncs.length > 0) @@ -180,58 +189,3 @@ export interface BindGroupEntry */ resource: Sampler | TextureView | VideoTexture | BindingResource; } - -function getSetBindGroup(bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) -{ - const map: ChainMap, BindGroupDescriptor> = bindGroupLayout["_bindingResources"] = bindGroupLayout["_bindingResources"] || new ChainMap(); - const subBindingResources = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map(v => v.variableInfo.name).map((v) => bindingResources[v]); - let bindGroupDescriptor = map.get(subBindingResources); - if (bindGroupDescriptor) return bindGroupDescriptor; - - const entries: BindGroupEntry[] = []; - bindGroupDescriptor = { layout: bindGroupLayout, entries }; - map.set(subBindingResources, bindGroupDescriptor); - - // - (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).forEach((entry1) => - { - const { variableInfo, binding } = entry1; - // - const entry: BindGroupEntry = { binding, resource: null }; - - entries.push(entry); - - const resourceName = variableInfo.name; - - const updateResource = () => - { - const bindingResource = bindingResources[resourceName]; - console.assert(!!bindingResource, `在绑定资源中没有找到 ${resourceName} 。`); - - // - if (entry1.buffer) - { - const bufferBinding = ((typeof bindingResource === "number") ? [bindingResource] : bindingResource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 - const bufferBindingInfo: BufferBindingInfo = variableInfo["_bufferBindingInfo"] ||= getBufferBindingInfo(variableInfo.type); - // 更新缓冲区绑定的数据。 - updateBufferBinding(resourceName, bufferBindingInfo, bufferBinding); - // - const buffer = getGBuffer(bufferBinding.bufferView); - (buffer as any).label = buffer.label || (`BufferBinding ${variableInfo.name}`); - // - entry.resource = bufferBinding; - } - else - { - entry.resource = bindingResource; - } - }; - - // - updateResource(); - watcher.watch(bindingResources, resourceName, updateResource); - }); - - return bindGroupDescriptor; -} - -- Gitee From bb0d8f2b738667c54e436f6f46a04678cb37bf95 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 15 Mar 2025 17:19:29 +0800 Subject: [PATCH 068/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20getGPUBindGroup=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了未使用的变量 b,简化了代码结构 - 保留了原有的功能和逻辑,没有引入新的更改 --- src/caches/getGPUBindGroup.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 80d8f3c..a886191 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -60,7 +60,6 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup const gbuffer = getGBuffer(bufferBinding.bufferView); (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); // - const b = getGBuffer(resource.bufferView); const buffer = getGPUBuffer(device, gbuffer); const offset = resource.bufferView.byteOffset; -- Gitee From 2222943e56ddfe613c2848ffe36f305b3c307213 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 15 Mar 2025 17:24:51 +0800 Subject: [PATCH 069/214] =?UTF-8?q?refactor(webgpu):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=20bitonicSort=20=E7=A4=BA=E4=BE=8B=E4=B8=AD=E6=9C=AA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E7=9A=84=20Stats.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 Stats.js 的导入语句 - 移除了创建 Stats 实例和将之添加到文档体中的代码 --- examples/src/webgpu/bitonicSort/index.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 8620649..74b75b5 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,7 +1,6 @@ import { BindingResources, BufferBinding, CommandEncoder, GBuffer, RenderPassDescriptor, Submit, reactive } from "@feng3d/render-api"; import { ComputePass, ComputePipeline, TimestampQuery, WebGPU, getGBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; -import Stats from "stats.js"; import atomicToZero from "./atomicToZero.wgsl"; import { NaiveBitonicCompute } from "./bitonicCompute"; @@ -838,10 +837,7 @@ async function init( } const canvas = document.getElementById("webgpu") as HTMLCanvasElement; -const stats = new Stats(); const gui = new GUI(); -document.body.appendChild(stats.dom); - init(gui, canvas); -- Gitee From 19545802d18f22718c510ce5f498fc8305e786c7 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 15 Mar 2025 20:03:33 +0800 Subject: [PATCH 070/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E9=80=9A=E9=81=93=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 GPUComputeObject 和 GPUComputePass 重命名为 ComputeObject 和 ComputePass - 更新了相关类的导入路径和使用方式 - 保持了原有的功能和逻辑不变,仅修改了类名 --- src/WebGPUStep.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WebGPUStep.ts b/src/WebGPUStep.ts index 03bea60..b063c95 100644 --- a/src/WebGPUStep.ts +++ b/src/WebGPUStep.ts @@ -1,8 +1,8 @@ import { CopyBufferToBuffer, CopyTextureToTexture, RenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, Submit } from "@feng3d/render-api"; -import { GPUComputeObject } from "./data/IGPUComputeObject"; -import { GPUComputePass } from "./data/IGPUComputePass"; import { WebGPU } from "./WebGPU"; +import { ComputePass } from "./data/ComputePass"; +import { ComputeObject } from "./data/ComputeObject"; /** * 按步骤来组织 IGPUSubmit 对象。 @@ -13,7 +13,7 @@ export class WebGPUStep { private _currentSubmit: Submit; private _currentRenderPassEncoder: RenderPass; - private _currentComputePassEncoder: GPUComputePass; + private _currentComputePassEncoder: ComputePass; readonly webGPU: WebGPU; @@ -47,7 +47,7 @@ export class WebGPUStep this._currentSubmit.commandEncoders[0].passEncoders.push(this._currentComputePassEncoder); } - computeObject(computeObject: GPUComputeObject) + computeObject(computeObject: ComputeObject) { this._currentComputePassEncoder.computeObjects.push(computeObject); } -- Gitee From 964c568295521b22b5450008bbb41db6e719cefc Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 15 Mar 2025 20:44:16 +0800 Subject: [PATCH 071/214] =?UTF-8?q?refactor(webgpu):=20=E5=B0=86=20IPassEn?= =?UTF-8?q?coder=20=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20PassEncoder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在多个示例文件中将 IPassEncoder 替换为 PassEncoder - 更新相关的导入语句和类型引用 - 此更改统一了 PassEncoder 的命名,提高了代码的一致性和可读性 --- examples/src/webgpu/a-buffer/index.ts | 4 ++-- examples/src/webgpu/cornell/radiosity.ts | 4 ++-- examples/src/webgpu/cornell/raytracer.ts | 4 ++-- examples/src/webgpu/cornell/tonemapper.ts | 4 ++-- examples/src/webgpu/multipleCanvases/index.ts | 4 ++-- examples/src/webgpu/skinnedMesh/index.ts | 4 ++-- src/caches/getGPUTextureView.ts | 3 +++ 7 files changed, 15 insertions(+), 12 deletions(-) diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 525023c..c59ad2b 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, CanvasContext, IPassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; +import { BufferBinding, CanvasContext, PassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -271,7 +271,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => return viewProjMatrix; } - const passEncoders: IPassEncoder[] = []; + const passEncoders: PassEncoder[] = []; // Draw the opaque objects const opaquePassEncoder: RenderPass = { diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index 3d5d2e6..a8a19bf 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -1,4 +1,4 @@ -import { BindingResources, CommandEncoder, IPassEncoder, reactive, Texture } from "@feng3d/render-api"; +import { BindingResources, CommandEncoder, PassEncoder, reactive, Texture } from "@feng3d/render-api"; import { ComputePipeline, getGBuffer } from "@feng3d/webgpu"; import Common from "./common"; @@ -136,7 +136,7 @@ export default class Radiosity ], }]; } - private passEncoders: IPassEncoder[]; + private passEncoders: PassEncoder[]; encode(commandEncoder: CommandEncoder) { diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index 193d74e..98f80e7 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -1,4 +1,4 @@ -import { BindingResources, CommandEncoder, IPassEncoder, Texture } from "@feng3d/render-api"; +import { BindingResources, CommandEncoder, PassEncoder, Texture } from "@feng3d/render-api"; import { ComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -67,7 +67,7 @@ export default class Raytracer }], }; } - private passEncoder: IPassEncoder; + private passEncoder: PassEncoder; encode(commandEncoder: CommandEncoder) { diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index 5124cf2..89be3cc 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -1,4 +1,4 @@ -import { BindingResources, CanvasTexture, CommandEncoder, IPassEncoder, Texture } from "@feng3d/render-api"; +import { BindingResources, CanvasTexture, CommandEncoder, PassEncoder, Texture } from "@feng3d/render-api"; import { ComputePipeline } from "@feng3d/webgpu"; import Common from "./common"; @@ -58,7 +58,7 @@ export default class Tonemapper }], }; } - private passEncoder: IPassEncoder; + private passEncoder: PassEncoder; encode(commandEncoder: CommandEncoder) { diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index 75ef515..af089cc 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -1,4 +1,4 @@ -import { BindingResources, CanvasContext, IPassEncoder, reactive, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, CanvasContext, PassEncoder, reactive, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import { mat3, mat4 } from "wgpu-matrix"; import { modelData } from "./models"; @@ -251,7 +251,7 @@ const init = async () => time *= 0.001; // convert to seconds; // make a command encoder to start encoding commands - const passEncoders: IPassEncoder[] = []; + const passEncoders: PassEncoder[] = []; visibleCanvasSet.forEach((canvas) => { diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 9857e74..8f48e1f 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -7,7 +7,7 @@ import gridWGSL from "./grid.wgsl"; import { gridIndices } from "./gridData"; import { createSkinnedGridBuffers, createSkinnedGridRenderPipeline } from "./gridUtils"; -import { BindingResources, IPassEncoder, reactive, RenderObject, RenderPass, RenderPassDescriptor, Texture } from "@feng3d/render-api"; +import { BindingResources, PassEncoder, reactive, RenderObject, RenderPass, RenderPassDescriptor, Texture } from "@feng3d/render-api"; import { getGBuffer, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -483,7 +483,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Node 6 should be the only node with a drawable mesh so hopefully this works fine whaleScene.skins[0].update(6, whaleScene.nodes); - const passEncoders: IPassEncoder[] = []; + const passEncoders: PassEncoder[] = []; if (settings.object === "Whale") { diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index 36c60e9..8014720 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -14,6 +14,9 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) const textureView = texture.createView(view); return textureView; + // texture["view"] = texture["view"] || texture.createView(); + + // return texture["view"]; } // -- Gitee From 9e6081ed58ba388848c4ba606519552a85438c2f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 15 Mar 2025 20:57:46 +0800 Subject: [PATCH 072/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=A4=96=E9=83=A8=E7=BA=B9=E7=90=86=E7=9A=84=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整了外部纹理绑定的判断逻辑,提高代码效率 - 修复了外部纹理与其他纹理类型的处理顺序问题 - 优化了代码结构,提高了可读性和可维护性 --- src/caches/getGPUBindGroup.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index a886191..08a8330 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -6,12 +6,12 @@ import { getRealGPUBindGroup } from "../const"; import { VideoTexture } from "../data/VideoTexture"; import { GPUTextureView_destroy, IGPUSampler_changed } from "../eventnames"; import { ExternalSampledTextureType } from "../types/TextureType"; +import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; +import { updateBufferBinding } from "../utils/updateBufferBinding"; import { getGPUBuffer } from "./getGPUBuffer"; import { getGPUSampler } from "./getGPUSampler"; import { getGPUTextureView } from "./getGPUTextureView"; import { getGBuffer } from "./getIGPUBuffer"; -import { updateBufferBinding } from "../utils/updateBufferBinding"; -import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) { @@ -72,7 +72,16 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup }; }; } - else if (resourceType === ResourceType.Texture) + else if (ExternalSampledTextureType[type.name]) // 判断是否为外部纹理 + { + updateResource = () => + { + entry.resource = device.importExternalTexture(bindingResources[name] as VideoTexture); + }; + + awaysUpdateFuncs.push(updateResource); + } + else if (resourceType === ResourceType.Texture || resourceType === ResourceType.StorageTexture) { updateResource = () => { @@ -86,15 +95,6 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup awaysUpdateFuncs.push(updateResource); } } - else if (ExternalSampledTextureType[type.name]) // 判断是否为外部纹理 - { - updateResource = () => - { - entry.resource = device.importExternalTexture(bindingResources[name] as VideoTexture); - }; - - awaysUpdateFuncs.push(updateResource); - } else { updateResource = () => -- Gitee From 2eaf81cd338853aabb73a565159b6489f2484d27 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 10:03:51 +0800 Subject: [PATCH 073/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E7=BB=B4=E5=BA=A6=E8=8E=B7=E5=8F=96=E5=92=8C?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E9=80=9A=E9=81=93=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 getGPUTextureDimension 函数移至 getGPUTexture.ts 文件中 - 更新相关文件中的导入路径和接口名称 - 删除单独的 getGPUTextureDimension.ts 文件 --- src/caches/getGPURenderPassFormat.ts | 6 +++--- src/caches/getGPUTexture.ts | 20 ++++++++++++++++++-- src/caches/getGPUTextureDimension.ts | 16 ---------------- src/caches/getNGPURenderPipeline.ts | 4 ++-- src/internal/RenderPassFormat.ts | 2 +- src/runs/RunWebGPU.ts | 16 ++++++++-------- src/runs/RunWebGPUCommandCache.ts | 8 ++++---- src/utils/readPixels.ts | 1 - 8 files changed, 36 insertions(+), 37 deletions(-) delete mode 100644 src/caches/getGPUTextureDimension.ts diff --git a/src/caches/getGPURenderPassFormat.ts b/src/caches/getGPURenderPassFormat.ts index f05e297..38e763e 100644 --- a/src/caches/getGPURenderPassFormat.ts +++ b/src/caches/getGPURenderPassFormat.ts @@ -1,6 +1,6 @@ import { RenderPassDescriptor } from "@feng3d/render-api"; import { getGPUTextureFormat } from "../caches/getGPUTextureFormat"; -import { IRenderPassFormat } from "../internal/RenderPassFormat"; +import { RenderPassFormat } from "../internal/RenderPassFormat"; /** * 获取渲染通道格式。 @@ -8,9 +8,9 @@ import { IRenderPassFormat } from "../internal/RenderPassFormat"; * @param descriptor 渲染通道描述。 * @returns */ -export function getGPURenderPassFormat(descriptor: RenderPassDescriptor): IRenderPassFormat +export function getGPURenderPassFormat(descriptor: RenderPassDescriptor): RenderPassFormat { - let gpuRenderPassFormat: IRenderPassFormat = descriptor[_RenderPassFormat]; + let gpuRenderPassFormat: RenderPassFormat = descriptor[_RenderPassFormat]; if (gpuRenderPassFormat) return gpuRenderPassFormat; const colorAttachmentTextureFormats = descriptor.colorAttachments.map((v) => getGPUTextureFormat(v.view.texture)); diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index f466f24..4a0322d 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,11 +1,10 @@ import { anyEmitter } from "@feng3d/event"; -import { CanvasTexture, Texture, TextureDataSource, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; +import { Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { generateMipmap } from "../utils/generate-mipmap"; import { getGPUCanvasContext } from "./getGPUCanvasContext"; -import { getGPUTextureDimension } from "./getGPUTextureDimension"; import { getTextureUsageFromFormat } from "./getTextureUsageFromFormat"; /** @@ -249,3 +248,20 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC let autoIndex = 0; const _GPUTextureMap = "_GPUTextureMap"; + + +function getGPUTextureDimension(dimension: TextureDimension) +{ + const textureDimension = dimensionMap[dimension]; + + return textureDimension; +} + +const dimensionMap: Record = { + "1d": "1d", + "2d": "2d", + "2d-array": "2d", + cube: "2d", + "cube-array": "3d", + "3d": "3d", +}; diff --git a/src/caches/getGPUTextureDimension.ts b/src/caches/getGPUTextureDimension.ts deleted file mode 100644 index 4f73e9e..0000000 --- a/src/caches/getGPUTextureDimension.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TextureDimension } from "@feng3d/render-api"; - -export function getGPUTextureDimension(dimension: TextureDimension) -{ - const textureDimension: GPUTextureDimension = dimensionMap[dimension]; - -return textureDimension; -} -const dimensionMap: { [key: string]: GPUTextureDimension } = { - "1d": "1d", - "2d": "2d", - "2d-array": "2d", - cube: "2d", - "cube-array": "3d", - "3d": "3d", -}; diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index f32da9a..d9b0d9c 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -4,7 +4,7 @@ import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; import { gPartial } from "@feng3d/polyfill"; import { MultisampleState } from "../data/MultisampleState"; -import { IRenderPassFormat } from "../internal/RenderPassFormat"; +import { RenderPassFormat } from "../internal/RenderPassFormat"; import { NFragmentState } from "../internal/NFragmentState"; import { NRenderPipeline } from "../internal/NRenderPipeline"; import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; @@ -20,7 +20,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPassFormat: IRenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) +export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const indexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; diff --git a/src/internal/RenderPassFormat.ts b/src/internal/RenderPassFormat.ts index 9a6da2f..d83157f 100644 --- a/src/internal/RenderPassFormat.ts +++ b/src/internal/RenderPassFormat.ts @@ -1,4 +1,4 @@ -export interface IRenderPassFormat +export interface RenderPassFormat { readonly attachmentSize: { readonly width: number, readonly height: number } readonly colorFormats: readonly GPUTextureFormat[], diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index c0f810f..f3661e1 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -22,7 +22,7 @@ import "../data/polyfills/RenderPass"; import { RenderBundle } from "../data/RenderBundle"; import { Workgroups } from "../data/Workgroups"; import { GPUQueue_submit } from "../eventnames"; -import { IRenderPassFormat } from "../internal/RenderPassFormat"; +import { RenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; export class RunWebGPU @@ -105,7 +105,7 @@ export class RunWebGPU timestampQuery.resolve(device, commandEncoder, renderPass); } - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects: readonly RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) + protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: readonly RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { if (!renderObjects) return; // @@ -207,7 +207,7 @@ export class RunWebGPU ); } - protected runRenderOcclusionQueryObject(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderOcclusionQueryObject: OcclusionQuery, occlusionQuery: GPURenderOcclusionQuery) + protected runRenderOcclusionQueryObject(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderOcclusionQueryObject: OcclusionQuery, occlusionQuery: GPURenderOcclusionQuery) { passEncoder.beginOcclusionQuery(occlusionQuery.getQueryIndex(renderOcclusionQueryObject)); @@ -219,7 +219,7 @@ export class RunWebGPU passEncoder.endOcclusionQuery(); } - protected runRenderBundle(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderBundleObject: RenderBundle) + protected runRenderBundle(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) { const renderBundleMap: ChainMap<[RenderBundle, string], GPURenderBundle> = device["_renderBundleMap"] = device["_renderBundleMap"] || new ChainMap(); // @@ -240,7 +240,7 @@ export class RunWebGPU passEncoder.executeBundles([gpuRenderBundle]); } - protected runRenderBundleObjects(device: GPUDevice, passEncoder: GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: readonly RenderObject[]) + protected runRenderBundleObjects(device: GPUDevice, passEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: readonly RenderObject[]) { // renderObjects.forEach((element) => @@ -295,7 +295,7 @@ export class RunWebGPU * @param renderObject 渲染对象。 * @param renderPass 渲染通道。 */ - protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, renderObject: RenderObject) + protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) { const { viewport, scissorRect, pipeline, bindingResources: bindingResources, geometry } = renderObject; @@ -330,7 +330,7 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { // const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); @@ -426,7 +426,7 @@ export class RunWebGPU }); } - protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const renderPipeline = getNGPURenderPipeline(material, renderPassFormat, primitive, vertices, indices); diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/runs/RunWebGPUCommandCache.ts index 87fd08c..cc1838c 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/runs/RunWebGPUCommandCache.ts @@ -3,7 +3,7 @@ import { RenderObject, RenderPassObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { GPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; import { getRealGPUBindGroup } from "../const"; -import { IRenderPassFormat } from "../internal/RenderPassFormat"; +import { RenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; import { RunWebGPU } from "./RunWebGPU"; @@ -12,7 +12,7 @@ import { RunWebGPU } from "./RunWebGPU"; */ export class RunWebGPUCommandCache extends RunWebGPU { - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: IRenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) + protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { const map: ChainMap<[string, RenderPassObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); let caches = map.get([renderPassFormat._key, renderObjects]); @@ -48,7 +48,7 @@ export class RunWebGPUCommandCache extends RunWebGPU runCommands(passEncoder, caches); } - protected runRenderBundleObjects(device: GPUDevice, bundleEncoder: GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, renderObjects?: RenderObject[]) + protected runRenderBundleObjects(device: GPUDevice, bundleEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: RenderObject[]) { const map: ChainMap<[string, RenderObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); let caches = map.get([renderPassFormat._key, renderObjects]); @@ -87,7 +87,7 @@ export class RunWebGPUCommandCache extends RunWebGPU runCommands(bundleEncoder, { ...caches, commands }); } - protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: IRenderPassFormat, renderObject: RenderObject) + protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) { const map: ChainMap<[string, RenderObject], Array> = device["_IGPURenderObjectCommandMap"] = device["_IGPURenderObjectCommandMap"] || new ChainMap(); const _commands = passEncoder["_commands"] as any[]; diff --git a/src/utils/readPixels.ts b/src/utils/readPixels.ts index 2f39e1a..4b84fec 100644 --- a/src/utils/readPixels.ts +++ b/src/utils/readPixels.ts @@ -1,5 +1,4 @@ import { Texture } from "@feng3d/render-api"; -import { getGPUTextureFormat } from "../caches/getGPUTextureFormat"; /** * 从 GPU纹理 上读取数据。 -- Gitee From 4cc08b4e9bfbd9e8df54417b6351890215441e0c Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 11:18:13 +0800 Subject: [PATCH 074/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E5=88=9D=E5=A7=8B=E5=8C=96=E5=92=8C=E7=BA=B9?= =?UTF-8?q?=E7=90=86=E5=B0=BA=E5=AF=B8=E8=8E=B7=E5=8F=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 WebGPU 初始化逻辑移至 RunWebGPU 类 - 重命名 getIGPUTextureLikeSize 为 getTextureSize - 更新相关引用和实现 - 优化纹理尺寸获取逻辑,支持更多场景 --- src/WebGPU.ts | 61 ++----------------- src/caches/getGPURenderPassDescriptor.ts | 6 +- ...etIGPUTextureSize.ts => getTextureSize.ts} | 2 +- src/internal.ts | 2 +- src/runs/RunWebGPU.ts | 50 +++++++++++++++ 5 files changed, 59 insertions(+), 62 deletions(-) rename src/caches/{getIGPUTextureSize.ts => getTextureSize.ts} (90%) diff --git a/src/WebGPU.ts b/src/WebGPU.ts index 5acfc6b..8114681 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,9 +1,8 @@ import { GBuffer, ReadPixels, Submit, TextureLike } from "@feng3d/render-api"; import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUTexture } from "./caches/getGPUTexture"; -import { getIGPUTextureLikeSize } from "./caches/getIGPUTextureSize"; +import { getTextureSize } from "./caches/getTextureSize"; import "./data/polyfills/ReadPixels"; -import { RunWebGPU } from "./runs/RunWebGPU"; import { RunWebGPUCommandCache } from "./runs/RunWebGPUCommandCache"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { quitIfWebGPUNotAvailable } from "./utils/quitIfWebGPUNotAvailable"; @@ -15,60 +14,8 @@ import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultipl * * 提供 `WebGPU` 操作入口 {@link WebGPU.submit}。 */ -export class WebGPU +export class WebGPU extends RunWebGPUCommandCache { - private _runWebGPU: RunWebGPU = new RunWebGPUCommandCache(); - // private _runWebGPU: RunWebGPU = new RunWebGPU(); - - /** - * 初始化 WebGPU 获取 GPUDevice 。 - */ - async init(options?: GPURequestAdapterOptions, descriptor?: GPUDeviceDescriptor) - { - const adapter = await navigator.gpu?.requestAdapter(options); - // 获取支持的特性 - const features: GPUFeatureName[] = []; - adapter?.features.forEach((v) => { features.push(v as any); }); - // 判断请求的特性是否被支持 - const requiredFeatures = Array.from(descriptor?.requiredFeatures || []); - if (requiredFeatures.length > 0) - { - for (let i = requiredFeatures.length - 1; i >= 0; i--) - { - if (features.indexOf(requiredFeatures[i]) === -1) - { - console.error(`当前 GPUAdapter 不支持特性 ${requiredFeatures[i]}!`); - requiredFeatures.splice(i, 1); - } - } - descriptor.requiredFeatures = requiredFeatures; - } - // 默认开启当前本机支持的所有WebGPU特性。 - descriptor = descriptor || {}; - descriptor.requiredFeatures = (descriptor.requiredFeatures || features) as any; - // - const device = await adapter?.requestDevice(descriptor); - quitIfWebGPUNotAvailable(adapter, device); - - device?.lost.then(async (info) => - { - console.error(`WebGPU device was lost: ${info.message}`); - - // 'reason' will be 'destroyed' if we intentionally destroy the device. - if (info.reason !== "destroyed") - { - // try again - await this.init(options, descriptor); - } - }); - - this.device = device; - - return this; - } - - public device: GPUDevice; - /** * 提交 GPU 。 * @@ -78,7 +25,7 @@ export class WebGPU */ submit(submit: Submit) { - this._runWebGPU.runSubmit(this.device, submit); + this.runSubmit(this.device, submit); } /** @@ -163,6 +110,6 @@ export class WebGPU getGPUTextureSize(input: TextureLike) { - return getIGPUTextureLikeSize(input); + return getTextureSize(input); } } diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index c135cdb..5754532 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -6,7 +6,7 @@ import { MultisampleTexture } from "../internal/MultisampleTexture"; import { NGPURenderPassColorAttachment } from "../internal/internal"; import { getGPUTextureFormat } from "./getGPUTextureFormat"; import { getGPUTextureView } from "./getGPUTextureView"; -import { getIGPUTextureLikeSize } from "./getIGPUTextureSize"; +import { getTextureSize } from "./getTextureSize"; /** * 获取GPU渲染通道描述。 @@ -239,7 +239,7 @@ function getMultisampleTextureView(texture: TextureLike, sampleCount: 4) if (!multisampleTextureView) { // 新增用于解决多重采样的纹理 - const size = getIGPUTextureLikeSize(texture); + const size = getTextureSize(texture); const format = getGPUTextureFormat(texture); const multisampleTexture: MultisampleTexture = { label: "自动生成多重采样的纹理", @@ -340,7 +340,7 @@ function updateAttachmentSize(renderPass: RenderPassDescriptor) const attachmentTextures = getAttachmentTextures(renderPass.colorAttachments, renderPass.depthStencilAttachment); if (!renderPass.attachmentSize) { - const textureSize = getIGPUTextureLikeSize(attachmentTextures[0]); + const textureSize = getTextureSize(attachmentTextures[0]); renderPass.attachmentSize = { width: textureSize[0], height: textureSize[1] }; } attachmentTextures.forEach((v) => setIGPUTextureSize(v, renderPass.attachmentSize)); diff --git a/src/caches/getIGPUTextureSize.ts b/src/caches/getTextureSize.ts similarity index 90% rename from src/caches/getIGPUTextureSize.ts rename to src/caches/getTextureSize.ts index f611282..99e1d62 100644 --- a/src/caches/getIGPUTextureSize.ts +++ b/src/caches/getTextureSize.ts @@ -6,7 +6,7 @@ import { TextureLike, TextureSize, TextureImageSource, CanvasTexture } from "@fe * @param texture 纹理。 * @returns 纹理尺寸。 */ -export function getIGPUTextureLikeSize(texture: TextureLike) +export function getTextureSize(texture: TextureLike) { if ("context" in texture) { diff --git a/src/internal.ts b/src/internal.ts index fdc8584..7dfab12 100644 --- a/src/internal.ts +++ b/src/internal.ts @@ -1,4 +1,4 @@ -export { getIGPUTextureLikeSize as getGPUTextureSize } from "./caches/getIGPUTextureSize"; +export { getTextureSize as getGPUTextureSize } from "./caches/getTextureSize"; export * from "./caches/getWGSLReflectInfo"; diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index f3661e1..f2dc6d6 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -24,9 +24,59 @@ import { Workgroups } from "../data/Workgroups"; import { GPUQueue_submit } from "../eventnames"; import { RenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; +import { quitIfWebGPUNotAvailable } from "../utils/quitIfWebGPUNotAvailable"; export class RunWebGPU { + /** + * 初始化 WebGPU 获取 GPUDevice 。 + */ + async init(options?: GPURequestAdapterOptions, descriptor?: GPUDeviceDescriptor) + { + const adapter = await navigator.gpu?.requestAdapter(options); + // 获取支持的特性 + const features: GPUFeatureName[] = []; + adapter?.features.forEach((v) => { features.push(v as any); }); + // 判断请求的特性是否被支持 + const requiredFeatures = Array.from(descriptor?.requiredFeatures || []); + if (requiredFeatures.length > 0) + { + for (let i = requiredFeatures.length - 1; i >= 0; i--) + { + if (features.indexOf(requiredFeatures[i]) === -1) + { + console.error(`当前 GPUAdapter 不支持特性 ${requiredFeatures[i]}!`); + requiredFeatures.splice(i, 1); + } + } + descriptor.requiredFeatures = requiredFeatures; + } + // 默认开启当前本机支持的所有WebGPU特性。 + descriptor = descriptor || {}; + descriptor.requiredFeatures = (descriptor.requiredFeatures || features) as any; + // + const device = await adapter?.requestDevice(descriptor); + quitIfWebGPUNotAvailable(adapter, device); + + device?.lost.then(async (info) => + { + console.error(`WebGPU device was lost: ${info.message}`); + + // 'reason' will be 'destroyed' if we intentionally destroy the device. + if (info.reason !== "destroyed") + { + // try again + await this.init(options, descriptor); + } + }); + + this.device = device; + + return this; + } + + public device: GPUDevice; + runSubmit(device: GPUDevice, submit: Submit) { const commandBuffers = submit.commandEncoders.map((v) => -- Gitee From 8162ffc5713fbd02b38dfafa5f2af7be4cd597a9 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 11:30:43 +0800 Subject: [PATCH 075/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E5=88=9D=E5=A7=8B=E5=8C=96=E5=92=8C=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 WebGPU 初始化逻辑移至 WebGPU 类的 init 方法中 - 优化了 GPU 设备请求和特性检测流程 - 调整了渲染逻辑,移除了冗余的计算和渲染方法 - 重构了绑定资源、顶点和索引处理的代码 - 简化了计算和渲染管道的设置过程 --- src/WebGPU.ts | 55 ++++++++++++- src/runs/RunWebGPU.ts | 174 +++++++++++------------------------------- 2 files changed, 96 insertions(+), 133 deletions(-) diff --git a/src/WebGPU.ts b/src/WebGPU.ts index 8114681..76c4d57 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -14,8 +14,59 @@ import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultipl * * 提供 `WebGPU` 操作入口 {@link WebGPU.submit}。 */ -export class WebGPU extends RunWebGPUCommandCache +export class WebGPU { + private _runWebGPU: RunWebGPUCommandCache; + /** + * 初始化 WebGPU 获取 GPUDevice 。 + */ + async init(options?: GPURequestAdapterOptions, descriptor?: GPUDeviceDescriptor) + { + const adapter = await navigator.gpu?.requestAdapter(options); + // 获取支持的特性 + const features: GPUFeatureName[] = []; + adapter?.features.forEach((v) => { features.push(v as any); }); + // 判断请求的特性是否被支持 + const requiredFeatures = Array.from(descriptor?.requiredFeatures || []); + if (requiredFeatures.length > 0) + { + for (let i = requiredFeatures.length - 1; i >= 0; i--) + { + if (features.indexOf(requiredFeatures[i]) === -1) + { + console.error(`当前 GPUAdapter 不支持特性 ${requiredFeatures[i]}!`); + requiredFeatures.splice(i, 1); + } + } + descriptor.requiredFeatures = requiredFeatures; + } + // 默认开启当前本机支持的所有WebGPU特性。 + descriptor = descriptor || {}; + descriptor.requiredFeatures = (descriptor.requiredFeatures || features) as any; + // + const device = await adapter?.requestDevice(descriptor); + quitIfWebGPUNotAvailable(adapter, device); + + device?.lost.then(async (info) => + { + console.error(`WebGPU device was lost: ${info.message}`); + + // 'reason' will be 'destroyed' if we intentionally destroy the device. + if (info.reason !== "destroyed") + { + // try again + await this.init(options, descriptor); + } + }); + + this.device = device; + this._runWebGPU = new RunWebGPUCommandCache(); + + return this; + } + + public device: GPUDevice; + /** * 提交 GPU 。 * @@ -25,7 +76,7 @@ export class WebGPU extends RunWebGPUCommandCache */ submit(submit: Submit) { - this.runSubmit(this.device, submit); + this._runWebGPU.runSubmit(this.device, submit); } /** diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index f2dc6d6..88e6ee4 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DrawIndexed, DrawVertex, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -16,66 +16,15 @@ import { getNGPURenderPipeline } from "../caches/getNGPURenderPipeline"; import { getRealGPUBindGroup } from "../const"; import { ComputeObject } from "../data/ComputeObject"; import { ComputePass } from "../data/ComputePass"; -import { ComputePipeline } from "../data/ComputePipeline"; import "../data/polyfills/RenderObject"; import "../data/polyfills/RenderPass"; import { RenderBundle } from "../data/RenderBundle"; -import { Workgroups } from "../data/Workgroups"; import { GPUQueue_submit } from "../eventnames"; import { RenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; -import { quitIfWebGPUNotAvailable } from "../utils/quitIfWebGPUNotAvailable"; export class RunWebGPU { - /** - * 初始化 WebGPU 获取 GPUDevice 。 - */ - async init(options?: GPURequestAdapterOptions, descriptor?: GPUDeviceDescriptor) - { - const adapter = await navigator.gpu?.requestAdapter(options); - // 获取支持的特性 - const features: GPUFeatureName[] = []; - adapter?.features.forEach((v) => { features.push(v as any); }); - // 判断请求的特性是否被支持 - const requiredFeatures = Array.from(descriptor?.requiredFeatures || []); - if (requiredFeatures.length > 0) - { - for (let i = requiredFeatures.length - 1; i >= 0; i--) - { - if (features.indexOf(requiredFeatures[i]) === -1) - { - console.error(`当前 GPUAdapter 不支持特性 ${requiredFeatures[i]}!`); - requiredFeatures.splice(i, 1); - } - } - descriptor.requiredFeatures = requiredFeatures; - } - // 默认开启当前本机支持的所有WebGPU特性。 - descriptor = descriptor || {}; - descriptor.requiredFeatures = (descriptor.requiredFeatures || features) as any; - // - const device = await adapter?.requestDevice(descriptor); - quitIfWebGPUNotAvailable(adapter, device); - - device?.lost.then(async (info) => - { - console.error(`WebGPU device was lost: ${info.message}`); - - // 'reason' will be 'destroyed' if we intentionally destroy the device. - if (info.reason !== "destroyed") - { - // try again - await this.init(options, descriptor); - } - }); - - this.device = device; - - return this; - } - - public device: GPUDevice; runSubmit(device: GPUDevice, submit: Submit) { @@ -308,33 +257,22 @@ export class RunWebGPU */ protected runComputeObject(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObject: ComputeObject) { - const { pipeline: material, uniforms: bindingResources, workgroups } = computeObject; - - const shader: IGPUShader = { compute: material.compute.code }; - - this.runComputePipeline(device, passEncoder, material); + const { pipeline: pipeline, uniforms: bindingResources, workgroups } = computeObject; - this.runBindingResources(device, passEncoder, shader, bindingResources); + const shader: IGPUShader = { compute: pipeline.compute.code }; - this.runWorkgroups(passEncoder, workgroups); - } - - protected runComputePipeline(device: GPUDevice, passEncoder: GPUComputePassEncoder, pipeline: ComputePipeline) - { const computePipeline = getGPUComputePipeline(device, pipeline); passEncoder.setPipeline(computePipeline); - } - /** - * 执行计算工作组。 - * - * @param passEncoder 计算通道编码器。 - * @param workgroups 计算工作组。 - */ - protected runWorkgroups(passEncoder: GPUComputePassEncoder, workgroups?: Workgroups) - { - const { workgroupCountX, workgroupCountY, workgroupCountZ } = workgroups; - passEncoder.dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ); + // 计算 bindGroups + const layout = getGPUPipelineLayout(device, shader); + layout.bindGroupLayouts.forEach((bindGroupLayout, group) => + { + const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); + passEncoder.setBindGroup(group, gpuBindGroup); + }); + + passEncoder.dispatchWorkgroups(workgroups.workgroupCountX, workgroups.workgroupCountY, workgroups.workgroupCountZ); } /** @@ -364,19 +302,45 @@ export class RunWebGPU this.runRenderPipeline(device, passEncoder, renderPassFormat, pipeline, primitive, vertices, indices); - this.runBindingResources(device, passEncoder, shader, bindingResources); + // 计算 bindGroups + const layout = getGPUPipelineLayout(device, shader); + layout.bindGroupLayouts.forEach((bindGroupLayout, group) => + { + const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); + passEncoder.setBindGroup(group, gpuBindGroup); + }); + + const renderPipeline = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); - this.runVertices(device, passEncoder, renderPassFormat, pipeline, primitive, vertices, indices); + // + renderPipeline.vertexBuffers?.forEach((vertexBuffer, index) => + { + const buffer = getGBuffer(vertexBuffer.data); + (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); - this.runIndices(device, passEncoder, indices); + const gBuffer = getGPUBuffer(device, buffer); + + passEncoder.setVertexBuffer(index, gBuffer, vertexBuffer.offset, vertexBuffer.size); + }); + + if (indices) + { + const buffer = getGBuffer(indices); + (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); + + const gBuffer = getGPUBuffer(device, buffer); + + // + passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); + } if (draw.__type__ === 'DrawVertex') { - this.runDrawVertex(passEncoder, draw); + passEncoder.draw(draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance); } else { - this.runDrawIndexed(passEncoder, draw); + passEncoder.drawIndexed(draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance); } } @@ -464,58 +428,6 @@ export class RunWebGPU passEncoder.setScissorRect(0, 0, attachmentSize.width, attachmentSize.height); } } - - protected runBindingResources(device: GPUDevice, passEncoder: GPUBindingCommandsMixin, shader: IGPUShader, bindingResources: BindingResources) - { - // 计算 bindGroups - const layout = getGPUPipelineLayout(device, shader); - layout.bindGroupLayouts.forEach((bindGroupLayout, group) => - { - const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); - passEncoder.setBindGroup(group, gpuBindGroup); - }); - } - - protected runVertices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, material: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) - { - const renderPipeline = getNGPURenderPipeline(material, renderPassFormat, primitive, vertices, indices); - - // - renderPipeline.vertexBuffers?.forEach((vertexBuffer, index) => - { - const buffer = getGBuffer(vertexBuffer.data); - (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); - - const gBuffer = getGPUBuffer(device, buffer); - - passEncoder.setVertexBuffer(index, gBuffer, vertexBuffer.offset, vertexBuffer.size); - }); - } - - protected runIndices(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, indices: IIndicesDataTypes) - { - if (!indices) return; - - const buffer = getGBuffer(indices); - (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); - - const gBuffer = getGPUBuffer(device, buffer); - - // - passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); - } - - protected runDrawVertex(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, drawVertex: DrawVertex) - { - // - passEncoder.draw(drawVertex.vertexCount, drawVertex.instanceCount, drawVertex.firstVertex, drawVertex.firstInstance); - } - - protected runDrawIndexed(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, drawIndexed: DrawIndexed) - { - // - passEncoder.drawIndexed(drawIndexed.indexCount, drawIndexed.instanceCount, drawIndexed.firstIndex, drawIndexed.baseVertex, drawIndexed.firstInstance); - } } let autoIndex = 0; -- Gitee From a91a2cdc873efa4e4129bf748230d7b5c37c9a4e Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 12:07:35 +0800 Subject: [PATCH 076/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 WebGPU 类中的冗余代码和不必要的导入 - 将 GPU 相关的操作移至 RunWebGPU 类中 - 优化 WebGPU 类的结构,提高代码可维护性 --- src/WebGPU.ts | 81 ++++++++++----------------------------- src/runs/RunWebGPU.ts | 52 ++++++++++++++++++++++++- src/utils/getGPUDevice.ts | 31 +++++++++++++++ 3 files changed, 102 insertions(+), 62 deletions(-) create mode 100644 src/utils/getGPUDevice.ts diff --git a/src/WebGPU.ts b/src/WebGPU.ts index 76c4d57..2e00391 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,13 +1,8 @@ import { GBuffer, ReadPixels, Submit, TextureLike } from "@feng3d/render-api"; -import { getGPUBuffer } from "./caches/getGPUBuffer"; -import { getGPUTexture } from "./caches/getGPUTexture"; import { getTextureSize } from "./caches/getTextureSize"; import "./data/polyfills/ReadPixels"; import { RunWebGPUCommandCache } from "./runs/RunWebGPUCommandCache"; -import { copyDepthTexture } from "./utils/copyDepthTexture"; -import { quitIfWebGPUNotAvailable } from "./utils/quitIfWebGPUNotAvailable"; -import { readPixels } from "./utils/readPixels"; -import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; +import { getGPUDevice } from "./utils/getGPUDevice"; /** * WebGPU 对象。 @@ -17,37 +12,15 @@ import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultipl export class WebGPU { private _runWebGPU: RunWebGPUCommandCache; + /** * 初始化 WebGPU 获取 GPUDevice 。 */ async init(options?: GPURequestAdapterOptions, descriptor?: GPUDeviceDescriptor) { - const adapter = await navigator.gpu?.requestAdapter(options); - // 获取支持的特性 - const features: GPUFeatureName[] = []; - adapter?.features.forEach((v) => { features.push(v as any); }); - // 判断请求的特性是否被支持 - const requiredFeatures = Array.from(descriptor?.requiredFeatures || []); - if (requiredFeatures.length > 0) - { - for (let i = requiredFeatures.length - 1; i >= 0; i--) - { - if (features.indexOf(requiredFeatures[i]) === -1) - { - console.error(`当前 GPUAdapter 不支持特性 ${requiredFeatures[i]}!`); - requiredFeatures.splice(i, 1); - } - } - descriptor.requiredFeatures = requiredFeatures; - } - // 默认开启当前本机支持的所有WebGPU特性。 - descriptor = descriptor || {}; - descriptor.requiredFeatures = (descriptor.requiredFeatures || features) as any; + this.device = await getGPUDevice(options, descriptor); // - const device = await adapter?.requestDevice(descriptor); - quitIfWebGPUNotAvailable(adapter, device); - - device?.lost.then(async (info) => + this.device?.lost.then(async (info) => { console.error(`WebGPU device was lost: ${info.message}`); @@ -55,17 +28,24 @@ export class WebGPU if (info.reason !== "destroyed") { // try again - await this.init(options, descriptor); + this.device = await getGPUDevice(options, descriptor); } }); - this.device = device; - this._runWebGPU = new RunWebGPUCommandCache(); - return this; } - public device: GPUDevice; + get device() + { + return this._device; + } + set device(v) + { + this._device = v; + this._runWebGPU = new RunWebGPUCommandCache(); + } + + public _device: GPUDevice; /** * 提交 GPU 。 @@ -86,7 +66,7 @@ export class WebGPU */ destoryTexture(texture: TextureLike) { - getGPUTexture(this.device, texture, false)?.destroy(); + this._runWebGPU.destoryTexture(this.device, texture); } /** @@ -98,9 +78,7 @@ export class WebGPU */ textureInvertYPremultiplyAlpha(texture: TextureLike, options: { invertY?: boolean, premultiplyAlpha?: boolean }) { - const gpuTexture = getGPUTexture(this.device, texture); - - textureInvertYPremultiplyAlpha(this.device, gpuTexture, options); + this._runWebGPU.textureInvertYPremultiplyAlpha(this.device, texture, options); } /** @@ -112,10 +90,7 @@ export class WebGPU */ copyDepthTexture(sourceTexture: TextureLike, targetTexture: TextureLike) { - const gpuSourceTexture = getGPUTexture(this.device, sourceTexture); - const gpuTargetTexture = getGPUTexture(this.device, targetTexture); - - copyDepthTexture(this.device, gpuSourceTexture, gpuTargetTexture); + this._runWebGPU.copyDepthTexture(this.device, sourceTexture, targetTexture); } /** @@ -127,15 +102,7 @@ export class WebGPU */ async readPixels(gpuReadPixels: ReadPixels) { - const gpuTexture = getGPUTexture(this.device, gpuReadPixels.texture, false); - - const result = await readPixels(this.device, { - ...gpuReadPixels, - texture: gpuTexture, - }); - - gpuReadPixels.result = result; - + const result = await this._runWebGPU.readPixels(this.device, gpuReadPixels); return result; } @@ -149,13 +116,7 @@ export class WebGPU */ async readBuffer(buffer: GBuffer, offset?: GPUSize64, size?: GPUSize64) { - const gpuBuffer = getGPUBuffer(this.device, buffer); - await gpuBuffer.mapAsync(GPUMapMode.READ); - - const result = gpuBuffer.getMappedRange(offset, size).slice(0); - - gpuBuffer.unmap(); - + const result = await this._runWebGPU.readBuffer(this.device, buffer, offset, size); return result; } diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 88e6ee4..92379c1 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, TextureLike, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "../caches/getGPUBindGroup"; import { getGPUBuffer } from "../caches/getGPUBuffer"; @@ -22,10 +22,12 @@ import { RenderBundle } from "../data/RenderBundle"; import { GPUQueue_submit } from "../eventnames"; import { RenderPassFormat } from "../internal/RenderPassFormat"; import { ChainMap } from "../utils/ChainMap"; +import { copyDepthTexture } from "../utils/copyDepthTexture"; +import { readPixels } from "../utils/readPixels"; +import { textureInvertYPremultiplyAlpha } from "../utils/textureInvertYPremultiplyAlpha"; export class RunWebGPU { - runSubmit(device: GPUDevice, submit: Submit) { const commandBuffers = submit.commandEncoders.map((v) => @@ -41,6 +43,52 @@ export class RunWebGPU anyEmitter.emit(device.queue, GPUQueue_submit); } + destoryTexture(device: GPUDevice, texture: TextureLike) + { + getGPUTexture(device, texture, false)?.destroy(); + } + + textureInvertYPremultiplyAlpha(device: GPUDevice, texture: TextureLike, options: { invertY?: boolean, premultiplyAlpha?: boolean }) + { + const gpuTexture = getGPUTexture(device, texture); + + textureInvertYPremultiplyAlpha(device, gpuTexture, options); + } + + copyDepthTexture(device: GPUDevice, sourceTexture: TextureLike, targetTexture: TextureLike) + { + const gpuSourceTexture = getGPUTexture(device, sourceTexture); + const gpuTargetTexture = getGPUTexture(device, targetTexture); + + copyDepthTexture(device, gpuSourceTexture, gpuTargetTexture); + } + + async readPixels(device: GPUDevice, gpuReadPixels: ReadPixels) + { + const gpuTexture = getGPUTexture(device, gpuReadPixels.texture, false); + + const result = await readPixels(device, { + ...gpuReadPixels, + texture: gpuTexture, + }); + + gpuReadPixels.result = result; + + return result; + } + + async readBuffer(device: GPUDevice, buffer: GBuffer, offset?: GPUSize64, size?: GPUSize64) + { + const gpuBuffer = getGPUBuffer(device, buffer); + await gpuBuffer.mapAsync(GPUMapMode.READ); + + const result = gpuBuffer.getMappedRange(offset, size).slice(0); + + gpuBuffer.unmap(); + + return result; + } + protected runCommandEncoder(device: GPUDevice, commandEncoder: CommandEncoder) { const gpuCommandEncoder = device.createCommandEncoder(); diff --git a/src/utils/getGPUDevice.ts b/src/utils/getGPUDevice.ts new file mode 100644 index 0000000..9be65a2 --- /dev/null +++ b/src/utils/getGPUDevice.ts @@ -0,0 +1,31 @@ +import { quitIfWebGPUNotAvailable } from "./quitIfWebGPUNotAvailable"; + +export async function getGPUDevice(options?: GPURequestAdapterOptions, descriptor?: GPUDeviceDescriptor) +{ + const adapter = await navigator.gpu?.requestAdapter(options); + // 获取支持的特性 + const features: GPUFeatureName[] = []; + adapter?.features.forEach((v) => { features.push(v as any); }); + // 判断请求的特性是否被支持 + const requiredFeatures = Array.from(descriptor?.requiredFeatures || []); + if (requiredFeatures.length > 0) + { + for (let i = requiredFeatures.length - 1; i >= 0; i--) + { + if (features.indexOf(requiredFeatures[i]) === -1) + { + console.error(`当前 GPUAdapter 不支持特性 ${requiredFeatures[i]}!`); + requiredFeatures.splice(i, 1); + } + } + descriptor.requiredFeatures = requiredFeatures; + } + // 默认开启当前本机支持的所有WebGPU特性。 + descriptor = descriptor || {}; + descriptor.requiredFeatures = (descriptor.requiredFeatures || features) as any; + // + const device = await adapter?.requestDevice(descriptor); + quitIfWebGPUNotAvailable(adapter, device); + + return device; +} \ No newline at end of file -- Gitee From 939e5887f47ba8a215638fcb192d679aec227e9f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 12:17:34 +0800 Subject: [PATCH 077/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 GPU 设备传递给 RunWebGPUCommandCache 实例 - 简化 WebGPU 类中的方法调用 - 更新 RunWebGPU 类,使其使用类属性中的 GPU 设备 - 调整相关文件的导入顺序和内容 --- src/WebGPU.ts | 14 +++++++------- src/caches/getTextureSize.ts | 2 +- src/index.ts | 2 -- src/internal.ts | 4 ---- src/runs/RunWebGPU.ts | 25 ++++++++++++++++++------- 5 files changed, 26 insertions(+), 21 deletions(-) delete mode 100644 src/internal.ts diff --git a/src/WebGPU.ts b/src/WebGPU.ts index 2e00391..c11bc1e 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -42,7 +42,7 @@ export class WebGPU set device(v) { this._device = v; - this._runWebGPU = new RunWebGPUCommandCache(); + this._runWebGPU = new RunWebGPUCommandCache(this._device); } public _device: GPUDevice; @@ -56,7 +56,7 @@ export class WebGPU */ submit(submit: Submit) { - this._runWebGPU.runSubmit(this.device, submit); + this._runWebGPU.runSubmit(submit); } /** @@ -66,7 +66,7 @@ export class WebGPU */ destoryTexture(texture: TextureLike) { - this._runWebGPU.destoryTexture(this.device, texture); + this._runWebGPU.destoryTexture(texture); } /** @@ -78,7 +78,7 @@ export class WebGPU */ textureInvertYPremultiplyAlpha(texture: TextureLike, options: { invertY?: boolean, premultiplyAlpha?: boolean }) { - this._runWebGPU.textureInvertYPremultiplyAlpha(this.device, texture, options); + this._runWebGPU.textureInvertYPremultiplyAlpha(texture, options); } /** @@ -90,7 +90,7 @@ export class WebGPU */ copyDepthTexture(sourceTexture: TextureLike, targetTexture: TextureLike) { - this._runWebGPU.copyDepthTexture(this.device, sourceTexture, targetTexture); + this._runWebGPU.copyDepthTexture(sourceTexture, targetTexture); } /** @@ -102,7 +102,7 @@ export class WebGPU */ async readPixels(gpuReadPixels: ReadPixels) { - const result = await this._runWebGPU.readPixels(this.device, gpuReadPixels); + const result = await this._runWebGPU.readPixels(gpuReadPixels); return result; } @@ -116,7 +116,7 @@ export class WebGPU */ async readBuffer(buffer: GBuffer, offset?: GPUSize64, size?: GPUSize64) { - const result = await this._runWebGPU.readBuffer(this.device, buffer, offset, size); + const result = await this._runWebGPU.readBuffer(buffer, offset, size); return result; } diff --git a/src/caches/getTextureSize.ts b/src/caches/getTextureSize.ts index 99e1d62..2e5d875 100644 --- a/src/caches/getTextureSize.ts +++ b/src/caches/getTextureSize.ts @@ -1,4 +1,4 @@ -import { TextureLike, TextureSize, TextureImageSource, CanvasTexture } from "@feng3d/render-api"; +import { CanvasTexture, TextureLike, TextureSize } from "@feng3d/render-api"; /** * 获取纹理尺寸。 diff --git a/src/index.ts b/src/index.ts index 5efb4ec..50c2105 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,7 +27,5 @@ export * from "./types/VertexFormat"; /** * 内部 */ -export * as internal from "./internal"; export * from "./utils/ChainMap"; export * from "./utils/getOffscreenCanvasId"; - diff --git a/src/internal.ts b/src/internal.ts deleted file mode 100644 index 7dfab12..0000000 --- a/src/internal.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { getTextureSize as getGPUTextureSize } from "./caches/getTextureSize"; - -export * from "./caches/getWGSLReflectInfo"; - diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 92379c1..7ee07c9 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -28,8 +28,15 @@ import { textureInvertYPremultiplyAlpha } from "../utils/textureInvertYPremultip export class RunWebGPU { - runSubmit(device: GPUDevice, submit: Submit) + constructor(private readonly _device: GPUDevice) { + + } + + runSubmit(submit: Submit) + { + const device = this._device; + const commandBuffers = submit.commandEncoders.map((v) => { const commandBuffer = this.runCommandEncoder(device, v); @@ -43,28 +50,31 @@ export class RunWebGPU anyEmitter.emit(device.queue, GPUQueue_submit); } - destoryTexture(device: GPUDevice, texture: TextureLike) + destoryTexture(texture: TextureLike) { - getGPUTexture(device, texture, false)?.destroy(); + getGPUTexture(this._device, texture, false)?.destroy(); } - textureInvertYPremultiplyAlpha(device: GPUDevice, texture: TextureLike, options: { invertY?: boolean, premultiplyAlpha?: boolean }) + textureInvertYPremultiplyAlpha(texture: TextureLike, options: { invertY?: boolean, premultiplyAlpha?: boolean }) { + const device = this._device; const gpuTexture = getGPUTexture(device, texture); textureInvertYPremultiplyAlpha(device, gpuTexture, options); } - copyDepthTexture(device: GPUDevice, sourceTexture: TextureLike, targetTexture: TextureLike) + copyDepthTexture(sourceTexture: TextureLike, targetTexture: TextureLike) { + const device = this._device; const gpuSourceTexture = getGPUTexture(device, sourceTexture); const gpuTargetTexture = getGPUTexture(device, targetTexture); copyDepthTexture(device, gpuSourceTexture, gpuTargetTexture); } - async readPixels(device: GPUDevice, gpuReadPixels: ReadPixels) + async readPixels(gpuReadPixels: ReadPixels) { + const device = this._device; const gpuTexture = getGPUTexture(device, gpuReadPixels.texture, false); const result = await readPixels(device, { @@ -77,8 +87,9 @@ export class RunWebGPU return result; } - async readBuffer(device: GPUDevice, buffer: GBuffer, offset?: GPUSize64, size?: GPUSize64) + async readBuffer(buffer: GBuffer, offset?: GPUSize64, size?: GPUSize64) { + const device = this._device; const gpuBuffer = getGPUBuffer(device, buffer); await gpuBuffer.mapAsync(GPUMapMode.READ); -- Gitee From 1fbbf99e69df144aa6879f463dad7fe68f506fb9 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 13:23:38 +0800 Subject: [PATCH 078/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=94=BB=E5=B8=83=E4=B8=8A=E4=B8=8B=E6=96=87=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=92=8C=20OffscreenCanvas=20=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 getOffscreenCanvasId 函数,改为直接使用 OffscreenCanvas 实例 - 更新 CanvasContext 类型,支持 string 和 OffscreenCanvas 类型的 canvasId - 修改 getGPUCanvasContext、getGPURenderPassDescriptor 和 getTextureSize 函数,以支持新的 canvasId 类型 - 优化这些函数中的 canvas 查找逻辑,提高性能 --- examples/src/webgpu/worker/worker.ts | 4 ++-- src/caches/getGPUCanvasContext.ts | 11 +++++------ src/caches/getGPURenderPassDescriptor.ts | 8 ++++---- src/caches/getTextureSize.ts | 2 +- src/index.ts | 1 - src/utils/getOffscreenCanvasId.ts | 19 ------------------- 6 files changed, 12 insertions(+), 33 deletions(-) delete mode 100644 src/utils/getOffscreenCanvasId.ts diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 2d19f2d..b478041 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -1,7 +1,7 @@ import { mat4, vec3 } from "wgpu-matrix"; import { CanvasContext, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; -import { getOffscreenCanvasId, WebGPU } from "@feng3d/webgpu"; +import { WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -70,7 +70,7 @@ self.addEventListener("message", (ev) => async function init(canvas: OffscreenCanvas) { const webgpu = await new WebGPU().init(); - const context: CanvasContext = { canvasId: getOffscreenCanvasId(canvas) }; + const context: CanvasContext = { canvasId: canvas }; // Create a vertex buffer from the cube data. const verticesBuffer: VertexAttributes = { diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index b472aff..79d64f0 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -4,13 +4,12 @@ import "../data/polyfills/CanvasContext"; export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) { - let result = canvasContextMap[context.canvasId]; + let result = canvasContextMap.get(context); if (result) return result.value; - const canvas = document.getElementById(context.canvasId) as HTMLCanvasElement; - - const gpuCanvasContext = canvas.getContext("webgpu"); + const canvas = typeof context.canvasId === "string" ? document.getElementById(context.canvasId) as HTMLCanvasElement : context.canvasId; + const gpuCanvasContext = canvas.getContext("webgpu") as GPUCanvasContext; const ro = reactive(context); result = computed(() => { @@ -32,7 +31,7 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) return gpuCanvasContext; }); - canvasContextMap[context.canvasId] = result; + canvasContextMap.set(context, result); const updateConfigure = () => { @@ -61,4 +60,4 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) return result.value; } -const canvasContextMap: { [canvasId: string]: ComputedRef } = {}; +const canvasContextMap = new WeakMap>();; diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 5754532..d723507 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -160,7 +160,7 @@ function getAttachmentTextures(colorAttachments: readonly RenderPassColorAttachm function setIGPURenderPassAttachmentSize(colorAttachments: NGPURenderPassColorAttachment[], depthStencilAttachment: RenderPassDepthStencilAttachment, attachmentSize: { width: number; height: number; }) { const attachmentTextures = getIGPURenderPassAttachmentTextures(colorAttachments, depthStencilAttachment); - attachmentTextures.forEach((v) => setIGPUTextureSize(v, attachmentSize)); + attachmentTextures.forEach((v) => setTextureSize(v, attachmentSize)); } /** @@ -169,12 +169,12 @@ function setIGPURenderPassAttachmentSize(colorAttachments: NGPURenderPassColorAt * @param texture 纹理描述。 * @param attachmentSize 附件尺寸。 */ -function setIGPUTextureSize(texture: TextureLike, attachmentSize: { width: number, height: number }) +function setTextureSize(texture: TextureLike, attachmentSize: { width: number, height: number }) { if ("context" in texture) { texture = texture as CanvasTexture; - const element = document.getElementById(texture.context.canvasId) as HTMLCanvasElement; + const element = typeof texture.context.canvasId === "string" ? document.getElementById(texture.context.canvasId) as HTMLCanvasElement : texture.context.canvasId; if (element.width !== attachmentSize.width) element.width = attachmentSize.width; if (element.height !== attachmentSize.height) element.height = attachmentSize.height; } @@ -343,6 +343,6 @@ function updateAttachmentSize(renderPass: RenderPassDescriptor) const textureSize = getTextureSize(attachmentTextures[0]); renderPass.attachmentSize = { width: textureSize[0], height: textureSize[1] }; } - attachmentTextures.forEach((v) => setIGPUTextureSize(v, renderPass.attachmentSize)); + attachmentTextures.forEach((v) => setTextureSize(v, renderPass.attachmentSize)); } diff --git a/src/caches/getTextureSize.ts b/src/caches/getTextureSize.ts index 2e5d875..dc232ca 100644 --- a/src/caches/getTextureSize.ts +++ b/src/caches/getTextureSize.ts @@ -10,7 +10,7 @@ export function getTextureSize(texture: TextureLike) { if ("context" in texture) { - const element = document.getElementById(texture.context.canvasId) as HTMLCanvasElement; + const element = typeof texture.context.canvasId === "string"? document.getElementById(texture.context.canvasId) as HTMLCanvasElement : texture.context.canvasId; console.assert(!!element, `在 document 上没有找到 canvasId 为 ${(texture as CanvasTexture).context.canvasId} 的画布。`); return [element.width, element.height, 1] as TextureSize; diff --git a/src/index.ts b/src/index.ts index 50c2105..9ae38df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,4 +28,3 @@ export * from "./types/VertexFormat"; * 内部 */ export * from "./utils/ChainMap"; -export * from "./utils/getOffscreenCanvasId"; diff --git a/src/utils/getOffscreenCanvasId.ts b/src/utils/getOffscreenCanvasId.ts deleted file mode 100644 index 186a288..0000000 --- a/src/utils/getOffscreenCanvasId.ts +++ /dev/null @@ -1,19 +0,0 @@ -export function getOffscreenCanvasId(canvas: OffscreenCanvas) -{ - const id = canvas["id"] = canvas["id"] || (`OffscreenCanvas_${OffscreenCanvasAutoId++}`); - OffscreenCanvasMap[id] = canvas; - - return id; -} -let OffscreenCanvasAutoId = 0; - -const OffscreenCanvasMap = {}; - -if (!globalThis.document) -{ - globalThis.document = {} as any; -} -if (!globalThis.document.getElementById) -{ - globalThis.document.getElementById = (elementId: string) => OffscreenCanvasMap[elementId]; -} \ No newline at end of file -- Gitee From fb43c6b69b700c3617cce266292b987e5eec984b Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 14:07:42 +0800 Subject: [PATCH 079/214] =?UTF-8?q?refactor(src/runs):=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20WebGPU=20=E8=BF=90=E8=A1=8C=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=AD=BE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 device 参数从函数签名中移除,改为在类中使用 this._device - 优化部分函数名称,移除冗余的 'run' 前缀 - 调整参数顺序,将 passEncoder 类型参数放在前面 - 修复部分函数体内的参数引用 --- src/runs/RunWebGPU.ts | 78 ++++++++++++++++++------------- src/runs/RunWebGPUCommandCache.ts | 20 +++++--- 2 files changed, 59 insertions(+), 39 deletions(-) diff --git a/src/runs/RunWebGPU.ts b/src/runs/RunWebGPU.ts index 7ee07c9..a7c4e7e 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/runs/RunWebGPU.ts @@ -28,7 +28,7 @@ import { textureInvertYPremultiplyAlpha } from "../utils/textureInvertYPremultip export class RunWebGPU { - constructor(private readonly _device: GPUDevice) + constructor(protected readonly _device: GPUDevice) { } @@ -39,7 +39,7 @@ export class RunWebGPU const commandBuffers = submit.commandEncoders.map((v) => { - const commandBuffer = this.runCommandEncoder(device, v); + const commandBuffer = this.runCommandEncoder(v); return commandBuffer; }); @@ -100,31 +100,32 @@ export class RunWebGPU return result; } - protected runCommandEncoder(device: GPUDevice, commandEncoder: CommandEncoder) + protected runCommandEncoder(commandEncoder: CommandEncoder) { + const device = this._device; const gpuCommandEncoder = device.createCommandEncoder(); commandEncoder.passEncoders.forEach((passEncoder) => { if (!passEncoder.__type__) { - this.runRenderPass(device, gpuCommandEncoder, passEncoder as RenderPass); + this.runRenderPass(gpuCommandEncoder, passEncoder as RenderPass); } else if (passEncoder.__type__ === "RenderPass") { - this.runRenderPass(device, gpuCommandEncoder, passEncoder); + this.runRenderPass(gpuCommandEncoder, passEncoder); } else if (passEncoder.__type__ === "ComputePass") { - this.runComputePass(device, gpuCommandEncoder, passEncoder); + this.runComputePass(gpuCommandEncoder, passEncoder); } else if (passEncoder.__type__ === "CopyTextureToTexture") { - this.runCopyTextureToTexture(device, gpuCommandEncoder, passEncoder); + this.runCopyTextureToTexture(gpuCommandEncoder, passEncoder); } else if (passEncoder.__type__ === "CopyBufferToBuffer") { - this.runCopyBufferToBuffer(device, gpuCommandEncoder, passEncoder); + this.runCopyBufferToBuffer(gpuCommandEncoder, passEncoder); } else { @@ -135,8 +136,9 @@ export class RunWebGPU return gpuCommandEncoder.finish(); } - protected runRenderPass(device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass) + protected runRenderPass(commandEncoder: GPUCommandEncoder, renderPass: RenderPass) { + const device = this._device; const { descriptor, renderObjects } = renderPass; const renderPassDescriptor = getGPURenderPassDescriptor(device, descriptor); @@ -152,7 +154,7 @@ export class RunWebGPU const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); - this.runRenderPassObjects(device, passEncoder, renderPassFormat, renderObjects, occlusionQuery); + this.runRenderPassObjects(passEncoder, renderPassFormat, renderObjects, occlusionQuery); passEncoder.end(); @@ -163,27 +165,27 @@ export class RunWebGPU timestampQuery.resolve(device, commandEncoder, renderPass); } - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: readonly RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) + protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderPassObjects: readonly RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { - if (!renderObjects) return; + if (!renderPassObjects) return; // - renderObjects.forEach((element) => + renderPassObjects.forEach((element) => { if (!element.__type__) { - this.runRenderObject(device, passEncoder, renderPassFormat, element as RenderObject); + this.runRenderObject(passEncoder, renderPassFormat, element as RenderObject); } else if (element.__type__ === "RenderObject") { - this.runRenderObject(device, passEncoder, renderPassFormat, element); + this.runRenderObject(passEncoder, renderPassFormat, element); } else if (element.__type__ === "RenderBundle") { - this.runRenderBundle(device, passEncoder, renderPassFormat, element); + this.runRenderBundle(passEncoder, renderPassFormat, element); } else if (element.__type__ === "OcclusionQuery") { - this.runRenderOcclusionQueryObject(device, passEncoder, renderPassFormat, element, occlusionQuery); + this.runRenderOcclusionQueryObject(passEncoder, renderPassFormat, element, occlusionQuery); } else { @@ -199,8 +201,10 @@ export class RunWebGPU * @param commandEncoder 命令编码器。 * @param computePass 计算通道。 */ - protected runComputePass(device: GPUDevice, commandEncoder: GPUCommandEncoder, computePass: ComputePass) + protected runComputePass(commandEncoder: GPUCommandEncoder, computePass: ComputePass) { + const device = this._device; + const descriptor: GPUComputePassDescriptor = {}; // 处理时间戳查询 const timestampQuery = getGPURenderTimestampQuery(device, computePass?.timestampQuery); @@ -208,7 +212,7 @@ export class RunWebGPU const passEncoder = commandEncoder.beginComputePass(descriptor); - this.runComputeObjects(device, passEncoder, computePass.computeObjects); + this.runComputeObjects(passEncoder, computePass.computeObjects); passEncoder.end(); @@ -216,16 +220,18 @@ export class RunWebGPU timestampQuery.resolve(device, commandEncoder, computePass); } - protected runComputeObjects(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObjects: ComputeObject[]) + protected runComputeObjects(passEncoder: GPUComputePassEncoder, computeObjects: ComputeObject[]) { computeObjects.forEach((computeObject) => { - this.runComputeObject(device, passEncoder, computeObject); + this.runComputeObject(passEncoder, computeObject); }); } - protected runCopyTextureToTexture(device: GPUDevice, commandEncoder: GPUCommandEncoder, copyTextureToTexture: CopyTextureToTexture) + protected runCopyTextureToTexture(commandEncoder: GPUCommandEncoder, copyTextureToTexture: CopyTextureToTexture) { + const device = this._device; + const sourceTexture = getGPUTexture(device, copyTextureToTexture.source.texture); const destinationTexture = getGPUTexture(device, copyTextureToTexture.destination.texture); @@ -246,8 +252,10 @@ export class RunWebGPU ); } - protected runCopyBufferToBuffer(device: GPUDevice, commandEncoder: GPUCommandEncoder, v: CopyBufferToBuffer) + protected runCopyBufferToBuffer(commandEncoder: GPUCommandEncoder, v: CopyBufferToBuffer) { + const device = this._device; + v.sourceOffset ||= 0; v.destinationOffset ||= 0; v.size ||= v.source.size; @@ -265,20 +273,21 @@ export class RunWebGPU ); } - protected runRenderOcclusionQueryObject(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderOcclusionQueryObject: OcclusionQuery, occlusionQuery: GPURenderOcclusionQuery) + protected runRenderOcclusionQueryObject(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderOcclusionQueryObject: OcclusionQuery, occlusionQuery: GPURenderOcclusionQuery) { passEncoder.beginOcclusionQuery(occlusionQuery.getQueryIndex(renderOcclusionQueryObject)); renderOcclusionQueryObject.renderObjects.forEach((renderObject) => { - this.runRenderObject(device, passEncoder, renderPassFormat, renderObject); + this.runRenderObject(passEncoder, renderPassFormat, renderObject); }); passEncoder.endOcclusionQuery(); } - protected runRenderBundle(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) + protected runRenderBundle(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) { + const device = this._device; const renderBundleMap: ChainMap<[RenderBundle, string], GPURenderBundle> = device["_renderBundleMap"] = device["_renderBundleMap"] || new ChainMap(); // let gpuRenderBundle: GPURenderBundle = renderBundleMap.get([renderBundleObject, renderPassFormat._key]); @@ -289,7 +298,7 @@ export class RunWebGPU // const renderBundleEncoder = device.createRenderBundleEncoder(descriptor); - this.runRenderBundleObjects(device, renderBundleEncoder, renderPassFormat, renderBundleObject.renderObjects); + this.runRenderBundleObjects(renderBundleEncoder, renderPassFormat, renderBundleObject.renderObjects); gpuRenderBundle = renderBundleEncoder.finish(); renderBundleMap.set([renderBundleObject, renderPassFormat._key], gpuRenderBundle); @@ -298,12 +307,12 @@ export class RunWebGPU passEncoder.executeBundles([gpuRenderBundle]); } - protected runRenderBundleObjects(device: GPUDevice, passEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: readonly RenderObject[]) + protected runRenderBundleObjects(passEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: readonly RenderObject[]) { // renderObjects.forEach((element) => { - this.runRenderObject(device, passEncoder, renderPassFormat, element as RenderObject); + this.runRenderObject(passEncoder, renderPassFormat, element as RenderObject); }); } @@ -314,8 +323,9 @@ export class RunWebGPU * @param passEncoder 计算通道编码器。 * @param computeObject 计算对象。 */ - protected runComputeObject(device: GPUDevice, passEncoder: GPUComputePassEncoder, computeObject: ComputeObject) + protected runComputeObject(passEncoder: GPUComputePassEncoder, computeObject: ComputeObject) { + const device = this._device; const { pipeline: pipeline, uniforms: bindingResources, workgroups } = computeObject; const shader: IGPUShader = { compute: pipeline.compute.code }; @@ -342,8 +352,9 @@ export class RunWebGPU * @param renderObject 渲染对象。 * @param renderPass 渲染通道。 */ - protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) + protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) { + const device = this._device; const { viewport, scissorRect, pipeline, bindingResources: bindingResources, geometry } = renderObject; const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; @@ -359,7 +370,7 @@ export class RunWebGPU const { primitive, vertices, indices, draw } = geometry; - this.runRenderPipeline(device, passEncoder, renderPassFormat, pipeline, primitive, vertices, indices); + this.runRenderPipeline(passEncoder, renderPassFormat, pipeline, primitive, vertices, indices); // 计算 bindGroups const layout = getGPUPipelineLayout(device, shader); @@ -403,8 +414,9 @@ export class RunWebGPU } } - protected runRenderPipeline(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) + protected runRenderPipeline(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { + const device = this._device; // const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/runs/RunWebGPUCommandCache.ts index cc1838c..9b8605a 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/runs/RunWebGPUCommandCache.ts @@ -12,8 +12,9 @@ import { RunWebGPU } from "./RunWebGPU"; */ export class RunWebGPUCommandCache extends RunWebGPU { - protected runRenderPassObjects(device: GPUDevice, passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) + protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { + const device = this._device; const map: ChainMap<[string, RenderPassObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); let caches = map.get([renderPassFormat._key, renderObjects]); if (!caches) @@ -22,7 +23,7 @@ export class RunWebGPUCommandCache extends RunWebGPU const renderPassRecord = new GPURenderPassRecord(); const commands = renderPassRecord["_commands"] = []; - super.runRenderPassObjects(device, renderPassRecord, renderPassFormat, renderObjects, occlusionQuery); + super.runRenderPassObjects(renderPassRecord, renderPassFormat, renderObjects, occlusionQuery); // 排除无效命令 paichuWuxiaoCommands(renderPassFormat.attachmentSize, commands); @@ -48,8 +49,9 @@ export class RunWebGPUCommandCache extends RunWebGPU runCommands(passEncoder, caches); } - protected runRenderBundleObjects(device: GPUDevice, bundleEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: RenderObject[]) + protected runRenderBundleObjects(bundleEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: RenderObject[]) { + const device = this._device; const map: ChainMap<[string, RenderObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); let caches = map.get([renderPassFormat._key, renderObjects]); if (!caches) @@ -59,7 +61,7 @@ export class RunWebGPUCommandCache extends RunWebGPU const renderBundleRecord = new GPURenderPassRecord(); const commands = renderBundleRecord["_commands"] = []; - super.runRenderBundleObjects(device, renderBundleRecord as any, renderPassFormat, renderObjects); + super.runRenderBundleObjects(renderBundleRecord as any, renderPassFormat, renderObjects); // 排除无效命令 paichuWuxiaoCommands(renderPassFormat.attachmentSize, commands); @@ -87,8 +89,9 @@ export class RunWebGPUCommandCache extends RunWebGPU runCommands(bundleEncoder, { ...caches, commands }); } - protected runRenderObject(device: GPUDevice, passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) + protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) { + const device = this._device; const map: ChainMap<[string, RenderObject], Array> = device["_IGPURenderObjectCommandMap"] = device["_IGPURenderObjectCommandMap"] || new ChainMap(); const _commands = passEncoder["_commands"] as any[]; @@ -102,7 +105,7 @@ export class RunWebGPUCommandCache extends RunWebGPU const start = _commands.length; - super.runRenderObject(device, passEncoder, renderPassFormat, renderObject); + super.runRenderObject(passEncoder, renderPassFormat, renderObject); map.set([renderPassFormat._key, renderObject], _commands.slice(start)); @@ -167,6 +170,11 @@ function runCommands(_passEncoder: GPURenderPassEncoder | GPUComputePassEncoder }); } +/** + * 排除无效命令 + * + * @param attachmentSize + */ function paichuWuxiaoCommands(attachmentSize: { readonly width: number; readonly height: number; }, commands: any[]) { const _obj = { -- Gitee From 643f9af4afdc34246e722676832f653d7e9b1ea8 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 16:11:34 +0800 Subject: [PATCH 080/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 WebGPU 类中的方法移至 WebGPUCache 类 - 删除 WebGPUStep 类 - 移除 RunWebGPU 和 RunWebGPUCommandCache 类 - 简化 WebGPU 类的结构,提供更清晰的缓存管理 --- src/WebGPU.ts | 120 +----------------- src/{runs/RunWebGPU.ts => WebGPUBase.ts} | 91 +++++++++---- ...unWebGPUCommandCache.ts => WebGPUCache.ts} | 16 +-- src/WebGPUStep.ts | 93 -------------- 4 files changed, 73 insertions(+), 247 deletions(-) rename src/{runs/RunWebGPU.ts => WebGPUBase.ts} (87%) rename src/{runs/RunWebGPUCommandCache.ts => WebGPUCache.ts} (95%) delete mode 100644 src/WebGPUStep.ts diff --git a/src/WebGPU.ts b/src/WebGPU.ts index c11bc1e..7f63152 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,127 +1,11 @@ -import { GBuffer, ReadPixels, Submit, TextureLike } from "@feng3d/render-api"; -import { getTextureSize } from "./caches/getTextureSize"; -import "./data/polyfills/ReadPixels"; -import { RunWebGPUCommandCache } from "./runs/RunWebGPUCommandCache"; -import { getGPUDevice } from "./utils/getGPUDevice"; +import { WebGPUCache } from "./WebGPUCache"; /** * WebGPU 对象。 * * 提供 `WebGPU` 操作入口 {@link WebGPU.submit}。 */ -export class WebGPU +export class WebGPU extends WebGPUCache { - private _runWebGPU: RunWebGPUCommandCache; - /** - * 初始化 WebGPU 获取 GPUDevice 。 - */ - async init(options?: GPURequestAdapterOptions, descriptor?: GPUDeviceDescriptor) - { - this.device = await getGPUDevice(options, descriptor); - // - this.device?.lost.then(async (info) => - { - console.error(`WebGPU device was lost: ${info.message}`); - - // 'reason' will be 'destroyed' if we intentionally destroy the device. - if (info.reason !== "destroyed") - { - // try again - this.device = await getGPUDevice(options, descriptor); - } - }); - - return this; - } - - get device() - { - return this._device; - } - set device(v) - { - this._device = v; - this._runWebGPU = new RunWebGPUCommandCache(this._device); - } - - public _device: GPUDevice; - - /** - * 提交 GPU 。 - * - * @param submit 一次 GPU 提交内容。 - * - * @see GPUQueue.submit - */ - submit(submit: Submit) - { - this._runWebGPU.runSubmit(submit); - } - - /** - * 销毁纹理。 - * - * @param texture 需要被销毁的纹理。 - */ - destoryTexture(texture: TextureLike) - { - this._runWebGPU.destoryTexture(texture); - } - - /** - * 操作纹理进行Y轴翻转或进行预乘Alpha。 - * - * @param texture 被操作的纹理。 - * @param invertY 是否Y轴翻转 - * @param premultiplyAlpha 是否预乘Alpha。 - */ - textureInvertYPremultiplyAlpha(texture: TextureLike, options: { invertY?: boolean, premultiplyAlpha?: boolean }) - { - this._runWebGPU.textureInvertYPremultiplyAlpha(texture, options); - } - - /** - * 拷贝 深度纹理到 普通纹理。 - * - * @param device GPU设备。 - * @param sourceTexture 源纹理。 - * @param targetTexture 目标纹理。 - */ - copyDepthTexture(sourceTexture: TextureLike, targetTexture: TextureLike) - { - this._runWebGPU.copyDepthTexture(sourceTexture, targetTexture); - } - - /** - * 从 GPU纹理 上读取数据。 - * - * @param gpuReadPixels - * - * @returns 读取到的数据。 - */ - async readPixels(gpuReadPixels: ReadPixels) - { - const result = await this._runWebGPU.readPixels(gpuReadPixels); - return result; - } - - /** - * 从GPU缓冲区读取数据到CPU。 - * - * @param buffer GPU缓冲区。 - * @param offset 读取位置。 - * @param size 读取字节数量。 - * @returns CPU数据缓冲区。 - */ - async readBuffer(buffer: GBuffer, offset?: GPUSize64, size?: GPUSize64) - { - const result = await this._runWebGPU.readBuffer(buffer, offset, size); - return result; - } - - getGPUTextureSize(input: TextureLike) - { - return getTextureSize(input); - } } diff --git a/src/runs/RunWebGPU.ts b/src/WebGPUBase.ts similarity index 87% rename from src/runs/RunWebGPU.ts rename to src/WebGPUBase.ts index a7c4e7e..de4243d 100644 --- a/src/runs/RunWebGPU.ts +++ b/src/WebGPUBase.ts @@ -1,39 +1,74 @@ import { anyEmitter } from "@feng3d/event"; import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, TextureLike, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; -import { getGPUBindGroup } from "../caches/getGPUBindGroup"; -import { getGPUBuffer } from "../caches/getGPUBuffer"; -import { getGPUComputePipeline } from "../caches/getGPUComputePipeline"; -import { getGPUPipelineLayout, IGPUShader } from "../caches/getGPUPipelineLayout"; -import { getGPURenderOcclusionQuery, GPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; -import { getGPURenderPassDescriptor } from "../caches/getGPURenderPassDescriptor"; -import { getGPURenderPassFormat } from "../caches/getGPURenderPassFormat"; -import { getGPURenderPipeline } from "../caches/getGPURenderPipeline"; -import { getGPURenderTimestampQuery } from "../caches/getGPURenderTimestampQuery"; -import { getGPUTexture } from "../caches/getGPUTexture"; -import { getGBuffer } from "../caches/getIGPUBuffer"; -import { getNGPURenderPipeline } from "../caches/getNGPURenderPipeline"; -import { getRealGPUBindGroup } from "../const"; -import { ComputeObject } from "../data/ComputeObject"; -import { ComputePass } from "../data/ComputePass"; -import "../data/polyfills/RenderObject"; -import "../data/polyfills/RenderPass"; -import { RenderBundle } from "../data/RenderBundle"; -import { GPUQueue_submit } from "../eventnames"; -import { RenderPassFormat } from "../internal/RenderPassFormat"; -import { ChainMap } from "../utils/ChainMap"; -import { copyDepthTexture } from "../utils/copyDepthTexture"; -import { readPixels } from "../utils/readPixels"; -import { textureInvertYPremultiplyAlpha } from "../utils/textureInvertYPremultiplyAlpha"; - -export class RunWebGPU +import { getGPUBindGroup } from "./caches/getGPUBindGroup"; +import { getGPUBuffer } from "./caches/getGPUBuffer"; +import { getGPUComputePipeline } from "./caches/getGPUComputePipeline"; +import { getGPUPipelineLayout, IGPUShader } from "./caches/getGPUPipelineLayout"; +import { getGPURenderOcclusionQuery, GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; +import { getGPURenderPassDescriptor } from "./caches/getGPURenderPassDescriptor"; +import { getGPURenderPassFormat } from "./caches/getGPURenderPassFormat"; +import { getGPURenderPipeline } from "./caches/getGPURenderPipeline"; +import { getGPURenderTimestampQuery } from "./caches/getGPURenderTimestampQuery"; +import { getGPUTexture } from "./caches/getGPUTexture"; +import { getGBuffer } from "./caches/getIGPUBuffer"; +import { getNGPURenderPipeline } from "./caches/getNGPURenderPipeline"; +import { getRealGPUBindGroup } from "./const"; +import { ComputeObject } from "./data/ComputeObject"; +import { ComputePass } from "./data/ComputePass"; +import "./data/polyfills/RenderObject"; +import "./data/polyfills/RenderPass"; +import { RenderBundle } from "./data/RenderBundle"; +import { GPUQueue_submit } from "./eventnames"; +import { RenderPassFormat } from "./internal/RenderPassFormat"; +import { ChainMap } from "./utils/ChainMap"; +import { copyDepthTexture } from "./utils/copyDepthTexture"; +import { getGPUDevice } from "./utils/getGPUDevice"; +import { readPixels } from "./utils/readPixels"; +import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; + +/** + * WebGPU 基础类 + */ +export class WebGPUBase { - constructor(protected readonly _device: GPUDevice) + /** + * 初始化 WebGPU 获取 GPUDevice 。 + */ + async init(options?: GPURequestAdapterOptions, descriptor?: GPUDeviceDescriptor) + { + this.device = await getGPUDevice(options, descriptor); + // + this.device?.lost.then(async (info) => + { + console.error(`WebGPU device was lost: ${info.message}`); + + // 'reason' will be 'destroyed' if we intentionally destroy the device. + if (info.reason !== "destroyed") + { + // try again + this.device = await getGPUDevice(options, descriptor); + } + }); + + return this; + } + + get device() + { + return this._device; + } + set device(v) + { + this._device = v; + } + + constructor(protected _device?: GPUDevice) { } - runSubmit(submit: Submit) + submit(submit: Submit) { const device = this._device; diff --git a/src/runs/RunWebGPUCommandCache.ts b/src/WebGPUCache.ts similarity index 95% rename from src/runs/RunWebGPUCommandCache.ts rename to src/WebGPUCache.ts index 9b8605a..395de57 100644 --- a/src/runs/RunWebGPUCommandCache.ts +++ b/src/WebGPUCache.ts @@ -1,16 +1,16 @@ import { RenderObject, RenderPassObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { GPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; -import { getRealGPUBindGroup } from "../const"; -import { RenderPassFormat } from "../internal/RenderPassFormat"; -import { ChainMap } from "../utils/ChainMap"; -import { RunWebGPU } from "./RunWebGPU"; +import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; +import { getRealGPUBindGroup } from "./const"; +import { RenderPassFormat } from "./internal/RenderPassFormat"; +import { ChainMap } from "./utils/ChainMap"; +import { WebGPUBase } from "./WebGPUBase"; /** - * 套壳模式(RunWebGPUCommandCache)优于覆盖函数(RunWebGPUCommandCache1)的形式。 + * 缓存命令,优化性能。 */ -export class RunWebGPUCommandCache extends RunWebGPU +export class WebGPUCache extends WebGPUBase { protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { @@ -174,7 +174,7 @@ function runCommands(_passEncoder: GPURenderPassEncoder | GPUComputePassEncoder * 排除无效命令 * * @param attachmentSize - */ + */ function paichuWuxiaoCommands(attachmentSize: { readonly width: number; readonly height: number; }, commands: any[]) { const _obj = { diff --git a/src/WebGPUStep.ts b/src/WebGPUStep.ts deleted file mode 100644 index b063c95..0000000 --- a/src/WebGPUStep.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { CopyBufferToBuffer, CopyTextureToTexture, RenderPassObject, RenderObject, RenderPass, RenderPassDescriptor, Submit } from "@feng3d/render-api"; - -import { WebGPU } from "./WebGPU"; -import { ComputePass } from "./data/ComputePass"; -import { ComputeObject } from "./data/ComputeObject"; - -/** - * 按步骤来组织 IGPUSubmit 对象。 - * - * 不建议使用。 - */ -export class WebGPUStep -{ - private _currentSubmit: Submit; - private _currentRenderPassEncoder: RenderPass; - private _currentComputePassEncoder: ComputePass; - - readonly webGPU: WebGPU; - - constructor(webGPU: WebGPU) - { - this.webGPU = webGPU; - } - - renderPass(descriptor: RenderPassDescriptor) - { - this._currentSubmit = this._currentSubmit || { commandEncoders: [{ passEncoders: [] }] }; - // - if (this._currentRenderPassEncoder?.descriptor === descriptor) return; - // - this._currentRenderPassEncoder = { descriptor, renderObjects: [] }; - this._currentComputePassEncoder = null; - this._currentSubmit.commandEncoders[0].passEncoders.push(this._currentRenderPassEncoder); - } - - renderObject(renderObject: RenderObject) - { - (this._currentRenderPassEncoder.renderObjects as RenderPassObject[]).push(renderObject); - } - - computePass() - { - this._currentSubmit = this._currentSubmit || { commandEncoders: [{ passEncoders: [] }] }; - // - this._currentRenderPassEncoder = null; - this._currentComputePassEncoder = { __type__: "ComputePass", computeObjects: [] }; - this._currentSubmit.commandEncoders[0].passEncoders.push(this._currentComputePassEncoder); - } - - computeObject(computeObject: ComputeObject) - { - this._currentComputePassEncoder.computeObjects.push(computeObject); - } - - copyTextureToTexture(copyTextureToTexture: CopyTextureToTexture) - { - this._currentSubmit = this._currentSubmit || { commandEncoders: [{ passEncoders: [] }] }; - - this._currentRenderPassEncoder = null; - this._currentComputePassEncoder = null; - this._currentSubmit.commandEncoders[0].passEncoders.push(copyTextureToTexture); - } - - copyBufferToBuffer(copyBufferToBuffer: CopyBufferToBuffer) - { - this._currentSubmit = this._currentSubmit || { commandEncoders: [{ passEncoders: [] }] }; - - this._currentRenderPassEncoder = null; - this._currentComputePassEncoder = null; - this._currentSubmit.commandEncoders[0].passEncoders.push(copyBufferToBuffer); - } - - /** - * 提交 GPU 。 - * - * @param submit 一次 GPU 提交内容。 - * - * @see GPUQueue.submit - */ - submit(submit?: Submit) - { - if (!submit) - { - if (!this._currentSubmit) return; - submit = this._currentSubmit; - this._currentSubmit = null; - this._currentRenderPassEncoder = null; - this._currentComputePassEncoder = null; - } - - this.webGPU.submit(submit); - } -} -- Gitee From 8d325c8333d4ec9029f1ea414774ec2b46e58580 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 16:28:58 +0800 Subject: [PATCH 081/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 bindGroup 和 buffer 的缓存移至 GPUDevice 对象 - 优化缓存访问和存储逻辑 - 移除不必要的弱引用和计算属性 --- src/WebGPUBase.ts | 22 +++++++++++++++++++--- src/caches/getGPUBindGroup.ts | 6 ++---- src/caches/getGPUBindGroupLayout.ts | 0 src/caches/getGPUBuffer.ts | 13 ++++++------- 4 files changed, 27 insertions(+), 14 deletions(-) delete mode 100644 src/caches/getGPUBindGroupLayout.ts diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index de4243d..9fd895b 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, TextureLike, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { BindingResources, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, TextureLike, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -27,6 +27,15 @@ import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; +declare global +{ + interface GPUDevice + { + _bindGroupMap: ChainMap<[GPUBindGroupLayout, BindingResources], GPUBindGroup>; + _bufferMap: WeakMap>; + } +} + /** * WebGPU 基础类 */ @@ -61,11 +70,18 @@ export class WebGPUBase set device(v) { this._device = v; + // + if (this._device) + { + this._device._bindGroupMap ??= new ChainMap(); + this._device._bufferMap ??= new WeakMap(); + } } + protected _device: GPUDevice; - constructor(protected _device?: GPUDevice) + constructor(device?: GPUDevice) { - + this.device = device; } submit(submit: Submit) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 08a8330..08c9cab 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -15,9 +15,7 @@ import { getGBuffer } from "./getIGPUBuffer"; export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) { - const bindGroupMap: WeakMap = bindGroupLayout["_bindGroupMap"] = bindGroupLayout["_bindGroupMap"] || new WeakMap(); - - let gBindGroup = bindGroupMap.get(bindingResources); + let gBindGroup = device._bindGroupMap.get([bindGroupLayout, bindingResources]); if (gBindGroup) return gBindGroup; // 总是更新函数列表。 @@ -126,7 +124,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup gBindGroup = device.createBindGroup({ layout: bindGroupLayout, entries }); - bindGroupMap.set(bindingResources, gBindGroup); + device._bindGroupMap.set([bindGroupLayout, bindingResources], gBindGroup); // 设置更新外部纹理/画布纹理视图 if (awaysUpdateFuncs.length > 0) diff --git a/src/caches/getGPUBindGroupLayout.ts b/src/caches/getGPUBindGroupLayout.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/caches/getGPUBuffer.ts b/src/caches/getGPUBuffer.ts index b6dbc67..e7dbd52 100644 --- a/src/caches/getGPUBuffer.ts +++ b/src/caches/getGPUBuffer.ts @@ -1,4 +1,4 @@ -import { computed, ComputedRef, effect, GBuffer, reactive, UnReadonly } from "@feng3d/render-api"; +import { computed, effect, GBuffer, reactive, UnReadonly } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; /** @@ -26,9 +26,7 @@ const defaultGPUBufferUsage = 0 */ export function getGPUBuffer(device: GPUDevice, buffer: GBuffer) { - const gBufferMap: WeakMap> = device["_gBufferMap"] = device["_gBufferMap"] || new WeakMap>(); - - let result = gBufferMap.get(buffer); + let result = device._bufferMap.get(buffer); if (result) return result.value; const size = buffer.size; @@ -119,7 +117,8 @@ export function getGPUBuffer(device: GPUDevice, buffer: GBuffer) }); // 这行是不是可以删掉? - effect(() =>{ + effect(() => + { result.value; }) @@ -139,14 +138,14 @@ export function getGPUBuffer(device: GPUDevice, buffer: GBuffer) { oldDestroy.apply(gBuffer); - gBufferMap.delete(buffer); + device._bufferMap.delete(buffer); // watcher.unwatch(buffer, "data", dataChange); }; })(gBuffer.destroy); - gBufferMap.set(buffer, result); + device._bufferMap.set(buffer, result); return result.value; } -- Gitee From b0b590fa26f2b031e2bc381f77cacdfe1344f93f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 16:40:47 +0800 Subject: [PATCH 082/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将全局缓存移至 GPUDevice 实例中 - 优化了 GPUCanvasContext 和 GPUComputePipeline 的缓存逻辑 - 更新了相关函数以使用新的缓存机制 --- src/WebGPUBase.ts | 7 ++++++- src/caches/getGPUCanvasContext.ts | 8 +++----- src/caches/getGPUComputePipeline.ts | 6 ++---- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 9fd895b..c9c28dd 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, TextureLike, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { BindingResources, CanvasContext, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, TextureLike, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -26,6 +26,7 @@ import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; +import { ComputePipeline } from "./data/ComputePipeline"; declare global { @@ -33,6 +34,8 @@ declare global { _bindGroupMap: ChainMap<[GPUBindGroupLayout, BindingResources], GPUBindGroup>; _bufferMap: WeakMap>; + _contextMap: WeakMap>; + _computePipelineMap: WeakMap } } @@ -75,6 +78,8 @@ export class WebGPUBase { this._device._bindGroupMap ??= new ChainMap(); this._device._bufferMap ??= new WeakMap(); + this._device._contextMap ??= new WeakMap(); + this._device._computePipelineMap ??= new WeakMap(); } } protected _device: GPUDevice; diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index 79d64f0..0112957 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -1,10 +1,10 @@ import { CanvasContext } from "@feng3d/render-api"; -import { computed, ComputedRef, reactive } from "@vue/reactivity"; +import { computed, reactive } from "@vue/reactivity"; import "../data/polyfills/CanvasContext"; export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) { - let result = canvasContextMap.get(context); + let result = device._contextMap.get(context); if (result) return result.value; const canvas = typeof context.canvasId === "string" ? document.getElementById(context.canvasId) as HTMLCanvasElement : context.canvasId; @@ -31,7 +31,7 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) return gpuCanvasContext; }); - canvasContextMap.set(context, result); + device._contextMap.set(context, result); const updateConfigure = () => { @@ -59,5 +59,3 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) return result.value; } - -const canvasContextMap = new WeakMap>();; diff --git a/src/caches/getGPUComputePipeline.ts b/src/caches/getGPUComputePipeline.ts index f8927b6..41fa67d 100644 --- a/src/caches/getGPUComputePipeline.ts +++ b/src/caches/getGPUComputePipeline.ts @@ -7,9 +7,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; export function getGPUComputePipeline(device: GPUDevice, computePipeline: ComputePipeline) { - const computePipelineMap: WeakMap = device["_computePipelineMap"] = device["_computePipelineMap"] || new WeakMap(); - - let pipeline = computePipelineMap.get(computePipeline); + let pipeline = device._computePipelineMap.get(computePipeline); if (pipeline) return pipeline; const computeStage = computePipeline.compute; @@ -38,7 +36,7 @@ export function getGPUComputePipeline(device: GPUDevice, computePipeline: Comput module: getGPUShaderModule(device, computeStage.code), }, }); - computePipelineMap.set(computePipeline, pipeline); + device._computePipelineMap.set(computePipeline, pipeline); return pipeline; } -- Gitee From 24aa044d65021414c9099b597b2dbc649beb81bd Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 17:34:36 +0800 Subject: [PATCH 083/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 ChainMap 的使用,改为直接使用 WeakMap 和 Map - 优化纹理和采样器的缓存管理,移除冗余的 Map 实例 - 调整 GPU 资源的创建和销毁逻辑,提高缓存效率 - 删除未使用的 ChainMap 类,简化代码结构 --- src/WebGPUBase.ts | 13 +++-- src/WebGPUCache.ts | 3 +- src/caches/getGPURenderPassDescriptor.ts | 30 +++++----- src/caches/getGPUSampler.ts | 7 +-- src/caches/getGPUTexture.ts | 10 +--- src/caches/getGPUTextureView.ts | 8 +-- src/caches/getNGPURenderPipeline.ts | 5 +- src/index.ts | 5 -- src/utils/ChainMap.ts | 74 ------------------------ 9 files changed, 34 insertions(+), 121 deletions(-) delete mode 100644 src/utils/ChainMap.ts diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index c9c28dd..facc82b 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, CanvasContext, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, TextureLike, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { BindingResources, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Sampler, ScissorRect, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -16,17 +16,16 @@ import { getNGPURenderPipeline } from "./caches/getNGPURenderPipeline"; import { getRealGPUBindGroup } from "./const"; import { ComputeObject } from "./data/ComputeObject"; import { ComputePass } from "./data/ComputePass"; +import { ComputePipeline } from "./data/ComputePipeline"; import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit } from "./eventnames"; import { RenderPassFormat } from "./internal/RenderPassFormat"; -import { ChainMap } from "./utils/ChainMap"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; -import { ComputePipeline } from "./data/ComputePipeline"; declare global { @@ -35,7 +34,10 @@ declare global _bindGroupMap: ChainMap<[GPUBindGroupLayout, BindingResources], GPUBindGroup>; _bufferMap: WeakMap>; _contextMap: WeakMap>; - _computePipelineMap: WeakMap + _computePipelineMap: WeakMap; + _samplerMap: WeakMap; + _textureViewMap: WeakMap; + _textureMap: WeakMap; } } @@ -80,6 +82,9 @@ export class WebGPUBase this._device._bufferMap ??= new WeakMap(); this._device._contextMap ??= new WeakMap(); this._device._computePipelineMap ??= new WeakMap(); + this._device._samplerMap ??= new WeakMap(); + this._device._textureMap ??= new WeakMap(); + this._device._textureViewMap ??= new WeakMap(); } } protected _device: GPUDevice; diff --git a/src/WebGPUCache.ts b/src/WebGPUCache.ts index 395de57..5cdd20b 100644 --- a/src/WebGPUCache.ts +++ b/src/WebGPUCache.ts @@ -1,10 +1,9 @@ -import { RenderObject, RenderPassObject } from "@feng3d/render-api"; +import { ChainMap, RenderObject, RenderPassObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; import { getRealGPUBindGroup } from "./const"; import { RenderPassFormat } from "./internal/RenderPassFormat"; -import { ChainMap } from "./utils/ChainMap"; import { WebGPUBase } from "./WebGPUBase"; /** diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index d723507..2ce591e 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -235,27 +235,23 @@ function getIGPURenderPassAttachmentTextures(colorAttachments: NGPURenderPassCol */ function getMultisampleTextureView(texture: TextureLike, sampleCount: 4) { - let multisampleTextureView = multisampleTextureMap.get(texture); - if (!multisampleTextureView) - { - // 新增用于解决多重采样的纹理 - const size = getTextureSize(texture); - const format = getGPUTextureFormat(texture); - const multisampleTexture: MultisampleTexture = { - label: "自动生成多重采样的纹理", - size, - sampleCount, - format, - }; - multisampleTextureView = { texture: multisampleTexture }; - multisampleTextureMap.set(texture, multisampleTextureView); - } + let multisampleTextureView: TextureView = texture["_multisampleTextureView"]; + if (multisampleTextureView) return multisampleTextureView; + + // 新增用于解决多重采样的纹理 + const size = getTextureSize(texture); + const format = getGPUTextureFormat(texture); + const multisampleTexture: MultisampleTexture = { + label: "自动生成多重采样的纹理", + size, + sampleCount, + format, + }; + multisampleTextureView = texture["_multisampleTextureView"] = { texture: multisampleTexture }; return multisampleTextureView; } -const multisampleTextureMap = new WeakMap(); - /** * 获取深度模板附件完整描述。 * diff --git a/src/caches/getGPUSampler.ts b/src/caches/getGPUSampler.ts index 3b3e2ee..7b8959d 100644 --- a/src/caches/getGPUSampler.ts +++ b/src/caches/getGPUSampler.ts @@ -5,7 +5,7 @@ import { IGPUSampler_changed } from "../eventnames"; export function getGPUSampler(device: GPUDevice, sampler: Sampler) { - let gSampler = samplerMap.get(sampler); + let gSampler = device._samplerMap.get(sampler); if (gSampler) return gSampler; // 处理默认值 @@ -18,21 +18,20 @@ export function getGPUSampler(device: GPUDevice, sampler: Sampler) // gSampler = device.createSampler(sampler); - samplerMap.set(sampler, gSampler); + device._samplerMap.set(sampler, gSampler); // watcher.watchobject(sampler, defaultSampler, () => { // 移除监听,删除缓存 watcher.unwatchobject(sampler, defaultSampler); - samplerMap.delete(sampler); + device._samplerMap.delete(sampler); // anyEmitter.emit(sampler, IGPUSampler_changed); }); return gSampler; } -const samplerMap = new WeakMap(); /** * GPU采样器默认值。 diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 4a0322d..a67b2ea 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -29,8 +29,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC const texture = textureLike as Texture; - const textureMap: Map = device[_GPUTextureMap] = device[_GPUTextureMap] || new Map(); - gpuTexture = textureMap.get(texture); + gpuTexture = device._textureMap.get(texture); if (gpuTexture) return gpuTexture; if (!autoCreate) return null; @@ -73,7 +72,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC viewFormats, }); - textureMap.set(texture, gpuTexture); + device._textureMap.set(texture, gpuTexture); }; createTexture(); @@ -230,7 +229,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC { oldDestroy.apply(gpuTexture); // - textureMap.delete(texture); + device._textureMap.delete(texture); // watcher.unwatch(texture, "size", resize); watcher.unwatch(texture, "sources", updateSources); @@ -247,9 +246,6 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC } let autoIndex = 0; -const _GPUTextureMap = "_GPUTextureMap"; - - function getGPUTextureDimension(dimension: TextureDimension) { const textureDimension = dimensionMap[dimension]; diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index 8014720..7ef0b3c 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -5,8 +5,6 @@ import { getGPUTexture } from "./getGPUTexture"; export function getGPUTextureView(device: GPUDevice, view: TextureView) { - const textureViewMap: WeakMap = device["_textureViewMap"] = device["_textureViewMap"] || new WeakMap(); - if ((view.texture as CanvasTexture).context) { const texture = getGPUTexture(device, view.texture); @@ -20,7 +18,7 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) } // - let textureView = textureViewMap.get(view); + let textureView = device._textureViewMap.get(view); if (textureView) return textureView; // @@ -29,11 +27,11 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) const dimension = view.dimension ?? texture.dimension; textureView = gpuTexture.createView({ ...view, dimension }); - textureViewMap.set(view, textureView); + device._textureViewMap.set(view, textureView); // 销毁纹理时清除对应的纹理视图。 anyEmitter.once(gpuTexture, GPUTexture_destroy, () => { - textureViewMap.delete(view); + device._textureViewMap.delete(view); anyEmitter.emit(textureView, GPUTextureView_destroy); }); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index d9b0d9c..989305d 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; +import { BlendState, ChainMap, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -9,7 +9,6 @@ import { NFragmentState } from "../internal/NFragmentState"; import { NRenderPipeline } from "../internal/NRenderPipeline"; import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; import { NGPUVertexState } from "../internal/NGPUVertexState"; -import { ChainMap } from "../utils/ChainMap"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; /** @@ -285,7 +284,7 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) const vertexBuffers: NVertexBuffer[] = []; - const map: WeakMap = new WeakMap(); + const map: Map = new Map(); vertex.inputs.forEach((v) => { diff --git a/src/index.ts b/src/index.ts index 9ae38df..7a9f1c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,8 +23,3 @@ export * from "./data/polyfills/Uniforms"; export * from "./caches/getIGPUBuffer"; export * from "./types/VertexFormat"; - -/** - * 内部 - */ -export * from "./utils/ChainMap"; diff --git a/src/utils/ChainMap.ts b/src/utils/ChainMap.ts deleted file mode 100644 index 14e069d..0000000 --- a/src/utils/ChainMap.ts +++ /dev/null @@ -1,74 +0,0 @@ -/** - * 链式Map。 - * - * 多个key数组对应一个值。 - * - * 由于键值可能是字面值也可能是对象,因此无法使用 {@link WeakMap} 来构建{@link ChainMap},只能使用 {@link Map}。 - */ -export class ChainMap, V> -{ - private _map = new Map(); - - /** - * 获取键对应的值。 - * - * @param keys 键。 - * @returns 值。 - */ - get(keys: K): V - { - let map = this._map; - - for (let i = 0, n = keys.length - 1; i < n; i++) - { - map = map.get(keys[i]); - - if (map === undefined) return undefined; - } - - return map.get(keys[keys.length - 1]); - } - - /** - * 设置映射。 - * - * @param keys 键。 - * @param value 值。 - */ - set(keys: K, value: V) - { - let map = this._map; - - for (let i = 0; i < keys.length - 1; i++) - { - const key = keys[i]; - - if (map.has(key) === false) map.set(key, new Map()); - - map = map.get(key); - } - - map.set(keys[keys.length - 1], value); - } - - /** - * 删除映射。 - * - * @param keys 键。 - * @returns 如果找到目标值且被删除返回 `true` ,否则返回 `false` 。 - */ - delete(keys: K): boolean - { - let map = this._map; - - for (let i = 0; i < keys.length - 1; i++) - { - map = map.get(keys[i]); - - if (map === undefined) return false; - } - - return map.delete(keys[keys.length - 1]); - } -} - -- Gitee From 7fe5dbd350c4953746a74011dee1ea22887448cb Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 20:09:00 +0800 Subject: [PATCH 084/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将全局缓存移至 GPUDevice 实例中 - 优化了 RenderPassDescriptor、RenderPipeline 和 ShaderModule 的缓存逻辑 - 删除了不必要的 Map 实例,减少了内存占用 --- src/WebGPUBase.ts | 9 ++++++++- src/caches/getGPURenderPassDescriptor.ts | 5 ++--- src/caches/getGPURenderPipeline.ts | 5 ++--- src/caches/getGPUShaderModule.ts | 6 ++---- src/caches/getNGPURenderPipeline.ts | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index facc82b..eaa33c0 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Sampler, ScissorRect, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { BindingResources, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, ScissorRect, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -26,6 +26,7 @@ import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; +import { NRenderPipeline } from "./internal/NRenderPipeline"; declare global { @@ -38,6 +39,9 @@ declare global _samplerMap: WeakMap; _textureViewMap: WeakMap; _textureMap: WeakMap; + _renderPassDescriptorMap: WeakMap; + _pipelineMap: WeakMap; + _shaderMap: Map; } } @@ -85,6 +89,9 @@ export class WebGPUBase this._device._samplerMap ??= new WeakMap(); this._device._textureMap ??= new WeakMap(); this._device._textureViewMap ??= new WeakMap(); + this._device._renderPassDescriptorMap ??= new WeakMap(); + this._device._pipelineMap ??= new WeakMap(); + this._device._shaderMap ??= new Map(); } } protected _device: GPUDevice; diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 2ce591e..15af5a6 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -17,8 +17,7 @@ import { getTextureSize } from "./getTextureSize"; */ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: RenderPassDescriptor): GPURenderPassDescriptor { - const renderPassDescriptorMap: Map = device["_RenderPassDescriptorMap"] = device["_RenderPassDescriptorMap"] || new Map(); - let renderPassDescriptor = renderPassDescriptorMap.get(descriptor); + let renderPassDescriptor = device._renderPassDescriptorMap.get(descriptor); if (renderPassDescriptor) { // 执行更新函数。 @@ -28,7 +27,7 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render } renderPassDescriptor = { colorAttachments: [] }; - renderPassDescriptorMap.set(descriptor, renderPassDescriptor); + device._renderPassDescriptorMap.set(descriptor, renderPassDescriptor); const _updates: Function[] = renderPassDescriptor["_updates"] = []; diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index 154854e..0af129a 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -4,7 +4,7 @@ import { getGPUShaderModule } from "./getGPUShaderModule"; export function getGPURenderPipeline(device: GPUDevice, renderPipeline: NRenderPipeline) { - let pipeline = pipelineMap.get(renderPipeline); + let pipeline = device._pipelineMap.get(renderPipeline); if (pipeline) return pipeline; // 从GPU管线中获取管线布局。 @@ -31,9 +31,8 @@ export function getGPURenderPipeline(device: GPUDevice, renderPipeline: NRenderP pipeline = device.createRenderPipeline(gpuRenderPipelineDescriptor); - pipelineMap.set(renderPipeline, pipeline); + device._pipelineMap.set(renderPipeline, pipeline); return pipeline; } -const pipelineMap = new Map(); diff --git a/src/caches/getGPUShaderModule.ts b/src/caches/getGPUShaderModule.ts index 16a4efb..c2633ba 100644 --- a/src/caches/getGPUShaderModule.ts +++ b/src/caches/getGPUShaderModule.ts @@ -1,14 +1,12 @@ export function getGPUShaderModule(device: GPUDevice, code: string) { - let gShaderModule = shaderMap.get(code); + let gShaderModule = device._shaderMap.get(code); if (gShaderModule) return gShaderModule; gShaderModule = device.createShaderModule({ code, }); - shaderMap.set(code, gShaderModule); + device._shaderMap.set(code, gShaderModule); return gShaderModule; } - -const shaderMap = new Map(); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 989305d..1601c7b 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -284,7 +284,7 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) const vertexBuffers: NVertexBuffer[] = []; - const map: Map = new Map(); + const map = new Map(); vertex.inputs.forEach((v) => { -- Gitee From 7782d25676b80e388eb30d2df7dadeddfe882687 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 20:26:39 +0800 Subject: [PATCH 085/214] =?UTF-8?q?feat(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 WebGPUBase 中添加新的 ChainMap 属性,用于缓存渲染命令 - 优化 WebGPUCache 中的缓存获取和设置逻辑 - 重构 runRenderPassObjects、runRenderBundleObjects 和 runRenderObject 方法 --- src/WebGPUBase.ts | 7 +++++++ src/WebGPUCache.ts | 21 +++++++++------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index eaa33c0..9f1c940 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -42,6 +42,11 @@ declare global _renderPassDescriptorMap: WeakMap; _pipelineMap: WeakMap; _shaderMap: Map; + _renderPassObjectsCommandMap: ChainMap<[string, RenderPassObject[]], { + commands: Array; + setBindGroupCommands: Array; + }>; + _renderObjectCommandMap: ChainMap<[string, RenderObject], Array>; } } @@ -83,6 +88,8 @@ export class WebGPUBase if (this._device) { this._device._bindGroupMap ??= new ChainMap(); + this._device._renderPassObjectsCommandMap ??= new ChainMap(); + this._device._renderObjectCommandMap ??= new ChainMap(); this._device._bufferMap ??= new WeakMap(); this._device._contextMap ??= new WeakMap(); this._device._computePipelineMap ??= new WeakMap(); diff --git a/src/WebGPUCache.ts b/src/WebGPUCache.ts index 5cdd20b..9b35766 100644 --- a/src/WebGPUCache.ts +++ b/src/WebGPUCache.ts @@ -14,8 +14,7 @@ export class WebGPUCache extends WebGPUBase protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { const device = this._device; - const map: ChainMap<[string, RenderPassObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); - let caches = map.get([renderPassFormat._key, renderObjects]); + let caches = device._renderPassObjectsCommandMap.get([renderPassFormat._key, renderObjects]); if (!caches) { // 收集命令 @@ -32,12 +31,12 @@ export class WebGPUCache extends WebGPUBase caches = { commands, setBindGroupCommands }; - map.set([renderPassFormat._key, renderObjects], caches); + device._renderPassObjectsCommandMap.set([renderPassFormat._key, renderObjects], caches); // 监听变化 const onchanged = () => { - map.delete([renderPassFormat._key, renderObjects]); + device._renderPassObjectsCommandMap.delete([renderPassFormat._key, renderObjects]); // renderObjects.forEach((v) => { watcher.unwatch(v, "_version" as any, onchanged); }); }; @@ -51,8 +50,7 @@ export class WebGPUCache extends WebGPUBase protected runRenderBundleObjects(bundleEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: RenderObject[]) { const device = this._device; - const map: ChainMap<[string, RenderObject[]], { commands: Array, setBindGroupCommands: Array }> = device["_IGPURenderPassObjectsCommandMap"] = device["_IGPURenderPassObjectsCommandMap"] || new ChainMap(); - let caches = map.get([renderPassFormat._key, renderObjects]); + let caches = device._renderPassObjectsCommandMap.get([renderPassFormat._key, renderObjects]); if (!caches) { // 收集命令 @@ -69,12 +67,12 @@ export class WebGPUCache extends WebGPUBase caches = { commands, setBindGroupCommands }; - map.set([renderPassFormat._key, renderObjects], caches); + device._renderPassObjectsCommandMap.set([renderPassFormat._key, renderObjects], caches); // 监听变化 const onchanged = () => { - map.delete([renderPassFormat._key, renderObjects]); + device._renderPassObjectsCommandMap.delete([renderPassFormat._key, renderObjects]); // renderObjects.forEach((v) => { watcher.unwatch(v, "_version", onchanged); }); }; @@ -91,10 +89,9 @@ export class WebGPUCache extends WebGPUBase protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) { const device = this._device; - const map: ChainMap<[string, RenderObject], Array> = device["_IGPURenderObjectCommandMap"] = device["_IGPURenderObjectCommandMap"] || new ChainMap(); const _commands = passEncoder["_commands"] as any[]; - const commands = map.get([renderPassFormat._key, renderObject]); + const commands = device._renderObjectCommandMap.get([renderPassFormat._key, renderObject]); if (commands) { commands.forEach((v) => _commands.push(v)); @@ -106,12 +103,12 @@ export class WebGPUCache extends WebGPUBase super.runRenderObject(passEncoder, renderPassFormat, renderObject); - map.set([renderPassFormat._key, renderObject], _commands.slice(start)); + device._renderObjectCommandMap.set([renderPassFormat._key, renderObject], _commands.slice(start)); // const onchanged = () => { - map.delete([renderPassFormat._key, renderObject]); + device._renderObjectCommandMap.delete([renderPassFormat._key, renderObject]); // renderObject._version = ~~renderObject._version + 1; watcher.unwatch(renderObject.pipeline, '_version', onchanged); -- Gitee From ebfe7b3fe6772b7cf771ab79050fd26157ef7867 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 20:44:06 +0800 Subject: [PATCH 086/214] =?UTF-8?q?refactor(WebGPUBase):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 合并了多个方法,简化了渲染管线的执行流程 - 优化了视口和剪裁矩形的设置逻辑 - 调整了顶点缓冲区和索引缓冲区的设置顺序 - 重构了 NRenderPipeline 的创建过程 --- src/WebGPUBase.ts | 157 ++++++++++++---------------- src/caches/getNGPURenderPipeline.ts | 9 +- 2 files changed, 74 insertions(+), 92 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 9f1c940..c2e933b 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -431,71 +431,60 @@ export class WebGPUBase { const device = this._device; const { viewport, scissorRect, pipeline, bindingResources: bindingResources, geometry } = renderObject; + const attachmentSize = renderPassFormat.attachmentSize; const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; if ("setViewport" in passEncoder) { - this.runViewport(passEncoder, renderPassFormat.attachmentSize, viewport); + if (viewport) + { + const isYup = viewport.isYup ?? true; + const x = viewport.x ?? 0; + let y = viewport.y ?? 0; + const width = viewport.width ?? attachmentSize.width; + const height = viewport.height ?? attachmentSize.height; + const minDepth = viewport.minDepth ?? 0; + const maxDepth = viewport.maxDepth ?? 0; + + if (isYup) + { + y = attachmentSize.height - y - height; + } + passEncoder.setViewport(x, y, width, height, minDepth, maxDepth); + } + else + { + passEncoder.setViewport(0, 0, attachmentSize.width, attachmentSize.height, 0, 1); + } } if ("setScissorRect" in passEncoder) { - this.runScissorRect(passEncoder as GPURenderPassEncoder, renderPassFormat.attachmentSize, scissorRect); + if (scissorRect) + { + const isYup = scissorRect.isYup ?? true; + const x = scissorRect.x ?? 0; + let y = scissorRect.y ?? 0; + const width = scissorRect.width ?? attachmentSize.width; + const height = scissorRect.height ?? attachmentSize.height; + + if (isYup) + { + y = attachmentSize.height - y - height; + } + + passEncoder.setScissorRect(x, y, width, height); + } + else + { + passEncoder.setScissorRect(0, 0, attachmentSize.width, attachmentSize.height); + } } const { primitive, vertices, indices, draw } = geometry; - this.runRenderPipeline(passEncoder, renderPassFormat, pipeline, primitive, vertices, indices); - - // 计算 bindGroups - const layout = getGPUPipelineLayout(device, shader); - layout.bindGroupLayouts.forEach((bindGroupLayout, group) => - { - const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); - passEncoder.setBindGroup(group, gpuBindGroup); - }); - - const renderPipeline = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); - - // - renderPipeline.vertexBuffers?.forEach((vertexBuffer, index) => - { - const buffer = getGBuffer(vertexBuffer.data); - (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); - - const gBuffer = getGPUBuffer(device, buffer); - - passEncoder.setVertexBuffer(index, gBuffer, vertexBuffer.offset, vertexBuffer.size); - }); - - if (indices) - { - const buffer = getGBuffer(indices); - (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); - - const gBuffer = getGPUBuffer(device, buffer); - - // - passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); - } - - if (draw.__type__ === 'DrawVertex') - { - passEncoder.draw(draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance); - } - else - { - passEncoder.drawIndexed(draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance); - } - } - - protected runRenderPipeline(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, pipeline: RenderPipeline, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) - { - const device = this._device; // - const renderPipelineResult = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); - - const nPipeline = renderPipelineResult.pipeline; + const { pipeline: nPipeline, vertexBuffers } = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); const gpuRenderPipeline = getGPURenderPipeline(device, nPipeline); @@ -526,52 +515,44 @@ export class WebGPUBase console.warn(`不支持在 ${passEncoder.constructor.name} 中设置 setBlendConstant 值!`); } } - } - protected runViewport(passEncoder: GPURenderPassEncoder, attachmentSize: { width: number, height: number }, viewport: Viewport) - { - if (viewport) + // 计算 bindGroups + const layout = getGPUPipelineLayout(device, shader); + layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { - const isYup = viewport.isYup ?? true; - const x = viewport.x ?? 0; - let y = viewport.y ?? 0; - const width = viewport.width ?? attachmentSize.width; - const height = viewport.height ?? attachmentSize.height; - const minDepth = viewport.minDepth ?? 0; - const maxDepth = viewport.maxDepth ?? 0; - - if (isYup) - { - y = attachmentSize.height - y - height; - } - passEncoder.setViewport(x, y, width, height, minDepth, maxDepth); - } - else + const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); + passEncoder.setBindGroup(group, gpuBindGroup); + }); + + // + vertexBuffers?.forEach((vertexBuffer, index) => { - passEncoder.setViewport(0, 0, attachmentSize.width, attachmentSize.height, 0, 1); - } - } + const buffer = getGBuffer(vertexBuffer.data); + (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); - protected runScissorRect(passEncoder: GPURenderPassEncoder, attachmentSize: { width: number, height: number }, scissorRect: ScissorRect) - { - if (scissorRect) + const gBuffer = getGPUBuffer(device, buffer); + + passEncoder.setVertexBuffer(index, gBuffer, vertexBuffer.offset, vertexBuffer.size); + }); + + if (indices) { - const isYup = scissorRect.isYup ?? true; - const x = scissorRect.x ?? 0; - let y = scissorRect.y ?? 0; - const width = scissorRect.width ?? attachmentSize.width; - const height = scissorRect.height ?? attachmentSize.height; + const buffer = getGBuffer(indices); + (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); - if (isYup) - { - y = attachmentSize.height - y - height; - } + const gBuffer = getGPUBuffer(device, buffer); - passEncoder.setScissorRect(x, y, width, height); + // + passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); + } + + if (draw.__type__ === 'DrawVertex') + { + passEncoder.draw(draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance); } else { - passEncoder.setScissorRect(0, 0, attachmentSize.width, attachmentSize.height); + passEncoder.drawIndexed(draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance); } } } diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 1601c7b..14993fc 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -4,11 +4,11 @@ import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; import { gPartial } from "@feng3d/polyfill"; import { MultisampleState } from "../data/MultisampleState"; -import { RenderPassFormat } from "../internal/RenderPassFormat"; import { NFragmentState } from "../internal/NFragmentState"; -import { NRenderPipeline } from "../internal/NRenderPipeline"; import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; import { NGPUVertexState } from "../internal/NGPUVertexState"; +import { NRenderPipeline } from "../internal/NRenderPipeline"; +import { RenderPassFormat } from "../internal/RenderPassFormat"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; /** @@ -44,11 +44,12 @@ export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPass // const stencilReference = getStencilReference(renderPipeline.depthStencil); + // const blendConstantColor = BlendState.getBlendConstantColor(renderPipeline.fragment?.targets?.[0]?.blend); // - const material: NRenderPipeline = { + const pipeline: NRenderPipeline = { label, primitive: gpuPrimitive, vertex: vertexStateResult.gpuVertexState, @@ -59,7 +60,7 @@ export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPass blendConstantColor, }; - result = { _version: 0, pipeline: material, vertexBuffers: vertexStateResult.vertexBuffers }; + result = { _version: 0, pipeline: pipeline, vertexBuffers: vertexStateResult.vertexBuffers }; renderPipelineMap.set([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat], result); // 监听管线变化 -- Gitee From 96be35f355747c6a925fbb7878870cc726b92f5a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 20:58:58 +0800 Subject: [PATCH 087/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=AE=A1=E7=BA=BF=E5=B8=83=E5=B1=80=E5=88=9B=E5=BB=BA=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 getGPUPipelineLayout 函数,使其支持 RenderPipeline 和 ComputePipeline 类型的参数 - 更新相关文件中的导入和使用方式,以适应新的管线布局创建逻辑 - 移除了 IGPUShader 类型,直接使用 RenderPipeline 和 ComputePipeline 类型 --- src/WebGPUBase.ts | 16 ++++------ src/caches/getGPUComputePipeline.ts | 2 +- src/caches/getGPUPipelineLayout.ts | 49 +++++++++++++++-------------- src/caches/getGPURenderPipeline.ts | 2 +- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index c2e933b..61bf4ce 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,10 +1,10 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, IIndicesDataTypes, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, ScissorRect, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes, Viewport } from "@feng3d/render-api"; +import { BindingResources, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUComputePipeline } from "./caches/getGPUComputePipeline"; -import { getGPUPipelineLayout, IGPUShader } from "./caches/getGPUPipelineLayout"; +import { getGPUPipelineLayout } from "./caches/getGPUPipelineLayout"; import { getGPURenderOcclusionQuery, GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; import { getGPURenderPassDescriptor } from "./caches/getGPURenderPassDescriptor"; import { getGPURenderPassFormat } from "./caches/getGPURenderPassFormat"; @@ -21,12 +21,12 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit } from "./eventnames"; +import { NRenderPipeline } from "./internal/NRenderPipeline"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; -import { NRenderPipeline } from "./internal/NRenderPipeline"; declare global { @@ -401,15 +401,13 @@ export class WebGPUBase protected runComputeObject(passEncoder: GPUComputePassEncoder, computeObject: ComputeObject) { const device = this._device; - const { pipeline: pipeline, uniforms: bindingResources, workgroups } = computeObject; - - const shader: IGPUShader = { compute: pipeline.compute.code }; + const { pipeline, uniforms: bindingResources, workgroups } = computeObject; const computePipeline = getGPUComputePipeline(device, pipeline); passEncoder.setPipeline(computePipeline); // 计算 bindGroups - const layout = getGPUPipelineLayout(device, shader); + const layout = getGPUPipelineLayout(device, pipeline); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); @@ -433,8 +431,6 @@ export class WebGPUBase const { viewport, scissorRect, pipeline, bindingResources: bindingResources, geometry } = renderObject; const attachmentSize = renderPassFormat.attachmentSize; - const shader: IGPUShader = { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }; - if ("setViewport" in passEncoder) { if (viewport) @@ -517,7 +513,7 @@ export class WebGPUBase } // 计算 bindGroups - const layout = getGPUPipelineLayout(device, shader); + const layout = getGPUPipelineLayout(device, pipeline); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); diff --git a/src/caches/getGPUComputePipeline.ts b/src/caches/getGPUComputePipeline.ts index 41fa67d..877b738 100644 --- a/src/caches/getGPUComputePipeline.ts +++ b/src/caches/getGPUComputePipeline.ts @@ -27,7 +27,7 @@ export function getGPUComputePipeline(device: GPUDevice, computePipeline: Comput } // 从GPU管线中获取管线布局。 - const layout = getGPUPipelineLayout(device, { compute: computeStage.code }); + const layout = getGPUPipelineLayout(device, computePipeline); pipeline = device.createComputePipeline({ layout, diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index fca7f42..020d26c 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,4 +1,6 @@ +import { RenderPipeline } from "@feng3d/render-api"; import { VariableInfo } from "wgsl_reflect"; +import { ComputePipeline } from "../data/ComputePipeline"; import { getIGPUBindGroupLayoutEntryMap, GPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; declare global @@ -48,15 +50,24 @@ declare global } } -export function getGPUPipelineLayout(device: GPUDevice, shader: IGPUShader): GPUPipelineLayout +export function getGPUPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | ComputePipeline): GPUPipelineLayout { - const shaderKey = shader.vertex + shader.fragment + shader.compute; + let shaderKey = ""; + if ("compute" in pipeline) + { + shaderKey += pipeline.compute; + } + else + { + shaderKey += pipeline.vertex.code; + if (pipeline.fragment) shaderKey += pipeline.fragment.code; + } // let gpuPipelineLayout = gpuPipelineLayoutMap0[shaderKey]; if (gpuPipelineLayout) return gpuPipelineLayout; - const layout = getIGPUPipelineLayout(device, shader); + const layout = getPipelineLayout(device, pipeline); gpuPipelineLayoutMap0[shaderKey] = layout; @@ -64,35 +75,27 @@ export function getGPUPipelineLayout(device: GPUDevice, shader: IGPUShader): GPU } const gpuPipelineLayoutMap0: { [key: string]: GPUPipelineLayout } = {}; -export type IGPUShader = { readonly vertex?: string, readonly fragment?: string, readonly compute?: string }; - /** * 从GPU管线中获取管线布局。 * - * @param shader GPU管线。 + * @param pipeline GPU管线。 * @returns 管线布局。 */ -function getIGPUPipelineLayout(device: GPUDevice, shader: IGPUShader) +function getPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | ComputePipeline) { - const vertexCode = shader.vertex; - const fragmentCode = shader.fragment; - const computeCode = shader.compute; - - let entryMap: GPUBindGroupLayoutEntryMap = {}; - if (vertexCode) - { - const vertexEntryMap = getIGPUBindGroupLayoutEntryMap(vertexCode); - entryMap = mergeBindGroupLayouts(entryMap, vertexEntryMap); - } - if (fragmentCode && fragmentCode !== vertexCode) + let entryMap: GPUBindGroupLayoutEntryMap; + if ("compute" in pipeline) { - const fragmentEntryMap = getIGPUBindGroupLayoutEntryMap(fragmentCode); - entryMap = mergeBindGroupLayouts(entryMap, fragmentEntryMap); + entryMap = getIGPUBindGroupLayoutEntryMap(pipeline.compute.code); } - if (computeCode && computeCode !== vertexCode && computeCode !== fragmentCode) + else { - const computeEntryMap = getIGPUBindGroupLayoutEntryMap(computeCode); - entryMap = mergeBindGroupLayouts(entryMap, computeEntryMap); + entryMap = getIGPUBindGroupLayoutEntryMap(pipeline.vertex.code); + if ("fragment" in pipeline) + { + const fragmentEntryMap = getIGPUBindGroupLayoutEntryMap(pipeline.fragment.code); + entryMap = mergeBindGroupLayouts(entryMap, fragmentEntryMap); + } } // 绑定组布局描述列表。 diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index 0af129a..2faf125 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -8,7 +8,7 @@ export function getGPURenderPipeline(device: GPUDevice, renderPipeline: NRenderP if (pipeline) return pipeline; // 从GPU管线中获取管线布局。 - const layout = getGPUPipelineLayout(device, { vertex: renderPipeline.vertex.code, fragment: renderPipeline.fragment?.code }); + const layout = getGPUPipelineLayout(device, renderPipeline); const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { layout, -- Gitee From 720750e9d25c4ed8da3c4b64c647c5fe3f4b05bf Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 21:09:42 +0800 Subject: [PATCH 088/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E8=AE=BE=E7=BD=AE=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 getStencilReference 和 blendConstantColor 的计算逻辑移至 WebGPUBase 中 - 更新 getNGPURenderPipeline 函数,使其返回 GPURenderPipeline 而不是 NRenderPipeline - 移除 NRenderPipeline 中的 stencilReference 和 blendConstantColor 属性 - 优化 WebGPUBase 中的渲染管线设置,直接使用新的 getNGPURenderPipeline 结果 --- src/WebGPUBase.ts | 54 ++++++++++++++++++++++++----- src/caches/getNGPURenderPipeline.ts | 51 ++++----------------------- src/internal/NRenderPipeline.ts | 10 ------ 3 files changed, 51 insertions(+), 64 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 61bf4ce..42fbd09 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly } from "@feng3d/render-api"; +import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -8,7 +8,6 @@ import { getGPUPipelineLayout } from "./caches/getGPUPipelineLayout"; import { getGPURenderOcclusionQuery, GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; import { getGPURenderPassDescriptor } from "./caches/getGPURenderPassDescriptor"; import { getGPURenderPassFormat } from "./caches/getGPURenderPassFormat"; -import { getGPURenderPipeline } from "./caches/getGPURenderPipeline"; import { getGPURenderTimestampQuery } from "./caches/getGPURenderTimestampQuery"; import { getGPUTexture } from "./caches/getGPUTexture"; import { getGBuffer } from "./caches/getIGPUBuffer"; @@ -480,19 +479,23 @@ export class WebGPUBase const { primitive, vertices, indices, draw } = geometry; // - const { pipeline: nPipeline, vertexBuffers } = getNGPURenderPipeline(pipeline, renderPassFormat, primitive, vertices, indices); + const { pipeline: nPipeline, vertexBuffers } = getNGPURenderPipeline(device, pipeline, renderPassFormat, primitive, vertices, indices); - const gpuRenderPipeline = getGPURenderPipeline(device, nPipeline); + // + passEncoder.setPipeline(nPipeline); + + // + const stencilReference = getStencilReference(pipeline.depthStencil); // - passEncoder.setPipeline(gpuRenderPipeline); + const blendConstantColor = BlendState.getBlendConstantColor(pipeline.fragment?.targets?.[0]?.blend); // 设置模板测试替换值 - if (nPipeline.stencilReference !== undefined) + if (stencilReference !== undefined) { if ("setStencilReference" in passEncoder) { - passEncoder.setStencilReference(nPipeline.stencilReference); + passEncoder.setStencilReference(stencilReference); } else { @@ -500,11 +503,11 @@ export class WebGPUBase } } - if (nPipeline.blendConstantColor !== undefined) + if (blendConstantColor !== undefined) { if ("setBlendConstant" in passEncoder) { - passEncoder.setBlendConstant(nPipeline.blendConstantColor); + passEncoder.setBlendConstant(blendConstantColor); } else { @@ -556,3 +559,36 @@ export class WebGPUBase let autoIndex = 0; let autoVertexIndex = 0; +/** + * 如果任意模板测试结果使用了 "replace" 运算,则需要再渲染前设置 `stencilReference` 值。 + * + * @param depthStencil + * @returns + */ +function getStencilReference(depthStencil?: DepthStencilState) +{ + if (!depthStencil) return undefined; + + const { stencilFront, stencilBack } = depthStencil; + + // 如果开启了模板测试,则需要设置模板索引值 + let stencilReference: number; + if (stencilFront) + { + const { failOp, depthFailOp, passOp } = stencilFront; + if (failOp === "replace" || depthFailOp === "replace" || passOp === "replace") + { + stencilReference = depthStencil?.stencilReference ?? 0; + } + } + if (stencilBack) + { + const { failOp, depthFailOp, passOp } = stencilBack; + if (failOp === "replace" || depthFailOp === "replace" || passOp === "replace") + { + stencilReference = depthStencil?.stencilReference ?? 0; + } + } + + return stencilReference; +} \ No newline at end of file diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 14993fc..1171a9d 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -10,6 +10,7 @@ import { NGPUVertexState } from "../internal/NGPUVertexState"; import { NRenderPipeline } from "../internal/NRenderPipeline"; import { RenderPassFormat } from "../internal/RenderPassFormat"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; +import { getGPURenderPipeline } from "./getGPURenderPipeline"; /** * 从渲染管线描述、渲染通道描述以及完整的顶点属性数据映射获得完整的渲染管线描述以及顶点缓冲区数组。 @@ -19,7 +20,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) +export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) { const indexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; @@ -42,12 +43,6 @@ export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPass // 从渲染通道上获取多重采样数量 const gpuMultisampleState = getGPUMultisampleState(renderPipeline.multisample, renderPassFormat.sampleCount); - // - const stencilReference = getStencilReference(renderPipeline.depthStencil); - - // - const blendConstantColor = BlendState.getBlendConstantColor(renderPipeline.fragment?.targets?.[0]?.blend); - // const pipeline: NRenderPipeline = { label, @@ -56,11 +51,11 @@ export function getNGPURenderPipeline(renderPipeline: RenderPipeline, renderPass fragment: gpuFragmentState, depthStencil: gpuDepthStencilState, multisample: gpuMultisampleState, - stencilReference, - blendConstantColor, }; - result = { _version: 0, pipeline: pipeline, vertexBuffers: vertexStateResult.vertexBuffers }; + const gpuRenderPipeline = getGPURenderPipeline(device, pipeline); + + result = { _version: 0, pipeline: gpuRenderPipeline, vertexBuffers: vertexStateResult.vertexBuffers }; renderPipelineMap.set([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat], result); // 监听管线变化 @@ -84,7 +79,7 @@ const renderPipelineMap = new ChainMap< /** * GPU渲染管线描述。 */ - pipeline: NRenderPipeline; + pipeline: GPURenderPipeline; /** * GPU渲染时使用的顶点缓冲区列表。 */ @@ -96,40 +91,6 @@ const renderPipelineMap = new ChainMap< } >(); -/** - * 如果任意模板测试结果使用了 "replace" 运算,则需要再渲染前设置 `stencilReference` 值。 - * - * @param depthStencil - * @returns - */ -function getStencilReference(depthStencil?: DepthStencilState) -{ - if (!depthStencil) return undefined; - - const { stencilFront, stencilBack } = depthStencil; - - // 如果开启了模板测试,则需要设置模板索引值 - let stencilReference: number; - if (stencilFront) - { - const { failOp, depthFailOp, passOp } = stencilFront; - if (failOp === "replace" || depthFailOp === "replace" || passOp === "replace") - { - stencilReference = depthStencil?.stencilReference ?? 0; - } - } - if (stencilBack) - { - const { failOp, depthFailOp, passOp } = stencilBack; - if (failOp === "replace" || depthFailOp === "replace" || passOp === "replace") - { - stencilReference = depthStencil?.stencilReference ?? 0; - } - } - - return stencilReference; -} - function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndexFormat) { let stripIndexFormat: GPUIndexFormat; diff --git a/src/internal/NRenderPipeline.ts b/src/internal/NRenderPipeline.ts index 41f7557..a2b6ffb 100644 --- a/src/internal/NRenderPipeline.ts +++ b/src/internal/NRenderPipeline.ts @@ -13,14 +13,4 @@ export interface NRenderPipeline readonly fragment: NFragmentState, readonly depthStencil: GPUDepthStencilState, readonly multisample: GPUMultisampleState, - - /** - * 如果任意模板测试结果使用了 "replace" 运算,则需要再渲染前设置 `stencilReference` 值。 - */ - readonly stencilReference: number; - - /** - * 当混合系数用到了混合常量值时设置混合常量值。 - */ - readonly blendConstantColor: Color; } \ No newline at end of file -- Gitee From 26149f2665fdb36c339c4f3ca913e054c908853d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 21:37:58 +0800 Subject: [PATCH 089/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E5=88=9B=E5=BB=BA=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 NRenderPipeline 接口,直接使用 RenderPipeline 描述渲染管线 - 重新定义 GPU 渲染管线缓存,使用 ChainMap 存储不同配置的管线 - 优化 getNGPURenderPipeline 函数,直接创建 GPU 渲染管线 - 删除不再使用的 getGPURenderPipeline 函数 --- src/WebGPUBase.ts | 12 ++++--- src/caches/getGPURenderPipeline.ts | 38 -------------------- src/caches/getNGPURenderPipeline.ts | 55 +++++++++++++---------------- src/internal/NRenderPipeline.ts | 16 --------- 4 files changed, 32 insertions(+), 89 deletions(-) delete mode 100644 src/caches/getGPURenderPipeline.ts delete mode 100644 src/internal/NRenderPipeline.ts diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 42fbd09..9e101e8 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly } from "@feng3d/render-api"; +import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -20,12 +20,12 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit } from "./eventnames"; -import { NRenderPipeline } from "./internal/NRenderPipeline"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; +import { NVertexBuffer } from "./internal/NGPUVertexBuffer"; declare global { @@ -39,13 +39,17 @@ declare global _textureViewMap: WeakMap; _textureMap: WeakMap; _renderPassDescriptorMap: WeakMap; - _pipelineMap: WeakMap; _shaderMap: Map; _renderPassObjectsCommandMap: ChainMap<[string, RenderPassObject[]], { commands: Array; setBindGroupCommands: Array; }>; _renderObjectCommandMap: ChainMap<[string, RenderObject], Array>; + _renderPipelineMap: ChainMap<[RenderPipeline, string, PrimitiveState, VertexAttributes, GPUIndexFormat], { + pipeline: GPURenderPipeline; + vertexBuffers: NVertexBuffer[]; + _version: number; + }> } } @@ -88,6 +92,7 @@ export class WebGPUBase { this._device._bindGroupMap ??= new ChainMap(); this._device._renderPassObjectsCommandMap ??= new ChainMap(); + this._device._renderPipelineMap ??= new ChainMap(); this._device._renderObjectCommandMap ??= new ChainMap(); this._device._bufferMap ??= new WeakMap(); this._device._contextMap ??= new WeakMap(); @@ -96,7 +101,6 @@ export class WebGPUBase this._device._textureMap ??= new WeakMap(); this._device._textureViewMap ??= new WeakMap(); this._device._renderPassDescriptorMap ??= new WeakMap(); - this._device._pipelineMap ??= new WeakMap(); this._device._shaderMap ??= new Map(); } } diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts deleted file mode 100644 index 2faf125..0000000 --- a/src/caches/getGPURenderPipeline.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { NRenderPipeline } from "../internal/NRenderPipeline"; -import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; -import { getGPUShaderModule } from "./getGPUShaderModule"; - -export function getGPURenderPipeline(device: GPUDevice, renderPipeline: NRenderPipeline) -{ - let pipeline = device._pipelineMap.get(renderPipeline); - if (pipeline) return pipeline; - - // 从GPU管线中获取管线布局。 - const layout = getGPUPipelineLayout(device, renderPipeline); - - const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { - layout, - vertex: { - ...renderPipeline.vertex, - module: getGPUShaderModule(device, renderPipeline.vertex.code), - }, - primitive: renderPipeline.primitive, - depthStencil: renderPipeline.depthStencil, - multisample: renderPipeline.multisample, - }; - - if (renderPipeline.fragment) - { - gpuRenderPipelineDescriptor.fragment = { - ...renderPipeline.fragment, - module: getGPUShaderModule(device, renderPipeline.fragment.code), - }; - } - - pipeline = device.createRenderPipeline(gpuRenderPipelineDescriptor); - - device._pipelineMap.set(renderPipeline, pipeline); - - return pipeline; -} - diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 1171a9d..b4a8cc6 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -7,10 +7,10 @@ import { MultisampleState } from "../data/MultisampleState"; import { NFragmentState } from "../internal/NFragmentState"; import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; import { NGPUVertexState } from "../internal/NGPUVertexState"; -import { NRenderPipeline } from "../internal/NRenderPipeline"; import { RenderPassFormat } from "../internal/RenderPassFormat"; +import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; +import { getGPUShaderModule } from "./getGPUShaderModule"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; -import { getGPURenderPipeline } from "./getGPURenderPipeline"; /** * 从渲染管线描述、渲染通道描述以及完整的顶点属性数据映射获得完整的渲染管线描述以及顶点缓冲区数组。 @@ -24,11 +24,9 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP { const indexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; - let result = renderPipelineMap.get([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); + let result = device._renderPipelineMap.get([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); if (result) return result; - const { label } = renderPipeline; - const gpuPrimitive = getGPUPrimitiveState(primitive, indexFormat); // 获取完整的顶点阶段描述与顶点缓冲区列表。 @@ -43,27 +41,40 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP // 从渲染通道上获取多重采样数量 const gpuMultisampleState = getGPUMultisampleState(renderPipeline.multisample, renderPassFormat.sampleCount); - // - const pipeline: NRenderPipeline = { - label, + // 从GPU管线中获取管线布局。 + const layout = getGPUPipelineLayout(device, renderPipeline); + + const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { + label: renderPipeline.label, + layout, + vertex: { + ...vertexStateResult.gpuVertexState, + module: getGPUShaderModule(device, renderPipeline.vertex.code), + }, primitive: gpuPrimitive, - vertex: vertexStateResult.gpuVertexState, - fragment: gpuFragmentState, depthStencil: gpuDepthStencilState, multisample: gpuMultisampleState, }; - const gpuRenderPipeline = getGPURenderPipeline(device, pipeline); + if (gpuFragmentState) + { + gpuRenderPipelineDescriptor.fragment = { + ...gpuFragmentState, + module: getGPUShaderModule(device, renderPipeline.fragment.code), + }; + } + + const gpuRenderPipeline = device.createRenderPipeline(gpuRenderPipelineDescriptor); result = { _version: 0, pipeline: gpuRenderPipeline, vertexBuffers: vertexStateResult.vertexBuffers }; - renderPipelineMap.set([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat], result); + device._renderPipelineMap.set([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat], result); // 监听管线变化 const onchanged = () => { result._version++; renderPipeline._version = ~~renderPipeline._version + 1; - renderPipelineMap.delete([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); + device._renderPipelineMap.delete([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); watcher.unwatch(vertexStateResult, "_version", onchanged); gpuFragmentState && watcher.unwatch(gpuFragmentState, "_version", onchanged); } @@ -73,24 +84,6 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP return result; } -const renderPipelineMap = new ChainMap< - [RenderPipeline, string, PrimitiveState, VertexAttributes, GPUIndexFormat], - { - /** - * GPU渲染管线描述。 - */ - pipeline: GPURenderPipeline; - /** - * GPU渲染时使用的顶点缓冲区列表。 - */ - vertexBuffers: NVertexBuffer[]; - /** - * 版本号 - */ - _version: number; - } ->(); - function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndexFormat) { let stripIndexFormat: GPUIndexFormat; diff --git a/src/internal/NRenderPipeline.ts b/src/internal/NRenderPipeline.ts deleted file mode 100644 index a2b6ffb..0000000 --- a/src/internal/NRenderPipeline.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Color } from "@feng3d/render-api"; -import { NFragmentState } from "./NFragmentState"; -import { NGPUVertexState } from "./NGPUVertexState"; - -/** - * 内部对象。 - */ -export interface NRenderPipeline -{ - readonly label: string; - readonly primitive: GPUPrimitiveState; - readonly vertex: NGPUVertexState - readonly fragment: NFragmentState, - readonly depthStencil: GPUDepthStencilState, - readonly multisample: GPUMultisampleState, -} \ No newline at end of file -- Gitee From f96c766cfa3ad4b400dd5f1859ee7e7aeacbbb8f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 22:13:09 +0800 Subject: [PATCH 090/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E5=B8=83=E5=B1=80=E5=92=8C?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E5=AF=B9=E8=B1=A1=E5=88=9B=E5=BB=BA=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 WebGPUBase 中添加 _pipelineLayoutMap 用于缓存管线布局 - 优化 getGPUPipelineLayout 函数,增加对已有布局的缓存使用 - 重构 getNGPURenderPipeline 函数,简化顶点和片段状态的创建 - 删除不再使用的 NFragmentState 和 NGPUVertexState 接口 --- src/WebGPUBase.ts | 2 ++ src/caches/getGPUPipelineLayout.ts | 27 ++++++++++++++++------ src/caches/getNGPURenderPipeline.ts | 36 ++++++++++------------------- src/internal/NFragmentState.ts | 15 ------------ src/internal/NGPUVertexState.ts | 21 ----------------- 5 files changed, 34 insertions(+), 67 deletions(-) delete mode 100644 src/internal/NFragmentState.ts delete mode 100644 src/internal/NGPUVertexState.ts diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 9e101e8..c30119c 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -40,6 +40,7 @@ declare global _textureMap: WeakMap; _renderPassDescriptorMap: WeakMap; _shaderMap: Map; + _pipelineLayoutMap: WeakMap; _renderPassObjectsCommandMap: ChainMap<[string, RenderPassObject[]], { commands: Array; setBindGroupCommands: Array; @@ -101,6 +102,7 @@ export class WebGPUBase this._device._textureMap ??= new WeakMap(); this._device._textureViewMap ??= new WeakMap(); this._device._renderPassDescriptorMap ??= new WeakMap(); + this._device._pipelineLayoutMap ??= new WeakMap(); this._device._shaderMap ??= new Map(); } } diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 020d26c..61f8f22 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -83,6 +83,9 @@ const gpuPipelineLayoutMap0: { [key: string]: GPUPipelineLayout } = {}; */ function getPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | ComputePipeline) { + let gpuPipelineLayout = device._pipelineLayoutMap.get(pipeline); + if (gpuPipelineLayout) return gpuPipelineLayout; + let entryMap: GPUBindGroupLayoutEntryMap; if ("compute" in pipeline) { @@ -133,9 +136,13 @@ function getPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | Compute console.log(`命中相同的布局 ${key},公用绑定组布局对象。`); } } - const bindGroupLayout: GPUBindGroupLayout = bindGroupLayoutMap[key] = bindGroupLayoutMap[key] || device.createBindGroupLayout({ entries, label: key }); - bindGroupLayout.entries = entries; - bindGroupLayout.key = key; + let bindGroupLayout = bindGroupLayoutMap[key]; + if (!bindGroupLayout) + { + bindGroupLayout = bindGroupLayoutMap[key] = device.createBindGroupLayout({ entries, label: key }); + bindGroupLayout.entries = entries; + bindGroupLayout.key = key; + } return bindGroupLayout; }); @@ -148,10 +155,16 @@ function getPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | Compute console.log(`命中相同的布局 ${pipelineLayoutKey},公用管线布局对象。`); } } - const gpuPipelineLayout: GPUPipelineLayout = pipelineLayoutDescriptorMap[pipelineLayoutKey] = pipelineLayoutDescriptorMap[pipelineLayoutKey] || device.createPipelineLayout({ - bindGroupLayouts, - }); - gpuPipelineLayout.bindGroupLayouts = bindGroupLayouts; + gpuPipelineLayout = pipelineLayoutDescriptorMap[pipelineLayoutKey]; + if (!gpuPipelineLayout) + { + gpuPipelineLayout = pipelineLayoutDescriptorMap[pipelineLayoutKey] = device.createPipelineLayout({ + bindGroupLayouts, + }); + gpuPipelineLayout.bindGroupLayouts = bindGroupLayouts; + } + + device._pipelineLayoutMap.set(pipeline, gpuPipelineLayout); return gpuPipelineLayout; } diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index b4a8cc6..2a9fb02 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -4,9 +4,7 @@ import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; import { gPartial } from "@feng3d/polyfill"; import { MultisampleState } from "../data/MultisampleState"; -import { NFragmentState } from "../internal/NFragmentState"; import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; -import { NGPUVertexState } from "../internal/NGPUVertexState"; import { RenderPassFormat } from "../internal/RenderPassFormat"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; import { getGPUShaderModule } from "./getGPUShaderModule"; @@ -30,10 +28,10 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const gpuPrimitive = getGPUPrimitiveState(primitive, indexFormat); // 获取完整的顶点阶段描述与顶点缓冲区列表。 - const vertexStateResult = getNGPUVertexState(renderPipeline.vertex, vertices); + const vertexStateResult = getNGPUVertexState(device, renderPipeline.vertex, vertices); // 获取片段阶段完整描述。 - const gpuFragmentState = getNGPUFragmentState(renderPipeline.fragment, renderPassFormat.colorFormats); + const gpuFragmentState = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); // 获取深度模板阶段完整描述。 const gpuDepthStencilState = getGPUDepthStencilState(renderPipeline.depthStencil, renderPassFormat.depthStencilFormat); @@ -47,23 +45,13 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { label: renderPipeline.label, layout, - vertex: { - ...vertexStateResult.gpuVertexState, - module: getGPUShaderModule(device, renderPipeline.vertex.code), - }, + vertex: vertexStateResult.gpuVertexState, + fragment: gpuFragmentState, primitive: gpuPrimitive, depthStencil: gpuDepthStencilState, multisample: gpuMultisampleState, }; - if (gpuFragmentState) - { - gpuRenderPipelineDescriptor.fragment = { - ...gpuFragmentState, - module: getGPUShaderModule(device, renderPipeline.fragment.code), - }; - } - const gpuRenderPipeline = device.createRenderPipeline(gpuRenderPipelineDescriptor); result = { _version: 0, pipeline: gpuRenderPipeline, vertexBuffers: vertexStateResult.vertexBuffers }; @@ -170,7 +158,7 @@ function getGPUStencilFaceState(stencilFaceState?: StencilFaceState) * @param vertices 顶点数据。 * @returns 完整的顶点阶段描述与顶点缓冲区列表。 */ -function getNGPUVertexState(vertexState: VertexState, vertices: VertexAttributes) +function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) { let result = vertexStateMap.get([vertexState, vertices]); if (result) return result; @@ -193,8 +181,8 @@ function getNGPUVertexState(vertexState: VertexState, vertices: VertexAttributes const { vertexBufferLayouts, vertexBuffers } = getNGPUVertexBuffers(vertex, vertices); - const gpuVertexState: NGPUVertexState = { - code, + const gpuVertexState: GPUVertexState = { + module: getGPUShaderModule(device, vertexState.code), entryPoint, buffers: vertexBufferLayouts, constants: vertexState.constants, @@ -218,7 +206,7 @@ function getNGPUVertexState(vertexState: VertexState, vertices: VertexAttributes } const vertexStateMap = new ChainMap<[VertexState, VertexAttributes], { - gpuVertexState: NGPUVertexState; + gpuVertexState: GPUVertexState; vertexBuffers: NVertexBuffer[]; /** * 版本号,用于版本控制。 @@ -315,13 +303,13 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) * @param colorAttachmentTextureFormats 颜色附件格式。 * @returns 片段阶段完整描述。 */ -function getNGPUFragmentState(fragmentState: FragmentState, colorAttachments: readonly GPUTextureFormat[]) +function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, colorAttachments: readonly GPUTextureFormat[]) { if (!fragmentState) return undefined; const colorAttachmentsKey = colorAttachments.toString(); - let gpuFragmentState: NFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); + let gpuFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); if (gpuFragmentState) return gpuFragmentState; const code = fragmentState.code; @@ -363,7 +351,7 @@ function getNGPUFragmentState(fragmentState: FragmentState, colorAttachments: re }); gpuFragmentState = { - code, + module: getGPUShaderModule(device, fragmentState.code), entryPoint, targets, constants: fragmentState.constants @@ -384,7 +372,7 @@ function getNGPUFragmentState(fragmentState: FragmentState, colorAttachments: re return gpuFragmentState; } -const fragmentStateMap = new ChainMap<[FragmentState, string], NFragmentState>(); +const fragmentStateMap = new ChainMap<[FragmentState, string], GPUFragmentState>(); function getGPUBlendState(blend?: BlendState): GPUBlendState { diff --git a/src/internal/NFragmentState.ts b/src/internal/NFragmentState.ts deleted file mode 100644 index 361f839..0000000 --- a/src/internal/NFragmentState.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * 内部对象。 - */ -export interface NFragmentState -{ - readonly code: string; - readonly entryPoint: string; - readonly targets: readonly GPUColorTargetState[]; - readonly constants: Readonly>; - - _version?: number; -} \ No newline at end of file diff --git a/src/internal/NGPUVertexState.ts b/src/internal/NGPUVertexState.ts deleted file mode 100644 index 70d4d45..0000000 --- a/src/internal/NGPUVertexState.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { VertexState } from "@feng3d/render-api"; - -/** - * 内部对象。 - */ -export interface NGPUVertexState extends VertexState -{ - readonly entryPoint: string; - readonly constants: Readonly>; - - /** - * A list of {@link GPUVertexBufferLayout}s defining the layout of the vertex attribute data in the - * vertex buffers used by this pipeline. - * - * 自动根据反射信息生成,不用设置。 - */ - readonly buffers: GPUVertexBufferLayout[]; -} -- Gitee From d0c076061ecf5a1c6d165f7e0442f3badfd57a16 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 22:26:05 +0800 Subject: [PATCH 091/214] =?UTF-8?q?refactor(WebGPU):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=AE=A1=E7=BA=BF=E5=B8=83=E5=B1=80=E7=BC=93=E5=AD=98=E7=AD=96?= =?UTF-8?q?=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 _pipelineLayoutMap 从 WeakMap 改为 Map,使用字符串作为键值 - 在 getGPUPipelineLayout 中实现着色器代码的更高效处理 - 移除冗余的 mergeBindGroupLayouts 函数,直接在 getPipelineLayout 中处理 - 优化了对相同名称变量的检测和警告逻辑 --- src/WebGPUBase.ts | 4 +- src/caches/getGPUPipelineLayout.ts | 77 +++++++++++------------------- 2 files changed, 30 insertions(+), 51 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index c30119c..c95550d 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -40,7 +40,7 @@ declare global _textureMap: WeakMap; _renderPassDescriptorMap: WeakMap; _shaderMap: Map; - _pipelineLayoutMap: WeakMap; + _pipelineLayoutMap: Map; _renderPassObjectsCommandMap: ChainMap<[string, RenderPassObject[]], { commands: Array; setBindGroupCommands: Array; @@ -102,7 +102,7 @@ export class WebGPUBase this._device._textureMap ??= new WeakMap(); this._device._textureViewMap ??= new WeakMap(); this._device._renderPassDescriptorMap ??= new WeakMap(); - this._device._pipelineLayoutMap ??= new WeakMap(); + this._device._pipelineLayoutMap ??= new Map(); this._device._shaderMap ??= new Map(); } } diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 61f8f22..41ae669 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -50,7 +50,13 @@ declare global } } -export function getGPUPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | ComputePipeline): GPUPipelineLayout +/** + * 从GPU管线中获取管线布局。 + * + * @param pipeline GPU管线。 + * @returns 管线布局。 + */ +export function getGPUPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | ComputePipeline) { let shaderKey = ""; if ("compute" in pipeline) @@ -60,30 +66,10 @@ export function getGPUPipelineLayout(device: GPUDevice, pipeline: RenderPipeline else { shaderKey += pipeline.vertex.code; - if (pipeline.fragment) shaderKey += pipeline.fragment.code; + if (pipeline.fragment) shaderKey += `\n// ------顶点与片段着色器分界--------\n` + pipeline.fragment.code; } - // - let gpuPipelineLayout = gpuPipelineLayoutMap0[shaderKey]; - if (gpuPipelineLayout) return gpuPipelineLayout; - - const layout = getPipelineLayout(device, pipeline); - - gpuPipelineLayoutMap0[shaderKey] = layout; - - return layout; -} -const gpuPipelineLayoutMap0: { [key: string]: GPUPipelineLayout } = {}; - -/** - * 从GPU管线中获取管线布局。 - * - * @param pipeline GPU管线。 - * @returns 管线布局。 - */ -function getPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | ComputePipeline) -{ - let gpuPipelineLayout = device._pipelineLayoutMap.get(pipeline); + let gpuPipelineLayout = device._pipelineLayoutMap.get(shaderKey); if (gpuPipelineLayout) return gpuPipelineLayout; let entryMap: GPUBindGroupLayoutEntryMap; @@ -97,7 +83,24 @@ function getPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | Compute if ("fragment" in pipeline) { const fragmentEntryMap = getIGPUBindGroupLayoutEntryMap(pipeline.fragment.code); - entryMap = mergeBindGroupLayouts(entryMap, fragmentEntryMap); + for (const resourceName in fragmentEntryMap) + { + // 检测相同名称是否被定义在多个地方 + if (entryMap[resourceName]) + { + const preEntry = entryMap[resourceName].variableInfo; + const currentEntry = fragmentEntryMap[resourceName].variableInfo; + + if (preEntry.group !== currentEntry.group + || preEntry.binding !== currentEntry.binding + || preEntry.resourceType !== currentEntry.resourceType + ) + { + console.warn(`分别在 着色器 @group(${preEntry.group}) @binding(${preEntry.binding}) 与 @group(${currentEntry.group}) @binding(${currentEntry.binding}) 处存在相同名称的变量 ${currentEntry.name} 。`); + } + } + entryMap[resourceName] = fragmentEntryMap[resourceName]; + } } } @@ -164,34 +167,10 @@ function getPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | Compute gpuPipelineLayout.bindGroupLayouts = bindGroupLayouts; } - device._pipelineLayoutMap.set(pipeline, gpuPipelineLayout); + device._pipelineLayoutMap.set(shaderKey, gpuPipelineLayout); return gpuPipelineLayout; } const bindGroupLayoutMap: { [key: string]: GPUBindGroupLayout } = {}; const pipelineLayoutDescriptorMap: { [key: string]: GPUPipelineLayout } = {}; - -function mergeBindGroupLayouts(entryMap: GPUBindGroupLayoutEntryMap, entryMap1: GPUBindGroupLayoutEntryMap): GPUBindGroupLayoutEntryMap -{ - for (const resourceName in entryMap1) - { - // 检测相同名称是否被定义在多个地方 - if (entryMap[resourceName]) - { - const preEntry = entryMap[resourceName].variableInfo; - const currentEntry = entryMap1[resourceName].variableInfo; - - if (preEntry.group !== currentEntry.group - || preEntry.binding !== currentEntry.binding - || preEntry.resourceType !== currentEntry.resourceType - ) - { - console.warn(`分别在 着色器 @group(${preEntry.group}) @binding(${preEntry.binding}) 与 @group(${currentEntry.group}) @binding(${currentEntry.binding}) 处存在相同名称的变量 ${currentEntry.name} 。`); - } - } - entryMap[resourceName] = entryMap1[resourceName]; - } - - return entryMap; -} -- Gitee From bf08342ea9916e67677b5936f1d87d0e5003ccaf Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 22:33:14 +0800 Subject: [PATCH 092/214] =?UTF-8?q?refactor(caches):=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=20GPUBindGroupLayoutEntry=20=E6=8E=A5=E5=8F=A3=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 GPUBindGroupLayoutEntry 接口从 getGPUPipelineLayout.ts 移动到 getWGSLReflectInfo.ts - 这个改动有助于更好地组织代码结构,将相关定义集中到一起 --- src/caches/getGPUPipelineLayout.ts | 17 ----------------- src/caches/getWGSLReflectInfo.ts | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 41ae669..b3d6e31 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -31,23 +31,6 @@ declare global */ key: string, } - - interface GPUBindGroupLayoutEntry - { - /** - * 绑定资源变量信息。 - * - * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 - */ - variableInfo: VariableInfo; - - /** - * 用于判断布局信息是否相同的标识。 - * - * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 - */ - key: string; - } } /** diff --git a/src/caches/getWGSLReflectInfo.ts b/src/caches/getWGSLReflectInfo.ts index f9d7251..403a301 100644 --- a/src/caches/getWGSLReflectInfo.ts +++ b/src/caches/getWGSLReflectInfo.ts @@ -1,6 +1,26 @@ import { ResourceType, TemplateInfo, VariableInfo, WgslReflect } from "wgsl_reflect"; import { DepthTextureType, ExternalSampledTextureType, MultisampledTextureType, TextureType } from "../types/TextureType"; +declare global +{ + interface GPUBindGroupLayoutEntry + { + /** + * 绑定资源变量信息。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + variableInfo: VariableInfo; + + /** + * 用于判断布局信息是否相同的标识。 + * + * 注:wgsl着色器被反射过程中将会被引擎自动赋值。 + */ + key: string; + } +} + /** * 从WebGPU着色器代码中获取反射信息。 * -- Gitee From 586f93f75d8d3589d647cd2b47e32aabde0b9b7c Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 16 Mar 2025 23:43:36 +0800 Subject: [PATCH 093/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E9=81=93=E7=BC=93=E5=AD=98=E5=92=8C?= =?UTF-8?q?=E7=9D=80=E8=89=B2=E5=99=A8=E5=85=A5=E5=8F=A3=E7=82=B9=E8=AE=A1?= =?UTF-8?q?=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 reactive 和 computed 优化 FragmentState 的响应式处理 - 改进着色器入口点的计算逻辑,支持动态变化 - 优化 RenderObject 的着色器代码更新方式 - 调整 getNGPURenderPipeline 中的 FragmentState 处理流程 --- .../src/webgpu/RenderObjectChanges/index.ts | 4 +- src/caches/getNGPURenderPipeline.ts | 85 +++++++++++-------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index e45415b..39287e0 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -1,4 +1,4 @@ -import { Submit, RenderObject } from "@feng3d/render-api"; +import { Submit, RenderObject, reactive } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement) => @@ -80,7 +80,7 @@ const init = async (canvas: HTMLCanvasElement) => `; // 修改片段着色器代码 - renderObject.pipeline.fragment.code = ` + reactive(renderObject.pipeline.fragment).code = ` @binding(0) @group(0) var color : vec4; @fragment fn main() -> @location(0) vec4f { diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 2a9fb02..ecb85b8 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState, ChainMap, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; +import { BlendState, ChainMap, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -87,7 +87,6 @@ function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndex // const gpuPrimitive: GPUPrimitiveState = { - ...primitive, topology, stripIndexFormat, frontFace, @@ -310,24 +309,7 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co const colorAttachmentsKey = colorAttachments.toString(); let gpuFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); - if (gpuFragmentState) return gpuFragmentState; - - const code = fragmentState.code; - let entryPoint = fragmentState.entryPoint; - let fragment: FunctionInfo; - const reflect = getWGSLReflectInfo(code); - if (!entryPoint) - { - fragment = reflect.entry.fragment[0]; - console.assert(!!fragment, `WGSL着色器 ${code} 中不存在片元入口点。`); - entryPoint = fragment.name; - } - else - { - // 验证着色器中包含指定片段入口函数。 - fragment = reflect.entry.fragment.filter((v) => v.name === entryPoint)[0]; - console.assert(!!fragment, `WGSL着色器 ${code} 中不存在指定的片元入口点 ${entryPoint} 。`); - } + if (gpuFragmentState) return gpuFragmentState.value; const targets = colorAttachments.map((format, i) => { @@ -350,29 +332,58 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co return gpuColorTargetState; }); - gpuFragmentState = { - module: getGPUShaderModule(device, fragmentState.code), - entryPoint, - targets, - constants: fragmentState.constants - }; + const entryPoint = computed(() => + { + // 监听着色器入口点变化 + reactive(fragmentState).entryPoint; - fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); + // + let entryPoint = fragmentState.entryPoint; + if (entryPoint) return entryPoint; - // 监听变化 - const watchpropertys: gPartial = { code: "" }; - const onchanged = () => + // 监听着色器代码变化 + reactive(fragmentState).code; + + // 计算片元着色器入口点 + const code = fragmentState.code; + let fragment: FunctionInfo; + if (!entryPoint) + { + const reflect = getWGSLReflectInfo(code); + fragment = reflect.entry.fragment[0]; + console.assert(!!fragment, `WGSL着色器 ${code} 中不存在片元入口点。`); + entryPoint = fragment.name; + } + else + { + // 验证着色器中包含指定片段入口函数。 + const reflect = getWGSLReflectInfo(code); + fragment = reflect.entry.fragment.filter((v) => v.name === entryPoint)[0]; + console.assert(!!fragment, `WGSL着色器 ${code} 中不存在指定的片元入口点 ${entryPoint} 。`); + } + return entryPoint; + }); + + gpuFragmentState = computed(() => { - fragmentStateMap.delete([fragmentState, colorAttachmentsKey]); - gpuFragmentState._version = ~~gpuFragmentState._version + 1; - watcher.unwatchobject(fragmentState, watchpropertys, onchanged); - }; - watcher.watchobject(fragmentState, watchpropertys, onchanged); + // 监听着色器代码变化 + reactive(fragmentState).code; + + return { + module: getGPUShaderModule(device, fragmentState.code), + entryPoint: entryPoint.value, + targets, + constants: fragmentState.constants + } as GPUFragmentState; + }); - return gpuFragmentState; + fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); + + return gpuFragmentState.value; } -const fragmentStateMap = new ChainMap<[FragmentState, string], GPUFragmentState>(); +const fragmentStateMap = new ChainMap<[FragmentState, string], ComputedRef>(); + function getGPUBlendState(blend?: BlendState): GPUBlendState { -- Gitee From 304358a63107f6d804756e3b8e1ed08da1bcfca2 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 17 Mar 2025 13:39:24 +0800 Subject: [PATCH 094/214] =?UTF-8?q?refactor(blending):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E9=A2=9C=E8=89=B2=E6=B7=B7=E5=90=88=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化颜色和 alpha 混合组件的定义和使用 - 采用响应式编程方式更新混合状态 - 调整渲染对象和提交结构 - 重构 WebGPU 和 WebGPUBase 类 - 优化 getNGPURenderPipeline 和相关函数 --- examples/src/webgpu/blending/index.ts | 196 +++++++++++++------------- src/WebGPU.ts | 4 +- src/WebGPUBase.ts | 4 +- src/caches/getNGPURenderPipeline.ts | 134 ++++++++++-------- 4 files changed, 180 insertions(+), 158 deletions(-) diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 07a5e5c..1d5ef6e 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import texturedQuadWGSL from "./texturedQuad.wgsl"; -import { BindingResources, BlendComponent, CanvasContext, reactive, RenderObject, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureView } from "@feng3d/render-api"; +import { BindingResources, BlendComponent, CanvasContext, Color, computed, reactive, RenderObject, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureView } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; declare module "@feng3d/render-api" @@ -328,22 +328,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const kPresets = keysOf(presets); type Preset = (typeof kPresets)[number]; - const color: BlendComponent = { - operation: "add", - srcFactor: "one", - dstFactor: "one-minus-src", - }; - - const alpha: BlendComponent = { - operation: "add", - srcFactor: "one", - dstFactor: "one-minus-src", - }; - - const constant = { + const constant = reactive({ color: [1, 0.5, 0.25], alpha: 1, - }; + }); const clear = { color: [0, 0, 0], @@ -383,11 +371,41 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } } + const srcPipeline: RenderPipeline = { + label: "hardcoded textured quad pipeline", + vertex: { + code: texturedQuadWGSL, + }, + fragment: { + code: texturedQuadWGSL, + targets: [ + { + blend: { + constantColor: [0, 0, 0, 0], + color: { + operation: "add", + srcFactor: "one", + dstFactor: "one-minus-src", + }, + alpha: { + operation: "add", + srcFactor: "one", + dstFactor: "one-minus-src", + }, + }, + }, + ], + }, + }; + + const r_color = reactive(srcPipeline.fragment.targets[0].blend.color); + const r_alpha = reactive(srcPipeline.fragment.targets[0].blend.alpha); + function applyPreset() { const preset = presets[settings.preset]; - Object.assign(color, preset.color); - Object.assign(alpha, preset.alpha || preset.color); + Object.assign(r_color, preset.color); + Object.assign(r_alpha, preset.alpha || preset.color); } gui @@ -409,15 +427,15 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const colorFolder = gui.addFolder("color"); colorFolder.open(); - colorFolder.add(color, "operation", operations).onChange(render); - colorFolder.add(color, "srcFactor", factors).onChange(render); - colorFolder.add(color, "dstFactor", factors).onChange(render); + colorFolder.add(r_color, "operation", operations).onChange(render); + colorFolder.add(r_color, "srcFactor", factors).onChange(render); + colorFolder.add(r_color, "dstFactor", factors).onChange(render); const alphaFolder = gui.addFolder("alpha"); alphaFolder.open(); - alphaFolder.add(alpha, "operation", operations).onChange(render); - alphaFolder.add(alpha, "srcFactor", factors).onChange(render); - alphaFolder.add(alpha, "dstFactor", factors).onChange(render); + alphaFolder.add(r_alpha, "operation", operations).onChange(render); + alphaFolder.add(r_alpha, "srcFactor", factors).onChange(render); + alphaFolder.add(r_alpha, "dstFactor", factors).onChange(render); const constantFolder = gui.addFolder("constant"); constantFolder.open(); @@ -443,32 +461,69 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, }; + function updateUniforms( + uniforms: { matrix: Float32Array; }, + canvas: HTMLCanvasElement, + texture: Texture + ) + { + const projectionMatrix = mat4.ortho( + 0, + canvas.width / devicePixelRatio, + canvas.height / devicePixelRatio, + 0, + -1, + 1 + ); + + mat4.scale( + projectionMatrix, + [texture.size[0], texture.size[1], 1], + uniforms.matrix + ); + + uniforms.matrix = new Float32Array(uniforms.matrix); + } + + + const ro: RenderObject = { + pipeline: dstPipeline, + geometry: { + draw: { __type__: "DrawVertex", vertexCount: 6 }, + } + }; + + const ro1: RenderObject = { + pipeline: srcPipeline, + geometry: { + draw: { __type__: "DrawVertex", vertexCount: 6 }, + } + }; + + const renderObjects: RenderPassObject[] = [ + ro, + ro1, + ]; + + const submit: Submit = { + commandEncoders: [{ + passEncoders: [{ + descriptor: renderPassDescriptor, + renderObjects: renderObjects + }] + }], + }; + function render() { gui.updateDisplay(); - const srcPipeline: RenderPipeline = { - label: "hardcoded textured quad pipeline", - vertex: { - code: texturedQuadWGSL, - }, - fragment: { - code: texturedQuadWGSL, - targets: [ - { - blend: { - constantColor: [...constant.color, constant.alpha] as any, - color, - alpha, - }, - }, - ], - }, - }; - const { srcTexture, dstTexture, srcBindGroup, dstBindGroup } = textureSets[settings.textureSet === "premultiplied alpha" ? 0 : 1]; + ro.bindingResources = dstBindGroup; + ro1.bindingResources = srcBindGroup; + reactive(context.configuration).alphaMode = settings.alphaMode; // Apply the clearValue, pre-multiplying or not it based on the settings. @@ -481,65 +536,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => clearValue[3] = alpha; } - function updateUniforms( - uniforms: { - matrix: Float32Array; - }, - canvas: HTMLCanvasElement, - texture: Texture - ) - { - const projectionMatrix = mat4.ortho( - 0, - canvas.width / devicePixelRatio, - canvas.height / devicePixelRatio, - 0, - -1, - 1 - ); - - mat4.scale( - projectionMatrix, - [texture.size[0], texture.size[1], 1], - uniforms.matrix - ); - - uniforms.matrix = new Float32Array(uniforms.matrix); - } updateUniforms(srcUniform, canvas, srcTexture); updateUniforms(dstUniform, canvas, dstTexture); - const ro: RenderObject = { - pipeline: dstPipeline, - bindingResources: dstBindGroup, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6 }, - } - }; - - const ro1: RenderObject = { - pipeline: srcPipeline, - bindingResources: srcBindGroup, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6 }, - } - }; - - const renderObjects: RenderPassObject[] = [ - ro, - ro1, - ]; - - const submit: Submit = { - commandEncoders: [{ - passEncoders: [{ - descriptor: renderPassDescriptor, - renderObjects: renderObjects - }] - }], - }; - webgpu.submit(submit); + + requestAnimationFrame(render); } applyPreset(); diff --git a/src/WebGPU.ts b/src/WebGPU.ts index 7f63152..570b057 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,3 +1,4 @@ +import { WebGPUBase } from "./WebGPUBase"; import { WebGPUCache } from "./WebGPUCache"; /** @@ -5,7 +6,8 @@ import { WebGPUCache } from "./WebGPUCache"; * * 提供 `WebGPU` 操作入口 {@link WebGPU.submit}。 */ -export class WebGPU extends WebGPUCache +// export class WebGPU extends WebGPUCache +export class WebGPU extends WebGPUBase { } diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index c95550d..80628bb 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -47,7 +47,7 @@ declare global }>; _renderObjectCommandMap: ChainMap<[string, RenderObject], Array>; _renderPipelineMap: ChainMap<[RenderPipeline, string, PrimitiveState, VertexAttributes, GPUIndexFormat], { - pipeline: GPURenderPipeline; + pipeline: ComputedRef; vertexBuffers: NVertexBuffer[]; _version: number; }> @@ -488,7 +488,7 @@ export class WebGPUBase const { pipeline: nPipeline, vertexBuffers } = getNGPURenderPipeline(device, pipeline, renderPassFormat, primitive, vertices, indices); // - passEncoder.setPipeline(nPipeline); + passEncoder.setPipeline(nPipeline.value); // const stencilReference = getStencilReference(pipeline.depthStencil); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index ecb85b8..8e2aca6 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -30,9 +30,6 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP // 获取完整的顶点阶段描述与顶点缓冲区列表。 const vertexStateResult = getNGPUVertexState(device, renderPipeline.vertex, vertices); - // 获取片段阶段完整描述。 - const gpuFragmentState = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); - // 获取深度模板阶段完整描述。 const gpuDepthStencilState = getGPUDepthStencilState(renderPipeline.depthStencil, renderPassFormat.depthStencilFormat); @@ -42,17 +39,26 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP // 从GPU管线中获取管线布局。 const layout = getGPUPipelineLayout(device, renderPipeline); - const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { - label: renderPipeline.label, - layout, - vertex: vertexStateResult.gpuVertexState, - fragment: gpuFragmentState, - primitive: gpuPrimitive, - depthStencil: gpuDepthStencilState, - multisample: gpuMultisampleState, - }; + const gpuRenderPipeline = computed(() => + { + // 获取片段阶段完整描述。 + const gpuFragmentState = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); + + // + const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { + label: renderPipeline.label, + layout, + vertex: vertexStateResult.gpuVertexState, + fragment: gpuFragmentState, + primitive: gpuPrimitive, + depthStencil: gpuDepthStencilState, + multisample: gpuMultisampleState, + }; - const gpuRenderPipeline = device.createRenderPipeline(gpuRenderPipelineDescriptor); + const gpuRenderPipeline = device.createRenderPipeline(gpuRenderPipelineDescriptor); + + return gpuRenderPipeline; + }); result = { _version: 0, pipeline: gpuRenderPipeline, vertexBuffers: vertexStateResult.vertexBuffers }; device._renderPipelineMap.set([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat], result); @@ -64,10 +70,8 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP renderPipeline._version = ~~renderPipeline._version + 1; device._renderPipelineMap.delete([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); watcher.unwatch(vertexStateResult, "_version", onchanged); - gpuFragmentState && watcher.unwatch(gpuFragmentState, "_version", onchanged); } watcher.watch(vertexStateResult, "_version", onchanged); - gpuFragmentState && watcher.watch(gpuFragmentState, "_version", onchanged); return result; } @@ -311,25 +315,34 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co let gpuFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); if (gpuFragmentState) return gpuFragmentState.value; - const targets = colorAttachments.map((format, i) => + const targets = computed(() => { - if (!format) return undefined; + reactive(fragmentState).targets; - const colorTargetState = fragmentState.targets?.[i]; + return colorAttachments.map((format, i) => + { + if (!format) return undefined; - // - const writeMask = getGPUColorWriteFlags(colorTargetState?.writeMask); + // + reactive(fragmentState).targets?.[i]; + + // + const colorTargetState = fragmentState.targets?.[i]; - const blend: GPUBlendState = getGPUBlendState(colorTargetState?.blend); + // + const writeMask = getGPUColorWriteFlags(colorTargetState?.writeMask); - // - const gpuColorTargetState: GPUColorTargetState = { - format, - blend, - writeMask, - }; + const blend = getGPUBlendState(colorTargetState?.blend); - return gpuColorTargetState; + // + const gpuColorTargetState: GPUColorTargetState = { + format, + blend, + writeMask, + }; + + return gpuColorTargetState; + }); }); const entryPoint = computed(() => @@ -372,7 +385,7 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co return { module: getGPUShaderModule(device, fragmentState.code), entryPoint: entryPoint.value, - targets, + targets: targets.value, constants: fragmentState.constants } as GPUFragmentState; }); @@ -387,39 +400,44 @@ const fragmentStateMap = new ChainMap<[FragmentState, string], ComputedRef { - colorSrcFactor = colorDstFactor = "one"; - } - // - const alphaOperation: GPUBlendOperation = blend?.alpha?.operation || colorOperation; - let alphaSrcFactor: GPUBlendFactor = blend?.alpha?.srcFactor || colorSrcFactor; - let alphaDstFactor: GPUBlendFactor = blend?.alpha?.dstFactor || colorDstFactor; - if (alphaOperation === "max" || alphaOperation === "min") - { - alphaSrcFactor = alphaDstFactor = "one"; - } + const r_blend = reactive(blend); + // + const colorOperation: GPUBlendOperation = r_blend?.color?.operation || "add"; + let colorSrcFactor: GPUBlendFactor = r_blend?.color?.srcFactor || "one"; + let colorDstFactor: GPUBlendFactor = r_blend?.color?.dstFactor || "zero"; + if (colorOperation === "max" || colorOperation === "min") + { + colorSrcFactor = colorDstFactor = "one"; + } + // + const alphaOperation: GPUBlendOperation = r_blend?.alpha?.operation || colorOperation; + let alphaSrcFactor: GPUBlendFactor = r_blend?.alpha?.srcFactor || colorSrcFactor; + let alphaDstFactor: GPUBlendFactor = r_blend?.alpha?.dstFactor || colorDstFactor; + if (alphaOperation === "max" || alphaOperation === "min") + { + alphaSrcFactor = alphaDstFactor = "one"; + } - const gpuBlend: GPUBlendState = { - color: { - operation: colorOperation, - srcFactor: colorSrcFactor, - dstFactor: colorDstFactor, - }, - alpha: { - operation: alphaOperation, - srcFactor: alphaSrcFactor, - dstFactor: alphaDstFactor, - }, - }; + const gpuBlend: GPUBlendState = { + color: { + operation: colorOperation, + srcFactor: colorSrcFactor, + dstFactor: colorDstFactor, + }, + alpha: { + operation: alphaOperation, + srcFactor: alphaSrcFactor, + dstFactor: alphaDstFactor, + }, + }; + return gpuBlend; + }) - return gpuBlend; + return result.value; } function getGPUColorWriteFlags(writeMask?: IWriteMask) -- Gitee From 22043d077212daedc5d03414405da495e8de95b8 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 17 Mar 2025 18:24:55 +0800 Subject: [PATCH 095/214] =?UTF-8?q?refactor(gpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E9=81=93=E5=88=9B=E5=BB=BA=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了未使用的导入 - 提取了 GPUColorTargetState 的创建逻辑到单独的函数中 - 优化了 GPUBlendState 的创建,添加了缓存机制 - 调整了代码结构,提高了可读性和可维护性 --- src/caches/getGPUPipelineLayout.ts | 1 - src/caches/getNGPURenderPipeline.ts | 43 +++++++++++++++++------------ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index b3d6e31..90da4b0 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,5 +1,4 @@ import { RenderPipeline } from "@feng3d/render-api"; -import { VariableInfo } from "wgsl_reflect"; import { ComputePipeline } from "../data/ComputePipeline"; import { getIGPUBindGroupLayoutEntryMap, GPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 8e2aca6..9dd3ae3 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState, ChainMap, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; +import { BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -42,6 +42,7 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const gpuRenderPipeline = computed(() => { // 获取片段阶段完整描述。 + reactive(renderPipeline).fragment; const gpuFragmentState = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); // @@ -299,6 +300,25 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) return { vertexBufferLayouts, vertexBuffers }; } +function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUTextureFormat) +{ + if (!colorTargetState) return undefined; + + // + const writeMask = getGPUColorWriteFlags(colorTargetState.writeMask); + + const blend = getGPUBlendState(colorTargetState.blend); + + // + const gpuColorTargetState: GPUColorTargetState = { + format, + blend, + writeMask, + }; + + return gpuColorTargetState; +} + /** * 获取片段阶段完整描述。 * @@ -325,21 +345,7 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co // reactive(fragmentState).targets?.[i]; - - // - const colorTargetState = fragmentState.targets?.[i]; - - // - const writeMask = getGPUColorWriteFlags(colorTargetState?.writeMask); - - const blend = getGPUBlendState(colorTargetState?.blend); - - // - const gpuColorTargetState: GPUColorTargetState = { - format, - blend, - writeMask, - }; + const gpuColorTargetState = getGPUColorTargetState(fragmentState.targets?.[i], format); return gpuColorTargetState; }); @@ -402,7 +408,10 @@ function getGPUBlendState(blend?: BlendState): GPUBlendState { if (!blend) return undefined; - const result = computed(() => + let result: ComputedRef = blend["_GPUBlendState"]; + if (result) return result.value; + + result = blend["_GPUBlendState"] = computed(() => { const r_blend = reactive(blend); // -- Gitee From 50d5f7820f73a1625b1617ef0829469a06da102f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 17 Mar 2025 20:28:25 +0800 Subject: [PATCH 096/214] =?UTF-8?q?perf(getNGPURenderPipeline):=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=89=87=E6=AE=B5=E7=AE=A1=E7=BA=BF=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E7=9A=84=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 fragment 属性的获取移至单独的 computed 函数中 - 优化了对 colorAttachments 的处理方式,直接使用数组而不是字符串键 - 调整了 GPUFragmentState 的构建逻辑,提高了代码的可读性和性能 --- src/caches/getNGPURenderPipeline.ts | 38 +++++++++++++++++------------ 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 9dd3ae3..7fb93ae 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -39,18 +39,25 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP // 从GPU管线中获取管线布局。 const layout = getGPUPipelineLayout(device, renderPipeline); - const gpuRenderPipeline = computed(() => + const gpuFragmentState = computed(() => { // 获取片段阶段完整描述。 reactive(renderPipeline).fragment; - const gpuFragmentState = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); + const fragment = renderPipeline.fragment; + if (!fragment) return undefined; + + return getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); + }); + + const gpuRenderPipeline = computed(() => + { // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { label: renderPipeline.label, layout, vertex: vertexStateResult.gpuVertexState, - fragment: gpuFragmentState, + fragment: gpuFragmentState.value, primitive: gpuPrimitive, depthStencil: gpuDepthStencilState, multisample: gpuMultisampleState, @@ -302,12 +309,10 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUTextureFormat) { - if (!colorTargetState) return undefined; - // - const writeMask = getGPUColorWriteFlags(colorTargetState.writeMask); + const writeMask = getGPUColorWriteFlags(colorTargetState?.writeMask); - const blend = getGPUBlendState(colorTargetState.blend); + const blend = getGPUBlendState(colorTargetState?.blend); // const gpuColorTargetState: GPUColorTargetState = { @@ -328,11 +333,7 @@ function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUT */ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, colorAttachments: readonly GPUTextureFormat[]) { - if (!fragmentState) return undefined; - - const colorAttachmentsKey = colorAttachments.toString(); - - let gpuFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); + let gpuFragmentState = fragmentStateMap.get([fragmentState, colorAttachments]); if (gpuFragmentState) return gpuFragmentState.value; const targets = computed(() => @@ -383,25 +384,30 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co return entryPoint; }); - gpuFragmentState = computed(() => + const module = computed(() => { // 监听着色器代码变化 reactive(fragmentState).code; + return getGPUShaderModule(device, fragmentState.code); + }); + + gpuFragmentState = computed(() => + { return { - module: getGPUShaderModule(device, fragmentState.code), + module: module.value, entryPoint: entryPoint.value, targets: targets.value, constants: fragmentState.constants } as GPUFragmentState; }); - fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); + fragmentStateMap.set([fragmentState, colorAttachments], gpuFragmentState); return gpuFragmentState.value; } -const fragmentStateMap = new ChainMap<[FragmentState, string], ComputedRef>(); +const fragmentStateMap = new ChainMap<[FragmentState, readonly GPUTextureFormat[]], ComputedRef>(); function getGPUBlendState(blend?: BlendState): GPUBlendState -- Gitee From 05cb92da735f2760271d2cd134bae5eaf967f37e Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 17 Mar 2025 21:16:23 +0800 Subject: [PATCH 097/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=A1=B6=E7=82=B9=E7=AE=A1=E7=BA=BF=E5=B8=83=E5=B1=80=E5=92=8C?= =?UTF-8?q?=E5=85=A5=E5=8F=A3=E7=82=B9=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整 getGPUPipelineLayout 函数参数,使其直接接受 shader 代码 - 重构 getNGPUVertexState 函数,提取顶点入口函数信息逻辑 - 更新相关缓存函数,以适应新的逻辑 - 优化代码结构,提高可读性和可维护性 --- src/WebGPUBase.ts | 6 ++-- src/caches/getGPUComputePipeline.ts | 2 +- src/caches/getGPUPipelineLayout.ts | 24 ++++++------- src/caches/getNGPURenderPipeline.ts | 56 +++++++++++++++++++---------- 4 files changed, 52 insertions(+), 36 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 80628bb..e8b0045 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -20,12 +20,12 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit } from "./eventnames"; +import { NVertexBuffer } from "./internal/NGPUVertexBuffer"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; -import { NVertexBuffer } from "./internal/NGPUVertexBuffer"; declare global { @@ -412,7 +412,7 @@ export class WebGPUBase passEncoder.setPipeline(computePipeline); // 计算 bindGroups - const layout = getGPUPipelineLayout(device, pipeline); + const layout = getGPUPipelineLayout(device, { compute: pipeline.compute.code }); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); @@ -522,7 +522,7 @@ export class WebGPUBase } // 计算 bindGroups - const layout = getGPUPipelineLayout(device, pipeline); + const layout = getGPUPipelineLayout(device, { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); diff --git a/src/caches/getGPUComputePipeline.ts b/src/caches/getGPUComputePipeline.ts index 877b738..54e969d 100644 --- a/src/caches/getGPUComputePipeline.ts +++ b/src/caches/getGPUComputePipeline.ts @@ -27,7 +27,7 @@ export function getGPUComputePipeline(device: GPUDevice, computePipeline: Comput } // 从GPU管线中获取管线布局。 - const layout = getGPUPipelineLayout(device, computePipeline); + const layout = getGPUPipelineLayout(device, { compute: computePipeline.compute.code }); pipeline = device.createComputePipeline({ layout, diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 90da4b0..dae4554 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,5 +1,3 @@ -import { RenderPipeline } from "@feng3d/render-api"; -import { ComputePipeline } from "../data/ComputePipeline"; import { getIGPUBindGroupLayoutEntryMap, GPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; declare global @@ -35,36 +33,36 @@ declare global /** * 从GPU管线中获取管线布局。 * - * @param pipeline GPU管线。 + * @param shader GPU管线。 * @returns 管线布局。 */ -export function getGPUPipelineLayout(device: GPUDevice, pipeline: RenderPipeline | ComputePipeline) +export function getGPUPipelineLayout(device: GPUDevice, shader: { vertex: string, fragment: string } | { compute: string }) { let shaderKey = ""; - if ("compute" in pipeline) + if ("compute" in shader) { - shaderKey += pipeline.compute; + shaderKey += shader.compute; } else { - shaderKey += pipeline.vertex.code; - if (pipeline.fragment) shaderKey += `\n// ------顶点与片段着色器分界--------\n` + pipeline.fragment.code; + shaderKey += shader.vertex; + if (shader.fragment) shaderKey += `\n// ------顶点与片段着色器分界--------\n` + shader.fragment; } let gpuPipelineLayout = device._pipelineLayoutMap.get(shaderKey); if (gpuPipelineLayout) return gpuPipelineLayout; let entryMap: GPUBindGroupLayoutEntryMap; - if ("compute" in pipeline) + if ("compute" in shader) { - entryMap = getIGPUBindGroupLayoutEntryMap(pipeline.compute.code); + entryMap = getIGPUBindGroupLayoutEntryMap(shader.compute); } else { - entryMap = getIGPUBindGroupLayoutEntryMap(pipeline.vertex.code); - if ("fragment" in pipeline) + entryMap = getIGPUBindGroupLayoutEntryMap(shader.vertex); + if ("fragment" in shader) { - const fragmentEntryMap = getIGPUBindGroupLayoutEntryMap(pipeline.fragment.code); + const fragmentEntryMap = getIGPUBindGroupLayoutEntryMap(shader.fragment); for (const resourceName in fragmentEntryMap) { // 检测相同名称是否被定义在多个地方 diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 7fb93ae..88033b4 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -37,7 +37,7 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const gpuMultisampleState = getGPUMultisampleState(renderPipeline.multisample, renderPassFormat.sampleCount); // 从GPU管线中获取管线布局。 - const layout = getGPUPipelineLayout(device, renderPipeline); + const layout = getGPUPipelineLayout(device, { vertex: renderPipeline.vertex.code, fragment: renderPipeline.fragment.code }); const gpuFragmentState = computed(() => { @@ -54,7 +54,7 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP { // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { - label: renderPipeline.label, + label: reactive(renderPipeline).label, layout, vertex: vertexStateResult.gpuVertexState, fragment: gpuFragmentState.value, @@ -174,27 +174,13 @@ function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, vertice let result = vertexStateMap.get([vertexState, vertices]); if (result) return result; - const code = vertexState.code; - - // 解析顶点着色器 - const reflect = getWGSLReflectInfo(code); - let vertex: FunctionInfo; - // - let entryPoint = vertexState.entryPoint; - if (!entryPoint) - { - console.assert(!!reflect.entry.vertex[0], `WGSL着色器 ${code} 中不存在顶点入口点。`); - entryPoint = reflect.entry.vertex[0].name; - } - - vertex = reflect.entry.vertex.filter((v) => v.name === entryPoint)[0]; - console.assert(!!vertex, `WGSL着色器 ${code} 中不存在顶点入口点 ${entryPoint} 。`); + const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); - const { vertexBufferLayouts, vertexBuffers } = getNGPUVertexBuffers(vertex, vertices); + const { vertexBufferLayouts, vertexBuffers } = getNGPUVertexBuffers(vertexEntryFunctionInfo, vertices); const gpuVertexState: GPUVertexState = { module: getGPUShaderModule(device, vertexState.code), - entryPoint, + entryPoint: vertexEntryFunctionInfo.name, buffers: vertexBufferLayouts, constants: vertexState.constants, }; @@ -216,6 +202,38 @@ function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, vertice return result; } +/** + * 获取顶点入口函数信息。 + * + * @param vertexState 顶点阶段信息。 + * @returns + */ +function getVertexEntryFunctionInfo(vertexState: VertexState) +{ + let vertexEntryFunctionInfo: FunctionInfo = vertexState["_vertexEntry"]; + if (!vertexEntryFunctionInfo) return vertexEntryFunctionInfo; + + const code = vertexState.code; + + // 解析顶点着色器 + const reflect = getWGSLReflectInfo(code); + // + if (vertexState.entryPoint) + { + vertexEntryFunctionInfo = reflect.entry.vertex.filter((v) => v.name === vertexState.entryPoint)[0]; + console.assert(!!vertexEntryFunctionInfo, `WGSL着色器 ${code} 中不存在顶点入口点 ${vertexState.entryPoint} 。`); + } + else + { + vertexEntryFunctionInfo = reflect.entry.vertex[0]; + console.assert(!!reflect.entry.vertex[0], `WGSL着色器 ${code} 中不存在顶点入口点。`); + } + + vertexState["_vertexEntry"] = vertexEntryFunctionInfo; + + return vertexEntryFunctionInfo; +} + const vertexStateMap = new ChainMap<[VertexState, VertexAttributes], { gpuVertexState: GPUVertexState; vertexBuffers: NVertexBuffer[]; -- Gitee From 18128a44ae7f221d2b3eee75d7b6342089a6cb9f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 17 Mar 2025 22:24:40 +0800 Subject: [PATCH 098/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E7=BC=93=E5=AD=98=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化了 GPUColorTargetState、GPUFragmentState 和 GPUBlendState 的生成逻辑 - 引入了新的 BlendComponent 类型和 getGPUBlendComponent 函数 - 改进了缓存键的生成方式,使用字符串代替数组 - 优化了代码结构,提高了可读性和可维护性 --- src/caches/getNGPURenderPipeline.ts | 142 ++++++++++++++++------------ 1 file changed, 81 insertions(+), 61 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 88033b4..c8a1d00 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, IWriteMask, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType } from "@feng3d/render-api"; +import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType, WriteMask } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -211,7 +211,7 @@ function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, vertice function getVertexEntryFunctionInfo(vertexState: VertexState) { let vertexEntryFunctionInfo: FunctionInfo = vertexState["_vertexEntry"]; - if (!vertexEntryFunctionInfo) return vertexEntryFunctionInfo; + if (vertexEntryFunctionInfo) return vertexEntryFunctionInfo; const code = vertexState.code; @@ -327,19 +327,28 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUTextureFormat) { - // - const writeMask = getGPUColorWriteFlags(colorTargetState?.writeMask); + if (!colorTargetState) return { format, blend: getGPUBlendState(undefined), writeMask: getGPUColorWriteFlags(undefined) }; - const blend = getGPUBlendState(colorTargetState?.blend); + const result = colorTargetState["_GPUColorTargetState_" + format] ??= computed(() => + { + // + reactive(colorTargetState)?.writeMask; + const writeMask = getGPUColorWriteFlags(colorTargetState?.writeMask); - // - const gpuColorTargetState: GPUColorTargetState = { - format, - blend, - writeMask, - }; + reactive(colorTargetState)?.blend; + const blend = getGPUBlendState(colorTargetState?.blend); - return gpuColorTargetState; + // + const gpuColorTargetState: GPUColorTargetState = { + format, + blend, + writeMask, + }; + + return gpuColorTargetState; + }); + + return result.value; } /** @@ -351,13 +360,13 @@ function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUT */ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, colorAttachments: readonly GPUTextureFormat[]) { - let gpuFragmentState = fragmentStateMap.get([fragmentState, colorAttachments]); + const colorAttachmentsKey = colorAttachments.toLocaleString(); + + let gpuFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); if (gpuFragmentState) return gpuFragmentState.value; const targets = computed(() => { - reactive(fragmentState).targets; - return colorAttachments.map((format, i) => { if (!format) return undefined; @@ -420,12 +429,12 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co } as GPUFragmentState; }); - fragmentStateMap.set([fragmentState, colorAttachments], gpuFragmentState); + fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); return gpuFragmentState.value; } -const fragmentStateMap = new ChainMap<[FragmentState, readonly GPUTextureFormat[]], ComputedRef>(); +const fragmentStateMap = new ChainMap<[FragmentState, string], ComputedRef>(); function getGPUBlendState(blend?: BlendState): GPUBlendState @@ -437,65 +446,76 @@ function getGPUBlendState(blend?: BlendState): GPUBlendState result = blend["_GPUBlendState"] = computed(() => { - const r_blend = reactive(blend); + reactive(blend)?.color; + reactive(blend)?.alpha; // - const colorOperation: GPUBlendOperation = r_blend?.color?.operation || "add"; - let colorSrcFactor: GPUBlendFactor = r_blend?.color?.srcFactor || "one"; - let colorDstFactor: GPUBlendFactor = r_blend?.color?.dstFactor || "zero"; - if (colorOperation === "max" || colorOperation === "min") - { - colorSrcFactor = colorDstFactor = "one"; - } + const gpuBlend: GPUBlendState = { + color: getGPUBlendComponent(blend?.color), + alpha: getGPUBlendComponent(blend?.alpha), + }; + return gpuBlend; + }) + + return result.value; +} + +function getGPUBlendComponent(blendComponent?: BlendComponent): GPUBlendComponent +{ + if (!blendComponent) return { operation: "add", srcFactor: "one", dstFactor: "zero" }; + + const result: ComputedRef = blendComponent["_GPUBlendComponent"] ??= computed(() => + { + const r_blendComponent = reactive(blendComponent); // - const alphaOperation: GPUBlendOperation = r_blend?.alpha?.operation || colorOperation; - let alphaSrcFactor: GPUBlendFactor = r_blend?.alpha?.srcFactor || colorSrcFactor; - let alphaDstFactor: GPUBlendFactor = r_blend?.alpha?.dstFactor || colorDstFactor; - if (alphaOperation === "max" || alphaOperation === "min") + const operation: GPUBlendOperation = r_blendComponent?.operation ?? "add"; + let srcFactor: GPUBlendFactor = r_blendComponent?.srcFactor ?? "one"; + let dstFactor: GPUBlendFactor = r_blendComponent?.dstFactor ?? "zero"; + if (operation === "max" || operation === "min") { - alphaSrcFactor = alphaDstFactor = "one"; + srcFactor = dstFactor = "one"; } - const gpuBlend: GPUBlendState = { - color: { - operation: colorOperation, - srcFactor: colorSrcFactor, - dstFactor: colorDstFactor, - }, - alpha: { - operation: alphaOperation, - srcFactor: alphaSrcFactor, - dstFactor: alphaDstFactor, - }, + const gpuBlendComponent: GPUBlendComponent = { + operation, + srcFactor, + dstFactor, }; - return gpuBlend; - }) + return gpuBlendComponent; + }); return result.value; } -function getGPUColorWriteFlags(writeMask?: IWriteMask) +function getGPUColorWriteFlags(writeMask?: WriteMask) { if (!writeMask) return 15; - let gpuWriteMask: GPUColorWriteFlags = 0; - if (writeMask[0]) - { - gpuWriteMask += 1; - } - if (writeMask[1]) - { - gpuWriteMask += 2; - } - if (writeMask[2]) + const result: ComputedRef = writeMask["_GPUColorWriteFlags"] ??= computed(() => { - gpuWriteMask += 4; - } - if (writeMask[3]) - { - gpuWriteMask += 8; - } + const r_writeMask = reactive(writeMask); + // + let gpuWriteMask: GPUColorWriteFlags = 0; + if (r_writeMask[0]) + { + gpuWriteMask += 1; + } + if (r_writeMask[1]) + { + gpuWriteMask += 2; + } + if (r_writeMask[2]) + { + gpuWriteMask += 4; + } + if (r_writeMask[3]) + { + gpuWriteMask += 8; + } - return gpuWriteMask; + return gpuWriteMask; + }); + + return result.value; } function getWGSLType(type: TypeInfo) -- Gitee From 644f9e80b53733f48fe042cce9eb2995123a6005 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 17 Mar 2025 22:50:19 +0800 Subject: [PATCH 099/214] =?UTF-8?q?refactor(gpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=89=87=E6=AE=B5=E7=AE=A1=E7=BA=BF=E7=8A=B6=E6=80=81=E7=9A=84?= =?UTF-8?q?=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化了 GPUFragmentState 的获取流程,提高了代码的可读性和性能 - 新增 getGPUColorTargetStates 和 getEntryPoint 函数,用于处理颜色目标状态和入口点 - 通过计算属性和缓存机制,减少了不必要的重复计算 - 调整了 fragmentStateMap 的使用方式,提高了缓存效率 --- src/caches/getNGPURenderPipeline.ts | 82 ++++++++++++++++------------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index c8a1d00..3bcabf0 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -39,25 +39,17 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP // 从GPU管线中获取管线布局。 const layout = getGPUPipelineLayout(device, { vertex: renderPipeline.vertex.code, fragment: renderPipeline.fragment.code }); - const gpuFragmentState = computed(() => + const gpuRenderPipeline = computed(() => { // 获取片段阶段完整描述。 reactive(renderPipeline).fragment; - - const fragment = renderPipeline.fragment; - if (!fragment) return undefined; - - return getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); - }); - - const gpuRenderPipeline = computed(() => - { + const fragment = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { label: reactive(renderPipeline).label, layout, vertex: vertexStateResult.gpuVertexState, - fragment: gpuFragmentState.value, + fragment, primitive: gpuPrimitive, depthStencil: gpuDepthStencilState, multisample: gpuMultisampleState, @@ -360,26 +352,62 @@ function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUT */ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, colorAttachments: readonly GPUTextureFormat[]) { + if (!fragmentState) return undefined; + const colorAttachmentsKey = colorAttachments.toLocaleString(); let gpuFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); if (gpuFragmentState) return gpuFragmentState.value; - const targets = computed(() => + gpuFragmentState = computed(() => + { + // 监听着色器代码变化 + reactive(fragmentState).code; + const module = getGPUShaderModule(device, fragmentState.code); + + // + const entryPoint = getEntryPoint(fragmentState); + + reactive(fragmentState).targets; + const targets = getGPUColorTargetStates(fragmentState.targets, colorAttachments); + + return { + module, + entryPoint, + targets: targets, + constants: fragmentState.constants + } as GPUFragmentState; + }); + + fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); + + return gpuFragmentState.value; +} + +const fragmentStateMap = new ChainMap<[FragmentState, string], ComputedRef>(); + +function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]) +{ + const result = computed(() => { return colorAttachments.map((format, i) => { if (!format) return undefined; // - reactive(fragmentState).targets?.[i]; - const gpuColorTargetState = getGPUColorTargetState(fragmentState.targets?.[i], format); + targets && reactive(targets)[i]; + const gpuColorTargetState = getGPUColorTargetState(targets?.[i], format); return gpuColorTargetState; }); }); - const entryPoint = computed(() => + return result.value; +} + +function getEntryPoint(fragmentState: FragmentState) +{ + const result: ComputedRef = fragmentState["_entryPoint"] ??= computed(() => { // 监听着色器入口点变化 reactive(fragmentState).entryPoint; @@ -411,31 +439,9 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co return entryPoint; }); - const module = computed(() => - { - // 监听着色器代码变化 - reactive(fragmentState).code; - - return getGPUShaderModule(device, fragmentState.code); - }); - - gpuFragmentState = computed(() => - { - return { - module: module.value, - entryPoint: entryPoint.value, - targets: targets.value, - constants: fragmentState.constants - } as GPUFragmentState; - }); - - fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); - - return gpuFragmentState.value; + return result.value; } -const fragmentStateMap = new ChainMap<[FragmentState, string], ComputedRef>(); - function getGPUBlendState(blend?: BlendState): GPUBlendState { -- Gitee From 6e5ff5397e1048e9df5480e6abfe25b84a1dfcd7 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 17 Mar 2025 23:01:25 +0800 Subject: [PATCH 100/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=A2=9C=E8=89=B2=E7=9B=AE=E6=A0=87=E7=8A=B6=E6=80=81=E7=9A=84?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 getGPUColorTargetState 添加类型注解,提高代码可读性 - 优化 getGPUColorTargetStates 函数,处理未定义目标的情况 - 使用 computed 函数创建响应式缓存,提高性能 - 新增 undefinedMap 用于缓存未定义颜色目标状态 --- src/caches/getNGPURenderPipeline.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 3bcabf0..ca53f06 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -321,7 +321,7 @@ function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUT { if (!colorTargetState) return { format, blend: getGPUBlendState(undefined), writeMask: getGPUColorWriteFlags(undefined) }; - const result = colorTargetState["_GPUColorTargetState_" + format] ??= computed(() => + const result: ComputedRef = colorTargetState["_GPUColorTargetState_" + format] ??= computed(() => { // reactive(colorTargetState)?.writeMask; @@ -386,16 +386,24 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co const fragmentStateMap = new ChainMap<[FragmentState, string], ComputedRef>(); -function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]) +function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]): GPUColorTargetState[] { - const result = computed(() => + if (!targets) + { + return undefinedMap["_GPUColorTargetStates_" + colorAttachments.toString()] ??= colorAttachments.map((format) => + { + return getGPUColorTargetState(undefined, format); + }); + }; + + const result: ComputedRef = targets["_GPUColorTargetStates_" + colorAttachments.toString()] ??= computed(() => { return colorAttachments.map((format, i) => { if (!format) return undefined; // - targets && reactive(targets)[i]; + reactive(targets)[i]; const gpuColorTargetState = getGPUColorTargetState(targets?.[i], format); return gpuColorTargetState; @@ -404,6 +412,7 @@ function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAtta return result.value; } +const undefinedMap: { [key: string]: GPUColorTargetState[] } = {}; function getEntryPoint(fragmentState: FragmentState) { -- Gitee From 2d046e62278c5ae12bdfdc1ae62d40845e67c3d2 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 17 Mar 2025 23:16:24 +0800 Subject: [PATCH 101/214] =?UTF-8?q?feat(WebGPU):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=89=87=E6=AE=B5=E7=AE=A1=E9=81=93=E7=8A=B6=E6=80=81=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E5=A4=8D=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 WebGPUBase 中添加 _fragmentStateMap 属性,用于缓存片段状态对象 - 修改 getGPUFragmentState 函数,使用设备的 _fragmentStateMap 替代全局 fragmentStateMap - 增加对片段着色器入口点、渲染目标和常量的监听 - 移除全局 fragmentStateMap 变量 --- src/WebGPUBase.ts | 6 ++++-- src/caches/getNGPURenderPipeline.ts | 14 +++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index e8b0045..9f3ccdd 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, FragmentState, GBuffer, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -50,7 +50,8 @@ declare global pipeline: ComputedRef; vertexBuffers: NVertexBuffer[]; _version: number; - }> + }>; + _fragmentStateMap: ChainMap<[FragmentState, string], ComputedRef> } } @@ -95,6 +96,7 @@ export class WebGPUBase this._device._renderPassObjectsCommandMap ??= new ChainMap(); this._device._renderPipelineMap ??= new ChainMap(); this._device._renderObjectCommandMap ??= new ChainMap(); + this._device._fragmentStateMap ??= new ChainMap(); this._device._bufferMap ??= new WeakMap(); this._device._contextMap ??= new WeakMap(); this._device._computePipelineMap ??= new WeakMap(); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index ca53f06..a8d1ca7 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -356,7 +356,7 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co const colorAttachmentsKey = colorAttachments.toLocaleString(); - let gpuFragmentState = fragmentStateMap.get([fragmentState, colorAttachmentsKey]); + let gpuFragmentState = device._fragmentStateMap.get([fragmentState, colorAttachmentsKey]); if (gpuFragmentState) return gpuFragmentState.value; gpuFragmentState = computed(() => @@ -365,12 +365,18 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co reactive(fragmentState).code; const module = getGPUShaderModule(device, fragmentState.code); - // + // 监听着色器入口点变化 const entryPoint = getEntryPoint(fragmentState); + // 监听渲染目标变化 reactive(fragmentState).targets; const targets = getGPUColorTargetStates(fragmentState.targets, colorAttachments); + // 监听常量变化 + const r_constants = reactive(fragmentState).constants; + for (const key in r_constants) { r_constants[key]; } + + // return { module, entryPoint, @@ -379,13 +385,11 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co } as GPUFragmentState; }); - fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); + device._fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); return gpuFragmentState.value; } -const fragmentStateMap = new ChainMap<[FragmentState, string], ComputedRef>(); - function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]): GPUColorTargetState[] { if (!targets) -- Gitee From 345919a563de1cf37fd68eddd84d6280c59b36a1 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 17 Mar 2025 23:21:54 +0800 Subject: [PATCH 102/214] =?UTF-8?q?perf(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E7=9A=84=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E5=BC=8F=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除不必要的片段阶段完整描述获取 - 更新管线布局以响应顶点和片段着色器代码的变化 - 优化渲染管线描述符的构建过程 --- src/caches/getNGPURenderPipeline.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index a8d1ca7..d34aa02 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -36,17 +36,25 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP // 从渲染通道上获取多重采样数量 const gpuMultisampleState = getGPUMultisampleState(renderPipeline.multisample, renderPassFormat.sampleCount); - // 从GPU管线中获取管线布局。 - const layout = getGPUPipelineLayout(device, { vertex: renderPipeline.vertex.code, fragment: renderPipeline.fragment.code }); - const gpuRenderPipeline = computed(() => { - // 获取片段阶段完整描述。 + // + reactive(renderPipeline).label; + + // 更新管线布局 + reactive(renderPipeline).vertex.code; + reactive(renderPipeline).fragment?.code + const layout = getGPUPipelineLayout(device, { vertex: renderPipeline.vertex.code, fragment: renderPipeline.fragment?.code }); + + // reactive(renderPipeline).fragment; const fragment = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); + + + // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { - label: reactive(renderPipeline).label, + label: renderPipeline.label, layout, vertex: vertexStateResult.gpuVertexState, fragment, @@ -380,7 +388,7 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co return { module, entryPoint, - targets: targets, + targets, constants: fragmentState.constants } as GPUFragmentState; }); -- Gitee From 72a62c62be02ade2f376edd6c4e7b9d8d442d11d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 11:25:42 +0800 Subject: [PATCH 103/214] =?UTF-8?q?refactor(getNGPURenderPipeline):=20?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=B9=B6=E4=BC=98=E5=8C=96=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E7=AE=A1=E7=BA=BF=E5=88=9B=E5=BB=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整了 getGPUPrimitiveState 函数的调用时机,减少冗余计算 - 使用 computed 函数缓存 getGPUPrimitiveState 结果,提高性能 - 优化了 gpuRenderPipelineDescriptor 的构建过程 - 移除了不必要的变量声明和代码块,简化了逻辑结构 --- src/caches/getNGPURenderPipeline.ts | 43 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index d34aa02..72be148 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -25,8 +25,6 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP let result = device._renderPipelineMap.get([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); if (result) return result; - const gpuPrimitive = getGPUPrimitiveState(primitive, indexFormat); - // 获取完整的顶点阶段描述与顶点缓冲区列表。 const vertexStateResult = getNGPUVertexState(device, renderPipeline.vertex, vertices); @@ -40,6 +38,7 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP { // reactive(renderPipeline).label; + const label = renderPipeline.label; // 更新管线布局 reactive(renderPipeline).vertex.code; @@ -50,11 +49,12 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP reactive(renderPipeline).fragment; const fragment = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); - + // + const gpuPrimitive = getGPUPrimitiveState(primitive, indexFormat); // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { - label: renderPipeline.label, + label, layout, vertex: vertexStateResult.gpuVertexState, fragment, @@ -84,30 +84,29 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP return result; } -function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndexFormat) +function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndexFormat): GPUPrimitiveState { - let stripIndexFormat: GPUIndexFormat; - if (primitive?.topology === "triangle-strip" || primitive?.topology === "line-strip") + if (!primitive) return defaultGPUPrimitiveState; + + const result: ComputedRef = primitive["_cache_GPUPrimitiveState_" + indexFormat] ??= computed(() => { - stripIndexFormat = indexFormat; - } + let { topology, cullFace, frontFace, unclippedDepth } = reactive(primitive); - const topology: GPUPrimitiveTopology = primitive?.topology || "triangle-list"; - const cullMode: GPUCullMode = primitive?.cullFace || "none"; - const frontFace: GPUFrontFace = primitive?.frontFace || "ccw"; - const unclippedDepth: boolean = primitive?.unclippedDepth || false; + // + const gpuPrimitive: GPUPrimitiveState = { + topology: topology ?? "triangle-list", + stripIndexFormat: (topology === "triangle-strip" || topology === "line-strip") ? indexFormat : undefined, + frontFace: frontFace ?? "ccw", + cullMode: cullFace ?? "none", + unclippedDepth: unclippedDepth ?? false, + }; - // - const gpuPrimitive: GPUPrimitiveState = { - topology, - stripIndexFormat, - frontFace, - cullMode, - unclippedDepth, - }; + return gpuPrimitive; + }); - return gpuPrimitive; + return result.value; } +const defaultGPUPrimitiveState: GPUPrimitiveState = { topology: "triangle-list", cullMode: "none", frontFace: "ccw", } function getGPUMultisampleState(multisampleState?: MultisampleState, sampleCount?: 4) { -- Gitee From 9ffe2a6f7553bc7b490c77ffec40e3ff84d81c16 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 11:52:57 +0800 Subject: [PATCH 104/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E7=BC=93=E5=AD=98=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改了 renderPipelineMap 的键值结构,移除了 primitiveState - 将 depthStencil 和 primitive 的处理逻辑移至渲染管线描述符的构建过程中 - 为 depthStencil 和 stencilFaceState 添加了缓存机制,减少重复计算 - 优化了代码结构,提高了可读性和性能 --- src/WebGPUBase.ts | 6 +-- src/caches/getNGPURenderPipeline.ts | 83 ++++++++++++++++++----------- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 9f3ccdd..f53007d 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -46,7 +46,7 @@ declare global setBindGroupCommands: Array; }>; _renderObjectCommandMap: ChainMap<[string, RenderObject], Array>; - _renderPipelineMap: ChainMap<[RenderPipeline, string, PrimitiveState, VertexAttributes, GPUIndexFormat], { + _renderPipelineMap: ChainMap<[RenderPipeline, string, VertexAttributes, GPUIndexFormat], { pipeline: ComputedRef; vertexBuffers: NVertexBuffer[]; _version: number; @@ -484,10 +484,10 @@ export class WebGPUBase } } - const { primitive, vertices, indices, draw } = geometry; + const { vertices, indices, draw } = geometry; // - const { pipeline: nPipeline, vertexBuffers } = getNGPURenderPipeline(device, pipeline, renderPassFormat, primitive, vertices, indices); + const { pipeline: nPipeline, vertexBuffers } = getNGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indices); // passEncoder.setPipeline(nPipeline.value); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 72be148..7af931e 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType, WriteMask } from "@feng3d/render-api"; +import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, PrimitiveState, reactive, RenderPipeline, StencilFaceState, toRaw, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType, WriteMask } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -18,19 +18,16 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, primitive: PrimitiveState, vertices: VertexAttributes, indices: IIndicesDataTypes) +export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, vertices: VertexAttributes, indices: IIndicesDataTypes) { const indexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; - let result = device._renderPipelineMap.get([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); + let result = device._renderPipelineMap.get([renderPipeline, renderPassFormat._key, vertices, indexFormat]); if (result) return result; // 获取完整的顶点阶段描述与顶点缓冲区列表。 const vertexStateResult = getNGPUVertexState(device, renderPipeline.vertex, vertices); - // 获取深度模板阶段完整描述。 - const gpuDepthStencilState = getGPUDepthStencilState(renderPipeline.depthStencil, renderPassFormat.depthStencilFormat); - // 从渲染通道上获取多重采样数量 const gpuMultisampleState = getGPUMultisampleState(renderPipeline.multisample, renderPassFormat.sampleCount); @@ -50,7 +47,12 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const fragment = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); // - const gpuPrimitive = getGPUPrimitiveState(primitive, indexFormat); + reactive(renderPipeline).primitive; + const primitive = getGPUPrimitiveState(renderPipeline.primitive, indexFormat); + + // 获取深度模板阶段完整描述。 + reactive(renderPipeline).depthStencil; + const depthStencil = getGPUDepthStencilState(renderPipeline.depthStencil, renderPassFormat.depthStencilFormat); // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { @@ -58,8 +60,8 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP layout, vertex: vertexStateResult.gpuVertexState, fragment, - primitive: gpuPrimitive, - depthStencil: gpuDepthStencilState, + primitive, + depthStencil, multisample: gpuMultisampleState, }; @@ -69,14 +71,14 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP }); result = { _version: 0, pipeline: gpuRenderPipeline, vertexBuffers: vertexStateResult.vertexBuffers }; - device._renderPipelineMap.set([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat], result); + device._renderPipelineMap.set([renderPipeline, renderPassFormat._key, vertices, indexFormat], result); // 监听管线变化 const onchanged = () => { result._version++; renderPipeline._version = ~~renderPipeline._version + 1; - device._renderPipelineMap.delete([renderPipeline, renderPassFormat._key, primitive, vertices, indexFormat]); + device._renderPipelineMap.delete([renderPipeline, renderPassFormat._key, vertices, indexFormat]); watcher.unwatch(vertexStateResult, "_version", onchanged); } watcher.watch(vertexStateResult, "_version", onchanged); @@ -130,35 +132,52 @@ function getGPUMultisampleState(multisampleState?: MultisampleState, sampleCount function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFormat?: GPUTextureFormat) { if (!depthStencilFormat) return undefined; - // - const gpuDepthStencilState: GPUDepthStencilState = { - format: depthStencilFormat, - depthWriteEnabled: depthStencil?.depthWriteEnabled ?? true, - depthCompare: depthStencil?.depthCompare ?? "less", - stencilFront: getGPUStencilFaceState(depthStencil?.stencilFront), - stencilBack: getGPUStencilFaceState(depthStencil?.stencilBack), - stencilReadMask: depthStencil?.stencilReadMask ?? 0xFFFFFFFF, - stencilWriteMask: depthStencil?.stencilWriteMask ?? 0xFFFFFFFF, - depthBias: depthStencil?.depthBias ?? 0, - depthBiasSlopeScale: depthStencil?.depthBiasSlopeScale ?? 0, - depthBiasClamp: depthStencil?.depthBiasClamp ?? 0, - }; - return gpuDepthStencilState; + if (!depthStencil) return { format: depthStencilFormat }; + + const result: ComputedRef = depthStencil["_cache_GPUDepthStencilState_" + depthStencilFormat] = computed(() => + { + const { depthWriteEnabled, depthCompare, stencilFront, stencilBack, stencilReadMask, stencilWriteMask, depthBias, depthBiasSlopeScale, depthBiasClamp } = reactive(depthStencil); + + // + const gpuDepthStencilState: GPUDepthStencilState = { + format: depthStencilFormat, + depthWriteEnabled: depthWriteEnabled ?? true, + depthCompare: depthCompare ?? "less", + stencilFront: getGPUStencilFaceState(toRaw(stencilFront)), + stencilBack: getGPUStencilFaceState(toRaw(stencilBack)), + stencilReadMask: stencilReadMask ?? 0xFFFFFFFF, + stencilWriteMask: stencilWriteMask ?? 0xFFFFFFFF, + depthBias: depthBias ?? 0, + depthBiasSlopeScale: depthBiasSlopeScale ?? 0, + depthBiasClamp: depthBiasClamp ?? 0, + }; + + return gpuDepthStencilState; + }); + + return result.value; } function getGPUStencilFaceState(stencilFaceState?: StencilFaceState) { if (!stencilFaceState) return {}; - const gpuStencilFaceState: GPUStencilFaceState = { - compare: stencilFaceState.compare ?? "always", - failOp: stencilFaceState.failOp ?? "keep", - depthFailOp: stencilFaceState.depthFailOp ?? "keep", - passOp: stencilFaceState.passOp ?? "keep", - }; + const result: ComputedRef = stencilFaceState["_cache_GPUStencilFaceState"] = computed(() => + { + const { compare, failOp, depthFailOp, passOp } = reactive(stencilFaceState); - return gpuStencilFaceState; + const gpuStencilFaceState: GPUStencilFaceState = { + compare: compare ?? "always", + failOp: failOp ?? "keep", + depthFailOp: depthFailOp ?? "keep", + passOp: passOp ?? "keep", + }; + + return gpuStencilFaceState; + }) + + return result.value; } /** -- Gitee From 1a879d8ef07678a5ded6c878f9f295dce2ffbb80 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 12:13:25 +0800 Subject: [PATCH 105/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E7=A4=BA=E4=BE=8B=E4=B8=AD=E7=9A=84=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E7=AE=A1=E9=81=93=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 primitive 属性从 geometry 移动到 pipeline 中 - 优化了多个示例中的渲染管道配置 - 调整了部分示例的 cullFace 和 topology 设置 --- examples/src/webgpu/a-buffer/index.ts | 18 ++++++------- examples/src/webgpu/animometer/index.ts | 6 ++--- .../src/webgpu/bitonicSort/bitonicDisplay.ts | 4 +-- examples/src/webgpu/bitonicSort/utils.ts | 10 ++++---- examples/src/webgpu/cameras/index.ts | 8 +++--- examples/src/webgpu/computeBoids/index.ts | 4 +-- examples/src/webgpu/cornell/rasterizer.ts | 6 ++--- examples/src/webgpu/cubemap/index.ts | 6 ++--- .../src/webgpu/deferredRendering/index.ts | 6 ++--- examples/src/webgpu/fractalCube/index.ts | 4 +-- examples/src/webgpu/gameOfLife/index.ts | 6 ++--- examples/src/webgpu/instancedCube/index.ts | 4 +-- examples/src/webgpu/multipleCanvases/index.ts | 6 ++--- examples/src/webgpu/normalMap/index.ts | 4 --- examples/src/webgpu/normalMap/utils.ts | 4 +++ examples/src/webgpu/occlusionQuery/index.ts | 8 +++--- examples/src/webgpu/renderBundles/index.ts | 12 ++++----- examples/src/webgpu/reversedZ/index.ts | 21 +++++++--------- examples/src/webgpu/rotatingCube/index.ts | 4 +-- examples/src/webgpu/shadowMapping/index.ts | 4 +-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 2 +- examples/src/webgpu/skinnedMesh/gridUtils.ts | 3 +++ examples/src/webgpu/skinnedMesh/index.ts | 3 --- .../src/webgpu/textRenderingMsdf/index.ts | 12 ++++----- .../src/webgpu/textRenderingMsdf/msdfText.ts | 6 ++--- examples/src/webgpu/texturedCube/index.ts | 6 ++--- examples/src/webgpu/timestampQuery/index.ts | 15 ++++++----- .../src/webgpu/transparentCanvas/index.ts | 8 +++--- examples/src/webgpu/twoCubes/index.ts | 8 +++--- .../webgpu/volumeRenderingTexture3D/index.ts | 8 +++--- examples/src/webgpu/wireframe/index.ts | 25 ++++++++++--------- examples/src/webgpu/worker/worker.ts | 19 +++++++------- 32 files changed, 128 insertions(+), 132 deletions(-) diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index c59ad2b..27d3e89 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -63,6 +63,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: opaqueWGSL, }, + primitive: { + topology: "triangle-list", + }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -82,6 +85,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, ], }, + primitive: { + topology: "triangle-list", + }, label: "translucentPipeline", }; @@ -115,6 +121,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, ], }, + primitive: { + topology: "triangle-list", + }, label: "compositePipeline", }; @@ -280,9 +289,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: opaquePipeline, bindingResources: bindingResources, geometry: { - primitive: { - topology: "triangle-list", - }, vertices, indices, draw: { __type__: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, @@ -321,9 +327,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => sliceInfo: sliceInfoBuffer[slice], }, geometry: { - primitive: { - topology: "triangle-list", - }, vertices, indices, draw: { __type__: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, @@ -347,9 +350,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => sliceInfo: sliceInfoBuffer[slice] }, geometry: { - primitive: { - topology: "triangle-list", - }, draw: { __type__: "DrawVertex", vertexCount: 6 }, } } diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index 760a2ce..530908c 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -40,6 +40,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: animometerWGSL, }, + primitive: { + frontFace: "ccw", + }, }; const pipeline: RenderPipeline = { @@ -57,9 +60,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: pipeline, bindingResources: {}, geometry: { - primitive: { - frontFace: "ccw", - }, vertices: { position: { data: vertexBuffer, format: "float32x4", offset: 0, arrayStride: 2 * vec4Size }, color: { data: vertexBuffer, format: "float32x4", offset: vec4Size, arrayStride: 2 * vec4Size }, diff --git a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts index d79c7d0..e564e18 100644 --- a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts +++ b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts @@ -30,7 +30,7 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass computeBGDescript.fragment_uniforms = fragment_uniforms; - this.material = super.create2DRenderPipeline( + this.pipeline = super.create2DRenderPipeline( label, bitonicDisplay, ); @@ -44,6 +44,6 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass startRun(commandEncoder: CommandEncoder, args: BitonicDisplayRenderArgs) { this.setArguments(args); - super.executeRun(commandEncoder, this.renderPassDescriptor, this.material, this.computeBGDescript); + super.executeRun(commandEncoder, this.renderPassDescriptor, this.pipeline, this.computeBGDescript); } } diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index 51986ae..ab9c79a 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -43,7 +43,7 @@ export abstract class Base2DRendererClass ...args: unknown[] ): void; renderPassDescriptor: RenderPassDescriptor; - material: RenderPipeline; + pipeline: RenderPipeline; bindGroupMap: Record; currentBindGroupName: string; @@ -60,10 +60,6 @@ export abstract class Base2DRendererClass pipeline: pipeline, bindingResources: bindingResources, geometry: { - primitive: { - topology: "triangle-list", - cullFace: "none", - }, draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1 } } }], @@ -84,6 +80,10 @@ export abstract class Base2DRendererClass fragment: { code, }, + primitive: { + topology: "triangle-list", + cullFace: "none", + }, }; return renderPipeline; diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index 7e1b638..8d45f99 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -54,6 +54,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: cubeWGSL, }, + primitive: { + topology: "triangle-list", + cullFace: "back", + }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -96,10 +100,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: pipeline, bindingResources: bindingResources, geometry:{ - primitive: { - topology: "triangle-list", - cullFace: "back", - }, vertices, draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index 65c4ca0..abac7ea 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -93,11 +93,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: RenderObject = { pipeline: { vertex: { code: spriteWGSL }, fragment: { code: spriteWGSL }, - }, - geometry: { primitive: { cullFace: "back", }, + }, + geometry: { vertices: { a_particlePos: { data: particleBuffers[0], format: "float32x2", offset: 0, arrayStride: 4 * 4, stepMode: "instance" }, a_particleVel: { data: particleBuffers[0], format: "float32x2", offset: 2 * 4, arrayStride: 4 * 4, stepMode: "instance" }, diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index d882be6..aae2ba6 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -69,6 +69,9 @@ export default class Rasterizer fragment: { code: rasterizerWGSL + common.wgsl, }, + primitive: { + cullFace: "back", + }, }; // @@ -81,9 +84,6 @@ export default class Rasterizer ...this.bindGroup, }, geometry: { - primitive: { - cullFace: "back", - }, vertices: this.scene.vertexAttributes, indices: this.scene.indices, draw: { __type__: "DrawIndexed", indexCount: this.scene.indexCount }, diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index a20a367..2180b65 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -122,6 +122,9 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleCubemapWGSL }, + primitive: { + cullFace: "none", + }, }, bindingResources: { uniforms: { @@ -131,9 +134,6 @@ const init = async (canvas: HTMLCanvasElement) => myTexture: { texture: cubemapTexture }, }, geometry: { - primitive: { - cullFace: "none", - }, vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index abeb041..9824f7a 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -81,6 +81,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: fragmentWriteGBuffers, }, + primitive, }; const gBuffersDebugViewPipeline: RenderPipeline = { @@ -94,6 +95,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => canvasSizeHeight: canvas.height, }, }, + primitive, }; const deferredRenderPipeline: RenderPipeline = { vertex: { @@ -102,6 +104,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: fragmentDeferredRendering, }, + primitive, }; const depthTexture: Texture = { @@ -332,7 +335,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...sceneUniformBindGroup, }, geometry: { - primitive, vertices, indices: indexBuffer, draw: { __type__: "DrawIndexed", indexCount }, @@ -364,7 +366,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...gBufferTexturesBindGroup, }, geometry: { - primitive, draw: { __type__: "DrawVertex", vertexCount: 6 }, } }, @@ -381,7 +382,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...lightsBufferBindGroup, }, geometry: { - primitive, draw: { __type__: "DrawVertex", vertexCount: 6 }, }, }, diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 03e97b7..4df0ca2 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -79,11 +79,11 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleSelfWGSL }, - }, - geometry: { primitive: { cullFace: "back", }, + }, + geometry: { vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 9e09a54..973cc8b 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -93,6 +93,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: fragWGSL, }, + primitive: { + topology: "triangle-strip", + }, }; const uniformBindGroup: BindingResources = { @@ -136,9 +139,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: renderPipeline, bindingResources: uniformBindGroup, geometry: { - primitive: { - topology: "triangle-strip", - }, vertices: vertices1, draw: { __type__: "DrawVertex", vertexCount: 4, instanceCount: length }, } diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 318275d..29a0847 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -104,11 +104,11 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: RenderObject = { pipeline: { vertex: { code: instancedVertWGSL }, fragment: { code: vertexPositionColorWGSL }, - }, - geometry: { primitive: { cullFace: "back", }, + }, + geometry: { vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index af089cc..0018032 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -122,6 +122,9 @@ const init = async () => fragment: { ...module, }, + primitive: { + cullFace: "back", + }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -318,9 +321,6 @@ const init = async () => pipeline: pipeline, bindingResources: bindGroup, geometry: { - primitive: { - cullFace: "back", - }, vertices: vertexAttributes, indices, draw: { __type__: "DrawIndexed", indexCount: indices.length }, diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index cddef77..e8cdc19 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -325,10 +325,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // * tangent : float32x3 // * bitangent : float32x3 geometry: { - primitive: { - topology: "triangle-list", - cullFace: "back", - }, vertices: { position: { data: box.vertices, offset: 0, format: "float32x3", arrayStride: box.vertexStride }, normal: { data: box.vertices, offset: 12, format: "float32x3", arrayStride: box.vertexStride }, diff --git a/examples/src/webgpu/normalMap/utils.ts b/examples/src/webgpu/normalMap/utils.ts index 8c12aea..ae3865c 100644 --- a/examples/src/webgpu/normalMap/utils.ts +++ b/examples/src/webgpu/normalMap/utils.ts @@ -24,6 +24,10 @@ export const create3DRenderPipeline = ( fragment: { code: fragmentShader, }, + primitive: { + topology: "triangle-list", + cullFace: "back", + }, depthStencil, }; diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 3707ce0..8da2f11 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -27,6 +27,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: solidColorLitWGSL, }, + primitive: { + topology: "triangle-list", + cullFace: "back", + }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -123,10 +127,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: RenderObject = { pipeline: pipeline, geometry: { - primitive: { - topology: "triangle-list", - cullFace: "back", - }, vertices: { position: { data: vertexBuf, offset: 0, arrayStride: 6 * 4, format: "float32x3" }, normal: { data: vertexBuf, offset: 12, arrayStride: 6 * 4, format: "float32x3" }, diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index b7eb7a5..f5514f5 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -48,6 +48,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => fragment: { code: meshWGSL, }, + primitive: { + // Backface culling since the sphere is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullFace: "back", + }, // Enable depth testing so that the fragment closest to the camera // is rendered in front. }; @@ -253,12 +259,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => pipeline: pipeline, bindingResources: { ...frameBindGroup, ...renderable.bindGroup }, geometry: { - primitive: { - // Backface culling since the sphere is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - cullFace: "back", - }, vertices: renderable.vertexAttributes, indices: renderable.indices, draw: { __type__: "DrawIndexed", indexCount: renderable.indexCount }, diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 30b38ba..5986c04 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -91,6 +91,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => vertex: { code: vertexDepthPrePassWGSL, }, + primitive: { + cullFace: "back", + }, }; // we need the depthCompare to fit the depth buffer mode we are using. @@ -120,6 +123,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: fragmentPrecisionErrorPassWGSL, }, + primitive: { + cullFace: "back", + }, }; const precisionPassPipelines: RenderPipeline[] = []; @@ -146,6 +152,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: fragmentWGSL, }, + primitive: { + cullFace: "back", + }, }; // @@ -369,9 +378,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: colorPassPipelines[m], bindingResources: { ...uniformBindGroups[m] }, geometry: { - primitive: { - cullFace: "back", - }, vertices, draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } @@ -396,9 +402,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: depthPrePassPipelines[m], bindingResources: { ...uniformBindGroups[m] }, geometry: { - primitive: { - cullFace: "back", - }, vertices, draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } @@ -418,9 +421,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: precisionPassPipelines[m], bindingResources: { ...uniformBindGroups[m], ...depthTextureBindGroup }, geometry: { - primitive: { - cullFace: "back", - }, vertices, draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } @@ -445,9 +445,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: depthPrePassPipelines[m], bindingResources: { ...uniformBindGroups[m] }, geometry: { - primitive: { - cullFace: "back", - }, vertices, draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, } diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index dfa1356..1dcc562 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -36,11 +36,11 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, - }, - geometry:{ primitive: { cullFace: "back", }, + }, + geometry:{ vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 87b2bf3..cabfc28 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -57,6 +57,7 @@ const init = async (canvas: HTMLCanvasElement) => vertex: { code: vertexShadowWGSL, }, + primitive, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -76,6 +77,7 @@ const init = async (canvas: HTMLCanvasElement) => shadowDepthTextureSize, }, }, + primitive, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -224,7 +226,6 @@ const init = async (canvas: HTMLCanvasElement) => ...modelBindGroup, }, geometry: { - primitive, vertices, indices: indexBuffer, draw: { __type__: "DrawIndexed", indexCount }, @@ -242,7 +243,6 @@ const init = async (canvas: HTMLCanvasElement) => ...modelBindGroup, }, geometry: { - primitive, vertices, indices: indexBuffer, draw: { __type__: "DrawIndexed", indexCount }, diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 235b786..da64c59 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -466,13 +466,13 @@ export class GLTFPrimitive topology: "triangle-strip", }; } + reactive(this.renderPipeline).primitive = primitive; const renderObject: RenderObject = { pipeline: this.renderPipeline, bindingResources: bindingResources, //if skin do something with bone bind group geometry: { - primitive, vertices: this.vertices, indices: this.indices, draw, diff --git a/examples/src/webgpu/skinnedMesh/gridUtils.ts b/examples/src/webgpu/skinnedMesh/gridUtils.ts index 3104480..5fa4a07 100644 --- a/examples/src/webgpu/skinnedMesh/gridUtils.ts +++ b/examples/src/webgpu/skinnedMesh/gridUtils.ts @@ -32,6 +32,9 @@ export const createSkinnedGridRenderPipeline = ( fragment: { code: fragmentShader, }, + primitive: { + topology: "line-list", + }, }; return material; diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 8f48e1f..cdb5002 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -516,9 +516,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...skinnedGridBoneBGCluster, }, geometry: { - primitive: { - topology: "line-list", - }, vertices: skinnedGridVertexBuffers.vertices, indices: skinnedGridVertexBuffers.indices, draw: { __type__: "DrawIndexed", indexCount: gridIndices.length }, diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index 515d3e8..4f594c7 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -147,6 +147,12 @@ setBlendConstant().`, fragment: { code: vertexPositionColorWGSL, }, + primitive: { + // Backface culling since the cube is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullFace: "back", + }, // Enable depth testing so that the fragment closest to the camera // is rendered in front. depthStencil: { @@ -255,12 +261,6 @@ setBlendConstant().`, pipeline: pipeline, bindingResources: uniformBindGroup, geometry: { - primitive: { - // Backface culling since the cube is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - cullFace: "back", - }, vertices: verticesBuffer, draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: 1 }, } diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index 9d90cff..66b3704 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -189,6 +189,9 @@ export class MsdfTextRenderer }, ], }, + primitive: { + topology: "triangle-strip", + }, depthStencil: { depthWriteEnabled: false, depthCompare: "less", @@ -345,9 +348,6 @@ export class MsdfTextRenderer ...bindGroup, }, geometry: { - primitive: { - topology: "triangle-strip", - }, draw: { __type__: "DrawVertex", vertexCount: 4, instanceCount: measurements.printedCharCount }, } } diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index 23b40d1..0e93302 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -55,6 +55,9 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: sampleTextureMixColorWGSL }, + primitive: { + cullFace: "back", + }, }, bindingResources: { uniforms, @@ -62,9 +65,6 @@ const init = async (canvas: HTMLCanvasElement) => myTexture: { texture: cubeTexture }, }, geometry: { - primitive: { - cullFace: "back", - }, vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 3743e76..f7c9dfc 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -63,7 +63,14 @@ const init = async (canvas: HTMLCanvasElement) => fragment: { code: fragmentWGSL, }, + primitive: { + topology: "triangle-list", + // Backface culling since the cube is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullFace: "back", + }, // Enable depth testing so that the fragment closest to the camera // is rendered in front. depthStencil: { @@ -102,14 +109,6 @@ const init = async (canvas: HTMLCanvasElement) => uniforms, }, geometry: { - primitive: { - topology: "triangle-list", - - // Backface culling since the cube is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - cullFace: "back", - }, vertices, draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 5b25b29..1b453ca 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -37,6 +37,10 @@ const init = async (canvas: HTMLCanvasElement) => fragment: { code: vertexPositionColorWGSL, }, + primitive: { + topology: "triangle-list", + cullFace: "back", + }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -104,10 +108,6 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: pipeline, bindingResources: uniformBindGroup, geometry: { - primitive: { - topology: "triangle-list", - cullFace: "back", - }, vertices: verticesBuffer, draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index a755785..e6b6909 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { BufferBinding, RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderObject, RenderPassDescriptor, Submit } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -45,14 +45,14 @@ const init = async (canvas: HTMLCanvasElement) => const renderObject: RenderObject = { pipeline: { vertex: { code: basicVertWGSL }, fragment: { code: vertexPositionColorWGSL }, + primitive: { + cullFace: "back", + }, }, bindingResources: { uniforms, }, geometry: { - primitive: { - cullFace: "back", - }, vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index a72bd21..2df655d 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -35,6 +35,10 @@ const init = async (canvas: HTMLCanvasElement) => fragment: { code: volumeWGSL, }, + primitive: { + topology: "triangle-list", + cullFace: "back", + }, }; const uniformBuffer = { @@ -160,10 +164,6 @@ const init = async (canvas: HTMLCanvasElement) => pipeline, bindingResources: uniformBindGroup, geometry: { - primitive: { - topology: "triangle-list", - cullFace: "back", - }, draw: { __type__: "DrawVertex", vertexCount: 3 }, } }], diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index b70e46f..4e6b8c7 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -1,4 +1,4 @@ -import { BindingResources, PrimitiveState, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -58,6 +58,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => fragment: { code: solidColorLitWGSL, }, + primitive: { + cullFace: "back", + }, depthStencil: { depthWriteEnabled: true, depthCompare: "less", @@ -82,6 +85,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => code: wireframeWGSL, entryPoint: "fs", }, + primitive: { + topology: "line-list", + }, depthStencil: { depthWriteEnabled: true, depthCompare: "less-equal", @@ -112,6 +118,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, ], }, + primitive: { + topology: "triangle-list", + }, depthStencil: { depthWriteEnabled: true, depthCompare: "less-equal", @@ -321,9 +330,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: litPipeline, bindingResources: litBindGroup, geometry: { - primitive: { - cullFace: "back", - }, vertices: vertexAttributes, indices, draw: { __type__: "DrawIndexed", indexCount: indices.length }, @@ -338,21 +344,16 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Note: If we're using the line-list based pipeline then we need to // multiply the vertex count by 2 since we need to emit 6 vertices // for each triangle (3 edges). - const [bindGroupNdx, countMult, pipeline, primitive] + const [bindGroupNdx, countMult, pipeline] = settings.barycentricCoordinatesBased - ? [1, 1, barycentricCoordinatesBasedWireframePipeline, { - topology: "triangle-list", - } as PrimitiveState] - : [0, 2, wireframePipeline, { - topology: "line-list", - } as PrimitiveState]; + ? [1, 1, barycentricCoordinatesBasedWireframePipeline] + : [0, 2, wireframePipeline]; objectInfos.forEach(({ wireframeBindGroups, model: { indices } }) => { renderObjects.push({ pipeline, bindingResources: wireframeBindGroups[bindGroupNdx], geometry: { - primitive, draw: { __type__: "DrawVertex", vertexCount: indices.length * countMult }, } }); diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index b478041..8971cbd 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -85,7 +85,15 @@ async function init(canvas: OffscreenCanvas) fragment: { code: vertexPositionColorWGSL, }, - + primitive: { + topology: "triangle-list", + + // Backface culling since the cube is solid piece of geometry. + // Faces pointing away from the camera will be occluded by faces + // pointing toward the camera. + cullFace: "back", + frontFace: "ccw", + }, // Enable depth testing so that the fragment closest to the camera // is rendered in front. depthStencil: { @@ -149,15 +157,6 @@ async function init(canvas: OffscreenCanvas) pipeline, bindingResources: uniformBindGroup, geometry: { - primitive: { - topology: "triangle-list", - - // Backface culling since the cube is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - cullFace: "back", - frontFace: "ccw", - }, vertices: verticesBuffer, draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount } } -- Gitee From 1b5adf3596e5d49757bbfe3f474985ebfcbe90e0 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 16:29:38 +0800 Subject: [PATCH 106/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E5=88=9B=E5=BB=BA=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构了 getNGPURenderPipeline 函数,提高了代码可读性和维护性 - 优化了对渲染管线各阶段状态的处理,减少了不必要的中间变量 - 改进了对 reactive 对象的使用,确保了响应式更新的正确性 - 调整了部分属性的访问方式,提高了代码的健壮性 --- src/caches/getNGPURenderPipeline.ts | 126 ++++++++++++++++----------- src/data/polyfills/PrimitiveState.ts | 2 +- 2 files changed, 74 insertions(+), 54 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 7af931e..cd84068 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, PrimitiveState, reactive, RenderPipeline, StencilFaceState, toRaw, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType, WriteMask } from "@feng3d/render-api"; +import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType, WriteMask } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; @@ -33,35 +33,28 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const gpuRenderPipeline = computed(() => { - // - reactive(renderPipeline).label; - const label = renderPipeline.label; - - // 更新管线布局 - reactive(renderPipeline).vertex.code; - reactive(renderPipeline).fragment?.code - const layout = getGPUPipelineLayout(device, { vertex: renderPipeline.vertex.code, fragment: renderPipeline.fragment?.code }); - - // - reactive(renderPipeline).fragment; - const fragment = getGPUFragmentState(device, renderPipeline.fragment, renderPassFormat.colorFormats); - - // - reactive(renderPipeline).primitive; - const primitive = getGPUPrimitiveState(renderPipeline.primitive, indexFormat); - - // 获取深度模板阶段完整描述。 - reactive(renderPipeline).depthStencil; - const depthStencil = getGPUDepthStencilState(renderPipeline.depthStencil, renderPassFormat.depthStencilFormat); - + // 监听 + const r_renderPipeline = reactive(renderPipeline); + r_renderPipeline.label; + r_renderPipeline.fragment; + r_renderPipeline.primitive; + r_renderPipeline.depthStencil; + // r_renderPipeline.vertex + r_renderPipeline.vertex.code; + // r_renderPipeline.fragment + r_renderPipeline.fragment?.code + + // 计算 + const { label, vertex, fragment, primitive, depthStencil } = renderPipeline; + const shader = { vertex: vertex.code, fragment: fragment?.code }; // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { - label, - layout, + label: label, + layout: getGPUPipelineLayout(device, shader), vertex: vertexStateResult.gpuVertexState, - fragment, - primitive, - depthStencil, + fragment: getGPUFragmentState(device, fragment, renderPassFormat.colorFormats), + primitive: getGPUPrimitiveState(primitive, indexFormat), + depthStencil: getGPUDepthStencilState(depthStencil, renderPassFormat.depthStencilFormat), multisample: gpuMultisampleState, }; @@ -92,9 +85,15 @@ function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndex const result: ComputedRef = primitive["_cache_GPUPrimitiveState_" + indexFormat] ??= computed(() => { - let { topology, cullFace, frontFace, unclippedDepth } = reactive(primitive); - - // + // 监听 + const r_primitive = reactive(primitive); + r_primitive.topology; + r_primitive.cullFace; + r_primitive.frontFace; + r_primitive.unclippedDepth; + + // 计算 + const { topology, cullFace, frontFace, unclippedDepth } = primitive; const gpuPrimitive: GPUPrimitiveState = { topology: topology ?? "triangle-list", stripIndexFormat: (topology === "triangle-strip" || topology === "line-strip") ? indexFormat : undefined, @@ -137,15 +136,26 @@ function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFo const result: ComputedRef = depthStencil["_cache_GPUDepthStencilState_" + depthStencilFormat] = computed(() => { - const { depthWriteEnabled, depthCompare, stencilFront, stencilBack, stencilReadMask, stencilWriteMask, depthBias, depthBiasSlopeScale, depthBiasClamp } = reactive(depthStencil); - - // + // 监听 + const r_depthStencil = reactive(depthStencil); + r_depthStencil.depthWriteEnabled; + r_depthStencil.depthCompare; + r_depthStencil.stencilFront; + r_depthStencil.stencilBack; + r_depthStencil.stencilReadMask; + r_depthStencil.stencilWriteMask; + r_depthStencil.depthBias; + r_depthStencil.depthBiasSlopeScale; + r_depthStencil.depthBiasClamp; + + // 计算 + const { depthWriteEnabled, depthCompare, stencilFront, stencilBack, stencilReadMask, stencilWriteMask, depthBias, depthBiasSlopeScale, depthBiasClamp } = depthStencil; const gpuDepthStencilState: GPUDepthStencilState = { format: depthStencilFormat, depthWriteEnabled: depthWriteEnabled ?? true, depthCompare: depthCompare ?? "less", - stencilFront: getGPUStencilFaceState(toRaw(stencilFront)), - stencilBack: getGPUStencilFaceState(toRaw(stencilBack)), + stencilFront: getGPUStencilFaceState(stencilFront), + stencilBack: getGPUStencilFaceState(stencilBack), stencilReadMask: stencilReadMask ?? 0xFFFFFFFF, stencilWriteMask: stencilWriteMask ?? 0xFFFFFFFF, depthBias: depthBias ?? 0, @@ -165,8 +175,15 @@ function getGPUStencilFaceState(stencilFaceState?: StencilFaceState) const result: ComputedRef = stencilFaceState["_cache_GPUStencilFaceState"] = computed(() => { - const { compare, failOp, depthFailOp, passOp } = reactive(stencilFaceState); - + // 监听 + const r_stencilFaceState = reactive(stencilFaceState); + r_stencilFaceState.compare; + r_stencilFaceState.failOp; + r_stencilFaceState.depthFailOp; + r_stencilFaceState.passOp; + + // 计算 + const { compare, failOp, depthFailOp, passOp } = stencilFaceState; const gpuStencilFaceState: GPUStencilFaceState = { compare: compare ?? "always", failOp: failOp ?? "keep", @@ -349,18 +366,17 @@ function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUT const result: ComputedRef = colorTargetState["_GPUColorTargetState_" + format] ??= computed(() => { - // - reactive(colorTargetState)?.writeMask; - const writeMask = getGPUColorWriteFlags(colorTargetState?.writeMask); - - reactive(colorTargetState)?.blend; - const blend = getGPUBlendState(colorTargetState?.blend); + // 监听 + const r_colorTargetState = reactive(colorTargetState); + r_colorTargetState.writeMask; + r_colorTargetState.blend; - // + // 计算 + const { writeMask, blend } = colorTargetState; const gpuColorTargetState: GPUColorTargetState = { format, - blend, - writeMask, + blend: getGPUBlendState(blend), + writeMask: getGPUColorWriteFlags(writeMask), }; return gpuColorTargetState; @@ -387,8 +403,10 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co gpuFragmentState = computed(() => { - // 监听着色器代码变化 - reactive(fragmentState).code; + // 监听 + const r_fragmentState = reactive(fragmentState); + r_fragmentState.code; + const module = getGPUShaderModule(device, fragmentState.code); // 监听着色器入口点变化 @@ -491,12 +509,14 @@ function getGPUBlendState(blend?: BlendState): GPUBlendState result = blend["_GPUBlendState"] = computed(() => { - reactive(blend)?.color; - reactive(blend)?.alpha; - // + // 监听 + const r_blend = reactive(blend); + r_blend.color; + r_blend.alpha; + // 计算 const gpuBlend: GPUBlendState = { - color: getGPUBlendComponent(blend?.color), - alpha: getGPUBlendComponent(blend?.alpha), + color: getGPUBlendComponent(blend.color), + alpha: getGPUBlendComponent(blend.alpha), }; return gpuBlend; }) diff --git a/src/data/polyfills/PrimitiveState.ts b/src/data/polyfills/PrimitiveState.ts index c400f9c..f9ff0bc 100644 --- a/src/data/polyfills/PrimitiveState.ts +++ b/src/data/polyfills/PrimitiveState.ts @@ -13,7 +13,7 @@ declare module "@feng3d/render-api" * If true, indicates that depth clipping is disabled. * Requires the {@link GPUFeatureName#"depth-clip-control"} feature to be enabled. */ - unclippedDepth?: boolean; + readonly unclippedDepth?: boolean; } } -- Gitee From 1d713ba2f4b74622f69ba1b6f5fdf0422bbaf192 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 17:42:05 +0800 Subject: [PATCH 107/214] =?UTF-8?q?refactor(src):=20=E9=87=8D=E6=9E=84=20G?= =?UTF-8?q?PU=20=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E9=A2=9C=E8=89=B2=E7=9B=AE=E6=A0=87=E7=8A=B6=E6=80=81=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 defaultGPUColorTargetState 和 defaultGPUColorTargetStates 函数,用于处理默认颜色目标状态 - 优化 getGPUColorTargetState 和 getGPUColorTargetStates 函数的实现 - 重构 getGPUFragmentState 函数,提高代码可读性和性能 - 优化 getEntryPoint 函数,简化片元着色器入口点的获取逻辑 - 调整 getGPUBlendState 和 getGPUBlendComponent 函数,提高代码可读性 - 优化 getGPUColorWriteFlags 函数的实现 --- src/caches/getNGPURenderPipeline.ts | 136 +++++++++++++--------------- 1 file changed, 64 insertions(+), 72 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index cd84068..10b24ae 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -362,7 +362,7 @@ function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUTextureFormat) { - if (!colorTargetState) return { format, blend: getGPUBlendState(undefined), writeMask: getGPUColorWriteFlags(undefined) }; + if (!colorTargetState) return defaultGPUColorTargetState(format); const result: ComputedRef = colorTargetState["_GPUColorTargetState_" + format] ??= computed(() => { @@ -385,6 +385,12 @@ function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUT return result.value; } +const _defaultGPUColorTargetState = {}; +const defaultGPUColorTargetState = (format: GPUTextureFormat) => +{ + return _defaultGPUColorTargetState[format] ??= { format, blend: getGPUBlendState(undefined), writeMask: getGPUColorWriteFlags(undefined) } +}; + /** * 获取片段阶段完整描述。 * @@ -406,26 +412,16 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co // 监听 const r_fragmentState = reactive(fragmentState); r_fragmentState.code; + r_fragmentState.targets; + for (const key in r_fragmentState.constants) { r_fragmentState.constants[key]; } - const module = getGPUShaderModule(device, fragmentState.code); - - // 监听着色器入口点变化 - const entryPoint = getEntryPoint(fragmentState); - - // 监听渲染目标变化 - reactive(fragmentState).targets; - const targets = getGPUColorTargetStates(fragmentState.targets, colorAttachments); - - // 监听常量变化 - const r_constants = reactive(fragmentState).constants; - for (const key in r_constants) { r_constants[key]; } - - // + // 计算 + const { code, targets, constants } = fragmentState; return { - module, - entryPoint, - targets, - constants: fragmentState.constants + module: getGPUShaderModule(device, code), + entryPoint: getEntryPoint(fragmentState), + targets: getGPUColorTargetStates(targets, colorAttachments), + constants: constants } as GPUFragmentState; }); @@ -436,13 +432,7 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]): GPUColorTargetState[] { - if (!targets) - { - return undefinedMap["_GPUColorTargetStates_" + colorAttachments.toString()] ??= colorAttachments.map((format) => - { - return getGPUColorTargetState(undefined, format); - }); - }; + if (!targets) return defaultGPUColorTargetStates(colorAttachments); const result: ComputedRef = targets["_GPUColorTargetStates_" + colorAttachments.toString()] ??= computed(() => { @@ -450,9 +440,11 @@ function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAtta { if (!format) return undefined; - // + // 监听 reactive(targets)[i]; - const gpuColorTargetState = getGPUColorTargetState(targets?.[i], format); + + // 计算 + const gpuColorTargetState = getGPUColorTargetState(targets[i], format); return gpuColorTargetState; }); @@ -460,40 +452,33 @@ function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAtta return result.value; } -const undefinedMap: { [key: string]: GPUColorTargetState[] } = {}; +const _defaultGPUColorTargetStates: { [key: string]: GPUColorTargetState[] } = {}; +const defaultGPUColorTargetStates = (colorAttachments: readonly GPUTextureFormat[]) => +{ + return _defaultGPUColorTargetStates[colorAttachments.toString()] ??= colorAttachments.map((format) => + { + return getGPUColorTargetState(undefined, format); + }); +}; function getEntryPoint(fragmentState: FragmentState) { const result: ComputedRef = fragmentState["_entryPoint"] ??= computed(() => { - // 监听着色器入口点变化 - reactive(fragmentState).entryPoint; + // 监听 + const r_fragmentState = reactive(fragmentState); + r_fragmentState.entryPoint; + r_fragmentState.code; - // - let entryPoint = fragmentState.entryPoint; + // 计算 + const { entryPoint, code } = fragmentState; + // if (entryPoint) return entryPoint; + const reflect = getWGSLReflectInfo(code); + const fragment = reflect.entry.fragment[0]; + console.assert(!!fragment, `WGSL着色器 ${code} 中不存在片元入口点。`); - // 监听着色器代码变化 - reactive(fragmentState).code; - - // 计算片元着色器入口点 - const code = fragmentState.code; - let fragment: FunctionInfo; - if (!entryPoint) - { - const reflect = getWGSLReflectInfo(code); - fragment = reflect.entry.fragment[0]; - console.assert(!!fragment, `WGSL着色器 ${code} 中不存在片元入口点。`); - entryPoint = fragment.name; - } - else - { - // 验证着色器中包含指定片段入口函数。 - const reflect = getWGSLReflectInfo(code); - fragment = reflect.entry.fragment.filter((v) => v.name === entryPoint)[0]; - console.assert(!!fragment, `WGSL着色器 ${code} 中不存在指定的片元入口点 ${entryPoint} 。`); - } - return entryPoint; + return fragment.name; }); return result.value; @@ -514,9 +499,10 @@ function getGPUBlendState(blend?: BlendState): GPUBlendState r_blend.color; r_blend.alpha; // 计算 + const { color, alpha } = blend; const gpuBlend: GPUBlendState = { - color: getGPUBlendComponent(blend.color), - alpha: getGPUBlendComponent(blend.alpha), + color: getGPUBlendComponent(color), + alpha: getGPUBlendComponent(alpha), }; return gpuBlend; }) @@ -530,20 +516,19 @@ function getGPUBlendComponent(blendComponent?: BlendComponent): GPUBlendComponen const result: ComputedRef = blendComponent["_GPUBlendComponent"] ??= computed(() => { + // 监听 const r_blendComponent = reactive(blendComponent); - // - const operation: GPUBlendOperation = r_blendComponent?.operation ?? "add"; - let srcFactor: GPUBlendFactor = r_blendComponent?.srcFactor ?? "one"; - let dstFactor: GPUBlendFactor = r_blendComponent?.dstFactor ?? "zero"; - if (operation === "max" || operation === "min") - { - srcFactor = dstFactor = "one"; - } + r_blendComponent.operation; + r_blendComponent.srcFactor; + r_blendComponent.dstFactor; + // 计算 + const { operation, srcFactor, dstFactor } = blendComponent; + // 当 operation 为 max 或 min 时,srcFactor 和 dstFactor 必须为 one。 const gpuBlendComponent: GPUBlendComponent = { - operation, - srcFactor, - dstFactor, + operation: operation ?? "add", + srcFactor: (operation === "max" || operation === "min") ? "one" : (srcFactor ?? "one"), + dstFactor: (operation === "max" || operation === "min") ? "one" : (dstFactor ?? "zero"), }; return gpuBlendComponent; }); @@ -557,22 +542,29 @@ function getGPUColorWriteFlags(writeMask?: WriteMask) const result: ComputedRef = writeMask["_GPUColorWriteFlags"] ??= computed(() => { + // 监听 const r_writeMask = reactive(writeMask); - // + r_writeMask[0]; + r_writeMask[1]; + r_writeMask[2]; + r_writeMask[3]; + + // 计算 + const [red, green, blue, alpha] = writeMask; let gpuWriteMask: GPUColorWriteFlags = 0; - if (r_writeMask[0]) + if (red) { gpuWriteMask += 1; } - if (r_writeMask[1]) + if (green) { gpuWriteMask += 2; } - if (r_writeMask[2]) + if (blue) { gpuWriteMask += 4; } - if (r_writeMask[3]) + if (alpha) { gpuWriteMask += 8; } -- Gitee From 4cefbfd611e6224908a6bec1804aa34d91992c0f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 18:01:49 +0800 Subject: [PATCH 108/214] =?UTF-8?q?refactor(getNGPURenderPipeline):=20?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=A4=9A=E9=87=87=E6=A0=B7=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 getGPUMultisampleState 函数从渲染管道中移出,作为独立的计算属性 - 优化多采样状态的计算,包括 mask 和 alphaToCoverageEnabled 属性 - 调整 renderPipeline 和 renderPassFormat 的解构方式,提高代码可读性 - 移除不必要的注释,简化代码结构 --- src/caches/getNGPURenderPipeline.ts | 36 +++++++++++++++++++---------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 10b24ae..28caa5a 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -28,9 +28,6 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP // 获取完整的顶点阶段描述与顶点缓冲区列表。 const vertexStateResult = getNGPUVertexState(device, renderPipeline.vertex, vertices); - // 从渲染通道上获取多重采样数量 - const gpuMultisampleState = getGPUMultisampleState(renderPipeline.multisample, renderPassFormat.sampleCount); - const gpuRenderPipeline = computed(() => { // 监听 @@ -43,19 +40,21 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP r_renderPipeline.vertex.code; // r_renderPipeline.fragment r_renderPipeline.fragment?.code + r_renderPipeline.multisample // 计算 - const { label, vertex, fragment, primitive, depthStencil } = renderPipeline; + const { label, vertex, fragment, primitive, depthStencil, multisample } = renderPipeline; const shader = { vertex: vertex.code, fragment: fragment?.code }; + const { colorFormats, depthStencilFormat, sampleCount } = renderPassFormat; // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { label: label, layout: getGPUPipelineLayout(device, shader), vertex: vertexStateResult.gpuVertexState, - fragment: getGPUFragmentState(device, fragment, renderPassFormat.colorFormats), + fragment: getGPUFragmentState(device, fragment, colorFormats), primitive: getGPUPrimitiveState(primitive, indexFormat), - depthStencil: getGPUDepthStencilState(depthStencil, renderPassFormat.depthStencilFormat), - multisample: gpuMultisampleState, + depthStencil: getGPUDepthStencilState(depthStencil, depthStencilFormat), + multisample: getGPUMultisampleState(multisample, sampleCount), }; const gpuRenderPipeline = device.createRenderPipeline(gpuRenderPipelineDescriptor); @@ -113,12 +112,25 @@ function getGPUMultisampleState(multisampleState?: MultisampleState, sampleCount { if (!sampleCount) return undefined; - const gpuMultisampleState: GPUMultisampleState = { - ...multisampleState, - count: sampleCount, - }; + const result: ComputedRef = multisampleState["_cache_GPUMultisampleState_" + sampleCount] ??= computed(() => + { + // 监听 + const r_multisampleState = reactive(multisampleState); + r_multisampleState.mask; + r_multisampleState.alphaToCoverageEnabled; + + // 计算 + const { mask, alphaToCoverageEnabled } = multisampleState; + const gpuMultisampleState: GPUMultisampleState = { + count: sampleCount, + mask: mask ?? 0xFFFFFFFF, + alphaToCoverageEnabled: alphaToCoverageEnabled ?? false, + }; - return gpuMultisampleState; + return gpuMultisampleState; + }); + + return result.value; } /** -- Gitee From 54bd5a659927ae44209eed230cff6aa8a51eddd6 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 19:47:55 +0800 Subject: [PATCH 109/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E5=92=8C=E9=A1=B6=E7=82=B9?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 NVertexBuffer 类,改为直接使用 GPUVertexState - 重构 getNGPURenderPipeline 方法,使用 computed 引用代替手动版本控制 - 提取 getNGPUVertexState 方法到单独的模块中 - 删除冗余的 watcher 使用 - 优化代码结构,提高可读性和性能 --- src/WebGPUBase.ts | 15 +-- src/caches/getNGPURenderPipeline.ts | 193 +--------------------------- src/caches/getNGPUVertexState.ts | 157 ++++++++++++++++++++++ 3 files changed, 170 insertions(+), 195 deletions(-) create mode 100644 src/caches/getNGPUVertexState.ts diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index f53007d..4d215a0 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, FragmentState, GBuffer, OcclusionQuery, PrimitiveState, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, FragmentState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -12,6 +12,7 @@ import { getGPURenderTimestampQuery } from "./caches/getGPURenderTimestampQuery" import { getGPUTexture } from "./caches/getGPUTexture"; import { getGBuffer } from "./caches/getIGPUBuffer"; import { getNGPURenderPipeline } from "./caches/getNGPURenderPipeline"; +import { getNGPUVertexState } from "./caches/getNGPUVertexState"; import { getRealGPUBindGroup } from "./const"; import { ComputeObject } from "./data/ComputeObject"; import { ComputePass } from "./data/ComputePass"; @@ -20,7 +21,6 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit } from "./eventnames"; -import { NVertexBuffer } from "./internal/NGPUVertexBuffer"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; @@ -46,11 +46,7 @@ declare global setBindGroupCommands: Array; }>; _renderObjectCommandMap: ChainMap<[string, RenderObject], Array>; - _renderPipelineMap: ChainMap<[RenderPipeline, string, VertexAttributes, GPUIndexFormat], { - pipeline: ComputedRef; - vertexBuffers: NVertexBuffer[]; - _version: number; - }>; + _renderPipelineMap: ChainMap<[RenderPipeline, string, VertexAttributes, GPUIndexFormat], ComputedRef>; _fragmentStateMap: ChainMap<[FragmentState, string], ComputedRef> } } @@ -487,10 +483,10 @@ export class WebGPUBase const { vertices, indices, draw } = geometry; // - const { pipeline: nPipeline, vertexBuffers } = getNGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indices); + const nPipeline = getNGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indices); // - passEncoder.setPipeline(nPipeline.value); + passEncoder.setPipeline(nPipeline); // const stencilReference = getStencilReference(pipeline.depthStencil); @@ -532,6 +528,7 @@ export class WebGPUBase }); // + const { vertexBuffers } = getNGPUVertexState(device, pipeline.vertex, vertices); vertexBuffers?.forEach((vertexBuffer, index) => { const buffer = getGBuffer(vertexBuffer.data); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 28caa5a..6afe61c 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -1,13 +1,11 @@ -import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, vertexFormatMap, VertexState, WGSLVertexType, WriteMask } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; -import { FunctionInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; +import { BlendComponent, BlendState, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, WGSLVertexType, WriteMask } from "@feng3d/render-api"; +import { TemplateInfo, TypeInfo } from "wgsl_reflect"; -import { gPartial } from "@feng3d/polyfill"; import { MultisampleState } from "../data/MultisampleState"; -import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; import { RenderPassFormat } from "../internal/RenderPassFormat"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; import { getGPUShaderModule } from "./getGPUShaderModule"; +import { getNGPUVertexState } from "./getNGPUVertexState"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; /** @@ -23,12 +21,9 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const indexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; let result = device._renderPipelineMap.get([renderPipeline, renderPassFormat._key, vertices, indexFormat]); - if (result) return result; - - // 获取完整的顶点阶段描述与顶点缓冲区列表。 - const vertexStateResult = getNGPUVertexState(device, renderPipeline.vertex, vertices); + if (result) return result.value; - const gpuRenderPipeline = computed(() => + result = computed(() => { // 监听 const r_renderPipeline = reactive(renderPipeline); @@ -46,6 +41,7 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const { label, vertex, fragment, primitive, depthStencil, multisample } = renderPipeline; const shader = { vertex: vertex.code, fragment: fragment?.code }; const { colorFormats, depthStencilFormat, sampleCount } = renderPassFormat; + const vertexStateResult = getNGPUVertexState(device, vertex, vertices); // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { label: label, @@ -61,21 +57,9 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP return gpuRenderPipeline; }); - - result = { _version: 0, pipeline: gpuRenderPipeline, vertexBuffers: vertexStateResult.vertexBuffers }; device._renderPipelineMap.set([renderPipeline, renderPassFormat._key, vertices, indexFormat], result); - // 监听管线变化 - const onchanged = () => - { - result._version++; - renderPipeline._version = ~~renderPipeline._version + 1; - device._renderPipelineMap.delete([renderPipeline, renderPassFormat._key, vertices, indexFormat]); - watcher.unwatch(vertexStateResult, "_version", onchanged); - } - watcher.watch(vertexStateResult, "_version", onchanged); - - return result; + return result.value; } function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndexFormat): GPUPrimitiveState @@ -209,169 +193,6 @@ function getGPUStencilFaceState(stencilFaceState?: StencilFaceState) return result.value; } -/** - * 获取完整的顶点阶段描述与顶点缓冲区列表。 - * - * @param vertexState 顶点阶段信息。 - * @param vertices 顶点数据。 - * @returns 完整的顶点阶段描述与顶点缓冲区列表。 - */ -function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) -{ - let result = vertexStateMap.get([vertexState, vertices]); - if (result) return result; - - const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); - - const { vertexBufferLayouts, vertexBuffers } = getNGPUVertexBuffers(vertexEntryFunctionInfo, vertices); - - const gpuVertexState: GPUVertexState = { - module: getGPUShaderModule(device, vertexState.code), - entryPoint: vertexEntryFunctionInfo.name, - buffers: vertexBufferLayouts, - constants: vertexState.constants, - }; - - // - result = { _version: 0, gpuVertexState, vertexBuffers }; - vertexStateMap.set([vertexState, vertices], result); - - // 监听变化 - const watchpropertys: gPartial = { code: "" }; - const onchanged = () => - { - vertexStateMap.delete([vertexState, vertices]); - watcher.unwatchobject(vertexState, watchpropertys, onchanged); - result._version++; - }; - watcher.watchobject(vertexState, watchpropertys, onchanged); - - return result; -} - -/** - * 获取顶点入口函数信息。 - * - * @param vertexState 顶点阶段信息。 - * @returns - */ -function getVertexEntryFunctionInfo(vertexState: VertexState) -{ - let vertexEntryFunctionInfo: FunctionInfo = vertexState["_vertexEntry"]; - if (vertexEntryFunctionInfo) return vertexEntryFunctionInfo; - - const code = vertexState.code; - - // 解析顶点着色器 - const reflect = getWGSLReflectInfo(code); - // - if (vertexState.entryPoint) - { - vertexEntryFunctionInfo = reflect.entry.vertex.filter((v) => v.name === vertexState.entryPoint)[0]; - console.assert(!!vertexEntryFunctionInfo, `WGSL着色器 ${code} 中不存在顶点入口点 ${vertexState.entryPoint} 。`); - } - else - { - vertexEntryFunctionInfo = reflect.entry.vertex[0]; - console.assert(!!reflect.entry.vertex[0], `WGSL着色器 ${code} 中不存在顶点入口点。`); - } - - vertexState["_vertexEntry"] = vertexEntryFunctionInfo; - - return vertexEntryFunctionInfo; -} - -const vertexStateMap = new ChainMap<[VertexState, VertexAttributes], { - gpuVertexState: GPUVertexState; - vertexBuffers: NVertexBuffer[]; - /** - * 版本号,用于版本控制。 - */ - _version: number; -}>(); - -/** - * 从顶点属性信息与顶点数据中获取顶点缓冲区布局数组以及顶点缓冲区数组。 - * - * @param vertex 顶点着色器函数信息。 - * @param vertices 顶点数据。 - * @returns 顶点缓冲区布局数组以及顶点缓冲区数组。 - */ -function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) -{ - const vertexBufferLayouts: GPUVertexBufferLayout[] = []; - - const vertexBuffers: NVertexBuffer[] = []; - - const map = new Map(); - - vertex.inputs.forEach((v) => - { - // 跳过内置属性。 - if (v.locationType === "builtin") return; - - const shaderLocation = v.location as number; - const attributeName = v.name; - - const vertexAttribute = vertices[attributeName]; - console.assert(!!vertexAttribute, `在提供的顶点属性数据中未找到 ${attributeName} 。`); - // - const data = vertexAttribute.data; - const attributeOffset = vertexAttribute.offset || 0; - let arrayStride = vertexAttribute.arrayStride; - const stepMode = vertexAttribute.stepMode; - const format = vertexAttribute.format; - // 检查提供的顶点数据格式是否与着色器匹配 - // const wgslType = getWGSLType(v.type); - // let possibleFormats = wgslVertexTypeMap[wgslType].possibleFormats; - // console.assert(possibleFormats.indexOf(format) !== -1, `顶点${attributeName} 提供的数据格式 ${format} 与着色器中类型 ${wgslType} 不匹配!`); - console.assert(data.constructor.name === vertexFormatMap[format].typedArrayConstructor.name, - `顶点${attributeName} 提供的数据类型 ${data.constructor.name} 与格式 ${format} 不匹配!请使用 ${data.constructor.name} 来组织数据或者更改数据格式。`); - - // 如果 偏移值大于 单个顶点尺寸,则该值被放入 IGPUVertexBuffer.offset。 - const vertexByteSize = vertexFormatMap[format].byteSize; - // - if (!arrayStride) - { - arrayStride = vertexByteSize; - } - console.assert(attributeOffset + vertexByteSize <= arrayStride, `offset(${attributeOffset}) + vertexByteSize(${vertexByteSize}) 必须不超出 arrayStride(${arrayStride})。`); - - watcher.watch(vertexAttribute, "data", () => - { - const index = map.get(data); - const attributeData = vertexAttribute.data; - - vertexBuffers[index].data = attributeData; - vertexBuffers[index].offset = attributeData.byteOffset; - vertexBuffers[index].size = attributeData.byteLength; - }); - - let index = map.get(data); - if (index === undefined) - { - index = vertexBufferLayouts.length; - map.set(data, index); - - vertexBuffers[index] = { data, offset: data.byteOffset, size: data.byteLength }; - - // - vertexBufferLayouts[index] = { stepMode, arrayStride, attributes: [] }; - } - else - { - // 要求同一顶点缓冲区中 arrayStride 与 stepMode 必须相同。 - const gpuVertexBufferLayout = vertexBufferLayouts[index]; - console.assert(gpuVertexBufferLayout.arrayStride === arrayStride); - console.assert(gpuVertexBufferLayout.stepMode === stepMode); - } - - (vertexBufferLayouts[index].attributes as Array).push({ shaderLocation, offset: attributeOffset, format }); - }); - - return { vertexBufferLayouts, vertexBuffers }; -} - function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUTextureFormat) { if (!colorTargetState) return defaultGPUColorTargetState(format); diff --git a/src/caches/getNGPUVertexState.ts b/src/caches/getNGPUVertexState.ts new file mode 100644 index 0000000..bcfc049 --- /dev/null +++ b/src/caches/getNGPUVertexState.ts @@ -0,0 +1,157 @@ +import { VertexState, VertexAttributes, computed, ChainMap, ComputedRef, vertexFormatMap } from "@feng3d/render-api"; +import { getGPUShaderModule } from "./getGPUShaderModule"; +import { watcher } from "@feng3d/watcher"; +import { FunctionInfo } from "wgsl_reflect"; +import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; +import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; + +/** + * 获取完整的顶点阶段描述与顶点缓冲区列表。 + * + * @param vertexState 顶点阶段信息。 + * @param vertices 顶点数据。 + * @returns 完整的顶点阶段描述与顶点缓冲区列表。 + */ +export function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) +{ + let result = vertexStateMap.get([vertexState, vertices]); + if (result) return result.value; + + result = computed(() => + { + const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); + + const { vertexBufferLayouts, vertexBuffers } = getNGPUVertexBuffers(vertexEntryFunctionInfo, vertices); + + const gpuVertexState: GPUVertexState = { + module: getGPUShaderModule(device, vertexState.code), + entryPoint: vertexEntryFunctionInfo.name, + buffers: vertexBufferLayouts, + constants: vertexState.constants, + }; + + return { gpuVertexState, vertexBuffers }; + }); + vertexStateMap.set([vertexState, vertices], result); + + return result.value; +} + +/** + * 获取顶点入口函数信息。 + * + * @param vertexState 顶点阶段信息。 + * @returns + */ +function getVertexEntryFunctionInfo(vertexState: VertexState) +{ + let vertexEntryFunctionInfo: FunctionInfo = vertexState["_vertexEntry"]; + if (vertexEntryFunctionInfo) return vertexEntryFunctionInfo; + + const code = vertexState.code; + + // 解析顶点着色器 + const reflect = getWGSLReflectInfo(code); + // + if (vertexState.entryPoint) + { + vertexEntryFunctionInfo = reflect.entry.vertex.filter((v) => v.name === vertexState.entryPoint)[0]; + console.assert(!!vertexEntryFunctionInfo, `WGSL着色器 ${code} 中不存在顶点入口点 ${vertexState.entryPoint} 。`); + } + else + { + vertexEntryFunctionInfo = reflect.entry.vertex[0]; + console.assert(!!reflect.entry.vertex[0], `WGSL着色器 ${code} 中不存在顶点入口点。`); + } + + vertexState["_vertexEntry"] = vertexEntryFunctionInfo; + + return vertexEntryFunctionInfo; +} + +const vertexStateMap = new ChainMap<[VertexState, VertexAttributes], ComputedRef<{ + gpuVertexState: GPUVertexState; + vertexBuffers: NVertexBuffer[]; +}>>(); + +/** + * 从顶点属性信息与顶点数据中获取顶点缓冲区布局数组以及顶点缓冲区数组。 + * + * @param vertex 顶点着色器函数信息。 + * @param vertices 顶点数据。 + * @returns 顶点缓冲区布局数组以及顶点缓冲区数组。 + */ +function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) +{ + const vertexBufferLayouts: GPUVertexBufferLayout[] = []; + + const vertexBuffers: NVertexBuffer[] = []; + + const map = new Map(); + + vertex.inputs.forEach((v) => + { + // 跳过内置属性。 + if (v.locationType === "builtin") return; + + const shaderLocation = v.location as number; + const attributeName = v.name; + + const vertexAttribute = vertices[attributeName]; + console.assert(!!vertexAttribute, `在提供的顶点属性数据中未找到 ${attributeName} 。`); + // + const data = vertexAttribute.data; + const attributeOffset = vertexAttribute.offset || 0; + let arrayStride = vertexAttribute.arrayStride; + const stepMode = vertexAttribute.stepMode; + const format = vertexAttribute.format; + // 检查提供的顶点数据格式是否与着色器匹配 + // const wgslType = getWGSLType(v.type); + // let possibleFormats = wgslVertexTypeMap[wgslType].possibleFormats; + // console.assert(possibleFormats.indexOf(format) !== -1, `顶点${attributeName} 提供的数据格式 ${format} 与着色器中类型 ${wgslType} 不匹配!`); + console.assert(data.constructor.name === vertexFormatMap[format].typedArrayConstructor.name, + `顶点${attributeName} 提供的数据类型 ${data.constructor.name} 与格式 ${format} 不匹配!请使用 ${data.constructor.name} 来组织数据或者更改数据格式。`); + + // 如果 偏移值大于 单个顶点尺寸,则该值被放入 IGPUVertexBuffer.offset。 + const vertexByteSize = vertexFormatMap[format].byteSize; + // + if (!arrayStride) + { + arrayStride = vertexByteSize; + } + console.assert(attributeOffset + vertexByteSize <= arrayStride, `offset(${attributeOffset}) + vertexByteSize(${vertexByteSize}) 必须不超出 arrayStride(${arrayStride})。`); + + watcher.watch(vertexAttribute, "data", () => + { + const index = map.get(data); + const attributeData = vertexAttribute.data; + + vertexBuffers[index].data = attributeData; + vertexBuffers[index].offset = attributeData.byteOffset; + vertexBuffers[index].size = attributeData.byteLength; + }); + + let index = map.get(data); + if (index === undefined) + { + index = vertexBufferLayouts.length; + map.set(data, index); + + vertexBuffers[index] = { data, offset: data.byteOffset, size: data.byteLength }; + + // + vertexBufferLayouts[index] = { stepMode, arrayStride, attributes: [] }; + } + else + { + // 要求同一顶点缓冲区中 arrayStride 与 stepMode 必须相同。 + const gpuVertexBufferLayout = vertexBufferLayouts[index]; + console.assert(gpuVertexBufferLayout.arrayStride === arrayStride); + console.assert(gpuVertexBufferLayout.stepMode === stepMode); + } + + (vertexBufferLayouts[index].attributes as Array).push({ shaderLocation, offset: attributeOffset, format }); + }); + + return { vertexBufferLayouts, vertexBuffers }; +} -- Gitee From 00a16ab18c131efab0db5dc4033a79ed5ec667ef Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 20:06:27 +0800 Subject: [PATCH 110/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=A1=B6=E7=82=B9=E7=8A=B6=E6=80=81=E5=92=8C=E7=BC=93=E5=86=B2?= =?UTF-8?q?=E5=8C=BA=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构 getNGPUVertexState 函数,移除顶点缓冲区相关处理 - 新增 getNGPUVertexBuffers 函数,专门处理顶点缓冲区布局和数据 - 优化 WebGPUBase 中的顶点缓冲区处理逻辑 - 删除 getNGPUVertexState 中的冗余代码和不必要的导入 --- src/WebGPUBase.ts | 4 +- src/caches/getNGPURenderPipeline.ts | 4 +- src/caches/getNGPUVertexBuffers.ts | 87 +++++++++++++++ src/caches/getNGPUVertexState.ts | 132 ++--------------------- src/caches/getVertexEntryFunctionInfo.ts | 35 ++++++ 5 files changed, 132 insertions(+), 130 deletions(-) create mode 100644 src/caches/getNGPUVertexBuffers.ts create mode 100644 src/caches/getVertexEntryFunctionInfo.ts diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 4d215a0..ef3a3aa 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -12,7 +12,7 @@ import { getGPURenderTimestampQuery } from "./caches/getGPURenderTimestampQuery" import { getGPUTexture } from "./caches/getGPUTexture"; import { getGBuffer } from "./caches/getIGPUBuffer"; import { getNGPURenderPipeline } from "./caches/getNGPURenderPipeline"; -import { getNGPUVertexState } from "./caches/getNGPUVertexState"; +import { getNGPUVertexBuffers } from "./caches/getNGPUVertexBuffers"; import { getRealGPUBindGroup } from "./const"; import { ComputeObject } from "./data/ComputeObject"; import { ComputePass } from "./data/ComputePass"; @@ -528,7 +528,7 @@ export class WebGPUBase }); // - const { vertexBuffers } = getNGPUVertexState(device, pipeline.vertex, vertices); + const { vertexBuffers } = getNGPUVertexBuffers(pipeline.vertex, vertices) vertexBuffers?.forEach((vertexBuffer, index) => { const buffer = getGBuffer(vertexBuffer.data); diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index 6afe61c..d14c6df 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -41,12 +41,12 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const { label, vertex, fragment, primitive, depthStencil, multisample } = renderPipeline; const shader = { vertex: vertex.code, fragment: fragment?.code }; const { colorFormats, depthStencilFormat, sampleCount } = renderPassFormat; - const vertexStateResult = getNGPUVertexState(device, vertex, vertices); + const gpuVertexState = getNGPUVertexState(device, vertex, vertices); // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { label: label, layout: getGPUPipelineLayout(device, shader), - vertex: vertexStateResult.gpuVertexState, + vertex: gpuVertexState, fragment: getGPUFragmentState(device, fragment, colorFormats), primitive: getGPUPrimitiveState(primitive, indexFormat), depthStencil: getGPUDepthStencilState(depthStencil, depthStencilFormat), diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts new file mode 100644 index 0000000..5c5e51a --- /dev/null +++ b/src/caches/getNGPUVertexBuffers.ts @@ -0,0 +1,87 @@ +import { VertexState, VertexAttributes, vertexFormatMap } from "@feng3d/render-api"; +import { watcher } from "@feng3d/watcher"; +import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; +import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; + +/** + * 从顶点属性信息与顶点数据中获取顶点缓冲区布局数组以及顶点缓冲区数组。 + * + * @param vertices 顶点数据。 + * @returns 顶点缓冲区布局数组以及顶点缓冲区数组。 + */ +export function getNGPUVertexBuffers(vertexState: VertexState, vertices: VertexAttributes) +{ + const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); + + const vertexBufferLayouts: GPUVertexBufferLayout[] = []; + + const vertexBuffers: NVertexBuffer[] = []; + + const map = new Map(); + + vertexEntryFunctionInfo.inputs.forEach((v) => + { + // 跳过内置属性。 + if (v.locationType === "builtin") return; + + const shaderLocation = v.location as number; + const attributeName = v.name; + + const vertexAttribute = vertices[attributeName]; + console.assert(!!vertexAttribute, `在提供的顶点属性数据中未找到 ${attributeName} 。`); + // + const data = vertexAttribute.data; + const attributeOffset = vertexAttribute.offset || 0; + let arrayStride = vertexAttribute.arrayStride; + const stepMode = vertexAttribute.stepMode; + const format = vertexAttribute.format; + // 检查提供的顶点数据格式是否与着色器匹配 + // const wgslType = getWGSLType(v.type); + // let possibleFormats = wgslVertexTypeMap[wgslType].possibleFormats; + // console.assert(possibleFormats.indexOf(format) !== -1, `顶点${attributeName} 提供的数据格式 ${format} 与着色器中类型 ${wgslType} 不匹配!`); + console.assert(data.constructor.name === vertexFormatMap[format].typedArrayConstructor.name, + `顶点${attributeName} 提供的数据类型 ${data.constructor.name} 与格式 ${format} 不匹配!请使用 ${data.constructor.name} 来组织数据或者更改数据格式。`); + + // 如果 偏移值大于 单个顶点尺寸,则该值被放入 IGPUVertexBuffer.offset。 + const vertexByteSize = vertexFormatMap[format].byteSize; + // + if (!arrayStride) + { + arrayStride = vertexByteSize; + } + console.assert(attributeOffset + vertexByteSize <= arrayStride, `offset(${attributeOffset}) + vertexByteSize(${vertexByteSize}) 必须不超出 arrayStride(${arrayStride})。`); + + watcher.watch(vertexAttribute, "data", () => + { + const index = map.get(data); + const attributeData = vertexAttribute.data; + + vertexBuffers[index].data = attributeData; + vertexBuffers[index].offset = attributeData.byteOffset; + vertexBuffers[index].size = attributeData.byteLength; + }); + + let index = map.get(data); + if (index === undefined) + { + index = vertexBufferLayouts.length; + map.set(data, index); + + vertexBuffers[index] = { data, offset: data.byteOffset, size: data.byteLength }; + + // + vertexBufferLayouts[index] = { stepMode, arrayStride, attributes: [] }; + } + else + { + // 要求同一顶点缓冲区中 arrayStride 与 stepMode 必须相同。 + const gpuVertexBufferLayout = vertexBufferLayouts[index]; + console.assert(gpuVertexBufferLayout.arrayStride === arrayStride); + console.assert(gpuVertexBufferLayout.stepMode === stepMode); + } + + (vertexBufferLayouts[index].attributes as Array).push({ shaderLocation, offset: attributeOffset, format }); + }); + + return { vertexBufferLayouts, vertexBuffers }; +} diff --git a/src/caches/getNGPUVertexState.ts b/src/caches/getNGPUVertexState.ts index bcfc049..a8b692b 100644 --- a/src/caches/getNGPUVertexState.ts +++ b/src/caches/getNGPUVertexState.ts @@ -1,9 +1,7 @@ -import { VertexState, VertexAttributes, computed, ChainMap, ComputedRef, vertexFormatMap } from "@feng3d/render-api"; +import { ChainMap, ComputedRef, VertexAttributes, VertexState, computed } from "@feng3d/render-api"; import { getGPUShaderModule } from "./getGPUShaderModule"; -import { watcher } from "@feng3d/watcher"; -import { FunctionInfo } from "wgsl_reflect"; -import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; -import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; +import { getNGPUVertexBuffers } from "./getNGPUVertexBuffers"; +import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; /** * 获取完整的顶点阶段描述与顶点缓冲区列表。 @@ -20,8 +18,7 @@ export function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, result = computed(() => { const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); - - const { vertexBufferLayouts, vertexBuffers } = getNGPUVertexBuffers(vertexEntryFunctionInfo, vertices); + const { vertexBufferLayouts } = getNGPUVertexBuffers(vertexState, vertices); const gpuVertexState: GPUVertexState = { module: getGPUShaderModule(device, vertexState.code), @@ -30,128 +27,11 @@ export function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, constants: vertexState.constants, }; - return { gpuVertexState, vertexBuffers }; + return gpuVertexState; }); vertexStateMap.set([vertexState, vertices], result); return result.value; } -/** - * 获取顶点入口函数信息。 - * - * @param vertexState 顶点阶段信息。 - * @returns - */ -function getVertexEntryFunctionInfo(vertexState: VertexState) -{ - let vertexEntryFunctionInfo: FunctionInfo = vertexState["_vertexEntry"]; - if (vertexEntryFunctionInfo) return vertexEntryFunctionInfo; - - const code = vertexState.code; - - // 解析顶点着色器 - const reflect = getWGSLReflectInfo(code); - // - if (vertexState.entryPoint) - { - vertexEntryFunctionInfo = reflect.entry.vertex.filter((v) => v.name === vertexState.entryPoint)[0]; - console.assert(!!vertexEntryFunctionInfo, `WGSL着色器 ${code} 中不存在顶点入口点 ${vertexState.entryPoint} 。`); - } - else - { - vertexEntryFunctionInfo = reflect.entry.vertex[0]; - console.assert(!!reflect.entry.vertex[0], `WGSL着色器 ${code} 中不存在顶点入口点。`); - } - - vertexState["_vertexEntry"] = vertexEntryFunctionInfo; - - return vertexEntryFunctionInfo; -} - -const vertexStateMap = new ChainMap<[VertexState, VertexAttributes], ComputedRef<{ - gpuVertexState: GPUVertexState; - vertexBuffers: NVertexBuffer[]; -}>>(); - -/** - * 从顶点属性信息与顶点数据中获取顶点缓冲区布局数组以及顶点缓冲区数组。 - * - * @param vertex 顶点着色器函数信息。 - * @param vertices 顶点数据。 - * @returns 顶点缓冲区布局数组以及顶点缓冲区数组。 - */ -function getNGPUVertexBuffers(vertex: FunctionInfo, vertices: VertexAttributes) -{ - const vertexBufferLayouts: GPUVertexBufferLayout[] = []; - - const vertexBuffers: NVertexBuffer[] = []; - - const map = new Map(); - - vertex.inputs.forEach((v) => - { - // 跳过内置属性。 - if (v.locationType === "builtin") return; - - const shaderLocation = v.location as number; - const attributeName = v.name; - - const vertexAttribute = vertices[attributeName]; - console.assert(!!vertexAttribute, `在提供的顶点属性数据中未找到 ${attributeName} 。`); - // - const data = vertexAttribute.data; - const attributeOffset = vertexAttribute.offset || 0; - let arrayStride = vertexAttribute.arrayStride; - const stepMode = vertexAttribute.stepMode; - const format = vertexAttribute.format; - // 检查提供的顶点数据格式是否与着色器匹配 - // const wgslType = getWGSLType(v.type); - // let possibleFormats = wgslVertexTypeMap[wgslType].possibleFormats; - // console.assert(possibleFormats.indexOf(format) !== -1, `顶点${attributeName} 提供的数据格式 ${format} 与着色器中类型 ${wgslType} 不匹配!`); - console.assert(data.constructor.name === vertexFormatMap[format].typedArrayConstructor.name, - `顶点${attributeName} 提供的数据类型 ${data.constructor.name} 与格式 ${format} 不匹配!请使用 ${data.constructor.name} 来组织数据或者更改数据格式。`); - - // 如果 偏移值大于 单个顶点尺寸,则该值被放入 IGPUVertexBuffer.offset。 - const vertexByteSize = vertexFormatMap[format].byteSize; - // - if (!arrayStride) - { - arrayStride = vertexByteSize; - } - console.assert(attributeOffset + vertexByteSize <= arrayStride, `offset(${attributeOffset}) + vertexByteSize(${vertexByteSize}) 必须不超出 arrayStride(${arrayStride})。`); - - watcher.watch(vertexAttribute, "data", () => - { - const index = map.get(data); - const attributeData = vertexAttribute.data; - - vertexBuffers[index].data = attributeData; - vertexBuffers[index].offset = attributeData.byteOffset; - vertexBuffers[index].size = attributeData.byteLength; - }); - - let index = map.get(data); - if (index === undefined) - { - index = vertexBufferLayouts.length; - map.set(data, index); - - vertexBuffers[index] = { data, offset: data.byteOffset, size: data.byteLength }; - - // - vertexBufferLayouts[index] = { stepMode, arrayStride, attributes: [] }; - } - else - { - // 要求同一顶点缓冲区中 arrayStride 与 stepMode 必须相同。 - const gpuVertexBufferLayout = vertexBufferLayouts[index]; - console.assert(gpuVertexBufferLayout.arrayStride === arrayStride); - console.assert(gpuVertexBufferLayout.stepMode === stepMode); - } - - (vertexBufferLayouts[index].attributes as Array).push({ shaderLocation, offset: attributeOffset, format }); - }); - - return { vertexBufferLayouts, vertexBuffers }; -} +const vertexStateMap = new ChainMap<[VertexState, VertexAttributes], ComputedRef>(); diff --git a/src/caches/getVertexEntryFunctionInfo.ts b/src/caches/getVertexEntryFunctionInfo.ts new file mode 100644 index 0000000..13da57f --- /dev/null +++ b/src/caches/getVertexEntryFunctionInfo.ts @@ -0,0 +1,35 @@ +import { VertexState } from "@feng3d/render-api"; +import { FunctionInfo } from "wgsl_reflect"; +import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; + +/** + * 获取顶点入口函数信息。 + * + * @param vertexState 顶点阶段信息。 + * @returns + */ +export function getVertexEntryFunctionInfo(vertexState: VertexState) +{ + let vertexEntryFunctionInfo: FunctionInfo = vertexState["_vertexEntry"]; + if (vertexEntryFunctionInfo) return vertexEntryFunctionInfo; + + const code = vertexState.code; + + // 解析顶点着色器 + const reflect = getWGSLReflectInfo(code); + // + if (vertexState.entryPoint) + { + vertexEntryFunctionInfo = reflect.entry.vertex.filter((v) => v.name === vertexState.entryPoint)[0]; + console.assert(!!vertexEntryFunctionInfo, `WGSL着色器 ${code} 中不存在顶点入口点 ${vertexState.entryPoint} 。`); + } + else + { + vertexEntryFunctionInfo = reflect.entry.vertex[0]; + console.assert(!!reflect.entry.vertex[0], `WGSL着色器 ${code} 中不存在顶点入口点。`); + } + + vertexState["_vertexEntry"] = vertexEntryFunctionInfo; + + return vertexEntryFunctionInfo; +} -- Gitee From 46321fc119d7d636870efa1fd02d7b90a49d9133 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 20:16:52 +0800 Subject: [PATCH 111/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=A1=B6=E7=82=B9=E7=BC=93=E5=86=B2=E5=8C=BA=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 分离 getNGPUVertexBuffers 函数,新增 getGPUVertexBufferLayouts 和 getNVertexBuffers 函数 - 优化顶点缓冲区布局和数据的缓存逻辑 - 更新相关引用,以适应新的函数结构 --- src/WebGPUBase.ts | 4 ++-- src/caches/getNGPUVertexBuffers.ts | 26 +++++++++++++++++++++++--- src/caches/getNGPUVertexState.ts | 4 ++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index ef3a3aa..72c7076 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -12,7 +12,6 @@ import { getGPURenderTimestampQuery } from "./caches/getGPURenderTimestampQuery" import { getGPUTexture } from "./caches/getGPUTexture"; import { getGBuffer } from "./caches/getIGPUBuffer"; import { getNGPURenderPipeline } from "./caches/getNGPURenderPipeline"; -import { getNGPUVertexBuffers } from "./caches/getNGPUVertexBuffers"; import { getRealGPUBindGroup } from "./const"; import { ComputeObject } from "./data/ComputeObject"; import { ComputePass } from "./data/ComputePass"; @@ -26,6 +25,7 @@ import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; +import { getNVertexBuffers } from "./caches/getNGPUVertexBuffers"; declare global { @@ -528,7 +528,7 @@ export class WebGPUBase }); // - const { vertexBuffers } = getNGPUVertexBuffers(pipeline.vertex, vertices) + const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) vertexBuffers?.forEach((vertexBuffer, index) => { const buffer = getGBuffer(vertexBuffer.data); diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts index 5c5e51a..568b9d2 100644 --- a/src/caches/getNGPUVertexBuffers.ts +++ b/src/caches/getNGPUVertexBuffers.ts @@ -1,16 +1,31 @@ -import { VertexState, VertexAttributes, vertexFormatMap } from "@feng3d/render-api"; +import { ChainMap, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; +export function getGPUVertexBufferLayouts(vertexState: VertexState, vertices: VertexAttributes) +{ + const { vertexBufferLayouts } = getVertexBuffersBuffers(vertexState, vertices); + return vertexBufferLayouts; +} + +export function getNVertexBuffers(vertexState: VertexState, vertices: VertexAttributes) +{ + const { vertexBuffers } = getVertexBuffersBuffers(vertexState, vertices); + return vertexBuffers; +} + /** * 从顶点属性信息与顶点数据中获取顶点缓冲区布局数组以及顶点缓冲区数组。 * * @param vertices 顶点数据。 * @returns 顶点缓冲区布局数组以及顶点缓冲区数组。 */ -export function getNGPUVertexBuffers(vertexState: VertexState, vertices: VertexAttributes) +function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttributes) { + let result = _map.get([vertexState, vertices]); + if (result) return result; + const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); const vertexBufferLayouts: GPUVertexBufferLayout[] = []; @@ -83,5 +98,10 @@ export function getNGPUVertexBuffers(vertexState: VertexState, vertices: VertexA (vertexBufferLayouts[index].attributes as Array).push({ shaderLocation, offset: attributeOffset, format }); }); - return { vertexBufferLayouts, vertexBuffers }; + result = { vertexBufferLayouts, vertexBuffers }; + _map.set([vertexState, vertices], result); + + return result; } + +const _map = new ChainMap<[VertexState, VertexAttributes], { vertexBufferLayouts: GPUVertexBufferLayout[], vertexBuffers: NVertexBuffer[] }>(); \ No newline at end of file diff --git a/src/caches/getNGPUVertexState.ts b/src/caches/getNGPUVertexState.ts index a8b692b..4878fc6 100644 --- a/src/caches/getNGPUVertexState.ts +++ b/src/caches/getNGPUVertexState.ts @@ -1,6 +1,6 @@ import { ChainMap, ComputedRef, VertexAttributes, VertexState, computed } from "@feng3d/render-api"; import { getGPUShaderModule } from "./getGPUShaderModule"; -import { getNGPUVertexBuffers } from "./getNGPUVertexBuffers"; +import { getGPUVertexBufferLayouts } from "./getNGPUVertexBuffers"; import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; /** @@ -18,7 +18,7 @@ export function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, result = computed(() => { const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); - const { vertexBufferLayouts } = getNGPUVertexBuffers(vertexState, vertices); + const vertexBufferLayouts = getGPUVertexBufferLayouts(vertexState, vertices); const gpuVertexState: GPUVertexState = { module: getGPUShaderModule(device, vertexState.code), -- Gitee From 3070cff851afd9aa496c19e046681857e17f2ac6 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 20:40:41 +0800 Subject: [PATCH 112/214] =?UTF-8?q?refactor(gpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=A1=B6=E7=82=B9=E7=8A=B6=E6=80=81=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 getNGPUVertexState 重命名为 getGPUVertexState - 移除 getNGPUVertexState.ts 文件 - 更新相关引用 --- src/caches/{getNGPUVertexState.ts => getGPUVertexState.ts} | 2 +- src/caches/getNGPURenderPipeline.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/caches/{getNGPUVertexState.ts => getGPUVertexState.ts} (92%) diff --git a/src/caches/getNGPUVertexState.ts b/src/caches/getGPUVertexState.ts similarity index 92% rename from src/caches/getNGPUVertexState.ts rename to src/caches/getGPUVertexState.ts index 4878fc6..49cc80a 100644 --- a/src/caches/getNGPUVertexState.ts +++ b/src/caches/getGPUVertexState.ts @@ -10,7 +10,7 @@ import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; * @param vertices 顶点数据。 * @returns 完整的顶点阶段描述与顶点缓冲区列表。 */ -export function getNGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) +export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) { let result = vertexStateMap.get([vertexState, vertices]); if (result) return result.value; diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getNGPURenderPipeline.ts index d14c6df..501f290 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getNGPURenderPipeline.ts @@ -5,7 +5,7 @@ import { MultisampleState } from "../data/MultisampleState"; import { RenderPassFormat } from "../internal/RenderPassFormat"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; import { getGPUShaderModule } from "./getGPUShaderModule"; -import { getNGPUVertexState } from "./getNGPUVertexState"; +import { getGPUVertexState } from "./getGPUVertexState"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; /** @@ -41,7 +41,7 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP const { label, vertex, fragment, primitive, depthStencil, multisample } = renderPipeline; const shader = { vertex: vertex.code, fragment: fragment?.code }; const { colorFormats, depthStencilFormat, sampleCount } = renderPassFormat; - const gpuVertexState = getNGPUVertexState(device, vertex, vertices); + const gpuVertexState = getGPUVertexState(device, vertex, vertices); // const gpuRenderPipelineDescriptor: GPURenderPipelineDescriptor = { label: label, -- Gitee From a9602bb33988ee53e57eda052235578202480506 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 21:15:41 +0800 Subject: [PATCH 113/214] =?UTF-8?q?refactor(vertex):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=A1=B6=E7=82=B9=E7=8A=B6=E6=80=81=E5=92=8C=E5=85=A5=E5=8F=A3?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 WebGPUBase 中添加 _GPUVertexStateMap 用于缓存 GPU 顶点状态 - 重构 getGPUVertexState 函数,使用设备上的缓存 - 优化 getVertexEntryFunctionInfo 函数,使用计算属性和响应式编程 --- src/WebGPUBase.ts | 6 ++- src/caches/getGPUVertexState.ts | 17 +++++--- src/caches/getVertexEntryFunctionInfo.ts | 51 ++++++++++++++---------- 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 72c7076..e31d03e 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, FragmentState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, FragmentState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes, VertexState } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -47,7 +47,8 @@ declare global }>; _renderObjectCommandMap: ChainMap<[string, RenderObject], Array>; _renderPipelineMap: ChainMap<[RenderPipeline, string, VertexAttributes, GPUIndexFormat], ComputedRef>; - _fragmentStateMap: ChainMap<[FragmentState, string], ComputedRef> + _fragmentStateMap: ChainMap<[FragmentState, string], ComputedRef>; + _GPUVertexStateMap: ChainMap<[VertexState, VertexAttributes], ComputedRef> } } @@ -102,6 +103,7 @@ export class WebGPUBase this._device._renderPassDescriptorMap ??= new WeakMap(); this._device._pipelineLayoutMap ??= new Map(); this._device._shaderMap ??= new Map(); + this._device._GPUVertexStateMap ??= new ChainMap(); } } protected _device: GPUDevice; diff --git a/src/caches/getGPUVertexState.ts b/src/caches/getGPUVertexState.ts index 49cc80a..cdeda6d 100644 --- a/src/caches/getGPUVertexState.ts +++ b/src/caches/getGPUVertexState.ts @@ -1,4 +1,4 @@ -import { ChainMap, ComputedRef, VertexAttributes, VertexState, computed } from "@feng3d/render-api"; +import { VertexAttributes, VertexState, computed, reactive } from "@feng3d/render-api"; import { getGPUShaderModule } from "./getGPUShaderModule"; import { getGPUVertexBufferLayouts } from "./getNGPUVertexBuffers"; import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; @@ -12,16 +12,23 @@ import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; */ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) { - let result = vertexStateMap.get([vertexState, vertices]); + let result = device._GPUVertexStateMap.get([vertexState, vertices]); if (result) return result.value; result = computed(() => { + // 监听 + const r_vertexState = reactive(vertexState); + r_vertexState.code; + + // 计算 + const { code } = vertexState; + const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); const vertexBufferLayouts = getGPUVertexBufferLayouts(vertexState, vertices); const gpuVertexState: GPUVertexState = { - module: getGPUShaderModule(device, vertexState.code), + module: getGPUShaderModule(device, code), entryPoint: vertexEntryFunctionInfo.name, buffers: vertexBufferLayouts, constants: vertexState.constants, @@ -29,9 +36,7 @@ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, v return gpuVertexState; }); - vertexStateMap.set([vertexState, vertices], result); + device._GPUVertexStateMap.set([vertexState, vertices], result); return result.value; } - -const vertexStateMap = new ChainMap<[VertexState, VertexAttributes], ComputedRef>(); diff --git a/src/caches/getVertexEntryFunctionInfo.ts b/src/caches/getVertexEntryFunctionInfo.ts index 13da57f..d9db4b7 100644 --- a/src/caches/getVertexEntryFunctionInfo.ts +++ b/src/caches/getVertexEntryFunctionInfo.ts @@ -1,4 +1,4 @@ -import { VertexState } from "@feng3d/render-api"; +import { computed, ComputedRef, reactive, VertexState } from "@feng3d/render-api"; import { FunctionInfo } from "wgsl_reflect"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; @@ -10,26 +10,37 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; */ export function getVertexEntryFunctionInfo(vertexState: VertexState) { - let vertexEntryFunctionInfo: FunctionInfo = vertexState["_vertexEntry"]; - if (vertexEntryFunctionInfo) return vertexEntryFunctionInfo; + let result: ComputedRef = vertexState["_vertexEntry"]; + if (result) return result.value; - const code = vertexState.code; - - // 解析顶点着色器 - const reflect = getWGSLReflectInfo(code); - // - if (vertexState.entryPoint) - { - vertexEntryFunctionInfo = reflect.entry.vertex.filter((v) => v.name === vertexState.entryPoint)[0]; - console.assert(!!vertexEntryFunctionInfo, `WGSL着色器 ${code} 中不存在顶点入口点 ${vertexState.entryPoint} 。`); - } - else + result = computed(() => { - vertexEntryFunctionInfo = reflect.entry.vertex[0]; - console.assert(!!reflect.entry.vertex[0], `WGSL着色器 ${code} 中不存在顶点入口点。`); - } + // 监听 + const r_vertexState = reactive(vertexState); + r_vertexState.code; + r_vertexState.entryPoint; + + // 计算 + const { code, entryPoint } = vertexState; + // 解析顶点着色器 + const reflect = getWGSLReflectInfo(code); + // + let vertexEntryFunctionInfo: FunctionInfo; + if (entryPoint) + { + vertexEntryFunctionInfo = reflect.entry.vertex.filter((v) => v.name === entryPoint)[0]; + console.assert(!!vertexEntryFunctionInfo, `WGSL着色器 ${code} 中不存在顶点入口点 ${entryPoint} 。`); + } + else + { + vertexEntryFunctionInfo = reflect.entry.vertex[0]; + console.assert(!!reflect.entry.vertex[0], `WGSL着色器 ${code} 中不存在顶点入口点。`); + } + + return vertexEntryFunctionInfo; + }); - vertexState["_vertexEntry"] = vertexEntryFunctionInfo; + vertexState["_vertexEntry"] = result; - return vertexEntryFunctionInfo; -} + return result.value; +} \ No newline at end of file -- Gitee From fcbf76762a5a8bb55d6c04961b80aa5fc91bf61a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 21:32:22 +0800 Subject: [PATCH 114/214] =?UTF-8?q?refactor(caches):=20=E6=94=B9=E7=94=A8?= =?UTF-8?q?=20WeakMap=20=E5=AD=98=E5=82=A8=E9=A1=B6=E7=82=B9=E5=85=A5?= =?UTF-8?q?=E5=8F=A3=E5=87=BD=E6=95=B0=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使用 WeakMap 替代直接在 VertexState 对象上存储顶点入口函数信息,可以提高代码的可维护性和减少潜在的内存泄漏风险。这项改动不影响现有功能,但有助于优化内部实现。 --- src/caches/getVertexEntryFunctionInfo.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/caches/getVertexEntryFunctionInfo.ts b/src/caches/getVertexEntryFunctionInfo.ts index d9db4b7..db8da2b 100644 --- a/src/caches/getVertexEntryFunctionInfo.ts +++ b/src/caches/getVertexEntryFunctionInfo.ts @@ -10,7 +10,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; */ export function getVertexEntryFunctionInfo(vertexState: VertexState) { - let result: ComputedRef = vertexState["_vertexEntry"]; + let result: ComputedRef = _vertexEntryFunctionInfoMap.get(vertexState); if (result) return result.value; result = computed(() => @@ -39,8 +39,8 @@ export function getVertexEntryFunctionInfo(vertexState: VertexState) return vertexEntryFunctionInfo; }); - - vertexState["_vertexEntry"] = result; + _vertexEntryFunctionInfoMap.set(vertexState, result); return result.value; -} \ No newline at end of file +} +const _vertexEntryFunctionInfoMap = new WeakMap>(); \ No newline at end of file -- Gitee From b4989ece631d7eb284a71324e4ed6a42aae0780b Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 21:37:52 +0800 Subject: [PATCH 115/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E5=91=BD?= =?UTF-8?q?=E5=90=8D=E5=8F=98=E9=87=8F=E4=BB=A5=E6=8F=90=E5=8D=87=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=8F=AF=E8=AF=BB=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 _vertexEntryFunctionInfoMap 重命名为 _getVertexEntryFunctionInfoMap - 更新相关函数中使用新变量名,提高代码的一致性和可理解性 --- src/caches/getVertexEntryFunctionInfo.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/caches/getVertexEntryFunctionInfo.ts b/src/caches/getVertexEntryFunctionInfo.ts index db8da2b..10de884 100644 --- a/src/caches/getVertexEntryFunctionInfo.ts +++ b/src/caches/getVertexEntryFunctionInfo.ts @@ -10,7 +10,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; */ export function getVertexEntryFunctionInfo(vertexState: VertexState) { - let result: ComputedRef = _vertexEntryFunctionInfoMap.get(vertexState); + let result: ComputedRef = _getVertexEntryFunctionInfoMap.get(vertexState); if (result) return result.value; result = computed(() => @@ -39,8 +39,8 @@ export function getVertexEntryFunctionInfo(vertexState: VertexState) return vertexEntryFunctionInfo; }); - _vertexEntryFunctionInfoMap.set(vertexState, result); + _getVertexEntryFunctionInfoMap.set(vertexState, result); return result.value; } -const _vertexEntryFunctionInfoMap = new WeakMap>(); \ No newline at end of file +const _getVertexEntryFunctionInfoMap = new WeakMap>(); \ No newline at end of file -- Gitee From d9e07f5ebe7fd71522d9b32d866e278530feada7 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Tue, 18 Mar 2025 22:06:45 +0800 Subject: [PATCH 116/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20getNGPUVertexBuffers=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重命名 _map 为 _getVertexBuffersBuffersMap,提高变量命名的可读性 - 优化变量命名,提高代码的可读性和可维护性 - 引入 VertexDataTypes 类型,为后续功能扩展做准备 --- src/caches/getNGPUVertexBuffers.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts index 568b9d2..3f2611a 100644 --- a/src/caches/getNGPUVertexBuffers.ts +++ b/src/caches/getNGPUVertexBuffers.ts @@ -1,4 +1,4 @@ -import { ChainMap, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; +import { ChainMap, VertexAttributes, VertexDataTypes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; @@ -23,7 +23,7 @@ export function getNVertexBuffers(vertexState: VertexState, vertices: VertexAttr */ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttributes) { - let result = _map.get([vertexState, vertices]); + let result = _getVertexBuffersBuffersMap.get([vertexState, vertices]); if (result) return result; const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); @@ -32,15 +32,15 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri const vertexBuffers: NVertexBuffer[] = []; - const map = new Map(); + const bufferIndexMap = new Map(); - vertexEntryFunctionInfo.inputs.forEach((v) => + vertexEntryFunctionInfo.inputs.forEach((inputInfo) => { // 跳过内置属性。 - if (v.locationType === "builtin") return; + if (inputInfo.locationType === "builtin") return; - const shaderLocation = v.location as number; - const attributeName = v.name; + const shaderLocation = inputInfo.location as number; + const attributeName = inputInfo.name; const vertexAttribute = vertices[attributeName]; console.assert(!!vertexAttribute, `在提供的顶点属性数据中未找到 ${attributeName} 。`); @@ -68,7 +68,7 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri watcher.watch(vertexAttribute, "data", () => { - const index = map.get(data); + const index = bufferIndexMap.get(data); const attributeData = vertexAttribute.data; vertexBuffers[index].data = attributeData; @@ -76,11 +76,11 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri vertexBuffers[index].size = attributeData.byteLength; }); - let index = map.get(data); + let index = bufferIndexMap.get(data); if (index === undefined) { index = vertexBufferLayouts.length; - map.set(data, index); + bufferIndexMap.set(data, index); vertexBuffers[index] = { data, offset: data.byteOffset, size: data.byteLength }; @@ -99,9 +99,9 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri }); result = { vertexBufferLayouts, vertexBuffers }; - _map.set([vertexState, vertices], result); + _getVertexBuffersBuffersMap.set([vertexState, vertices], result); return result; } -const _map = new ChainMap<[VertexState, VertexAttributes], { vertexBufferLayouts: GPUVertexBufferLayout[], vertexBuffers: NVertexBuffer[] }>(); \ No newline at end of file +const _getVertexBuffersBuffersMap = new ChainMap<[VertexState, VertexAttributes], { vertexBufferLayouts: GPUVertexBufferLayout[], vertexBuffers: NVertexBuffer[] }>(); \ No newline at end of file -- Gitee From 1c539c22eb168f2cebdcb5eeb3ca20d1b89651eb Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 10:16:54 +0800 Subject: [PATCH 117/214] =?UTF-8?q?feat(caches):=20=E9=87=8D=E6=9E=84=20ge?= =?UTF-8?q?tNGPUVertexBuffers=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 computed 和 reactive 优化顶点缓冲区计算 - 添加对顶点属性数据的监听 - 优化缓存机制,使用 WeakMap 存储计算结果 - 重构代码结构,提高可读性和可维护性 --- src/caches/getNGPUVertexBuffers.ts | 163 +++++++++++++++++------------ 1 file changed, 96 insertions(+), 67 deletions(-) diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts index 3f2611a..74d1c07 100644 --- a/src/caches/getNGPUVertexBuffers.ts +++ b/src/caches/getNGPUVertexBuffers.ts @@ -1,5 +1,4 @@ -import { ChainMap, VertexAttributes, VertexDataTypes, vertexFormatMap, VertexState } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; +import { ChainMap, computed, ComputedRef, reactive, VertexAttribute, VertexAttributes, VertexDataTypes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; @@ -24,84 +23,114 @@ export function getNVertexBuffers(vertexState: VertexState, vertices: VertexAttr function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttributes) { let result = _getVertexBuffersBuffersMap.get([vertexState, vertices]); - if (result) return result; + if (result) return result.value; - const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); - - const vertexBufferLayouts: GPUVertexBufferLayout[] = []; - - const vertexBuffers: NVertexBuffer[] = []; - - const bufferIndexMap = new Map(); - - vertexEntryFunctionInfo.inputs.forEach((inputInfo) => + result = computed(() => { - // 跳过内置属性。 - if (inputInfo.locationType === "builtin") return; - - const shaderLocation = inputInfo.location as number; - const attributeName = inputInfo.name; - - const vertexAttribute = vertices[attributeName]; - console.assert(!!vertexAttribute, `在提供的顶点属性数据中未找到 ${attributeName} 。`); - // - const data = vertexAttribute.data; - const attributeOffset = vertexAttribute.offset || 0; - let arrayStride = vertexAttribute.arrayStride; - const stepMode = vertexAttribute.stepMode; - const format = vertexAttribute.format; - // 检查提供的顶点数据格式是否与着色器匹配 - // const wgslType = getWGSLType(v.type); - // let possibleFormats = wgslVertexTypeMap[wgslType].possibleFormats; - // console.assert(possibleFormats.indexOf(format) !== -1, `顶点${attributeName} 提供的数据格式 ${format} 与着色器中类型 ${wgslType} 不匹配!`); - console.assert(data.constructor.name === vertexFormatMap[format].typedArrayConstructor.name, - `顶点${attributeName} 提供的数据类型 ${data.constructor.name} 与格式 ${format} 不匹配!请使用 ${data.constructor.name} 来组织数据或者更改数据格式。`); - - // 如果 偏移值大于 单个顶点尺寸,则该值被放入 IGPUVertexBuffer.offset。 - const vertexByteSize = vertexFormatMap[format].byteSize; - // - if (!arrayStride) + const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); + // 监听 + const r_vertices = reactive(vertices); + vertexEntryFunctionInfo.inputs.forEach((inputInfo) => { - arrayStride = vertexByteSize; - } - console.assert(attributeOffset + vertexByteSize <= arrayStride, `offset(${attributeOffset}) + vertexByteSize(${vertexByteSize}) 必须不超出 arrayStride(${arrayStride})。`); - - watcher.watch(vertexAttribute, "data", () => - { - const index = bufferIndexMap.get(data); - const attributeData = vertexAttribute.data; - - vertexBuffers[index].data = attributeData; - vertexBuffers[index].offset = attributeData.byteOffset; - vertexBuffers[index].size = attributeData.byteLength; + // 跳过内置属性。 + if (inputInfo.locationType === "builtin") return; + // 监听每个顶点属性数据。 + const vertexAttribute = r_vertices[inputInfo.name]; + if (vertexAttribute) + { + vertexAttribute.arrayStride; + vertexAttribute.format; + vertexAttribute.offset; + vertexAttribute.stepMode; + } }); - let index = bufferIndexMap.get(data); - if (index === undefined) + // 计算 + const vertexBufferLayouts: GPUVertexBufferLayout[] = []; + const vertexBuffers: NVertexBuffer[] = []; + const bufferIndexMap = new Map(); + + vertexEntryFunctionInfo.inputs.forEach((inputInfo) => { - index = vertexBufferLayouts.length; - bufferIndexMap.set(data, index); + // 跳过内置属性。 + if (inputInfo.locationType === "builtin") return; - vertexBuffers[index] = { data, offset: data.byteOffset, size: data.byteLength }; + const shaderLocation = inputInfo.location as number; + const attributeName = inputInfo.name; + const vertexAttribute = vertices[attributeName]; + console.assert(!!vertexAttribute, `在提供的顶点属性数据中未找到 ${attributeName} 。`); // - vertexBufferLayouts[index] = { stepMode, arrayStride, attributes: [] }; - } - else - { - // 要求同一顶点缓冲区中 arrayStride 与 stepMode 必须相同。 - const gpuVertexBufferLayout = vertexBufferLayouts[index]; - console.assert(gpuVertexBufferLayout.arrayStride === arrayStride); - console.assert(gpuVertexBufferLayout.stepMode === stepMode); - } + const data = vertexAttribute.data; + const attributeOffset = vertexAttribute.offset || 0; + let arrayStride = vertexAttribute.arrayStride; + const stepMode = vertexAttribute.stepMode; + const format = vertexAttribute.format; + // 检查提供的顶点数据格式是否与着色器匹配 + // const wgslType = getWGSLType(v.type); + // let possibleFormats = wgslVertexTypeMap[wgslType].possibleFormats; + // console.assert(possibleFormats.indexOf(format) !== -1, `顶点${attributeName} 提供的数据格式 ${format} 与着色器中类型 ${wgslType} 不匹配!`); + console.assert(data.constructor.name === vertexFormatMap[format].typedArrayConstructor.name, + `顶点${attributeName} 提供的数据类型 ${data.constructor.name} 与格式 ${format} 不匹配!请使用 ${data.constructor.name} 来组织数据或者更改数据格式。`); + + // 如果 偏移值大于 单个顶点尺寸,则该值被放入 IGPUVertexBuffer.offset。 + const vertexByteSize = vertexFormatMap[format].byteSize; + // + if (!arrayStride) + { + arrayStride = vertexByteSize; + } + console.assert(attributeOffset + vertexByteSize <= arrayStride, `offset(${attributeOffset}) + vertexByteSize(${vertexByteSize}) 必须不超出 arrayStride(${arrayStride})。`); + + let index = bufferIndexMap.get(data); + if (index === undefined) + { + index = vertexBufferLayouts.length; + bufferIndexMap.set(data, index); + + vertexBuffers[index] = getVertexBuffers(vertexAttribute); + + // + vertexBufferLayouts[index] = { stepMode, arrayStride, attributes: [] }; + } + else + { + // 要求同一顶点缓冲区中 arrayStride 与 stepMode 必须相同。 + const gpuVertexBufferLayout = vertexBufferLayouts[index]; + console.assert(gpuVertexBufferLayout.arrayStride === arrayStride); + console.assert(gpuVertexBufferLayout.stepMode === stepMode); + } + + (vertexBufferLayouts[index].attributes as Array).push({ shaderLocation, offset: attributeOffset, format }); + }); - (vertexBufferLayouts[index].attributes as Array).push({ shaderLocation, offset: attributeOffset, format }); + return { vertexBufferLayouts, vertexBuffers }; }); - result = { vertexBufferLayouts, vertexBuffers }; _getVertexBuffersBuffersMap.set([vertexState, vertices], result); - return result; + return result.value; +} + +function getVertexBuffers(vertexAttribute: VertexAttribute) +{ + let result = _NVertexBufferMap.get(vertexAttribute); + if (result) return result.value; + const NVertexBuffer: NVertexBuffer = {} as any; + result = computed(() => + { + // 监听 + reactive(vertexAttribute).data; + // + const data = vertexAttribute.data; + NVertexBuffer.data = data; + NVertexBuffer.offset = data.byteOffset; + NVertexBuffer.size = data.byteLength; + return NVertexBuffer; + }); + _NVertexBufferMap.set(vertexAttribute, result); + return result.value; } +const _NVertexBufferMap = new WeakMap>(); -const _getVertexBuffersBuffersMap = new ChainMap<[VertexState, VertexAttributes], { vertexBufferLayouts: GPUVertexBufferLayout[], vertexBuffers: NVertexBuffer[] }>(); \ No newline at end of file +const _getVertexBuffersBuffersMap = new ChainMap<[VertexState, VertexAttributes], ComputedRef<{ vertexBufferLayouts: GPUVertexBufferLayout[], vertexBuffers: NVertexBuffer[] }>>(); \ No newline at end of file -- Gitee From 36263295354ec86e6bb5bd9d2ca41fd66c87f991 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 11:07:47 +0800 Subject: [PATCH 118/214] =?UTF-8?q?feat(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=A1=B6=E7=82=B9=E7=BC=93=E5=86=B2=E5=8C=BA=E5=B8=83=E5=B1=80?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 getGPUVertexState 中添加缓存逻辑,避免重复创建 GPUVertexState - 在 getNGPUVertexBuffers 中优化顶点缓冲区布局的生成和缓存 - 调整 RenderObjectChanges 示例,展示顶点属性的修改 --- .../src/webgpu/RenderObjectChanges/index.ts | 49 ++++++++++--------- src/caches/getGPUVertexState.ts | 10 +++- src/caches/getNGPUVertexBuffers.ts | 36 +++++++++++--- 3 files changed, 64 insertions(+), 31 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index 39287e0..1d2f367 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -67,30 +67,35 @@ const init = async (canvas: HTMLCanvasElement) => window.onclick = () => { + reactive(renderObject.geometry.vertices.position).stepMode = "instance"; + reactive(renderObject.geometry.vertices.position).stepMode = "vertex"; + reactive(renderObject.geometry.vertices.position).data = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -1]); + // reactive(renderObject.geometry.vertices.position).format = "float32x3"; + // reactive(renderObject.geometry.vertices.position).data = new Float32Array([0.0, 0.5,1.0, -0.5, -0.5,1.0, 0.5, -1,1.0]); // 修改顶点着色器代码 - renderObject.pipeline.vertex.code = ` - @vertex - fn main( - @location(0) position: vec2, - ) -> @builtin(position) vec4 { - var pos = position; - pos.x = pos.x + 0.5; - return vec4(pos, 0.0, 1.0); - } - `; + // reactive(renderObject.pipeline.vertex).code = ` + // @vertex + // fn main( + // @location(0) position: vec2, + // ) -> @builtin(position) vec4 { + // var pos = position; + // pos.x = pos.x + 0.5; + // return vec4(pos, 0.0, 1.0); + // } + // `; - // 修改片段着色器代码 - reactive(renderObject.pipeline.fragment).code = ` - @binding(0) @group(0) var color : vec4; - @fragment - fn main() -> @location(0) vec4f { - var col = color; - col.x = 0.5; - col.y = 0.6; - col.z = 0.7; - return col; - } - `; + // // 修改片段着色器代码 + // reactive(renderObject.pipeline.fragment).code = ` + // @binding(0) @group(0) var color : vec4; + // @fragment + // fn main() -> @location(0) vec4f { + // var col = color; + // col.x = 0.5; + // col.y = 0.6; + // col.z = 0.7; + // return col; + // } + // `; // // renderObject.uniforms.color = [0, 1, 0, 1]; }; diff --git a/src/caches/getGPUVertexState.ts b/src/caches/getGPUVertexState.ts index cdeda6d..6593c08 100644 --- a/src/caches/getGPUVertexState.ts +++ b/src/caches/getGPUVertexState.ts @@ -1,4 +1,4 @@ -import { VertexAttributes, VertexState, computed, reactive } from "@feng3d/render-api"; +import { ChainMap, VertexAttributes, VertexState, computed, reactive } from "@feng3d/render-api"; import { getGPUShaderModule } from "./getGPUShaderModule"; import { getGPUVertexBufferLayouts } from "./getNGPUVertexBuffers"; import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; @@ -34,9 +34,17 @@ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, v constants: vertexState.constants, }; + // 缓存 + const key: _GPUVertexStateMapKey = [gpuVertexState.module, gpuVertexState.entryPoint, gpuVertexState.buffers, gpuVertexState.constants]; + const cache = _GPUVertexStateMap.get(key); + if (cache) return cache; + _GPUVertexStateMap.set(key, gpuVertexState); + return gpuVertexState; }); device._GPUVertexStateMap.set([vertexState, vertices], result); return result.value; } +type _GPUVertexStateMapKey = [module: GPUShaderModule, entryPoint?: string, buffers?: Iterable, constants?: Record] +const _GPUVertexStateMap = new ChainMap<_GPUVertexStateMapKey, GPUVertexState>(); \ No newline at end of file diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts index 74d1c07..9b0db37 100644 --- a/src/caches/getNGPUVertexBuffers.ts +++ b/src/caches/getNGPUVertexBuffers.ts @@ -14,6 +14,17 @@ export function getNVertexBuffers(vertexState: VertexState, vertices: VertexAttr return vertexBuffers; } +declare global +{ + interface GPUVertexBufferLayout + { + /** + * 用于判断是否为相同的顶点缓冲区布局。 + */ + key: string; + } +} + /** * 从顶点属性信息与顶点数据中获取顶点缓冲区布局数组以及顶点缓冲区数组。 * @@ -64,7 +75,7 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri const data = vertexAttribute.data; const attributeOffset = vertexAttribute.offset || 0; let arrayStride = vertexAttribute.arrayStride; - const stepMode = vertexAttribute.stepMode; + const stepMode = vertexAttribute.stepMode ?? "vertex"; const format = vertexAttribute.format; // 检查提供的顶点数据格式是否与着色器匹配 // const wgslType = getWGSLType(v.type); @@ -83,6 +94,7 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri console.assert(attributeOffset + vertexByteSize <= arrayStride, `offset(${attributeOffset}) + vertexByteSize(${vertexByteSize}) 必须不超出 arrayStride(${arrayStride})。`); let index = bufferIndexMap.get(data); + let gpuVertexBufferLayout: GPUVertexBufferLayout; if (index === undefined) { index = vertexBufferLayouts.length; @@ -91,20 +103,26 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri vertexBuffers[index] = getVertexBuffers(vertexAttribute); // - vertexBufferLayouts[index] = { stepMode, arrayStride, attributes: [] }; + gpuVertexBufferLayout = vertexBufferLayouts[index] = { stepMode, arrayStride, attributes: [], key: `${stepMode}-${arrayStride}` }; } else { - // 要求同一顶点缓冲区中 arrayStride 与 stepMode 必须相同。 - const gpuVertexBufferLayout = vertexBufferLayouts[index]; - console.assert(gpuVertexBufferLayout.arrayStride === arrayStride); - console.assert(gpuVertexBufferLayout.stepMode === stepMode); + gpuVertexBufferLayout = vertexBufferLayouts[index]; + if (__DEV__) + { + console.assert(vertexBufferLayouts[index].arrayStride === arrayStride && vertexBufferLayouts[index].stepMode === stepMode, "要求同一顶点缓冲区中 arrayStride 与 stepMode 必须相同。"); + } } - (vertexBufferLayouts[index].attributes as Array).push({ shaderLocation, offset: attributeOffset, format }); + (gpuVertexBufferLayout.attributes as Array).push({ shaderLocation, offset: attributeOffset, format }); + gpuVertexBufferLayout.key += `-[${shaderLocation}, ${attributeOffset}, ${format}]`; }); - return { vertexBufferLayouts, vertexBuffers }; + // 相同的顶点缓冲区布局合并为一个。 + const vertexBufferLayoutsKey = vertexBufferLayouts.reduce((prev, cur) => { return prev + cur.key }, ""); + vertexBufferLayoutsMap[vertexBufferLayoutsKey] ??= vertexBufferLayouts; + + return { vertexBufferLayouts: vertexBufferLayoutsMap[vertexBufferLayoutsKey], vertexBuffers }; }); _getVertexBuffersBuffersMap.set([vertexState, vertices], result); @@ -112,6 +130,8 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri return result.value; } +const vertexBufferLayoutsMap: Record = {}; + function getVertexBuffers(vertexAttribute: VertexAttribute) { let result = _NVertexBufferMap.get(vertexAttribute); -- Gitee From 77a41039dac03a6d406acb23f370487378e78308 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 11:44:29 +0800 Subject: [PATCH 119/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20getGPUVertexState=20=E5=87=BD=E6=95=B0=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 const 声明键变量,提高代码可读性和性能 - 避免在每次调用时创建新的数组对象,减少垃圾回收压力 --- src/caches/getGPUVertexState.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/caches/getGPUVertexState.ts b/src/caches/getGPUVertexState.ts index 6593c08..16fad41 100644 --- a/src/caches/getGPUVertexState.ts +++ b/src/caches/getGPUVertexState.ts @@ -12,7 +12,8 @@ import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; */ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) { - let result = device._GPUVertexStateMap.get([vertexState, vertices]); + const _GPUVertexStateMap_key: [vertexState: VertexState, vertices: VertexAttributes] = [vertexState, vertices]; + let result = device._GPUVertexStateMap.get(_GPUVertexStateMap_key); if (result) return result.value; result = computed(() => @@ -42,7 +43,7 @@ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, v return gpuVertexState; }); - device._GPUVertexStateMap.set([vertexState, vertices], result); + device._GPUVertexStateMap.set(_GPUVertexStateMap_key, result); return result.value; } -- Gitee From 397ff3b876817fdefb7d8080b803ca97371abc4b Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 11:47:30 +0800 Subject: [PATCH 120/214] =?UTF-8?q?refactor(src):=20=E4=BC=98=E5=8C=96=20g?= =?UTF-8?q?etGPUVertexState=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将结果存储逻辑移至 computed 函数内部 - 简化代码结构,提高可读性和性能 - 使用 const 替代 let,提高变量声明的准确性 --- src/caches/getGPUVertexState.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/caches/getGPUVertexState.ts b/src/caches/getGPUVertexState.ts index 16fad41..7c87451 100644 --- a/src/caches/getGPUVertexState.ts +++ b/src/caches/getGPUVertexState.ts @@ -13,10 +13,10 @@ import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) { const _GPUVertexStateMap_key: [vertexState: VertexState, vertices: VertexAttributes] = [vertexState, vertices]; - let result = device._GPUVertexStateMap.get(_GPUVertexStateMap_key); + const result = device._GPUVertexStateMap.get(_GPUVertexStateMap_key); if (result) return result.value; - result = computed(() => + return device._GPUVertexStateMap.set(_GPUVertexStateMap_key, computed(() => { // 监听 const r_vertexState = reactive(vertexState); @@ -42,10 +42,7 @@ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, v _GPUVertexStateMap.set(key, gpuVertexState); return gpuVertexState; - }); - device._GPUVertexStateMap.set(_GPUVertexStateMap_key, result); - - return result.value; + })).value; } type _GPUVertexStateMapKey = [module: GPUShaderModule, entryPoint?: string, buffers?: Iterable, constants?: Record] const _GPUVertexStateMap = new ChainMap<_GPUVertexStateMapKey, GPUVertexState>(); \ No newline at end of file -- Gitee From e595564395e5cb58d96bb1f29b0a81b19c7259c3 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 12:21:20 +0800 Subject: [PATCH 121/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=A1=B6=E7=82=B9=E7=8A=B6=E6=80=81=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 WebGPUBase 类中的 _GPUVertexStateMap - 在 getGPUVertexState 函数中创建新的缓存逻辑 - 优化缓存键值的创建方式,提高缓存命中率 --- src/WebGPUBase.ts | 2 -- src/caches/getGPUVertexState.ts | 14 +++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index e31d03e..a471fdf 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -48,7 +48,6 @@ declare global _renderObjectCommandMap: ChainMap<[string, RenderObject], Array>; _renderPipelineMap: ChainMap<[RenderPipeline, string, VertexAttributes, GPUIndexFormat], ComputedRef>; _fragmentStateMap: ChainMap<[FragmentState, string], ComputedRef>; - _GPUVertexStateMap: ChainMap<[VertexState, VertexAttributes], ComputedRef> } } @@ -103,7 +102,6 @@ export class WebGPUBase this._device._renderPassDescriptorMap ??= new WeakMap(); this._device._pipelineLayoutMap ??= new Map(); this._device._shaderMap ??= new Map(); - this._device._GPUVertexStateMap ??= new ChainMap(); } } protected _device: GPUDevice; diff --git a/src/caches/getGPUVertexState.ts b/src/caches/getGPUVertexState.ts index 7c87451..162a264 100644 --- a/src/caches/getGPUVertexState.ts +++ b/src/caches/getGPUVertexState.ts @@ -1,4 +1,4 @@ -import { ChainMap, VertexAttributes, VertexState, computed, reactive } from "@feng3d/render-api"; +import { ChainMap, ComputedRef, VertexAttributes, VertexState, computed, reactive } from "@feng3d/render-api"; import { getGPUShaderModule } from "./getGPUShaderModule"; import { getGPUVertexBufferLayouts } from "./getNGPUVertexBuffers"; import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; @@ -12,11 +12,11 @@ import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; */ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) { - const _GPUVertexStateMap_key: [vertexState: VertexState, vertices: VertexAttributes] = [vertexState, vertices]; - const result = device._GPUVertexStateMap.get(_GPUVertexStateMap_key); + const _getGPUVertexStateMapKey = [device, vertexState, vertices]; + const result = _getGPUVertexStateMap.get(_getGPUVertexStateMapKey); if (result) return result.value; - return device._GPUVertexStateMap.set(_GPUVertexStateMap_key, computed(() => + return _getGPUVertexStateMap.set(_getGPUVertexStateMapKey, computed(() => { // 监听 const r_vertexState = reactive(vertexState); @@ -36,7 +36,7 @@ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, v }; // 缓存 - const key: _GPUVertexStateMapKey = [gpuVertexState.module, gpuVertexState.entryPoint, gpuVertexState.buffers, gpuVertexState.constants]; + const key = [gpuVertexState.module, gpuVertexState.entryPoint, gpuVertexState.buffers, gpuVertexState.constants]; const cache = _GPUVertexStateMap.get(key); if (cache) return cache; _GPUVertexStateMap.set(key, gpuVertexState); @@ -44,5 +44,5 @@ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, v return gpuVertexState; })).value; } -type _GPUVertexStateMapKey = [module: GPUShaderModule, entryPoint?: string, buffers?: Iterable, constants?: Record] -const _GPUVertexStateMap = new ChainMap<_GPUVertexStateMapKey, GPUVertexState>(); \ No newline at end of file +const _getGPUVertexStateMap = new ChainMap>(); +const _GPUVertexStateMap = new ChainMap(); \ No newline at end of file -- Gitee From 9561b121068ae2f86cb6b688ba3c1363c1f3fadc Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 12:29:28 +0800 Subject: [PATCH 122/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E7=BB=84=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 GPUDevice 接口中的 _bindGroupMap 属性 - 新增全局的 _getGPUBindGroupMap 用于缓存绑定组 - 修改 getGPUBindGroup 函数以使用新的缓存逻辑 - 优化了绑定组的创建和更新流程 --- src/WebGPUBase.ts | 2 -- src/caches/getGPUBindGroup.ts | 10 ++++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index a471fdf..12deae4 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -31,7 +31,6 @@ declare global { interface GPUDevice { - _bindGroupMap: ChainMap<[GPUBindGroupLayout, BindingResources], GPUBindGroup>; _bufferMap: WeakMap>; _contextMap: WeakMap>; _computePipelineMap: WeakMap; @@ -88,7 +87,6 @@ export class WebGPUBase // if (this._device) { - this._device._bindGroupMap ??= new ChainMap(); this._device._renderPassObjectsCommandMap ??= new ChainMap(); this._device._renderPipelineMap ??= new ChainMap(); this._device._renderObjectCommandMap ??= new ChainMap(); diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 08c9cab..9825373 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResource, BindingResources, BufferBinding, BufferBindingInfo, CanvasTexture, Sampler, TextureView } from "@feng3d/render-api"; +import { BindingResource, BindingResources, BufferBinding, BufferBindingInfo, CanvasTexture, ChainMap, Sampler, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { ResourceType } from "wgsl_reflect"; import { getRealGPUBindGroup } from "../const"; @@ -15,7 +15,8 @@ import { getGBuffer } from "./getIGPUBuffer"; export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) { - let gBindGroup = device._bindGroupMap.get([bindGroupLayout, bindingResources]); + const getGPUBindGroupMapKey: GetGPUBindGroupMapKey = [device, bindGroupLayout, bindingResources]; + let gBindGroup = _getGPUBindGroupMap.get(getGPUBindGroupMapKey); if (gBindGroup) return gBindGroup; // 总是更新函数列表。 @@ -124,7 +125,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup gBindGroup = device.createBindGroup({ layout: bindGroupLayout, entries }); - device._bindGroupMap.set([bindGroupLayout, bindingResources], gBindGroup); + _getGPUBindGroupMap.set(getGPUBindGroupMapKey, gBindGroup); // 设置更新外部纹理/画布纹理视图 if (awaysUpdateFuncs.length > 0) @@ -143,7 +144,8 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup return gBindGroup; } - +type GetGPUBindGroupMapKey = [device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; +const _getGPUBindGroupMap = new ChainMap(); /** * GPU 绑定组。 * -- Gitee From 099c7e6460590eef2b82b406575549f5331815b2 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 14:37:41 +0800 Subject: [PATCH 123/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E7=BC=93=E5=AD=98=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 GPUDevice 上的 _renderPassObjectsCommandMap 和 _renderPipelineMap - 新增全局的 _renderPassObjectsCommandMap 和 getGPUBufferMap - 重构 getGPUBuffer 和 getGPUCanvasContext 函数,使用新的缓存映射 - 删除未使用的 getNGPURenderPipeline 文件 --- src/WebGPUBase.ts | 20 +++++------------ src/WebGPUCache.ts | 22 +++++++++++++------ src/caches/getGPUBuffer.ts | 11 ++++++---- src/caches/getGPUCanvasContext.ts | 11 ++++++---- ...derPipeline.ts => getGPURenderPipeline.ts} | 13 ++++++----- 5 files changed, 41 insertions(+), 36 deletions(-) rename src/caches/{getNGPURenderPipeline.ts => getGPURenderPipeline.ts} (93%) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 12deae4..2f0e269 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, BlendState, CanvasContext, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, FragmentState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, RenderPipeline, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly, VertexAttributes, VertexState } from "@feng3d/render-api"; +import { BlendState, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, FragmentState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -8,10 +8,11 @@ import { getGPUPipelineLayout } from "./caches/getGPUPipelineLayout"; import { getGPURenderOcclusionQuery, GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; import { getGPURenderPassDescriptor } from "./caches/getGPURenderPassDescriptor"; import { getGPURenderPassFormat } from "./caches/getGPURenderPassFormat"; +import { getGPURenderPipeline } from "./caches/getGPURenderPipeline"; import { getGPURenderTimestampQuery } from "./caches/getGPURenderTimestampQuery"; import { getGPUTexture } from "./caches/getGPUTexture"; import { getGBuffer } from "./caches/getIGPUBuffer"; -import { getNGPURenderPipeline } from "./caches/getNGPURenderPipeline"; +import { getNVertexBuffers } from "./caches/getNGPUVertexBuffers"; import { getRealGPUBindGroup } from "./const"; import { ComputeObject } from "./data/ComputeObject"; import { ComputePass } from "./data/ComputePass"; @@ -25,14 +26,11 @@ import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; -import { getNVertexBuffers } from "./caches/getNGPUVertexBuffers"; declare global { interface GPUDevice { - _bufferMap: WeakMap>; - _contextMap: WeakMap>; _computePipelineMap: WeakMap; _samplerMap: WeakMap; _textureViewMap: WeakMap; @@ -40,12 +38,7 @@ declare global _renderPassDescriptorMap: WeakMap; _shaderMap: Map; _pipelineLayoutMap: Map; - _renderPassObjectsCommandMap: ChainMap<[string, RenderPassObject[]], { - commands: Array; - setBindGroupCommands: Array; - }>; _renderObjectCommandMap: ChainMap<[string, RenderObject], Array>; - _renderPipelineMap: ChainMap<[RenderPipeline, string, VertexAttributes, GPUIndexFormat], ComputedRef>; _fragmentStateMap: ChainMap<[FragmentState, string], ComputedRef>; } } @@ -87,12 +80,8 @@ export class WebGPUBase // if (this._device) { - this._device._renderPassObjectsCommandMap ??= new ChainMap(); - this._device._renderPipelineMap ??= new ChainMap(); this._device._renderObjectCommandMap ??= new ChainMap(); this._device._fragmentStateMap ??= new ChainMap(); - this._device._bufferMap ??= new WeakMap(); - this._device._contextMap ??= new WeakMap(); this._device._computePipelineMap ??= new WeakMap(); this._device._samplerMap ??= new WeakMap(); this._device._textureMap ??= new WeakMap(); @@ -481,7 +470,8 @@ export class WebGPUBase const { vertices, indices, draw } = geometry; // - const nPipeline = getNGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indices); + const indexFormat: GPUIndexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; + const nPipeline = getGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indexFormat); // passEncoder.setPipeline(nPipeline); diff --git a/src/WebGPUCache.ts b/src/WebGPUCache.ts index 9b35766..5233378 100644 --- a/src/WebGPUCache.ts +++ b/src/WebGPUCache.ts @@ -14,7 +14,8 @@ export class WebGPUCache extends WebGPUBase protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { const device = this._device; - let caches = device._renderPassObjectsCommandMap.get([renderPassFormat._key, renderObjects]); + const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat._key, renderObjects]; + let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); if (!caches) { // 收集命令 @@ -31,12 +32,12 @@ export class WebGPUCache extends WebGPUBase caches = { commands, setBindGroupCommands }; - device._renderPassObjectsCommandMap.set([renderPassFormat._key, renderObjects], caches); + _renderPassObjectsCommandMap.set(renderPassObjectsCommandKey, caches); // 监听变化 const onchanged = () => { - device._renderPassObjectsCommandMap.delete([renderPassFormat._key, renderObjects]); + _renderPassObjectsCommandMap.delete(renderPassObjectsCommandKey); // renderObjects.forEach((v) => { watcher.unwatch(v, "_version" as any, onchanged); }); }; @@ -50,7 +51,8 @@ export class WebGPUCache extends WebGPUBase protected runRenderBundleObjects(bundleEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: RenderObject[]) { const device = this._device; - let caches = device._renderPassObjectsCommandMap.get([renderPassFormat._key, renderObjects]); + const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat._key, renderObjects]; + let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); if (!caches) { // 收集命令 @@ -67,12 +69,12 @@ export class WebGPUCache extends WebGPUBase caches = { commands, setBindGroupCommands }; - device._renderPassObjectsCommandMap.set([renderPassFormat._key, renderObjects], caches); + _renderPassObjectsCommandMap.set(renderPassObjectsCommandKey, caches); // 监听变化 const onchanged = () => { - device._renderPassObjectsCommandMap.delete([renderPassFormat._key, renderObjects]); + _renderPassObjectsCommandMap.delete(renderPassObjectsCommandKey); // renderObjects.forEach((v) => { watcher.unwatch(v, "_version", onchanged); }); }; @@ -258,4 +260,10 @@ function arrayEq1(_obj: any, name: string, index: number, args: any[]) } return true; -} \ No newline at end of file +} + +type RenderPassObjectsCommandKey = [device: GPUDevice, RenderPassFormatKey: string, renderObjects: RenderPassObject[]]; +const _renderPassObjectsCommandMap = new ChainMap; + setBindGroupCommands: Array; +}>; \ No newline at end of file diff --git a/src/caches/getGPUBuffer.ts b/src/caches/getGPUBuffer.ts index e7dbd52..9f9c96b 100644 --- a/src/caches/getGPUBuffer.ts +++ b/src/caches/getGPUBuffer.ts @@ -1,4 +1,4 @@ -import { computed, effect, GBuffer, reactive, UnReadonly } from "@feng3d/render-api"; +import { ChainMap, computed, ComputedRef, effect, GBuffer, reactive, UnReadonly } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; /** @@ -26,7 +26,8 @@ const defaultGPUBufferUsage = 0 */ export function getGPUBuffer(device: GPUDevice, buffer: GBuffer) { - let result = device._bufferMap.get(buffer); + const getGPUBufferKey: GetGPUBufferKey = [device, buffer]; + let result = getGPUBufferMap.get(getGPUBufferKey); if (result) return result.value; const size = buffer.size; @@ -138,14 +139,16 @@ export function getGPUBuffer(device: GPUDevice, buffer: GBuffer) { oldDestroy.apply(gBuffer); - device._bufferMap.delete(buffer); + getGPUBufferMap.delete(getGPUBufferKey); // watcher.unwatch(buffer, "data", dataChange); }; })(gBuffer.destroy); - device._bufferMap.set(buffer, result); + getGPUBufferMap.set(getGPUBufferKey, result); return result.value; } +type GetGPUBufferKey = [device: GPUDevice, buffer: GBuffer]; +const getGPUBufferMap = new ChainMap>; \ No newline at end of file diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index 0112957..4008e20 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -1,10 +1,11 @@ -import { CanvasContext } from "@feng3d/render-api"; -import { computed, reactive } from "@vue/reactivity"; +import { CanvasContext, ChainMap } from "@feng3d/render-api"; +import { computed, ComputedRef, reactive } from "@vue/reactivity"; import "../data/polyfills/CanvasContext"; export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) { - let result = device._contextMap.get(context); + const getGPUCanvasContextKey: GetGPUCanvasContextKey = [device, context]; + let result = getGPUCanvasContextMap.get(getGPUCanvasContextKey); if (result) return result.value; const canvas = typeof context.canvasId === "string" ? document.getElementById(context.canvasId) as HTMLCanvasElement : context.canvasId; @@ -31,7 +32,7 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) return gpuCanvasContext; }); - device._contextMap.set(context, result); + getGPUCanvasContextMap.set(getGPUCanvasContextKey, result); const updateConfigure = () => { @@ -59,3 +60,5 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) return result.value; } +type GetGPUCanvasContextKey = [device: GPUDevice, context: CanvasContext]; +const getGPUCanvasContextMap = new ChainMap>; \ No newline at end of file diff --git a/src/caches/getNGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts similarity index 93% rename from src/caches/getNGPURenderPipeline.ts rename to src/caches/getGPURenderPipeline.ts index 501f290..a104efb 100644 --- a/src/caches/getNGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendComponent, BlendState, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, IIndicesDataTypes, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, WGSLVertexType, WriteMask } from "@feng3d/render-api"; +import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, WGSLVertexType, WriteMask } from "@feng3d/render-api"; import { TemplateInfo, TypeInfo } from "wgsl_reflect"; import { MultisampleState } from "../data/MultisampleState"; @@ -16,11 +16,10 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; * @param vertices 顶点属性数据映射。 * @returns 完整的渲染管线描述以及顶点缓冲区数组。 */ -export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, vertices: VertexAttributes, indices: IIndicesDataTypes) +export function getGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, vertices: VertexAttributes, indexFormat: GPUIndexFormat) { - const indexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; - - let result = device._renderPipelineMap.get([renderPipeline, renderPassFormat._key, vertices, indexFormat]); + const getNGPURenderPipeline: GetNGPURenderPipeline = [device, renderPipeline, renderPassFormat._key, vertices, indexFormat]; + let result = _renderPipelineMap.get(getNGPURenderPipeline); if (result) return result.value; result = computed(() => @@ -57,10 +56,12 @@ export function getNGPURenderPipeline(device: GPUDevice, renderPipeline: RenderP return gpuRenderPipeline; }); - device._renderPipelineMap.set([renderPipeline, renderPassFormat._key, vertices, indexFormat], result); + _renderPipelineMap.set(getNGPURenderPipeline, result); return result.value; } +type GetNGPURenderPipeline = [device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormatKey: string, vertices: VertexAttributes, indexFormat: GPUIndexFormat]; +const _renderPipelineMap = new ChainMap>; function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndexFormat): GPUPrimitiveState { -- Gitee From 30ff248549298e0772f2b1bc8932a7afaae80e32 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 15:02:51 +0800 Subject: [PATCH 124/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=AE=A1=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 GPUDevice 上的冗余缓存映射 - 创建全局的 ChainMap 缓存映射 - 更新缓存键值生成逻辑,使用复合键 - 调整缓存获取和设置方法 - 删除不必要的全局声明 --- src/WebGPUBase.ts | 32 +----------------------- src/WebGPUCache.ts | 9 ++++--- src/caches/getGPUComputePipeline.ts | 9 ++++--- src/caches/getGPUPipelineLayout.ts | 8 ++++-- src/caches/getGPURenderPassDescriptor.ts | 10 +++++--- src/caches/getGPURenderPipeline.ts | 7 ++++-- src/caches/getGPUSampler.ts | 11 +++++--- src/caches/getGPUShaderModule.ts | 9 +++++-- src/caches/getGPUTexture.ts | 11 +++++--- src/caches/getGPUTextureView.ts | 11 +++++--- 10 files changed, 59 insertions(+), 58 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 2f0e269..9510b81 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BlendState, ChainMap, CommandEncoder, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, FragmentState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassDescriptor, RenderPassObject, Sampler, Submit, Texture, TextureLike, TextureView, UnReadonly } from "@feng3d/render-api"; +import { BlendState, ChainMap, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassObject, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -16,7 +16,6 @@ import { getNVertexBuffers } from "./caches/getNGPUVertexBuffers"; import { getRealGPUBindGroup } from "./const"; import { ComputeObject } from "./data/ComputeObject"; import { ComputePass } from "./data/ComputePass"; -import { ComputePipeline } from "./data/ComputePipeline"; import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; @@ -27,22 +26,6 @@ import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; -declare global -{ - interface GPUDevice - { - _computePipelineMap: WeakMap; - _samplerMap: WeakMap; - _textureViewMap: WeakMap; - _textureMap: WeakMap; - _renderPassDescriptorMap: WeakMap; - _shaderMap: Map; - _pipelineLayoutMap: Map; - _renderObjectCommandMap: ChainMap<[string, RenderObject], Array>; - _fragmentStateMap: ChainMap<[FragmentState, string], ComputedRef>; - } -} - /** * WebGPU 基础类 */ @@ -77,19 +60,6 @@ export class WebGPUBase set device(v) { this._device = v; - // - if (this._device) - { - this._device._renderObjectCommandMap ??= new ChainMap(); - this._device._fragmentStateMap ??= new ChainMap(); - this._device._computePipelineMap ??= new WeakMap(); - this._device._samplerMap ??= new WeakMap(); - this._device._textureMap ??= new WeakMap(); - this._device._textureViewMap ??= new WeakMap(); - this._device._renderPassDescriptorMap ??= new WeakMap(); - this._device._pipelineLayoutMap ??= new Map(); - this._device._shaderMap ??= new Map(); - } } protected _device: GPUDevice; diff --git a/src/WebGPUCache.ts b/src/WebGPUCache.ts index 5233378..6c0feb9 100644 --- a/src/WebGPUCache.ts +++ b/src/WebGPUCache.ts @@ -93,7 +93,8 @@ export class WebGPUCache extends WebGPUBase const device = this._device; const _commands = passEncoder["_commands"] as any[]; - const commands = device._renderObjectCommandMap.get([renderPassFormat._key, renderObject]); + const renderObjectCommandKey: RenderObjectCommandKey = [device, renderPassFormat._key, renderObject]; + const commands = renderObjectCommandMap.get(renderObjectCommandKey); if (commands) { commands.forEach((v) => _commands.push(v)); @@ -105,12 +106,12 @@ export class WebGPUCache extends WebGPUBase super.runRenderObject(passEncoder, renderPassFormat, renderObject); - device._renderObjectCommandMap.set([renderPassFormat._key, renderObject], _commands.slice(start)); + renderObjectCommandMap.set(renderObjectCommandKey, _commands.slice(start)); // const onchanged = () => { - device._renderObjectCommandMap.delete([renderPassFormat._key, renderObject]); + renderObjectCommandMap.delete(renderObjectCommandKey); // renderObject._version = ~~renderObject._version + 1; watcher.unwatch(renderObject.pipeline, '_version', onchanged); @@ -118,6 +119,8 @@ export class WebGPUCache extends WebGPUBase watcher.watch(renderObject.pipeline, '_version', onchanged); } } +type RenderObjectCommandKey = [device: GPUDevice, renderPassFormatKey: string, renderObject: RenderObject]; +const renderObjectCommandMap = new ChainMap>(); class GPURenderPassRecord implements GPURenderPassEncoder { diff --git a/src/caches/getGPUComputePipeline.ts b/src/caches/getGPUComputePipeline.ts index 54e969d..e764719 100644 --- a/src/caches/getGPUComputePipeline.ts +++ b/src/caches/getGPUComputePipeline.ts @@ -1,4 +1,4 @@ -import { UnReadonly } from "@feng3d/render-api"; +import { ChainMap, UnReadonly } from "@feng3d/render-api"; import { ComputePipeline } from "../data/ComputePipeline"; import { ComputeStage } from "../data/ComputeStage"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; @@ -7,7 +7,8 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; export function getGPUComputePipeline(device: GPUDevice, computePipeline: ComputePipeline) { - let pipeline = device._computePipelineMap.get(computePipeline); + const getGPUComputePipelineKey: GetGPUComputePipeline = [device, computePipeline]; + let pipeline = _computePipelineMap.get(getGPUComputePipelineKey); if (pipeline) return pipeline; const computeStage = computePipeline.compute; @@ -36,8 +37,10 @@ export function getGPUComputePipeline(device: GPUDevice, computePipeline: Comput module: getGPUShaderModule(device, computeStage.code), }, }); - device._computePipelineMap.set(computePipeline, pipeline); + _computePipelineMap.set(getGPUComputePipelineKey, pipeline); return pipeline; } +type GetGPUComputePipeline = [device: GPUDevice, computePipeline: ComputePipeline]; +const _computePipelineMap = new ChainMap; \ No newline at end of file diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index dae4554..0caaea1 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -1,3 +1,4 @@ +import { ChainMap } from "@feng3d/render-api"; import { getIGPUBindGroupLayoutEntryMap, GPUBindGroupLayoutEntryMap } from "./getWGSLReflectInfo"; declare global @@ -49,7 +50,8 @@ export function getGPUPipelineLayout(device: GPUDevice, shader: { vertex: string if (shader.fragment) shaderKey += `\n// ------顶点与片段着色器分界--------\n` + shader.fragment; } - let gpuPipelineLayout = device._pipelineLayoutMap.get(shaderKey); + const getGPUPipelineLayoutKey: GetGPUPipelineLayoutKey = [device, shaderKey]; + let gpuPipelineLayout = getGPUPipelineLayoutMap.get(getGPUPipelineLayoutKey); if (gpuPipelineLayout) return gpuPipelineLayout; let entryMap: GPUBindGroupLayoutEntryMap; @@ -147,10 +149,12 @@ export function getGPUPipelineLayout(device: GPUDevice, shader: { vertex: string gpuPipelineLayout.bindGroupLayouts = bindGroupLayouts; } - device._pipelineLayoutMap.set(shaderKey, gpuPipelineLayout); + getGPUPipelineLayoutMap.set(getGPUPipelineLayoutKey, gpuPipelineLayout); return gpuPipelineLayout; } +type GetGPUPipelineLayoutKey = [device: GPUDevice, shaderKey: string]; +const getGPUPipelineLayoutMap = new ChainMap; const bindGroupLayoutMap: { [key: string]: GPUBindGroupLayout } = {}; const pipelineLayoutDescriptorMap: { [key: string]: GPUPipelineLayout } = {}; diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 15af5a6..c8d822e 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CanvasTexture, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; +import { CanvasTexture, ChainMap, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUTexture_resize } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; @@ -17,7 +17,8 @@ import { getTextureSize } from "./getTextureSize"; */ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: RenderPassDescriptor): GPURenderPassDescriptor { - let renderPassDescriptor = device._renderPassDescriptorMap.get(descriptor); + const getGPURenderPassDescriptor: GetGPURenderPassDescriptor = [device, descriptor]; + let renderPassDescriptor = getGPURenderPassDescriptorMap.get(getGPURenderPassDescriptor); if (renderPassDescriptor) { // 执行更新函数。 @@ -27,7 +28,7 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render } renderPassDescriptor = { colorAttachments: [] }; - device._renderPassDescriptorMap.set(descriptor, renderPassDescriptor); + getGPURenderPassDescriptorMap.set(getGPURenderPassDescriptor, renderPassDescriptor); const _updates: Function[] = renderPassDescriptor["_updates"] = []; @@ -117,6 +118,9 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render return renderPassDescriptor; } +type GetGPURenderPassDescriptor = [device: GPUDevice, descriptor: RenderPassDescriptor]; +const getGPURenderPassDescriptorMap = new ChainMap; + /** * 获取渲染通道附件上的纹理描述列表。 * diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index a104efb..ab837c2 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -238,7 +238,8 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co const colorAttachmentsKey = colorAttachments.toLocaleString(); - let gpuFragmentState = device._fragmentStateMap.get([fragmentState, colorAttachmentsKey]); + const getGPUFragmentStateKey: GetGPUFragmentStateKey = [device, fragmentState, colorAttachmentsKey]; + let gpuFragmentState = getGPUFragmentStateMap.get(getGPUFragmentStateKey); if (gpuFragmentState) return gpuFragmentState.value; gpuFragmentState = computed(() => @@ -259,10 +260,12 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co } as GPUFragmentState; }); - device._fragmentStateMap.set([fragmentState, colorAttachmentsKey], gpuFragmentState); + getGPUFragmentStateMap.set(getGPUFragmentStateKey, gpuFragmentState); return gpuFragmentState.value; } +type GetGPUFragmentStateKey = [device: GPUDevice, fragmentState: FragmentState, colorAttachmentsKey: string]; +const getGPUFragmentStateMap = new ChainMap>; function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]): GPUColorTargetState[] { diff --git a/src/caches/getGPUSampler.ts b/src/caches/getGPUSampler.ts index 7b8959d..7fb856d 100644 --- a/src/caches/getGPUSampler.ts +++ b/src/caches/getGPUSampler.ts @@ -1,11 +1,12 @@ import { anyEmitter } from "@feng3d/event"; -import { Sampler } from "@feng3d/render-api"; +import { ChainMap, Sampler } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUSampler_changed } from "../eventnames"; export function getGPUSampler(device: GPUDevice, sampler: Sampler) { - let gSampler = device._samplerMap.get(sampler); + const getGPUSamplerKey: GetGPUSamplerKey = [device, sampler]; + let gSampler = getGPUSamplerMap.get(getGPUSamplerKey); if (gSampler) return gSampler; // 处理默认值 @@ -18,20 +19,22 @@ export function getGPUSampler(device: GPUDevice, sampler: Sampler) // gSampler = device.createSampler(sampler); - device._samplerMap.set(sampler, gSampler); + getGPUSamplerMap.set(getGPUSamplerKey, gSampler); // watcher.watchobject(sampler, defaultSampler, () => { // 移除监听,删除缓存 watcher.unwatchobject(sampler, defaultSampler); - device._samplerMap.delete(sampler); + getGPUSamplerMap.delete(getGPUSamplerKey); // anyEmitter.emit(sampler, IGPUSampler_changed); }); return gSampler; } +type GetGPUSamplerKey = [device: GPUDevice, sampler: Sampler]; +const getGPUSamplerMap = new ChainMap; /** * GPU采样器默认值。 diff --git a/src/caches/getGPUShaderModule.ts b/src/caches/getGPUShaderModule.ts index c2633ba..585554e 100644 --- a/src/caches/getGPUShaderModule.ts +++ b/src/caches/getGPUShaderModule.ts @@ -1,12 +1,17 @@ +import { ChainMap } from "@feng3d/render-api"; + export function getGPUShaderModule(device: GPUDevice, code: string) { - let gShaderModule = device._shaderMap.get(code); + const getGPUShaderModuleKey: GetGPUShaderModuleKey = [device, code]; + let gShaderModule = getGPUShaderModuleMap.get(getGPUShaderModuleKey); if (gShaderModule) return gShaderModule; gShaderModule = device.createShaderModule({ code, }); - device._shaderMap.set(code, gShaderModule); + getGPUShaderModuleMap.set(getGPUShaderModuleKey, gShaderModule); return gShaderModule; } +type GetGPUShaderModuleKey = [device: GPUDevice, code: string]; +const getGPUShaderModuleMap = new ChainMap; \ No newline at end of file diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index a67b2ea..0dd657d 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; +import { ChainMap, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; @@ -29,7 +29,8 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC const texture = textureLike as Texture; - gpuTexture = device._textureMap.get(texture); + const getGPUTextureKey: GetGPUTextureMap = [device, texture]; + gpuTexture = getGPUTextureMap.get(getGPUTextureKey); if (gpuTexture) return gpuTexture; if (!autoCreate) return null; @@ -72,7 +73,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC viewFormats, }); - device._textureMap.set(texture, gpuTexture); + getGPUTextureMap.set(getGPUTextureKey, gpuTexture); }; createTexture(); @@ -229,7 +230,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC { oldDestroy.apply(gpuTexture); // - device._textureMap.delete(texture); + getGPUTextureMap.delete(getGPUTextureKey); // watcher.unwatch(texture, "size", resize); watcher.unwatch(texture, "sources", updateSources); @@ -245,6 +246,8 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC return gpuTexture; } let autoIndex = 0; +type GetGPUTextureMap = [device: GPUDevice, texture: Texture]; +const getGPUTextureMap = new ChainMap; function getGPUTextureDimension(dimension: TextureDimension) { diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index 7ef0b3c..097a9ee 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CanvasTexture, Texture, TextureView } from "@feng3d/render-api"; +import { CanvasTexture, ChainMap, Texture, TextureView } from "@feng3d/render-api"; import { GPUTexture_destroy, GPUTextureView_destroy } from "../eventnames"; import { getGPUTexture } from "./getGPUTexture"; @@ -18,7 +18,8 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) } // - let textureView = device._textureViewMap.get(view); + const getGPUTextureViewKey: GetGPUTextureViewKey = [device, view]; + let textureView = getGPUTextureViewMap.get(getGPUTextureViewKey); if (textureView) return textureView; // @@ -27,14 +28,16 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) const dimension = view.dimension ?? texture.dimension; textureView = gpuTexture.createView({ ...view, dimension }); - device._textureViewMap.set(view, textureView); + getGPUTextureViewMap.set(getGPUTextureViewKey, textureView); // 销毁纹理时清除对应的纹理视图。 anyEmitter.once(gpuTexture, GPUTexture_destroy, () => { - device._textureViewMap.delete(view); + getGPUTextureViewMap.delete(getGPUTextureViewKey); anyEmitter.emit(textureView, GPUTextureView_destroy); }); return textureView; } +type GetGPUTextureViewKey = [device: GPUDevice, view: TextureView]; +const getGPUTextureViewMap = new ChainMap; -- Gitee From cf50e47860c41d8cdbf3a63b9dc08803d5a40669 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 15:38:23 +0800 Subject: [PATCH 125/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=AE=A1=E7=90=86=E5=B9=B6=E6=8F=90=E9=AB=98?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=8F=AF=E7=BB=B4=E6=8A=A4=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为缓存键定义专用类型,提高类型安全性和可读性 - 优化缓存访问代码,使用专用键替代任何数组类型 - 重命名缓存相关变量,使其更具描述性和一致性 - 清理不必要的代码和注释,提高代码清晰度 --- src/caches/getGPUVertexState.ts | 18 ++++++++++-------- src/caches/getNGPUVertexBuffers.ts | 14 ++++++++------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/caches/getGPUVertexState.ts b/src/caches/getGPUVertexState.ts index 162a264..d2e0ef9 100644 --- a/src/caches/getGPUVertexState.ts +++ b/src/caches/getGPUVertexState.ts @@ -12,11 +12,11 @@ import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; */ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) { - const _getGPUVertexStateMapKey = [device, vertexState, vertices]; - const result = _getGPUVertexStateMap.get(_getGPUVertexStateMapKey); + const getGPUVertexStateKey: GetGPUVertexStateKey = [device, vertexState, vertices]; + const result = getGPUVertexStateMap.get(getGPUVertexStateKey); if (result) return result.value; - return _getGPUVertexStateMap.set(_getGPUVertexStateMapKey, computed(() => + return getGPUVertexStateMap.set(getGPUVertexStateKey, computed(() => { // 监听 const r_vertexState = reactive(vertexState); @@ -36,13 +36,15 @@ export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, v }; // 缓存 - const key = [gpuVertexState.module, gpuVertexState.entryPoint, gpuVertexState.buffers, gpuVertexState.constants]; - const cache = _GPUVertexStateMap.get(key); + const gpuVertexStateKey: GPUVertexStateKey = [gpuVertexState.module, gpuVertexState.entryPoint, gpuVertexState.buffers, gpuVertexState.constants]; + const cache = gpuVertexStateMap.get(gpuVertexStateKey); if (cache) return cache; - _GPUVertexStateMap.set(key, gpuVertexState); + gpuVertexStateMap.set(gpuVertexStateKey, gpuVertexState); return gpuVertexState; })).value; } -const _getGPUVertexStateMap = new ChainMap>(); -const _GPUVertexStateMap = new ChainMap(); \ No newline at end of file +type GetGPUVertexStateKey = [device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes]; +const getGPUVertexStateMap = new ChainMap>(); +type GPUVertexStateKey = [module: GPUShaderModule, entryPoint: string, buffers: Iterable, constants: Record]; +const gpuVertexStateMap = new ChainMap(); \ No newline at end of file diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts index 9b0db37..8f8f5b5 100644 --- a/src/caches/getNGPUVertexBuffers.ts +++ b/src/caches/getNGPUVertexBuffers.ts @@ -33,7 +33,8 @@ declare global */ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttributes) { - let result = _getVertexBuffersBuffersMap.get([vertexState, vertices]); + const getVertexBuffersBuffersKey: GetVertexBuffersBuffersKey = [vertexState, vertices]; + let result = getVertexBuffersBuffersMap.get(getVertexBuffersBuffersKey); if (result) return result.value; result = computed(() => @@ -125,7 +126,7 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri return { vertexBufferLayouts: vertexBufferLayoutsMap[vertexBufferLayoutsKey], vertexBuffers }; }); - _getVertexBuffersBuffersMap.set([vertexState, vertices], result); + getVertexBuffersBuffersMap.set(getVertexBuffersBuffersKey, result); return result.value; } @@ -134,7 +135,7 @@ const vertexBufferLayoutsMap: Record = {}; function getVertexBuffers(vertexAttribute: VertexAttribute) { - let result = _NVertexBufferMap.get(vertexAttribute); + let result = getVertexBuffersMap.get(vertexAttribute); if (result) return result.value; const NVertexBuffer: NVertexBuffer = {} as any; result = computed(() => @@ -148,9 +149,10 @@ function getVertexBuffers(vertexAttribute: VertexAttribute) NVertexBuffer.size = data.byteLength; return NVertexBuffer; }); - _NVertexBufferMap.set(vertexAttribute, result); + getVertexBuffersMap.set(vertexAttribute, result); return result.value; } -const _NVertexBufferMap = new WeakMap>(); +const getVertexBuffersMap = new WeakMap>(); -const _getVertexBuffersBuffersMap = new ChainMap<[VertexState, VertexAttributes], ComputedRef<{ vertexBufferLayouts: GPUVertexBufferLayout[], vertexBuffers: NVertexBuffer[] }>>(); \ No newline at end of file +type GetVertexBuffersBuffersKey = [vertexState: VertexState, vertices: VertexAttributes]; +const getVertexBuffersBuffersMap = new ChainMap>(); \ No newline at end of file -- Gitee From a3cc268f7cb47ddf76423d848088062d14a2a77d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 17:57:36 +0800 Subject: [PATCH 126/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=AE=A1=E7=BA=BF=E7=BC=93=E5=AD=98=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 合并 getGPUVertexState 和 getGPURenderPipeline 中的重复代码 - 优化 GPUVertexState 和 GPUPipeline 的缓存策略 - 新增 getConstants 函数以缓存常量值 - 重写 getGPUDepthStencilState 和 getGPUStencilFaceState 以使用缓存 - 优化 GPUColorTargetState 和 GPUFragmentState 的缓存逻辑 - 删除未使用的 getGPUVertexState.ts 文件 --- src/caches/getGPURenderPipeline.ts | 191 +++++++++++++++++++++++++---- src/caches/getGPUVertexState.ts | 50 -------- 2 files changed, 165 insertions(+), 76 deletions(-) delete mode 100644 src/caches/getGPUVertexState.ts diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index ab837c2..153923a 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -1,11 +1,12 @@ -import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, WGSLVertexType, WriteMask } from "@feng3d/render-api"; +import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, VertexState, WGSLVertexType, WriteMask } from "@feng3d/render-api"; import { TemplateInfo, TypeInfo } from "wgsl_reflect"; import { MultisampleState } from "../data/MultisampleState"; import { RenderPassFormat } from "../internal/RenderPassFormat"; import { getGPUPipelineLayout } from "./getGPUPipelineLayout"; import { getGPUShaderModule } from "./getGPUShaderModule"; -import { getGPUVertexState } from "./getGPUVertexState"; +import { getGPUVertexBufferLayouts } from "./getNGPUVertexBuffers"; +import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; /** @@ -18,8 +19,8 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; */ export function getGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, vertices: VertexAttributes, indexFormat: GPUIndexFormat) { - const getNGPURenderPipeline: GetNGPURenderPipeline = [device, renderPipeline, renderPassFormat._key, vertices, indexFormat]; - let result = _renderPipelineMap.get(getNGPURenderPipeline); + const getGPURenderPipelineKey: GetGPURenderPipelineKey = [device, renderPipeline, renderPassFormat._key, vertices, indexFormat]; + let result = getGPURenderPipelineMap.get(getGPURenderPipelineKey); if (result) return result.value; result = computed(() => @@ -56,12 +57,92 @@ export function getGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPi return gpuRenderPipeline; }); - _renderPipelineMap.set(getNGPURenderPipeline, result); + getGPURenderPipelineMap.set(getGPURenderPipelineKey, result); return result.value; } -type GetNGPURenderPipeline = [device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormatKey: string, vertices: VertexAttributes, indexFormat: GPUIndexFormat]; -const _renderPipelineMap = new ChainMap>; +type GetGPURenderPipelineKey = [device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormatKey: string, vertices: VertexAttributes, indexFormat: GPUIndexFormat]; +const getGPURenderPipelineMap = new ChainMap>; + +/** + * 获取完整的顶点阶段描述与顶点缓冲区列表。 + * + * @param vertexState 顶点阶段信息。 + * @param vertices 顶点数据。 + * @returns 完整的顶点阶段描述与顶点缓冲区列表。 + */ +function getGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) +{ + const getGPUVertexStateKey: GetGPUVertexStateKey = [device, vertexState, vertices]; + const result = getGPUVertexStateMap.get(getGPUVertexStateKey); + if (result) return result.value; + + return getGPUVertexStateMap.set(getGPUVertexStateKey, computed(() => + { + // 监听 + const r_vertexState = reactive(vertexState); + r_vertexState.code; + r_vertexState.constants; + + // 计算 + const { code, constants } = vertexState; + + const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); + const vertexBufferLayouts = getGPUVertexBufferLayouts(vertexState, vertices); + + const gpuVertexState: GPUVertexState = { + module: getGPUShaderModule(device, code), + entryPoint: vertexEntryFunctionInfo.name, + buffers: vertexBufferLayouts, + constants: getConstants(constants), + }; + + // 缓存 + const gpuVertexStateKey: GPUVertexStateKey = [gpuVertexState.module, gpuVertexState.entryPoint, gpuVertexState.buffers, gpuVertexState.constants]; + const cache = gpuVertexStateMap.get(gpuVertexStateKey); + if (cache) return cache; + gpuVertexStateMap.set(gpuVertexStateKey, gpuVertexState); + + return gpuVertexState; + })).value; +} + +type GetGPUVertexStateKey = [device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes]; +const getGPUVertexStateMap = new ChainMap>(); +type GPUVertexStateKey = [module: GPUShaderModule, entryPoint: string, buffers: Iterable, constants: Record]; +const gpuVertexStateMap = new ChainMap(); + +function getConstants(constants: Record) +{ + if (!constants) return undefined; + + let result: ComputedRef> = getConstantsMap.get(constants); + if (result) return result.value; + + result = computed(() => + { + const r_constants = reactive(constants); + + let constantsKey = ""; + for (const key in r_constants) + { + constantsKey += `${key}:${r_constants[key]},`; + } + + if (constantsMap[constantsKey]) + { + return constantsMap[constantsKey]; + } + constantsMap[constantsKey] = constants; + + return constants; + }); + getConstantsMap.set(constants, result); + + return result.value; +} +const constantsMap: { [constantsKey: string]: Record } = {}; +const getConstantsMap = new WeakMap, ComputedRef>>(); function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndexFormat): GPUPrimitiveState { @@ -129,9 +210,13 @@ function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFo { if (!depthStencilFormat) return undefined; - if (!depthStencil) return { format: depthStencilFormat }; + if (!depthStencil) return getDefaultGPUDepthStencilState(depthStencilFormat); + + const getGPUDepthStencilStateKey: GetGPUDepthStencilStateKey = [depthStencil, depthStencilFormat]; + let result = getGPUDepthStencilStateMap.get(getGPUDepthStencilStateKey); + if (result) return result.value; - const result: ComputedRef = depthStencil["_cache_GPUDepthStencilState_" + depthStencilFormat] = computed(() => + result = computed(() => { // 监听 const r_depthStencil = reactive(depthStencil); @@ -160,17 +245,42 @@ function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFo depthBiasClamp: depthBiasClamp ?? 0, }; + // 缓存 + + return gpuDepthStencilState; }); + getGPUDepthStencilStateMap.set(getGPUDepthStencilStateKey, result); return result.value; } +type GetGPUDepthStencilStateKey = [depthStencil: DepthStencilState, depthStencilFormat: GPUTextureFormat]; +const getGPUDepthStencilStateMap = new ChainMap>(); + +/** + * 获取片段阶段完整描述。 + * + * @param fragment 片段阶段描述。 + */ +function getDefaultGPUDepthStencilState(depthStencilFormat: GPUTextureFormat) +{ + let result = defaultGPUDepthStencilStates[depthStencilFormat]; + if (result) return result; + + result = defaultGPUDepthStencilStates[depthStencilFormat] = { format: depthStencilFormat }; + + return result; +} +const defaultGPUDepthStencilStates: Record = {} as any; function getGPUStencilFaceState(stencilFaceState?: StencilFaceState) { - if (!stencilFaceState) return {}; + if (!stencilFaceState) return defaultGPUStencilFaceState; - const result: ComputedRef = stencilFaceState["_cache_GPUStencilFaceState"] = computed(() => + let result = getGPUStencilFaceStateMap.get(stencilFaceState); + if (result) return result.value; + + result = computed(() => { // 监听 const r_stencilFaceState = reactive(stencilFaceState); @@ -188,15 +298,27 @@ function getGPUStencilFaceState(stencilFaceState?: StencilFaceState) passOp: passOp ?? "keep", }; + // 缓存 + const gpuStencilFaceStateKey: GPUStencilFaceStateKey = [gpuStencilFaceState.compare, gpuStencilFaceState.failOp, gpuStencilFaceState.depthFailOp, gpuStencilFaceState.passOp]; + const cache = GPUStencilFaceStateMap.get(gpuStencilFaceStateKey); + if (cache) return cache; + GPUStencilFaceStateMap.set(gpuStencilFaceStateKey, gpuStencilFaceState); + + // return gpuStencilFaceState; - }) + }); + getGPUStencilFaceStateMap.set(stencilFaceState, result); return result.value; } +const defaultGPUStencilFaceState: GPUStencilFaceState = {}; +const getGPUStencilFaceStateMap = new WeakMap>(); +type GPUStencilFaceStateKey = [compare: GPUCompareFunction, failOp: GPUStencilOperation, depthFailOp: GPUStencilOperation, passOp: GPUStencilOperation]; +const GPUStencilFaceStateMap = new ChainMap(); function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUTextureFormat) { - if (!colorTargetState) return defaultGPUColorTargetState(format); + if (!colorTargetState) return getDefaultGPUColorTargetState(format); const result: ComputedRef = colorTargetState["_GPUColorTargetState_" + format] ??= computed(() => { @@ -219,11 +341,11 @@ function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUT return result.value; } -const _defaultGPUColorTargetState = {}; -const defaultGPUColorTargetState = (format: GPUTextureFormat) => +const getDefaultGPUColorTargetState = (format: GPUTextureFormat): GPUColorTargetState => { - return _defaultGPUColorTargetState[format] ??= { format, blend: getGPUBlendState(undefined), writeMask: getGPUColorWriteFlags(undefined) } + return defaultGPUColorTargetState[format] ??= { format, blend: getGPUBlendState(undefined), writeMask: getGPUColorWriteFlags(undefined) } }; +const defaultGPUColorTargetState: Record = {} as any; /** * 获取片段阶段完整描述。 @@ -248,30 +370,44 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co const r_fragmentState = reactive(fragmentState); r_fragmentState.code; r_fragmentState.targets; - for (const key in r_fragmentState.constants) { r_fragmentState.constants[key]; } + r_fragmentState.constants; // 计算 const { code, targets, constants } = fragmentState; - return { + const gpuFragmentState: GPUFragmentState = { module: getGPUShaderModule(device, code), entryPoint: getEntryPoint(fragmentState), targets: getGPUColorTargetStates(targets, colorAttachments), - constants: constants - } as GPUFragmentState; + constants: getConstants(constants) + }; + + const gpuFragmentStateKey: GPUFragmentStateKey = [gpuFragmentState.module, gpuFragmentState.entryPoint, gpuFragmentState.targets, gpuFragmentState.constants]; + const cache = gpuFragmentStateMap.get(gpuFragmentStateKey); + if (cache) return cache; + + gpuFragmentStateMap.set(gpuFragmentStateKey, gpuFragmentState); + + return gpuFragmentState; }); getGPUFragmentStateMap.set(getGPUFragmentStateKey, gpuFragmentState); return gpuFragmentState.value; } +type GPUFragmentStateKey = [module: GPUShaderModule, entryPoint: string, targets: Iterable, constants: Record] +const gpuFragmentStateMap = new ChainMap(); type GetGPUFragmentStateKey = [device: GPUDevice, fragmentState: FragmentState, colorAttachmentsKey: string]; const getGPUFragmentStateMap = new ChainMap>; function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]): GPUColorTargetState[] { - if (!targets) return defaultGPUColorTargetStates(colorAttachments); + if (!targets) return getDefaultGPUColorTargetStates(colorAttachments); + + const getGPUColorTargetStatesKey: GetGPUColorTargetStatesKey = [targets, colorAttachments]; + let result = getGPUColorTargetStatesMap.get(getGPUColorTargetStatesKey); + if (result) return result.value; - const result: ComputedRef = targets["_GPUColorTargetStates_" + colorAttachments.toString()] ??= computed(() => + result = computed(() => { return colorAttachments.map((format, i) => { @@ -286,17 +422,21 @@ function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAtta return gpuColorTargetState; }); }); + getGPUColorTargetStatesMap.set(getGPUColorTargetStatesKey, result); return result.value; } -const _defaultGPUColorTargetStates: { [key: string]: GPUColorTargetState[] } = {}; -const defaultGPUColorTargetStates = (colorAttachments: readonly GPUTextureFormat[]) => +type GetGPUColorTargetStatesKey = [targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]]; +const getGPUColorTargetStatesMap = new ChainMap>(); + +const getDefaultGPUColorTargetStates = (colorAttachments: readonly GPUTextureFormat[]) => { - return _defaultGPUColorTargetStates[colorAttachments.toString()] ??= colorAttachments.map((format) => + return defaultGPUColorTargetStates[colorAttachments.toString()] ??= colorAttachments.map((format) => { return getGPUColorTargetState(undefined, format); }); }; +const defaultGPUColorTargetStates: { [key: string]: GPUColorTargetState[] } = {}; function getEntryPoint(fragmentState: FragmentState) { @@ -321,7 +461,6 @@ function getEntryPoint(fragmentState: FragmentState) return result.value; } - function getGPUBlendState(blend?: BlendState): GPUBlendState { if (!blend) return undefined; diff --git a/src/caches/getGPUVertexState.ts b/src/caches/getGPUVertexState.ts deleted file mode 100644 index d2e0ef9..0000000 --- a/src/caches/getGPUVertexState.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { ChainMap, ComputedRef, VertexAttributes, VertexState, computed, reactive } from "@feng3d/render-api"; -import { getGPUShaderModule } from "./getGPUShaderModule"; -import { getGPUVertexBufferLayouts } from "./getNGPUVertexBuffers"; -import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; - -/** - * 获取完整的顶点阶段描述与顶点缓冲区列表。 - * - * @param vertexState 顶点阶段信息。 - * @param vertices 顶点数据。 - * @returns 完整的顶点阶段描述与顶点缓冲区列表。 - */ -export function getGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes) -{ - const getGPUVertexStateKey: GetGPUVertexStateKey = [device, vertexState, vertices]; - const result = getGPUVertexStateMap.get(getGPUVertexStateKey); - if (result) return result.value; - - return getGPUVertexStateMap.set(getGPUVertexStateKey, computed(() => - { - // 监听 - const r_vertexState = reactive(vertexState); - r_vertexState.code; - - // 计算 - const { code } = vertexState; - - const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); - const vertexBufferLayouts = getGPUVertexBufferLayouts(vertexState, vertices); - - const gpuVertexState: GPUVertexState = { - module: getGPUShaderModule(device, code), - entryPoint: vertexEntryFunctionInfo.name, - buffers: vertexBufferLayouts, - constants: vertexState.constants, - }; - - // 缓存 - const gpuVertexStateKey: GPUVertexStateKey = [gpuVertexState.module, gpuVertexState.entryPoint, gpuVertexState.buffers, gpuVertexState.constants]; - const cache = gpuVertexStateMap.get(gpuVertexStateKey); - if (cache) return cache; - gpuVertexStateMap.set(gpuVertexStateKey, gpuVertexState); - - return gpuVertexState; - })).value; -} -type GetGPUVertexStateKey = [device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes]; -const getGPUVertexStateMap = new ChainMap>(); -type GPUVertexStateKey = [module: GPUShaderModule, entryPoint: string, buffers: Iterable, constants: Record]; -const gpuVertexStateMap = new ChainMap(); \ No newline at end of file -- Gitee From bc264f6646cc4be14aec173fa898430e86274c79 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 18:02:56 +0800 Subject: [PATCH 127/214] =?UTF-8?q?feat(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B7=B1=E5=BA=A6=E6=A8=A1=E6=9D=BF=E7=8A=B6=E6=80=81=E7=BC=93?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 GPUDepthStencilStateKey 类型,用于缓存深度模板状态 - 在 getGPUDepthStencilState 函数中实现深度模板状态的缓存逻辑 - 通过缓存减少不必要的 GPU 深度模板状态创建,提高性能 --- src/caches/getGPURenderPipeline.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index 153923a..032ac88 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -246,8 +246,23 @@ function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFo }; // 缓存 + const gpuDepthStencilStateKey: GPUDepthStencilStateKey = [ + gpuDepthStencilState.format, + gpuDepthStencilState.depthWriteEnabled, + gpuDepthStencilState.depthCompare, + gpuDepthStencilState.stencilFront, + gpuDepthStencilState.stencilBack, + gpuDepthStencilState.stencilReadMask, + gpuDepthStencilState.stencilWriteMask, + gpuDepthStencilState.depthBias, + gpuDepthStencilState.depthBiasSlopeScale, + gpuDepthStencilState.depthBiasClamp, + ]; + const cache = gpuDepthStencilStateMap.get(gpuDepthStencilStateKey); + if (cache) return cache; + gpuDepthStencilStateMap.set(gpuDepthStencilStateKey, gpuDepthStencilState); - + // return gpuDepthStencilState; }); getGPUDepthStencilStateMap.set(getGPUDepthStencilStateKey, result); @@ -256,6 +271,13 @@ function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFo } type GetGPUDepthStencilStateKey = [depthStencil: DepthStencilState, depthStencilFormat: GPUTextureFormat]; const getGPUDepthStencilStateMap = new ChainMap>(); +type GPUDepthStencilStateKey = [format: GPUTextureFormat, depthWriteEnabled: boolean, depthCompare: GPUCompareFunction, stencilFront: GPUStencilFaceState, stencilBack: GPUStencilFaceState, stencilReadMask: number, stencilWriteMask: number, depthBias: number, depthBiasSlopeScale: number, depthBiasClamp: number] +const gpuDepthStencilStateMap = new ChainMap(); + +/** + * 获取片段阶段完整描述。 + * + * @param fragment 片段阶段描述。 /** * 获取片段阶段完整描述。 -- Gitee From ad457325be4ebd208d1d2ec0caef1d91c8729a68 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 19:27:07 +0800 Subject: [PATCH 128/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=9C=BA=E5=88=B6=E5=92=8C=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构了 GPURenderBundle 和 RenderPassFormat 的缓存逻辑 - 优化了 getGPURenderPassFormat、getGPURenderPipeline 和 getGPUTextureFormat 函数 - 使用 computed 和 reactive 优化了缓存计算和依赖追踪 - 调整了部分类型定义和变量命名,提高了代码可读性 --- src/WebGPUBase.ts | 11 +++-- src/WebGPUCache.ts | 10 ++--- src/caches/getGPURenderPassFormat.ts | 61 +++++++++++++++++++--------- src/caches/getGPURenderPipeline.ts | 15 +++++-- src/caches/getGPUTextureFormat.ts | 29 +++++++++---- src/internal/RenderPassFormat.ts | 4 -- 6 files changed, 87 insertions(+), 43 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 9510b81..750761c 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -323,9 +323,9 @@ export class WebGPUBase protected runRenderBundle(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) { const device = this._device; - const renderBundleMap: ChainMap<[RenderBundle, string], GPURenderBundle> = device["_renderBundleMap"] = device["_renderBundleMap"] || new ChainMap(); // - let gpuRenderBundle: GPURenderBundle = renderBundleMap.get([renderBundleObject, renderPassFormat._key]); + const gpuRenderBundleKey: GPURenderBundleKey = [renderBundleObject, renderPassFormat]; + let gpuRenderBundle = gpuRenderBundleMap.get(gpuRenderBundleKey); if (!gpuRenderBundle) { const descriptor: GPURenderBundleEncoderDescriptor = { ...renderBundleObject.descriptor, ...renderPassFormat }; @@ -336,7 +336,7 @@ export class WebGPUBase this.runRenderBundleObjects(renderBundleEncoder, renderPassFormat, renderBundleObject.renderObjects); gpuRenderBundle = renderBundleEncoder.finish(); - renderBundleMap.set([renderBundleObject, renderPassFormat._key], gpuRenderBundle); + gpuRenderBundleMap.set(gpuRenderBundleKey, gpuRenderBundle); } passEncoder.executeBundles([gpuRenderBundle]); @@ -554,4 +554,7 @@ function getStencilReference(depthStencil?: DepthStencilState) } return stencilReference; -} \ No newline at end of file +} + +type GPURenderBundleKey = [renderBundle: RenderBundle, renderPassFormat: RenderPassFormat]; +const gpuRenderBundleMap = new ChainMap(); \ No newline at end of file diff --git a/src/WebGPUCache.ts b/src/WebGPUCache.ts index 6c0feb9..44fba11 100644 --- a/src/WebGPUCache.ts +++ b/src/WebGPUCache.ts @@ -14,7 +14,7 @@ export class WebGPUCache extends WebGPUBase protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { const device = this._device; - const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat._key, renderObjects]; + const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat, renderObjects]; let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); if (!caches) { @@ -51,7 +51,7 @@ export class WebGPUCache extends WebGPUBase protected runRenderBundleObjects(bundleEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: RenderObject[]) { const device = this._device; - const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat._key, renderObjects]; + const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat, renderObjects]; let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); if (!caches) { @@ -93,7 +93,7 @@ export class WebGPUCache extends WebGPUBase const device = this._device; const _commands = passEncoder["_commands"] as any[]; - const renderObjectCommandKey: RenderObjectCommandKey = [device, renderPassFormat._key, renderObject]; + const renderObjectCommandKey: RenderObjectCommandKey = [device, renderPassFormat, renderObject]; const commands = renderObjectCommandMap.get(renderObjectCommandKey); if (commands) { @@ -119,7 +119,7 @@ export class WebGPUCache extends WebGPUBase watcher.watch(renderObject.pipeline, '_version', onchanged); } } -type RenderObjectCommandKey = [device: GPUDevice, renderPassFormatKey: string, renderObject: RenderObject]; +type RenderObjectCommandKey = [device: GPUDevice, renderPassFormat: RenderPassFormat, renderObject: RenderObject]; const renderObjectCommandMap = new ChainMap>(); class GPURenderPassRecord implements GPURenderPassEncoder @@ -265,7 +265,7 @@ function arrayEq1(_obj: any, name: string, index: number, args: any[]) return true; } -type RenderPassObjectsCommandKey = [device: GPUDevice, RenderPassFormatKey: string, renderObjects: RenderPassObject[]]; +type RenderPassObjectsCommandKey = [device: GPUDevice, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[]]; const _renderPassObjectsCommandMap = new ChainMap; setBindGroupCommands: Array; diff --git a/src/caches/getGPURenderPassFormat.ts b/src/caches/getGPURenderPassFormat.ts index 38e763e..fa2e476 100644 --- a/src/caches/getGPURenderPassFormat.ts +++ b/src/caches/getGPURenderPassFormat.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor } from "@feng3d/render-api"; +import { computed, ComputedRef, reactive, RenderPassDescriptor } from "@feng3d/render-api"; import { getGPUTextureFormat } from "../caches/getGPUTextureFormat"; import { RenderPassFormat } from "../internal/RenderPassFormat"; @@ -10,28 +10,49 @@ import { RenderPassFormat } from "../internal/RenderPassFormat"; */ export function getGPURenderPassFormat(descriptor: RenderPassDescriptor): RenderPassFormat { - let gpuRenderPassFormat: RenderPassFormat = descriptor[_RenderPassFormat]; - if (gpuRenderPassFormat) return gpuRenderPassFormat; + let result = getGPURenderPassFormatMap.get(descriptor); + if (result) return result.value; - const colorAttachmentTextureFormats = descriptor.colorAttachments.map((v) => getGPUTextureFormat(v.view.texture)); - - let depthStencilAttachmentTextureFormat: GPUTextureFormat; - if (descriptor.depthStencilAttachment) + result = computed(() => { - depthStencilAttachmentTextureFormat = getGPUTextureFormat(descriptor.depthStencilAttachment.view?.texture) || "depth24plus"; - } + // 监听 + const r_descriptor = reactive(descriptor); + r_descriptor.attachmentSize?.width; + r_descriptor.attachmentSize?.height; + r_descriptor.colorAttachments?.map((v) => v.view.texture); + r_descriptor.depthStencilAttachment?.view?.texture; + r_descriptor.sampleCount; - const _key = `${colorAttachmentTextureFormats.toString()}|${depthStencilAttachmentTextureFormat}|${descriptor.sampleCount}`; + // 计算 + const colorAttachmentTextureFormats = descriptor.colorAttachments.map((v) => getGPUTextureFormat(v.view.texture)); - descriptor[_RenderPassFormat] = gpuRenderPassFormat = { - attachmentSize: descriptor.attachmentSize, - colorFormats: colorAttachmentTextureFormats, - depthStencilFormat: depthStencilAttachmentTextureFormat, - sampleCount: descriptor.sampleCount, - _key, - }; + let depthStencilAttachmentTextureFormat: GPUTextureFormat; + if (descriptor.depthStencilAttachment) + { + depthStencilAttachmentTextureFormat = getGPUTextureFormat(descriptor.depthStencilAttachment.view?.texture) || "depth24plus"; + } - return gpuRenderPassFormat; -} + const renderPassFormat: RenderPassFormat = { + attachmentSize: descriptor.attachmentSize, + colorFormats: colorAttachmentTextureFormats, + depthStencilFormat: depthStencilAttachmentTextureFormat, + sampleCount: descriptor.sampleCount, + }; + + // 缓存 + const renderPassFormatKey = renderPassFormat.attachmentSize.width + "," + renderPassFormat.attachmentSize.height + + "|" + renderPassFormat.colorFormats.join('') + + "|" + renderPassFormat.depthStencilFormat + + "|" + renderPassFormat.sampleCount; + const cache = renderPassFormatMap[renderPassFormatKey]; + if (cache) return cache; + renderPassFormatMap[renderPassFormatKey] = renderPassFormat; -const _RenderPassFormat = "_RenderPassFormat"; \ No newline at end of file + return renderPassFormat; + }); + getGPURenderPassFormatMap.set(descriptor, result); + + return result.value; +} +const renderPassFormatMap: Record = {}; +const getGPURenderPassFormatMap = new WeakMap>(); diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index 032ac88..d2b1d82 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -19,7 +19,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; */ export function getGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, vertices: VertexAttributes, indexFormat: GPUIndexFormat) { - const getGPURenderPipelineKey: GetGPURenderPipelineKey = [device, renderPipeline, renderPassFormat._key, vertices, indexFormat]; + const getGPURenderPipelineKey: GetGPURenderPipelineKey = [device, renderPipeline, renderPassFormat, vertices, indexFormat]; let result = getGPURenderPipelineMap.get(getGPURenderPipelineKey); if (result) return result.value; @@ -61,7 +61,7 @@ export function getGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPi return result.value; } -type GetGPURenderPipelineKey = [device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormatKey: string, vertices: VertexAttributes, indexFormat: GPUIndexFormat]; +type GetGPURenderPipelineKey = [device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, vertices: VertexAttributes, indexFormat: GPUIndexFormat]; const getGPURenderPipelineMap = new ChainMap>; /** @@ -231,7 +231,16 @@ function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFo r_depthStencil.depthBiasClamp; // 计算 - const { depthWriteEnabled, depthCompare, stencilFront, stencilBack, stencilReadMask, stencilWriteMask, depthBias, depthBiasSlopeScale, depthBiasClamp } = depthStencil; + const { depthWriteEnabled, + depthCompare, + stencilFront, + stencilBack, + stencilReadMask, + stencilWriteMask, + depthBias, + depthBiasSlopeScale, + depthBiasClamp, + } = depthStencil; const gpuDepthStencilState: GPUDepthStencilState = { format: depthStencilFormat, depthWriteEnabled: depthWriteEnabled ?? true, diff --git a/src/caches/getGPUTextureFormat.ts b/src/caches/getGPUTextureFormat.ts index effe6ee..f397d16 100644 --- a/src/caches/getGPUTextureFormat.ts +++ b/src/caches/getGPUTextureFormat.ts @@ -1,4 +1,4 @@ -import { TextureLike } from "@feng3d/render-api"; +import { computed, ComputedRef, reactive, TextureLike } from "@feng3d/render-api"; /** * 获取纹理格式。 @@ -6,16 +6,31 @@ import { TextureLike } from "@feng3d/render-api"; * @param texture 纹理。 * @returns 纹理格式。 */ -export function getGPUTextureFormat(texture: TextureLike) +export function getGPUTextureFormat(texture: TextureLike): GPUTextureFormat { if (!texture) return undefined; - if ("context" in texture) + let result = getGPUTextureFormatMap.get(texture); + if (result) return result.value; + + result = computed(() => { - const format = texture.context?.configuration?.format || navigator.gpu.getPreferredCanvasFormat(); + // 监听 + const r_texture = reactive(texture); + + // 计算 + if ("context" in r_texture) + { + const format = r_texture.context?.configuration?.format || navigator.gpu.getPreferredCanvasFormat(); - return format; - } + return format; + } - return texture.format; + return r_texture.format; + }); + getGPUTextureFormatMap.set(texture, result); + + return result.value; } + +const getGPUTextureFormatMap = new WeakMap>(); \ No newline at end of file diff --git a/src/internal/RenderPassFormat.ts b/src/internal/RenderPassFormat.ts index d83157f..1d85273 100644 --- a/src/internal/RenderPassFormat.ts +++ b/src/internal/RenderPassFormat.ts @@ -4,8 +4,4 @@ export interface RenderPassFormat readonly colorFormats: readonly GPUTextureFormat[], readonly depthStencilFormat: GPUTextureFormat, readonly sampleCount?: 4 - /** - * 初始化后被自动赋值,用于识别通道格式是否相同。 - */ - readonly _key?: string; } \ No newline at end of file -- Gitee From 1c9a645a842c2b789607fb9d4a607487ec29a627 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 19:49:06 +0800 Subject: [PATCH 129/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E9=80=9A=E9=81=93=E6=8F=8F=E8=BF=B0=E7=AC=A6?= =?UTF-8?q?=E7=9A=84=E7=BC=93=E5=AD=98=E9=94=AE=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 GetGPURenderPassDescriptor 类型更改为 GetGPURenderPassDescriptorKey - 更新相关变量和函数调用以使用新的键类型 - 此修改提高了代码的可读性和类型安全性,避免潜在的类型错误 --- src/caches/getGPURenderPassDescriptor.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index c8d822e..45ead81 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -17,8 +17,8 @@ import { getTextureSize } from "./getTextureSize"; */ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: RenderPassDescriptor): GPURenderPassDescriptor { - const getGPURenderPassDescriptor: GetGPURenderPassDescriptor = [device, descriptor]; - let renderPassDescriptor = getGPURenderPassDescriptorMap.get(getGPURenderPassDescriptor); + const getGPURenderPassDescriptorKey: GetGPURenderPassDescriptorKey = [device, descriptor]; + let renderPassDescriptor = getGPURenderPassDescriptorMap.get(getGPURenderPassDescriptorKey); if (renderPassDescriptor) { // 执行更新函数。 @@ -28,7 +28,7 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render } renderPassDescriptor = { colorAttachments: [] }; - getGPURenderPassDescriptorMap.set(getGPURenderPassDescriptor, renderPassDescriptor); + getGPURenderPassDescriptorMap.set(getGPURenderPassDescriptorKey, renderPassDescriptor); const _updates: Function[] = renderPassDescriptor["_updates"] = []; @@ -118,8 +118,8 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render return renderPassDescriptor; } -type GetGPURenderPassDescriptor = [device: GPUDevice, descriptor: RenderPassDescriptor]; -const getGPURenderPassDescriptorMap = new ChainMap; +type GetGPURenderPassDescriptorKey = [device: GPUDevice, descriptor: RenderPassDescriptor]; +const getGPURenderPassDescriptorMap = new ChainMap; /** * 获取渲染通道附件上的纹理描述列表。 -- Gitee From 7f6063c290b4196a4c8d0240b6790033cb19a671 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 20:11:33 +0800 Subject: [PATCH 130/214] =?UTF-8?q?feat(WebGPUBase):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=89=8D=E6=93=8D=E4=BD=9C=E8=AE=A1=E6=95=B0?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 GPUDevice 接口中添加 preSubmit 属性,用于在提交前执行操作 - 在 WebGPUBase 类的 device setter 中初始化 preSubmit 属性 - 在 submit 方法中增加 preSubmit 计数器,以便在提交前执行相关操作 - 此功能主要用于内部处理,外部用户无需关心 --- src/WebGPUBase.ts | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 750761c..dc302da 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BlendState, ChainMap, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, ReadPixels, RenderObject, RenderPass, RenderPassObject, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; +import { BlendState, ChainMap, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -26,6 +26,25 @@ import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; +declare global +{ + interface GPUDevice + { + /** + * 提交WebGPU前数值加一。 + * + * 用于处理提交前需要执行的操作。 + * + * 例如 {@link GPUCanvasContext.getCurrentTexture} 与 {@linkGPUDevice.importExternalTexture } 需要在提交前执行,检查结果是否变化。 + * + * 注:引擎内部处理,外部无需关心。 + * + * @private + */ + readonly preSubmit: number; + } +} + /** * WebGPU 基础类 */ @@ -60,6 +79,8 @@ export class WebGPUBase set device(v) { this._device = v; + + this._device && (reactive(this._device).preSubmit ??= 0); } protected _device: GPUDevice; @@ -71,6 +92,8 @@ export class WebGPUBase submit(submit: Submit) { const device = this._device; + // 提交前数值加一,用于处理提交前需要执行的操作。 + reactive(device).preSubmit++; const commandBuffers = submit.commandEncoders.map((v) => { -- Gitee From 32d32e1654771443fb89709f738093aedc810293 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 20:17:06 +0800 Subject: [PATCH 131/214] =?UTF-8?q?fix(caches):=20=E4=BF=AE=E5=A4=8D=20mul?= =?UTF-8?q?tisample=20state=20=E5=92=8C=20vertex=20buffers=20=E7=9A=84?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 getGPUMultisampleState 函数中添加了对默认值的处理 - 在 getVertexBuffersBuffers 函数中增加了对 vertices 参数的判断 - 这些修改确保了在参数未提供时能够正确处理默认值,提高了代码的健壮性 --- src/caches/getGPURenderPipeline.ts | 2 ++ src/caches/getNGPUVertexBuffers.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index d2b1d82..c16aed6 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -177,6 +177,7 @@ const defaultGPUPrimitiveState: GPUPrimitiveState = { topology: "triangle-list", function getGPUMultisampleState(multisampleState?: MultisampleState, sampleCount?: 4) { if (!sampleCount) return undefined; + if (!multisampleState) return defaultGPUMultisampleState; const result: ComputedRef = multisampleState["_cache_GPUMultisampleState_" + sampleCount] ??= computed(() => { @@ -198,6 +199,7 @@ function getGPUMultisampleState(multisampleState?: MultisampleState, sampleCount return result.value; } +const defaultGPUMultisampleState: GPUMultisampleState = { count: 4, mask: 0xFFFFFFFF, alphaToCoverageEnabled: false }; /** * 获取深度模板阶段完整描述。 diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts index 8f8f5b5..4339391 100644 --- a/src/caches/getNGPUVertexBuffers.ts +++ b/src/caches/getNGPUVertexBuffers.ts @@ -41,7 +41,7 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri { const vertexEntryFunctionInfo = getVertexEntryFunctionInfo(vertexState); // 监听 - const r_vertices = reactive(vertices); + const r_vertices = vertices && reactive(vertices); vertexEntryFunctionInfo.inputs.forEach((inputInfo) => { // 跳过内置属性。 -- Gitee From c270b06d12a208815138420c3bdd5518ee9aa1b6 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 20:32:52 +0800 Subject: [PATCH 132/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E9=80=9A=E9=81=93=E9=99=84=E4=BB=B6=E5=B0=BA?= =?UTF-8?q?=E5=AF=B8=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在修改 renderPassDescriptor.attachmentSize 时使用 reactive 函数,以确保响应式更新 - 完善默认深度模板状态的设置,添加缺失的属性 - 将 RenderPassDescriptor 上的 attachmentSize 和 maxDrawCount 属性标记为只读 --- examples/src/webgpu/resizeCanvas/index.ts | 6 +++--- src/caches/getGPURenderPassDescriptor.ts | 4 ++-- src/caches/getGPURenderPipeline.ts | 13 ++++++++++++- src/data/polyfills/RenderPassDescriptor.ts | 4 ++-- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/examples/src/webgpu/resizeCanvas/index.ts b/examples/src/webgpu/resizeCanvas/index.ts index 9f13846..de1a2f8 100644 --- a/examples/src/webgpu/resizeCanvas/index.ts +++ b/examples/src/webgpu/resizeCanvas/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; +import { RenderPassDescriptor, Submit, RenderObject, reactive } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import redFragWGSL from "../../shaders/red.frag.wgsl"; @@ -22,7 +22,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, - geometry:{ + geometry: { draw: { __type__: "DrawVertex", vertexCount: 3 }, } }; @@ -34,7 +34,7 @@ const init = async (canvas: HTMLCanvasElement) => // 画布尺寸发生变化时更改渲染通道附件尺寸。 const currentWidth = canvas.clientWidth * devicePixelRatio; const currentHeight = canvas.clientHeight * devicePixelRatio; - renderPassDescriptor.attachmentSize = { width: currentWidth, height: currentHeight }; + reactive(renderPassDescriptor).attachmentSize = { width: currentWidth, height: currentHeight }; const data: Submit = { commandEncoders: [ diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 45ead81..fd6b77c 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CanvasTexture, ChainMap, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; +import { CanvasTexture, ChainMap, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { IGPUTexture_resize } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; @@ -340,7 +340,7 @@ function updateAttachmentSize(renderPass: RenderPassDescriptor) if (!renderPass.attachmentSize) { const textureSize = getTextureSize(attachmentTextures[0]); - renderPass.attachmentSize = { width: textureSize[0], height: textureSize[1] }; + reactive(renderPass).attachmentSize = { width: textureSize[0], height: textureSize[1] }; } attachmentTextures.forEach((v) => setTextureSize(v, renderPass.attachmentSize)); } diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index c16aed6..ec313cd 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -300,7 +300,18 @@ function getDefaultGPUDepthStencilState(depthStencilFormat: GPUTextureFormat) let result = defaultGPUDepthStencilStates[depthStencilFormat]; if (result) return result; - result = defaultGPUDepthStencilStates[depthStencilFormat] = { format: depthStencilFormat }; + result = defaultGPUDepthStencilStates[depthStencilFormat] = { + format: depthStencilFormat, + depthWriteEnabled: true, + depthCompare: "less", + stencilFront: {}, + stencilBack: {}, + stencilReadMask: 0xFFFFFFFF, + stencilWriteMask: 0xFFFFFFFF, + depthBias: 0, + depthBiasSlopeScale: 0, + depthBiasClamp: 0, + }; return result; } diff --git a/src/data/polyfills/RenderPassDescriptor.ts b/src/data/polyfills/RenderPassDescriptor.ts index 9b00ef0..3170db6 100644 --- a/src/data/polyfills/RenderPassDescriptor.ts +++ b/src/data/polyfills/RenderPassDescriptor.ts @@ -16,14 +16,14 @@ declare module "@feng3d/render-api" * * 该值被修改后将会改变所有附件的尺寸,并释放附件上过时的GPU纹理资源。 */ - attachmentSize?: { width: number, height: number }; + readonly attachmentSize?: { readonly width: number, readonly height: number }; /** * The maximum number of draw calls that will be done in the render pass. Used by some * implementations to size work injected before the render pass. Keeping the default value * is a good default, unless it is known that more draw calls will be done. */ - maxDrawCount?: GPUSize64; + readonly maxDrawCount?: GPUSize64; } } -- Gitee From bdc71be08e0b98c24567be51888da4c42c6a3fe3 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 20:54:41 +0800 Subject: [PATCH 133/214] =?UTF-8?q?refactor(gpu):=20=E9=87=8D=E6=9E=84=20G?= =?UTF-8?q?PU=20=E7=BC=93=E5=AD=98=E5=92=8C=E7=BA=B9=E7=90=86=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化 getGPUCanvasContext 函数,使用 computed 和 reactive 优化响应式更新 - 重构 getGPUTexture 函数,采用 computed 函数封装纹理创建和更新逻辑 - 改进纹理更新机制,提高性能和可维护性 - 优化 GPUTexture_map 存储结构,提高缓存效率 --- src/caches/getGPUCanvasContext.ts | 44 ++-- src/caches/getGPUTexture.ts | 363 +++++++++++++++--------------- src/data/CanvasConfiguration.ts | 2 +- 3 files changed, 207 insertions(+), 202 deletions(-) diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index 4008e20..28844e4 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -8,35 +8,29 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) let result = getGPUCanvasContextMap.get(getGPUCanvasContextKey); if (result) return result.value; - const canvas = typeof context.canvasId === "string" ? document.getElementById(context.canvasId) as HTMLCanvasElement : context.canvasId; - - const gpuCanvasContext = canvas.getContext("webgpu") as GPUCanvasContext; - const ro = reactive(context); result = computed(() => { // 监听 - const configuration = ro.configuration; - if (configuration) - { - configuration.format; - configuration.usage; - configuration.viewFormats?.forEach(() => { }); - configuration.colorSpace; - configuration.toneMapping?.mode; - configuration.alphaMode; - } + const ro = reactive(context); + ro.canvasId; - // 执行 - updateConfigure(); + const canvas = typeof context.canvasId === "string" ? document.getElementById(context.canvasId) as HTMLCanvasElement : context.canvasId; - return gpuCanvasContext; - }); + const gpuCanvasContext = canvas.getContext("webgpu") as GPUCanvasContext; - getGPUCanvasContextMap.set(getGPUCanvasContextKey, result); + // 监听 + const r_configuration = ro.configuration; + if (r_configuration) + { + r_configuration.format; + r_configuration.usage; + r_configuration.viewFormats?.forEach(() => { }); + r_configuration.colorSpace; + r_configuration.toneMapping?.mode; + r_configuration.alphaMode; + } - const updateConfigure = () => - { - // + // 执行 const configuration = context.configuration || {}; const format = configuration.format || navigator.gpu.getPreferredCanvasFormat(); @@ -56,7 +50,11 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) usage, format, }); - }; + + return gpuCanvasContext; + }); + + getGPUCanvasContextMap.set(getGPUCanvasContextKey, result); return result.value; } diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 0dd657d..3b3a158 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { ChainMap, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; +import { ChainMap, computed, ComputedRef, reactive, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; @@ -16,13 +16,15 @@ import { getTextureUsageFromFormat } from "./getTextureUsageFromFormat"; */ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoCreate = true) { - let gpuTexture: GPUTexture; if ("context" in textureLike) { + // + reactive(device).preSubmit; + const canvasTexture = textureLike; const context = getGPUCanvasContext(device, canvasTexture.context); - gpuTexture = context.getCurrentTexture(); + const gpuTexture = context.getCurrentTexture(); return gpuTexture; } @@ -30,224 +32,229 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC const texture = textureLike as Texture; const getGPUTextureKey: GetGPUTextureMap = [device, texture]; - gpuTexture = getGPUTextureMap.get(getGPUTextureKey); - if (gpuTexture) return gpuTexture; + let result: ComputedRef = getGPUTextureMap.get(getGPUTextureKey); + if (result) return result.value; if (!autoCreate) return null; - // 创建纹理 - const createTexture = () => + result = computed(() => { - const { format, sampleCount, dimension, viewFormats } = texture as MultisampleTexture; - let { label, mipLevelCount } = texture; + let gpuTexture: GPUTexture; + // 创建纹理 + const createTexture = () => + { + const { format, sampleCount, dimension, viewFormats } = texture as MultisampleTexture; + let { label, mipLevelCount } = texture; - const size = texture.size; - console.assert(!!size, `无法从纹理中获取到正确的尺寸!size与source必须设置一个!`, texture); + const size = texture.size; + console.assert(!!size, `无法从纹理中获取到正确的尺寸!size与source必须设置一个!`, texture); - const usage = getTextureUsageFromFormat(device, format, sampleCount); + const usage = getTextureUsageFromFormat(device, format, sampleCount); - // 当需要生成 mipmap 并且 mipLevelCount 并未赋值时,将自动计算 可生成的 mipmap 数量。 - if (texture.generateMipmap && mipLevelCount === undefined) - { - // - const maxSize = Math.max(size[0], size[1]); - mipLevelCount = 1 + Math.log2(maxSize) | 0; - } - mipLevelCount = (texture as any).mipLevelCount = mipLevelCount || 1; - - if (label === undefined) - { - label = `GPUTexture ${autoIndex++}`; - } + // 当需要生成 mipmap 并且 mipLevelCount 并未赋值时,将自动计算 可生成的 mipmap 数量。 + if (texture.generateMipmap && mipLevelCount === undefined) + { + // + const maxSize = Math.max(size[0], size[1]); + mipLevelCount = 1 + Math.log2(maxSize) | 0; + } + mipLevelCount = (texture as any).mipLevelCount = mipLevelCount || 1; - const textureDimension = getGPUTextureDimension(dimension); - - gpuTexture = device.createTexture({ - label, - size, - mipLevelCount, - sampleCount, - dimension: textureDimension, - format, - usage, - viewFormats, - }); - - getGPUTextureMap.set(getGPUTextureKey, gpuTexture); - }; - createTexture(); - - // 更新纹理 - const updateSources = () => - { - if (texture.sources) - { - const writeTextures: TextureSource[] = []; - texture.sources.forEach((v) => + if (label === undefined) { - writeTextures.push(v); + label = `GPUTexture ${autoIndex++}`; + } + + const textureDimension = getGPUTextureDimension(dimension); + + gpuTexture = device.createTexture({ + label, + size, + mipLevelCount, + sampleCount, + dimension: textureDimension, + format, + usage, + viewFormats, }); - texture.writeTextures = writeTextures.concat(texture.writeTextures || []); - } - }; - updateSources(); - watcher.watch(texture, "sources", updateSources); + }; + createTexture(); - const updateWriteTextures = () => - { - if (texture.writeTextures) + // 更新纹理 + const updateSources = () => { - texture.writeTextures.forEach((v) => + if (texture.sources) { - // 处理图片纹理 - const imageSource = v as TextureImageSource; - if (imageSource.image) + const writeTextures: TextureSource[] = []; + texture.sources.forEach((v) => { - const { image, flipY, colorSpace, premultipliedAlpha, mipLevel, textureOrigin, aspect } = imageSource; - - // - const imageSize = TextureImageSource.getTexImageSourceSize(imageSource.image); - const copySize = imageSource.size || imageSize; - - let imageOrigin = imageSource.imageOrigin; + writeTextures.push(v); + }); + texture.writeTextures = writeTextures.concat(texture.writeTextures || []); + } + }; + updateSources(); + watcher.watch(texture, "sources", updateSources); - // 转换为WebGPU翻转模式 - if (flipY) + const updateWriteTextures = () => + { + if (texture.writeTextures) + { + texture.writeTextures.forEach((v) => + { + // 处理图片纹理 + const imageSource = v as TextureImageSource; + if (imageSource.image) { - const x = imageOrigin?.[0]; - let y = imageOrigin?.[1]; - - y = imageSize[1] - y - copySize[1]; - - imageOrigin = [x, y]; + const { image, flipY, colorSpace, premultipliedAlpha, mipLevel, textureOrigin, aspect } = imageSource; + + // + const imageSize = TextureImageSource.getTexImageSourceSize(imageSource.image); + const copySize = imageSource.size || imageSize; + + let imageOrigin = imageSource.imageOrigin; + + // 转换为WebGPU翻转模式 + if (flipY) + { + const x = imageOrigin?.[0]; + let y = imageOrigin?.[1]; + + y = imageSize[1] - y - copySize[1]; + + imageOrigin = [x, y]; + } + + // + const gpuSource: GPUImageCopyExternalImage = { + source: image, + origin: imageOrigin, + flipY, + }; + + // + const gpuDestination: GPUImageCopyTextureTagged = { + colorSpace, + premultipliedAlpha, + mipLevel, + origin: textureOrigin, + aspect, + texture: gpuTexture, + }; + + device.queue.copyExternalImageToTexture( + gpuSource, + gpuDestination, + copySize + ); + + return; } - // - const gpuSource: GPUImageCopyExternalImage = { - source: image, - origin: imageOrigin, - flipY, - }; + // 处理数据纹理 + const bufferSource = v as TextureDataSource; + const { data, dataLayout, dataImageOrigin, size, mipLevel, textureOrigin, aspect } = bufferSource; - // - const gpuDestination: GPUImageCopyTextureTagged = { - colorSpace, - premultipliedAlpha, + const gpuDestination: GPUImageCopyTexture = { mipLevel, origin: textureOrigin, aspect, texture: gpuTexture, }; - device.queue.copyExternalImageToTexture( - gpuSource, + // 计算 WebGPU 中支持的参数 + const offset = dataLayout?.offset || 0; + const width = dataLayout?.width || size[0]; + const height = dataLayout?.height || size[1]; + const x = dataImageOrigin?.[0] || 0; + const y = dataImageOrigin?.[1] || 0; + const depthOrArrayLayers = dataImageOrigin?.[2] || 0; + + // 获取纹理每个像素对应的字节数量。 + const bytesPerPixel = Texture.getTextureBytesPerPixel(texture.format); + + // 计算偏移 + const gpuOffset + = (offset || 0) // 头部 + + (depthOrArrayLayers || 0) * (width * height * bytesPerPixel) // 读取第几张图片 + + (x + (y * width)) * bytesPerPixel // 读取图片位置 + ; + + const gpuDataLayout: GPUImageDataLayout = { + offset: gpuOffset, + bytesPerRow: width * bytesPerPixel, + rowsPerImage: height, + }; + + device.queue.writeTexture( gpuDestination, - copySize + data, + gpuDataLayout, + size, ); + }); + texture.writeTextures = null; + } + }; + + updateWriteTextures(); + watcher.watch(texture, "writeTextures", updateWriteTextures); + // 监听纹理尺寸发生变化 + const resize = (newValue: TextureSize, oldValue: TextureSize) => + { + if (!!newValue && !!oldValue) + { + if (newValue[0] === oldValue[0] + && newValue[1] === oldValue[1] + && (newValue[2] || 1) === (oldValue[2] || 1) + ) + { return; } + } - // 处理数据纹理 - const bufferSource = v as TextureDataSource; - const { data, dataLayout, dataImageOrigin, size, mipLevel, textureOrigin, aspect } = bufferSource; - - const gpuDestination: GPUImageCopyTexture = { - mipLevel, - origin: textureOrigin, - aspect, - texture: gpuTexture, - }; - - // 计算 WebGPU 中支持的参数 - const offset = dataLayout?.offset || 0; - const width = dataLayout?.width || size[0]; - const height = dataLayout?.height || size[1]; - const x = dataImageOrigin?.[0] || 0; - const y = dataImageOrigin?.[1] || 0; - const depthOrArrayLayers = dataImageOrigin?.[2] || 0; - - // 获取纹理每个像素对应的字节数量。 - const bytesPerPixel = Texture.getTextureBytesPerPixel(texture.format); - - // 计算偏移 - const gpuOffset - = (offset || 0) // 头部 - + (depthOrArrayLayers || 0) * (width * height * bytesPerPixel) // 读取第几张图片 - + (x + (y * width)) * bytesPerPixel // 读取图片位置 - ; - - const gpuDataLayout: GPUImageDataLayout = { - offset: gpuOffset, - bytesPerRow: width * bytesPerPixel, - rowsPerImage: height, - }; - - device.queue.writeTexture( - gpuDestination, - data, - gpuDataLayout, - size, - ); - }); - texture.writeTextures = null; - } - }; - - updateWriteTextures(); - watcher.watch(texture, "writeTextures", updateWriteTextures); + gpuTexture.destroy(); + // + anyEmitter.emit(texture, IGPUTexture_resize); + }; + watcher.watch(texture, "size", resize); - // 监听纹理尺寸发生变化 - const resize = (newValue: TextureSize, oldValue: TextureSize) => - { - if (!!newValue && !!oldValue) + // 自动生成 mipmap。 + if (texture.generateMipmap) { - if (newValue[0] === oldValue[0] - && newValue[1] === oldValue[1] - && (newValue[2] || 1) === (oldValue[2] || 1) - ) - { - return; - } + generateMipmap(device, gpuTexture); } - gpuTexture.destroy(); // - anyEmitter.emit(texture, IGPUTexture_resize); - }; - watcher.watch(texture, "size", resize); - - // 自动生成 mipmap。 - if (texture.generateMipmap) - { - generateMipmap(device, gpuTexture); - } - - // - ((oldDestroy) => - { - gpuTexture.destroy = () => + ((oldDestroy) => { - oldDestroy.apply(gpuTexture); - // - getGPUTextureMap.delete(getGPUTextureKey); - // - watcher.unwatch(texture, "size", resize); - watcher.unwatch(texture, "sources", updateSources); - watcher.unwatch(texture, "writeTextures", updateWriteTextures); + gpuTexture.destroy = () => + { + oldDestroy.apply(gpuTexture); + // + getGPUTextureMap.delete(getGPUTextureKey); + // + watcher.unwatch(texture, "size", resize); + watcher.unwatch(texture, "sources", updateSources); + watcher.unwatch(texture, "writeTextures", updateWriteTextures); - // 派发销毁事件 - anyEmitter.emit(gpuTexture, GPUTexture_destroy); + // 派发销毁事件 + anyEmitter.emit(gpuTexture, GPUTexture_destroy); - return undefined; - }; - })(gpuTexture.destroy); + return undefined; + }; + })(gpuTexture.destroy); + + return gpuTexture; + }); + getGPUTextureMap.set(getGPUTextureKey, result); - return gpuTexture; + return result.value; } let autoIndex = 0; type GetGPUTextureMap = [device: GPUDevice, texture: Texture]; -const getGPUTextureMap = new ChainMap; +const getGPUTextureMap = new ChainMap>; function getGPUTextureDimension(dimension: TextureDimension) { diff --git a/src/data/CanvasConfiguration.ts b/src/data/CanvasConfiguration.ts index 36c77ad..fcad96c 100644 --- a/src/data/CanvasConfiguration.ts +++ b/src/data/CanvasConfiguration.ts @@ -35,7 +35,7 @@ export interface CanvasConfiguration * The formats that views created from textures returned by * {@link GPUCanvasContext#getCurrentTexture} may use. */ - readonly viewFormats?: GPUTextureFormat[]; + readonly viewFormats?: readonly GPUTextureFormat[]; /** * The color space that values written into textures returned by -- Gitee From a7079b44d1b2587becec977c8decd3720f1207fb Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 21:40:58 +0800 Subject: [PATCH 134/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E4=BA=8B=E4=BB=B6=E5=A4=84=E7=90=86=E6=9C=BA?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 GPUDevice 接口中的 preSubmit 属性 - 创建 webgpuEvents 对象统一管理 WebGPU 相关事件 - 更新 getGPUTexture 函数,使用 webgpuEvents.preSubmit 代替设备特定的 preSubmit - 优化 WebGPUBase 类中的 submit 方法,增加对 webgpuEvents.preSubmit 的处理 --- src/WebGPUBase.ts | 27 ++++---------------------- src/caches/getGPUTexture.ts | 38 ++++++++++++++++++------------------- src/eventnames.ts | 22 ++++++++++++++++++++- 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index dc302da..e099938 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -19,32 +19,13 @@ import { ComputePass } from "./data/ComputePass"; import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; -import { GPUQueue_submit } from "./eventnames"; +import { GPUQueue_submit, webgpuEvents } from "./eventnames"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; -declare global -{ - interface GPUDevice - { - /** - * 提交WebGPU前数值加一。 - * - * 用于处理提交前需要执行的操作。 - * - * 例如 {@link GPUCanvasContext.getCurrentTexture} 与 {@linkGPUDevice.importExternalTexture } 需要在提交前执行,检查结果是否变化。 - * - * 注:引擎内部处理,外部无需关心。 - * - * @private - */ - readonly preSubmit: number; - } -} - /** * WebGPU 基础类 */ @@ -79,8 +60,6 @@ export class WebGPUBase set device(v) { this._device = v; - - this._device && (reactive(this._device).preSubmit ??= 0); } protected _device: GPUDevice; @@ -92,9 +71,11 @@ export class WebGPUBase submit(submit: Submit) { const device = this._device; + // 提交前数值加一,用于处理提交前需要执行的操作。 - reactive(device).preSubmit++; + reactive(webgpuEvents).preSubmit = ~~reactive(webgpuEvents).preSubmit + 1; + // const commandBuffers = submit.commandEncoders.map((v) => { const commandBuffer = this.runCommandEncoder(v); diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 3b3a158..4574b29 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,7 +1,7 @@ import { anyEmitter } from "@feng3d/event"; -import { ChainMap, computed, ComputedRef, reactive, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; +import { ChainMap, computed, ComputedRef, effect, reactive, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; +import { webgpuEvents, GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { generateMipmap } from "../utils/generate-mipmap"; import { getGPUCanvasContext } from "./getGPUCanvasContext"; @@ -16,22 +16,7 @@ import { getTextureUsageFromFormat } from "./getTextureUsageFromFormat"; */ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoCreate = true) { - if ("context" in textureLike) - { - // - reactive(device).preSubmit; - - const canvasTexture = textureLike; - const context = getGPUCanvasContext(device, canvasTexture.context); - - const gpuTexture = context.getCurrentTexture(); - - return gpuTexture; - } - - const texture = textureLike as Texture; - - const getGPUTextureKey: GetGPUTextureMap = [device, texture]; + const getGPUTextureKey: GetGPUTextureMap = [device, textureLike]; let result: ComputedRef = getGPUTextureMap.get(getGPUTextureKey); if (result) return result.value; @@ -39,6 +24,21 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC result = computed(() => { + if ("context" in textureLike) + { + // + reactive(webgpuEvents).preSubmit; + + const canvasTexture = textureLike; + const context = getGPUCanvasContext(device, canvasTexture.context); + + const gpuTexture = context.getCurrentTexture(); + + return gpuTexture; + } + + const texture = textureLike as Texture; + let gpuTexture: GPUTexture; // 创建纹理 const createTexture = () => @@ -253,7 +253,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC return result.value; } let autoIndex = 0; -type GetGPUTextureMap = [device: GPUDevice, texture: Texture]; +type GetGPUTextureMap = [device: GPUDevice, texture: TextureLike]; const getGPUTextureMap = new ChainMap>; function getGPUTextureDimension(dimension: TextureDimension) diff --git a/src/eventnames.ts b/src/eventnames.ts index 036ab32..971cc37 100644 --- a/src/eventnames.ts +++ b/src/eventnames.ts @@ -11,4 +11,24 @@ export const GPUQueue_submit = "GPUQueue_submit"; export const IGPUTexture_resize = "IGPUTexture_resize"; -export const IGPUSampler_changed = "IGPUSampler_changed"; \ No newline at end of file +export const IGPUSampler_changed = "IGPUSampler_changed"; + +/** + * 通过反应式机制更改数值来触发事件。 + */ +export const webgpuEvents: { + /** + * 提交WebGPU前数值加一。 + * + * 用于处理提交前需要执行的操作。 + * + * 例如 {@link GPUCanvasContext.getCurrentTexture} 与 {@linkGPUDevice.importExternalTexture } 需要在提交前执行,检查结果是否变化。 + * + * 注:引擎内部处理,外部无需关心。 + * + * @private + */ + readonly preSubmit: number; +} = { + preSubmit: 0, +}; \ No newline at end of file -- Gitee From 3654ddeb947a1f6581b167a3fc25f68b1c9ffc50 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 21:59:20 +0800 Subject: [PATCH 135/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20getGPUTextureView=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 computed 和 reactive 优化缓存逻辑 - 提高代码的可读性和性能 - 改进纹理视图的创建和销毁处理 --- src/caches/getGPUTextureView.ts | 55 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index 097a9ee..83e2f34 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -1,43 +1,40 @@ import { anyEmitter } from "@feng3d/event"; -import { CanvasTexture, ChainMap, Texture, TextureView } from "@feng3d/render-api"; +import { ChainMap, computed, ComputedRef, reactive, Texture, TextureView } from "@feng3d/render-api"; import { GPUTexture_destroy, GPUTextureView_destroy } from "../eventnames"; import { getGPUTexture } from "./getGPUTexture"; export function getGPUTextureView(device: GPUDevice, view: TextureView) { - if ((view.texture as CanvasTexture).context) - { - const texture = getGPUTexture(device, view.texture); - - const textureView = texture.createView(view); - - return textureView; - // texture["view"] = texture["view"] || texture.createView(); - - // return texture["view"]; - } - - // const getGPUTextureViewKey: GetGPUTextureViewKey = [device, view]; - let textureView = getGPUTextureViewMap.get(getGPUTextureViewKey); - if (textureView) return textureView; - - // - const texture = view.texture as Texture; - const gpuTexture = getGPUTexture(device, texture); - const dimension = view.dimension ?? texture.dimension; + let result = getGPUTextureViewMap.get(getGPUTextureViewKey); + if (result) return result.value; - textureView = gpuTexture.createView({ ...view, dimension }); - getGPUTextureViewMap.set(getGPUTextureViewKey, textureView); - // 销毁纹理时清除对应的纹理视图。 - anyEmitter.once(gpuTexture, GPUTexture_destroy, () => + result = computed(() => { - getGPUTextureViewMap.delete(getGPUTextureViewKey); - anyEmitter.emit(textureView, GPUTextureView_destroy); + // 监听 + const r_view = reactive(view); + r_view.texture; + + // 执行 + const { texture } = view; + const gpuTexture = getGPUTexture(device, texture); + const textureView = gpuTexture.createView({ + ...r_view, + dimension: r_view.dimension ?? (texture as Texture).dimension, + }); + // 销毁纹理时清除对应的纹理视图。 + anyEmitter.once(gpuTexture, GPUTexture_destroy, () => + { + getGPUTextureViewMap.delete(getGPUTextureViewKey); + anyEmitter.emit(textureView, GPUTextureView_destroy); + }); + + return textureView; }); + getGPUTextureViewMap.set(getGPUTextureViewKey, result); - return textureView; + return result.value; } type GetGPUTextureViewKey = [device: GPUDevice, view: TextureView]; -const getGPUTextureViewMap = new ChainMap; +const getGPUTextureViewMap = new ChainMap>; -- Gitee From 2cb8f4deca4db55e54c9875f85c661fe376fa10e Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 19 Mar 2025 22:52:16 +0800 Subject: [PATCH 136/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E5=88=9B=E5=BB=BA=E5=92=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化了纹理创建流程,将相关代码组织得更清晰 - 新增 updateSources 和 updateWriteTextures 函数,用于更新纹理内容 - 改进了 mipmap 生成逻辑,自动计算 mipmap 数量 - 调整了纹理尺寸变化时的处理方式 - 优化了纹理资源的管理和监听机制 --- .../src/webgpu/samplerParameters/index.ts | 13 +- src/caches/getGPUTexture.ts | 358 ++++++++++-------- 2 files changed, 197 insertions(+), 174 deletions(-) diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index 9fcb6ec..bf003a1 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -229,12 +229,6 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const kTextureMipLevels = 4; const kTextureBaseSize = 16; - const checkerboard: Texture = { - format: "rgba8unorm", - size: [kTextureBaseSize, kTextureBaseSize], - mipLevelCount: 4, - }; - const kColorForLevel = [ [255, 255, 255, 255], [30, 136, 229, 255], // blue @@ -264,7 +258,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => size: [size, size] }); } - checkerboard.sources = writeTextures; + const checkerboard: Texture = { + format: "rgba8unorm", + size: [kTextureBaseSize, kTextureBaseSize], + mipLevelCount: 4, + sources: writeTextures + }; // // "Debug" view of the actual texture contents diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 4574b29..f451c64 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,7 +1,7 @@ import { anyEmitter } from "@feng3d/event"; -import { ChainMap, computed, ComputedRef, effect, reactive, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; +import { ChainMap, computed, ComputedRef, reactive, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; -import { webgpuEvents, GPUTexture_destroy, IGPUTexture_resize } from "../eventnames"; +import { GPUTexture_destroy, IGPUTexture_resize, webgpuEvents } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { generateMipmap } from "../utils/generate-mipmap"; import { getGPUCanvasContext } from "./getGPUCanvasContext"; @@ -17,7 +17,7 @@ import { getTextureUsageFromFormat } from "./getTextureUsageFromFormat"; export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoCreate = true) { const getGPUTextureKey: GetGPUTextureMap = [device, textureLike]; - let result: ComputedRef = getGPUTextureMap.get(getGPUTextureKey); + let result = getGPUTextureMap.get(getGPUTextureKey); if (result) return result.value; if (!autoCreate) return null; @@ -37,168 +37,66 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC return gpuTexture; } - const texture = textureLike as Texture; - - let gpuTexture: GPUTexture; - // 创建纹理 - const createTexture = () => + const texture = textureLike as MultisampleTexture; + // 监听 + const r_texture = reactive(texture); + r_texture.format; + r_texture.sampleCount; + r_texture.dimension; + r_texture.viewFormats; + r_texture.generateMipmap; + r_texture.mipLevelCount; + r_texture.size[0]; + r_texture.size[1]; + r_texture.size[2]; + + // 执行 + const { format, sampleCount, dimension, viewFormats } = texture; + let { label, mipLevelCount } = texture; + + const size = texture.size; + console.assert(!!size, `无法从纹理中获取到正确的尺寸!size与source必须设置一个!`, texture); + + const usage = getTextureUsageFromFormat(device, format, sampleCount); + + // 当需要生成 mipmap 并且 mipLevelCount 并未赋值时,将自动计算 可生成的 mipmap 数量。 + if (texture.generateMipmap && mipLevelCount === undefined) { - const { format, sampleCount, dimension, viewFormats } = texture as MultisampleTexture; - let { label, mipLevelCount } = texture; - - const size = texture.size; - console.assert(!!size, `无法从纹理中获取到正确的尺寸!size与source必须设置一个!`, texture); - - const usage = getTextureUsageFromFormat(device, format, sampleCount); - - // 当需要生成 mipmap 并且 mipLevelCount 并未赋值时,将自动计算 可生成的 mipmap 数量。 - if (texture.generateMipmap && mipLevelCount === undefined) - { - // - const maxSize = Math.max(size[0], size[1]); - mipLevelCount = 1 + Math.log2(maxSize) | 0; - } - mipLevelCount = (texture as any).mipLevelCount = mipLevelCount || 1; - - if (label === undefined) - { - label = `GPUTexture ${autoIndex++}`; - } + // + const maxSize = Math.max(size[0], size[1]); + mipLevelCount = 1 + Math.log2(maxSize) | 0; + } + mipLevelCount = mipLevelCount ?? 1; - const textureDimension = getGPUTextureDimension(dimension); + if (label === undefined) + { + label = `GPUTexture ${autoIndex++}`; + } - gpuTexture = device.createTexture({ - label, - size, - mipLevelCount, - sampleCount, - dimension: textureDimension, - format, - usage, - viewFormats, - }); - }; - createTexture(); + const textureDimension = getGPUTextureDimension(dimension); - // 更新纹理 - const updateSources = () => - { - if (texture.sources) - { - const writeTextures: TextureSource[] = []; - texture.sources.forEach((v) => - { - writeTextures.push(v); - }); - texture.writeTextures = writeTextures.concat(texture.writeTextures || []); - } - }; - updateSources(); - watcher.watch(texture, "sources", updateSources); + // 创建纹理 + const gpuTexture = device.createTexture({ + label, + size, + mipLevelCount, + sampleCount, + dimension: textureDimension, + format, + usage, + viewFormats, + }); + textureMap.set(texture, gpuTexture); + + // 初始化纹理内容 + updateSources(texture); + updateWriteTextures(device, gpuTexture, texture); - const updateWriteTextures = () => + // 自动生成 mipmap。 + if (texture.generateMipmap) { - if (texture.writeTextures) - { - texture.writeTextures.forEach((v) => - { - // 处理图片纹理 - const imageSource = v as TextureImageSource; - if (imageSource.image) - { - const { image, flipY, colorSpace, premultipliedAlpha, mipLevel, textureOrigin, aspect } = imageSource; - - // - const imageSize = TextureImageSource.getTexImageSourceSize(imageSource.image); - const copySize = imageSource.size || imageSize; - - let imageOrigin = imageSource.imageOrigin; - - // 转换为WebGPU翻转模式 - if (flipY) - { - const x = imageOrigin?.[0]; - let y = imageOrigin?.[1]; - - y = imageSize[1] - y - copySize[1]; - - imageOrigin = [x, y]; - } - - // - const gpuSource: GPUImageCopyExternalImage = { - source: image, - origin: imageOrigin, - flipY, - }; - - // - const gpuDestination: GPUImageCopyTextureTagged = { - colorSpace, - premultipliedAlpha, - mipLevel, - origin: textureOrigin, - aspect, - texture: gpuTexture, - }; - - device.queue.copyExternalImageToTexture( - gpuSource, - gpuDestination, - copySize - ); - - return; - } - - // 处理数据纹理 - const bufferSource = v as TextureDataSource; - const { data, dataLayout, dataImageOrigin, size, mipLevel, textureOrigin, aspect } = bufferSource; - - const gpuDestination: GPUImageCopyTexture = { - mipLevel, - origin: textureOrigin, - aspect, - texture: gpuTexture, - }; - - // 计算 WebGPU 中支持的参数 - const offset = dataLayout?.offset || 0; - const width = dataLayout?.width || size[0]; - const height = dataLayout?.height || size[1]; - const x = dataImageOrigin?.[0] || 0; - const y = dataImageOrigin?.[1] || 0; - const depthOrArrayLayers = dataImageOrigin?.[2] || 0; - - // 获取纹理每个像素对应的字节数量。 - const bytesPerPixel = Texture.getTextureBytesPerPixel(texture.format); - - // 计算偏移 - const gpuOffset - = (offset || 0) // 头部 - + (depthOrArrayLayers || 0) * (width * height * bytesPerPixel) // 读取第几张图片 - + (x + (y * width)) * bytesPerPixel // 读取图片位置 - ; - - const gpuDataLayout: GPUImageDataLayout = { - offset: gpuOffset, - bytesPerRow: width * bytesPerPixel, - rowsPerImage: height, - }; - - device.queue.writeTexture( - gpuDestination, - data, - gpuDataLayout, - size, - ); - }); - texture.writeTextures = null; - } - }; - - updateWriteTextures(); - watcher.watch(texture, "writeTextures", updateWriteTextures); + generateMipmap(device, gpuTexture); + } // 监听纹理尺寸发生变化 const resize = (newValue: TextureSize, oldValue: TextureSize) => @@ -220,12 +118,6 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC }; watcher.watch(texture, "size", resize); - // 自动生成 mipmap。 - if (texture.generateMipmap) - { - generateMipmap(device, gpuTexture); - } - // ((oldDestroy) => { @@ -236,8 +128,6 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC getGPUTextureMap.delete(getGPUTextureKey); // watcher.unwatch(texture, "size", resize); - watcher.unwatch(texture, "sources", updateSources); - watcher.unwatch(texture, "writeTextures", updateWriteTextures); // 派发销毁事件 anyEmitter.emit(gpuTexture, GPUTexture_destroy); @@ -256,6 +146,140 @@ let autoIndex = 0; type GetGPUTextureMap = [device: GPUDevice, texture: TextureLike]; const getGPUTextureMap = new ChainMap>; +const textureMap = new WeakMap(); + +/** + * 更新纹理 + * @param texture + */ +function updateSources(texture: Texture) +{ + computed(() => + { + const r_texture = reactive(texture); + r_texture.sources; + + if (!texture.sources) return; + + const writeTextures: TextureSource[] = []; + texture.sources.forEach((v) => + { + writeTextures.push(v); + }); + reactive(texture).writeTextures = writeTextures.concat(texture.writeTextures || []); + }).value; +}; + +function updateWriteTextures(device: GPUDevice, gpuTexture: GPUTexture, texture: Texture) +{ + computed(() => + { + // 监听 + const r_texture = reactive(texture) + r_texture.writeTextures + + // 执行 + if (!texture.writeTextures) return; + + const { writeTextures, format } = texture; + reactive(texture).writeTextures = null; + + writeTextures.forEach((v) => + { + // 处理图片纹理 + const imageSource = v as TextureImageSource; + if (imageSource.image) + { + const { image, flipY, colorSpace, premultipliedAlpha, mipLevel, textureOrigin, aspect } = imageSource; + + // + const imageSize = TextureImageSource.getTexImageSourceSize(imageSource.image); + const copySize = imageSource.size || imageSize; + + let imageOrigin = imageSource.imageOrigin; + + // 转换为WebGPU翻转模式 + if (flipY) + { + const x = imageOrigin?.[0]; + let y = imageOrigin?.[1]; + + y = imageSize[1] - y - copySize[1]; + + imageOrigin = [x, y]; + } + + // + const gpuSource: GPUImageCopyExternalImage = { + source: image, + origin: imageOrigin, + flipY, + }; + + // + const gpuDestination: GPUImageCopyTextureTagged = { + colorSpace, + premultipliedAlpha, + mipLevel, + origin: textureOrigin, + aspect, + texture: gpuTexture, + }; + + device.queue.copyExternalImageToTexture( + gpuSource, + gpuDestination, + copySize + ); + + return; + } + + // 处理数据纹理 + const bufferSource = v as TextureDataSource; + const { data, dataLayout, dataImageOrigin, size, mipLevel, textureOrigin, aspect } = bufferSource; + + const gpuDestination: GPUImageCopyTexture = { + mipLevel, + origin: textureOrigin, + aspect, + texture: gpuTexture, + }; + + // 计算 WebGPU 中支持的参数 + const offset = dataLayout?.offset || 0; + const width = dataLayout?.width || size[0]; + const height = dataLayout?.height || size[1]; + const x = dataImageOrigin?.[0] || 0; + const y = dataImageOrigin?.[1] || 0; + const depthOrArrayLayers = dataImageOrigin?.[2] || 0; + + // 获取纹理每个像素对应的字节数量。 + const bytesPerPixel = Texture.getTextureBytesPerPixel(format); + + // 计算偏移 + const gpuOffset + = (offset || 0) // 头部 + + (depthOrArrayLayers || 0) * (width * height * bytesPerPixel) // 读取第几张图片 + + (x + (y * width)) * bytesPerPixel // 读取图片位置 + ; + + const gpuDataLayout: GPUImageDataLayout = { + offset: gpuOffset, + bytesPerRow: width * bytesPerPixel, + rowsPerImage: height, + }; + + device.queue.writeTexture( + gpuDestination, + data, + gpuDataLayout, + size, + ); + }); + }).value; +}; + function getGPUTextureDimension(dimension: TextureDimension) { const textureDimension = dimensionMap[dimension]; -- Gitee From cea2e671e4403b711b9c3a5633d322a0f2996f41 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 00:18:53 +0800 Subject: [PATCH 137/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20WebGPU=20=E7=BC=93=E5=AD=98=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了不必要的事件监听和销毁逻辑 - 优化了纹理和渲染通道的创建和管理 - 使用 computed 和 reactive 代替手动更新逻辑 - 删除了未使用的事件名称 --- src/caches/getGPUBindGroup.ts | 5 - src/caches/getGPURenderPassDescriptor.ts | 224 ++++++++++++----------- src/caches/getGPUTexture.ts | 50 +---- src/caches/getGPUTextureView.ts | 10 +- src/eventnames.ts | 11 -- 5 files changed, 129 insertions(+), 171 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 9825373..78f2b57 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,10 +1,8 @@ -import { anyEmitter } from "@feng3d/event"; import { BindingResource, BindingResources, BufferBinding, BufferBindingInfo, CanvasTexture, ChainMap, Sampler, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { ResourceType } from "wgsl_reflect"; import { getRealGPUBindGroup } from "../const"; import { VideoTexture } from "../data/VideoTexture"; -import { GPUTextureView_destroy, IGPUSampler_changed } from "../eventnames"; import { ExternalSampledTextureType } from "../types/TextureType"; import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; import { updateBufferBinding } from "../utils/updateBufferBinding"; @@ -85,8 +83,6 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup updateResource = () => { entry.resource = getGPUTextureView(device, bindingResources[name] as TextureView); - - anyEmitter.once(entry.resource, GPUTextureView_destroy, onResourceChanged); }; if (((bindingResources[name] as TextureView).texture as CanvasTexture).context) @@ -99,7 +95,6 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup updateResource = () => { entry.resource = getGPUSampler(device, bindingResources[name] as Sampler); - anyEmitter.once(bindingResources[name] as Sampler, IGPUSampler_changed, onResourceChanged); }; } diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index fd6b77c..91de06c 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,7 +1,4 @@ -import { anyEmitter } from "@feng3d/event"; -import { CanvasTexture, ChainMap, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; -import { IGPUTexture_resize } from "../eventnames"; +import { CanvasTexture, ChainMap, computed, ComputedRef, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { NGPURenderPassColorAttachment } from "../internal/internal"; import { getGPUTextureFormat } from "./getGPUTextureFormat"; @@ -18,108 +15,53 @@ import { getTextureSize } from "./getTextureSize"; export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: RenderPassDescriptor): GPURenderPassDescriptor { const getGPURenderPassDescriptorKey: GetGPURenderPassDescriptorKey = [device, descriptor]; - let renderPassDescriptor = getGPURenderPassDescriptorMap.get(getGPURenderPassDescriptorKey); - if (renderPassDescriptor) - { - // 执行更新函数。 - (renderPassDescriptor["_updates"] as Function[]).forEach((v) => v()); - - return renderPassDescriptor; - } - - renderPassDescriptor = { colorAttachments: [] }; - getGPURenderPassDescriptorMap.set(getGPURenderPassDescriptorKey, renderPassDescriptor); - - const _updates: Function[] = renderPassDescriptor["_updates"] = []; - - // 更新渲染通道附件尺寸,使得附件上纹理尺寸一致。 - updateAttachmentSize(descriptor); + let result = getGPURenderPassDescriptorMap.get(getGPURenderPassDescriptorKey); + if (result) return result.value; - // 获取颜色附件完整描述列表。 - const colorAttachments = getIGPURenderPassColorAttachments(descriptor.colorAttachments, descriptor.sampleCount); + const renderPassDescriptor: GPURenderPassDescriptor = {} as any; - // 获取深度模板附件 - const depthStencilAttachment = getIGPURenderPassDepthStencilAttachment(descriptor.depthStencilAttachment, descriptor.attachmentSize, descriptor.sampleCount); - - // 附件尺寸变化时,渲染通道描述失效。 - const watchProperty = { attachmentSize: { width: 0, height: 0 } }; // 被监听的属性 - watcher.watchobject(descriptor, watchProperty, () => + result = computed(() => { - // 由于深度纹理与多重采样纹理可能是引擎自动生成的,这部分纹理需要更新。 - setIGPURenderPassAttachmentSize(colorAttachments, depthStencilAttachment, descriptor.attachmentSize); - }); + // // 更新渲染通道附件尺寸,使得附件上纹理尺寸一致。 + // updateAttachmentSize(descriptor); - colorAttachments?.forEach((v, i) => - { - if (!v) return; + // 获取颜色附件完整描述列表。 + renderPassDescriptor.colorAttachments = getIGPURenderPassColorAttachments(device, descriptor); - const { clearValue, loadOp, storeOp } = v; + // 获取深度模板附件 + const depthStencilAttachment = getIGPURenderPassDepthStencilAttachment(descriptor.depthStencilAttachment, descriptor.attachmentSize, descriptor.sampleCount); - const attachment: GPURenderPassColorAttachment = { - ...v, - view: undefined, - resolveTarget: undefined, - clearValue, - loadOp, - storeOp, - }; + // // 更新尺寸 + // computed(() => + // { + // // 监听 + // const r_descriptor = reactive(descriptor); + // r_descriptor.attachmentSize.width; + // r_descriptor.attachmentSize.height; - const updateView = () => - { - attachment.view = getGPUTextureView(device, v.view); - }; - updateView(); + // // 执行 + // setIGPURenderPassAttachmentSize(colorAttachments, depthStencilAttachment, descriptor.attachmentSize); + // }).value; - // - if ((v.view.texture as CanvasTexture).context) + if (depthStencilAttachment) { - _updates.push(updateView); - } - anyEmitter.on(v.view.texture, IGPUTexture_resize, updateView); + const v = depthStencilAttachment; - // - if (v.resolveTarget) - { - const updateResolveTarget = () => - { - attachment.resolveTarget = getGPUTextureView(device, v.resolveTarget); + renderPassDescriptor.depthStencilAttachment = { + ...v, + view: getGPUTextureView(device, v.view), }; - updateResolveTarget(); - // - if ((v.resolveTarget?.texture as CanvasTexture)?.context) - { - _updates.push(updateResolveTarget); - } - anyEmitter.on(v.resolveTarget.texture, IGPUTexture_resize, updateResolveTarget); } - // - renderPassDescriptor.colorAttachments[i] = attachment; + return renderPassDescriptor; }); + getGPURenderPassDescriptorMap.set(getGPURenderPassDescriptorKey, result); - if (depthStencilAttachment) - { - const v = depthStencilAttachment; - - renderPassDescriptor.depthStencilAttachment = { - ...v, - view: undefined, - }; - - const updateView = () => - { - renderPassDescriptor.depthStencilAttachment.view = getGPUTextureView(device, v.view); - }; - updateView(); - - anyEmitter.on(v.view.texture, IGPUTexture_resize, updateView); - } - - return renderPassDescriptor; + return result.value; } type GetGPURenderPassDescriptorKey = [device: GPUDevice, descriptor: RenderPassDescriptor]; -const getGPURenderPassDescriptorMap = new ChainMap; +const getGPURenderPassDescriptorMap = new ChainMap>; /** * 获取渲染通道附件上的纹理描述列表。 @@ -185,11 +127,11 @@ function setTextureSize(texture: TextureLike, attachmentSize: { width: number, h { if (texture.size?.[2]) { - texture.size = [attachmentSize.width, attachmentSize.height, texture.size[2]]; + reactive(texture).size = [attachmentSize.width, attachmentSize.height, texture.size[2]]; } else { - texture.size = [attachmentSize.width, attachmentSize.height]; + reactive(texture).size = [attachmentSize.width, attachmentSize.height]; } } } @@ -302,32 +244,108 @@ function getIGPURenderPassDepthStencilAttachment(depthStencilAttachment: RenderP * @param sampleCount 多重采样次数。 * @returns 颜色附件完整描述列表。 */ -function getIGPURenderPassColorAttachments(colorAttachments: readonly RenderPassColorAttachment[], sampleCount: 4) +function getIGPURenderPassColorAttachments(device: GPUDevice, descriptor: RenderPassDescriptor) { - const gpuColorAttachments: NGPURenderPassColorAttachment[] = colorAttachments.map((v) => + const getIGPURenderPassColorAttachmentsKey: GetIGPURenderPassColorAttachmentsKey = [device, descriptor]; + let result = getIGPURenderPassColorAttachmentsMap.get(getIGPURenderPassColorAttachmentsKey); + if (result) return result.value; + + const gpuColorAttachments: GPURenderPassColorAttachment[] = []; + result = computed(() => { - if (!v) return undefined; + // 监听 + const r_descriptor = reactive(descriptor); + r_descriptor.colorAttachments.forEach((v) => v); + + // 执行 + const { colorAttachments } = descriptor; + gpuColorAttachments.length = 0; + colorAttachments.forEach((v) => + { + if (!v) return; - let view = v.view; - let resolveTarget: TextureView; + const attachment = getGPURenderPassColorAttachment(device, v, descriptor); + + gpuColorAttachments.push(attachment); + }); + + return gpuColorAttachments; + }); + getIGPURenderPassColorAttachmentsMap.set(getIGPURenderPassColorAttachmentsKey, result); + + return result.value; +} +type GetIGPURenderPassColorAttachmentsKey = [device: GPUDevice, descriptor: RenderPassDescriptor]; +const getIGPURenderPassColorAttachmentsMap = new ChainMap>; + +/** + * 获取颜色附件完整描述。 + */ +function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttachment: RenderPassColorAttachment, descriptor: RenderPassDescriptor) +{ + const getGPURenderPassColorAttachmentKey: GetGPURenderPassColorAttachmentKey = [device, renderPassColorAttachment, descriptor]; + let result = getGPURenderPassColorAttachmentMap.get(getGPURenderPassColorAttachmentKey); + if (result) return result.value; + const attachment: GPURenderPassColorAttachment = {} as any; + result = computed(() => + { + // 监听 + const r_renderPassColorAttachment = reactive(renderPassColorAttachment); + r_renderPassColorAttachment.view; + r_renderPassColorAttachment.depthSlice; + r_renderPassColorAttachment.clearValue; + r_renderPassColorAttachment.loadOp; + r_renderPassColorAttachment.storeOp; + + // + const { depthSlice, clearValue, loadOp, storeOp } = renderPassColorAttachment; + let view = renderPassColorAttachment.view; + + // 初始化附件尺寸。 + if (!descriptor.attachmentSize) + { + const textureSize = getTextureSize(view.texture); + reactive(descriptor).attachmentSize = { width: textureSize[0], height: textureSize[1] }; + } + + const { sampleCount } = descriptor; + let resolveTarget: TextureView; if (sampleCount) { resolveTarget = view; view = getMultisampleTextureView(view.texture, sampleCount); } - return { - view, - resolveTarget, - clearValue: v.clearValue, - loadOp: v.loadOp ?? "clear", - storeOp: v.storeOp ?? "store", - }; + // + attachment.view = getGPUTextureView(device, view); + attachment.resolveTarget = getGPUTextureView(device, resolveTarget); + attachment.depthSlice = depthSlice; + attachment.clearValue = clearValue; + attachment.loadOp = loadOp ?? "clear"; + attachment.storeOp = storeOp ?? "store"; + + // 更新纹理尺寸 + computed(() => + { + // 监听 + const r_descriptor = reactive(descriptor); + r_descriptor.attachmentSize.width; + r_descriptor.attachmentSize.height; + + // 执行 + setTextureSize(view.texture, descriptor.attachmentSize); + resolveTarget && setTextureSize(resolveTarget.texture, descriptor.attachmentSize); + }).value; + + return attachment; }); + getGPURenderPassColorAttachmentMap.set(getGPURenderPassColorAttachmentKey, result); - return gpuColorAttachments; + return result.value; } +type GetGPURenderPassColorAttachmentKey = [device: GPUDevice, renderPassColorAttachment: RenderPassColorAttachment, descriptor: RenderPassDescriptor]; +const getGPURenderPassColorAttachmentMap = new ChainMap>; /** * 更新渲染通道附件尺寸,使得附件上纹理尺寸一致。 diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index f451c64..93c4d52 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,7 +1,5 @@ -import { anyEmitter } from "@feng3d/event"; -import { ChainMap, computed, ComputedRef, reactive, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSize, TextureSource } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; -import { GPUTexture_destroy, IGPUTexture_resize, webgpuEvents } from "../eventnames"; +import { ChainMap, computed, ComputedRef, reactive, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSource } from "@feng3d/render-api"; +import { webgpuEvents } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { generateMipmap } from "../utils/generate-mipmap"; import { getGPUCanvasContext } from "./getGPUCanvasContext"; @@ -38,6 +36,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC } const texture = textureLike as MultisampleTexture; + // 监听 const r_texture = reactive(texture); r_texture.format; @@ -86,7 +85,8 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC usage, viewFormats, }); - textureMap.set(texture, gpuTexture); + textureMap.get([device, textureLike])?.destroy(); // 销毁旧的纹理 + textureMap.set([device, textureLike], gpuTexture); // 初始化纹理内容 updateSources(texture); @@ -98,44 +98,6 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC generateMipmap(device, gpuTexture); } - // 监听纹理尺寸发生变化 - const resize = (newValue: TextureSize, oldValue: TextureSize) => - { - if (!!newValue && !!oldValue) - { - if (newValue[0] === oldValue[0] - && newValue[1] === oldValue[1] - && (newValue[2] || 1) === (oldValue[2] || 1) - ) - { - return; - } - } - - gpuTexture.destroy(); - // - anyEmitter.emit(texture, IGPUTexture_resize); - }; - watcher.watch(texture, "size", resize); - - // - ((oldDestroy) => - { - gpuTexture.destroy = () => - { - oldDestroy.apply(gpuTexture); - // - getGPUTextureMap.delete(getGPUTextureKey); - // - watcher.unwatch(texture, "size", resize); - - // 派发销毁事件 - anyEmitter.emit(gpuTexture, GPUTexture_destroy); - - return undefined; - }; - })(gpuTexture.destroy); - return gpuTexture; }); getGPUTextureMap.set(getGPUTextureKey, result); @@ -146,7 +108,7 @@ let autoIndex = 0; type GetGPUTextureMap = [device: GPUDevice, texture: TextureLike]; const getGPUTextureMap = new ChainMap>; -const textureMap = new WeakMap(); +const textureMap = new ChainMap<[device: GPUDevice, texture: Texture], GPUTexture>(); /** * 更新纹理 diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index 83e2f34..d4da178 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -1,10 +1,10 @@ -import { anyEmitter } from "@feng3d/event"; import { ChainMap, computed, ComputedRef, reactive, Texture, TextureView } from "@feng3d/render-api"; -import { GPUTexture_destroy, GPUTextureView_destroy } from "../eventnames"; import { getGPUTexture } from "./getGPUTexture"; export function getGPUTextureView(device: GPUDevice, view: TextureView) { + if (!view) return undefined; + const getGPUTextureViewKey: GetGPUTextureViewKey = [device, view]; let result = getGPUTextureViewMap.get(getGPUTextureViewKey); if (result) return result.value; @@ -22,12 +22,6 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) ...r_view, dimension: r_view.dimension ?? (texture as Texture).dimension, }); - // 销毁纹理时清除对应的纹理视图。 - anyEmitter.once(gpuTexture, GPUTexture_destroy, () => - { - getGPUTextureViewMap.delete(getGPUTextureViewKey); - anyEmitter.emit(textureView, GPUTextureView_destroy); - }); return textureView; }); diff --git a/src/eventnames.ts b/src/eventnames.ts index 971cc37..c1bd5f3 100644 --- a/src/eventnames.ts +++ b/src/eventnames.ts @@ -1,16 +1,5 @@ -/** - * WebGPU纹理销毁事件 - */ -export const GPUTexture_destroy = "GPUTexture_destroy"; -/** - * WebGPU纹理视图销毁事件 - */ -export const GPUTextureView_destroy = "GPUTextureView_destroy"; - export const GPUQueue_submit = "GPUQueue_submit"; -export const IGPUTexture_resize = "IGPUTexture_resize"; - export const IGPUSampler_changed = "IGPUSampler_changed"; /** -- Gitee From 49b06211a56fea144a5edf2c6fea3925a011b2ef Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 00:26:42 +0800 Subject: [PATCH 138/214] =?UTF-8?q?perf(getGPURenderPassDescriptor):=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BA=B9=E7=90=86=E5=B0=BA=E5=AF=B8=E6=9B=B4?= =?UTF-8?q?=E6=94=B9=E6=97=B6=E7=9A=84=E5=A4=84=E7=90=86=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将纹理尺寸更新相关的代码移至 computed 函数内部 - 在纹理尺寸更改后重新获取 GPUTextureView - 调整了 attachment 对象属性的设置顺序,以适应纹理尺寸更改的影响 --- src/caches/getGPURenderPassDescriptor.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 91de06c..5d3360d 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,4 +1,4 @@ -import { CanvasTexture, ChainMap, computed, ComputedRef, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; +import { CanvasTexture, ChainMap, computed, ComputedRef, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { NGPURenderPassColorAttachment } from "../internal/internal"; import { getGPUTextureFormat } from "./getGPUTextureFormat"; @@ -317,14 +317,6 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac view = getMultisampleTextureView(view.texture, sampleCount); } - // - attachment.view = getGPUTextureView(device, view); - attachment.resolveTarget = getGPUTextureView(device, resolveTarget); - attachment.depthSlice = depthSlice; - attachment.clearValue = clearValue; - attachment.loadOp = loadOp ?? "clear"; - attachment.storeOp = storeOp ?? "store"; - // 更新纹理尺寸 computed(() => { @@ -336,8 +328,18 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac // 执行 setTextureSize(view.texture, descriptor.attachmentSize); resolveTarget && setTextureSize(resolveTarget.texture, descriptor.attachmentSize); + + // 更改纹理尺寸将会销毁重新创建纹理,需要重新获取view。 + attachment.view = getGPUTextureView(device, view); + attachment.resolveTarget = getGPUTextureView(device, resolveTarget); }).value; + // + attachment.depthSlice = depthSlice; + attachment.clearValue = clearValue; + attachment.loadOp = loadOp ?? "clear"; + attachment.storeOp = storeOp ?? "store"; + return attachment; }); getGPURenderPassColorAttachmentMap.set(getGPURenderPassColorAttachmentKey, result); -- Gitee From 6a8b9cccbdb158758f328ac3d5aa4b54319ef20a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 09:06:50 +0800 Subject: [PATCH 139/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=A4=9A=E9=87=8D=E9=87=87=E6=A0=B7=E7=BA=B9=E7=90=86=E8=A7=86?= =?UTF-8?q?=E5=9B=BE=E5=92=8C=E7=BA=B9=E7=90=86=E5=B0=BA=E5=AF=B8=E8=8E=B7?= =?UTF-8?q?=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化了多重采样纹理视图的生成和缓存逻辑 - 重构了纹理尺寸获取函数,增加了对 CanvasTexture 的支持 - 引入了 computed 和 reactive 函数,提高了代码的响应式能力 - 使用 WeakMap 进行缓存,提升了性能 --- src/caches/getGPURenderPassDescriptor.ts | 31 ++++++++++++-------- src/caches/getTextureSize.ts | 36 ++++++++++++++++++------ 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 5d3360d..e4443ad 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -180,22 +180,27 @@ function getIGPURenderPassAttachmentTextures(colorAttachments: NGPURenderPassCol */ function getMultisampleTextureView(texture: TextureLike, sampleCount: 4) { - let multisampleTextureView: TextureView = texture["_multisampleTextureView"]; - if (multisampleTextureView) return multisampleTextureView; + if (sampleCount !== 4) return undefined; + if (!texture) return undefined; + + let result = getMultisampleTextureViewMap.get(texture); + if (result) return result.value; // 新增用于解决多重采样的纹理 - const size = getTextureSize(texture); - const format = getGPUTextureFormat(texture); - const multisampleTexture: MultisampleTexture = { - label: "自动生成多重采样的纹理", - size, - sampleCount, - format, - }; - multisampleTextureView = texture["_multisampleTextureView"] = { texture: multisampleTexture }; + const multisampleTexture: MultisampleTexture = { label: "自动生成多重采样的纹理", sampleCount } as any; + const multisampleTextureView: TextureView = { texture: multisampleTexture }; + result = computed(() => + { + // 新建的多重采样纹理尺寸与格式与原始纹理同步。 + reactive(multisampleTexture).size = getTextureSize(texture); + reactive(multisampleTexture).format = getGPUTextureFormat(texture); - return multisampleTextureView; + return multisampleTextureView; + }); + getMultisampleTextureViewMap.set(texture, result); + return result.value; } +const getMultisampleTextureViewMap = new WeakMap>; /** * 获取深度模板附件完整描述。 @@ -297,6 +302,8 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac r_renderPassColorAttachment.clearValue; r_renderPassColorAttachment.loadOp; r_renderPassColorAttachment.storeOp; + const r_descriptor = reactive(descriptor); + r_descriptor.sampleCount; // const { depthSlice, clearValue, loadOp, storeOp } = renderPassColorAttachment; diff --git a/src/caches/getTextureSize.ts b/src/caches/getTextureSize.ts index dc232ca..9bc5f03 100644 --- a/src/caches/getTextureSize.ts +++ b/src/caches/getTextureSize.ts @@ -1,4 +1,4 @@ -import { CanvasTexture, TextureLike, TextureSize } from "@feng3d/render-api"; +import { CanvasTexture, computed, ComputedRef, reactive, TextureLike, TextureSize } from "@feng3d/render-api"; /** * 获取纹理尺寸。 @@ -8,13 +8,33 @@ import { CanvasTexture, TextureLike, TextureSize } from "@feng3d/render-api"; */ export function getTextureSize(texture: TextureLike) { - if ("context" in texture) + let result = getTextureSizeMap.get(texture); + if (result) return result.value; + + result = computed(() => { - const element = typeof texture.context.canvasId === "string"? document.getElementById(texture.context.canvasId) as HTMLCanvasElement : texture.context.canvasId; - console.assert(!!element, `在 document 上没有找到 canvasId 为 ${(texture as CanvasTexture).context.canvasId} 的画布。`); + if ("context" in texture) + { + // 监听 + const r_texture = reactive(texture); + r_texture.context.canvasId; + + // 计算 + const element = typeof texture.context.canvasId === "string" ? document.getElementById(texture.context.canvasId) as HTMLCanvasElement : texture.context.canvasId; + console.assert(!!element, `在 document 上没有找到 canvasId 为 ${(texture as CanvasTexture).context.canvasId} 的画布。`); + + return [element.width, element.height, 1] as TextureSize; + } + // 监听 + const r_texture = reactive(texture); + r_texture.size[0]; + r_texture.size[1]; + r_texture.size[2]; - return [element.width, element.height, 1] as TextureSize; - } + return texture.size; + }); + getTextureSizeMap.set(texture, result); - return texture.size; -} \ No newline at end of file + return result.value; +} +const getTextureSizeMap = new WeakMap>(); \ No newline at end of file -- Gitee From 4a1432a7eeeac13c30039a18f5215318c42a9bf4 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 10:13:59 +0800 Subject: [PATCH 140/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E9=80=9A=E9=81=93=E6=8F=8F=E8=BF=B0=E7=94=9F?= =?UTF-8?q?=E6=88=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化了 GPURenderPassDescriptor 的生成过程 - 重构了深度模板附件和颜色附件的处理逻辑 - 移除了不必要的辅助函数,简化了代码结构 - 增加了对附件尺寸的自动初始化 - 调整了缓存机制,提高了性能 --- src/caches/getGPURenderPassDescriptor.ts | 278 +++++++++-------------- 1 file changed, 109 insertions(+), 169 deletions(-) diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index e4443ad..ceaa8d4 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,4 +1,4 @@ -import { CanvasTexture, ChainMap, computed, ComputedRef, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, TextureLike, TextureView } from "@feng3d/render-api"; +import { CanvasTexture, ChainMap, computed, ComputedRef, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { NGPURenderPassColorAttachment } from "../internal/internal"; import { getGPUTextureFormat } from "./getGPUTextureFormat"; @@ -14,44 +14,27 @@ import { getTextureSize } from "./getTextureSize"; */ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: RenderPassDescriptor): GPURenderPassDescriptor { + // 缓存 const getGPURenderPassDescriptorKey: GetGPURenderPassDescriptorKey = [device, descriptor]; let result = getGPURenderPassDescriptorMap.get(getGPURenderPassDescriptorKey); if (result) return result.value; + // 避免重复创建,触发反应链。 const renderPassDescriptor: GPURenderPassDescriptor = {} as any; - result = computed(() => { - // // 更新渲染通道附件尺寸,使得附件上纹理尺寸一致。 - // updateAttachmentSize(descriptor); - - // 获取颜色附件完整描述列表。 - renderPassDescriptor.colorAttachments = getIGPURenderPassColorAttachments(device, descriptor); - - // 获取深度模板附件 - const depthStencilAttachment = getIGPURenderPassDepthStencilAttachment(descriptor.depthStencilAttachment, descriptor.attachmentSize, descriptor.sampleCount); - - // // 更新尺寸 - // computed(() => - // { - // // 监听 - // const r_descriptor = reactive(descriptor); - // r_descriptor.attachmentSize.width; - // r_descriptor.attachmentSize.height; - - // // 执行 - // setIGPURenderPassAttachmentSize(colorAttachments, depthStencilAttachment, descriptor.attachmentSize); - // }).value; - - if (depthStencilAttachment) - { - const v = depthStencilAttachment; + // 监听 + const r_descriptor = reactive(descriptor); + r_descriptor.label; + r_descriptor.maxDrawCount; + r_descriptor.colorAttachments; + r_descriptor.depthStencilAttachment; - renderPassDescriptor.depthStencilAttachment = { - ...v, - view: getGPUTextureView(device, v.view), - }; - } + // 执行 + renderPassDescriptor.label = descriptor.label; + renderPassDescriptor.maxDrawCount = descriptor.maxDrawCount; + renderPassDescriptor.colorAttachments = getGPURenderPassColorAttachments(device, descriptor); + renderPassDescriptor.depthStencilAttachment = getGPURenderPassDepthStencilAttachment(device, descriptor); return renderPassDescriptor; }); @@ -64,52 +47,7 @@ type GetGPURenderPassDescriptorKey = [device: GPUDevice, descriptor: RenderPassD const getGPURenderPassDescriptorMap = new ChainMap>; /** - * 获取渲染通道附件上的纹理描述列表。 - * - * @param colorAttachments 颜色附件描述。 - * @param depthStencilAttachment 深度模板附件描述。 - * - * @returns 渲染通道附件上的纹理描述列表。 - */ -function getAttachmentTextures(colorAttachments: readonly RenderPassColorAttachment[], depthStencilAttachment?: RenderPassDepthStencilAttachment) -{ - const textures: TextureLike[] = []; - - for (let i = 0; i < colorAttachments.length; i++) - { - const element = colorAttachments[i]; - if (!element) continue; - if (element.view) - { - textures.push(element.view.texture); - } - } - - if (depthStencilAttachment) - { - if (depthStencilAttachment.view) - { - textures.push(depthStencilAttachment.view.texture); - } - } - - return textures; -} - -/** - * 更新渲染通道附件尺寸,使得附件上纹理尺寸一致。 - * - * @param renderPass 渲染通道描述。 - * @param attachmentSize 附件尺寸。 - */ -function setIGPURenderPassAttachmentSize(colorAttachments: NGPURenderPassColorAttachment[], depthStencilAttachment: RenderPassDepthStencilAttachment, attachmentSize: { width: number; height: number; }) -{ - const attachmentTextures = getIGPURenderPassAttachmentTextures(colorAttachments, depthStencilAttachment); - attachmentTextures.forEach((v) => setTextureSize(v, attachmentSize)); -} - -/** - * 设置纹理与附件相同尺寸。 + * 设置纹理尺寸。 * * @param texture 纹理描述。 * @param attachmentSize 附件尺寸。 @@ -125,50 +63,13 @@ function setTextureSize(texture: TextureLike, attachmentSize: { width: number, h } else { + reactive(texture.size)[0] = attachmentSize.width; + reactive(texture.size)[1] = attachmentSize.height; if (texture.size?.[2]) { - reactive(texture).size = [attachmentSize.width, attachmentSize.height, texture.size[2]]; - } - else - { - reactive(texture).size = [attachmentSize.width, attachmentSize.height]; - } - } -} - -/** - * 获取渲染通道附件上的纹理描述列表。 - * - * @param colorAttachments 颜色附件列表。 - * @param depthStencilAttachment 深度模板附件。 - * @returns 渲染通道附件上的纹理描述列表。 - */ -function getIGPURenderPassAttachmentTextures(colorAttachments: NGPURenderPassColorAttachment[], depthStencilAttachment?: RenderPassDepthStencilAttachment) -{ - const textures: TextureLike[] = []; - - for (let i = 0; i < colorAttachments.length; i++) - { - const element = colorAttachments[i]; - if (element.view) - { - textures.push(element.view.texture); - } - if (element.resolveTarget) - { - textures.push(element.resolveTarget.texture); - } - } - - if (depthStencilAttachment) - { - if (depthStencilAttachment.view) - { - textures.push(depthStencilAttachment.view.texture); + reactive(texture.size)[2] = texture.size[2]; } } - - return textures; } /** @@ -187,7 +88,7 @@ function getMultisampleTextureView(texture: TextureLike, sampleCount: 4) if (result) return result.value; // 新增用于解决多重采样的纹理 - const multisampleTexture: MultisampleTexture = { label: "自动生成多重采样的纹理", sampleCount } as any; + const multisampleTexture: MultisampleTexture = { label: "自动生成多重采样的纹理", sampleCount } as MultisampleTexture; const multisampleTextureView: TextureView = { texture: multisampleTexture }; result = computed(() => { @@ -210,37 +111,92 @@ const getMultisampleTextureViewMap = new WeakMap { - view = { - texture: { + // 监听 + const r_depthStencilAttachment = reactive(depthStencilAttachment); + r_depthStencilAttachment.depthClearValue; + r_depthStencilAttachment.depthLoadOp; + r_depthStencilAttachment.depthStoreOp; + r_depthStencilAttachment.depthReadOnly; + r_depthStencilAttachment.stencilClearValue; + r_depthStencilAttachment.stencilLoadOp; + r_depthStencilAttachment.stencilStoreOp; + r_depthStencilAttachment.stencilReadOnly; + r_depthStencilAttachment.view; + + // 执行 + const { depthClearValue, depthLoadOp, depthStoreOp, depthReadOnly, stencilClearValue, stencilLoadOp, stencilStoreOp, stencilReadOnly } = depthStencilAttachment; + let view = depthStencilAttachment.view; + if (!view) + { + atuoCreateDepthTexture ??= { label: `自动生成的深度纹理`, size: [attachmentSize.width, attachmentSize.height], format: "depth24plus", - } - }; - } + }; + atuoCreateDepthTextureView ??= { texture: atuoCreateDepthTexture }; + // + view = atuoCreateDepthTextureView; + } + + // 更新纹理尺寸 + computed(() => + { + // 监听 + const r_descriptor = reactive(descriptor); + r_descriptor.attachmentSize.width; + r_descriptor.attachmentSize.height; - const depthClearValue = (depthStencilAttachment.depthClearValue !== undefined) ? depthStencilAttachment.depthClearValue : 1; - const depthLoadOp = depthStencilAttachment.depthLoadOp || "load"; - const depthStoreOp = depthStencilAttachment.depthStoreOp; + // 执行 + setTextureSize(view.texture, descriptor.attachmentSize); - // - const gpuDepthStencilAttachment: RenderPassDepthStencilAttachment = { - ...depthStencilAttachment, - view, - depthClearValue, - depthLoadOp, - depthStoreOp, - }; - - return gpuDepthStencilAttachment; + // 更改纹理尺寸将会销毁重新创建纹理,需要重新获取view。 + gpuDepthStencilAttachment.view = getGPUTextureView(device, view); + }).value; + + // + gpuDepthStencilAttachment.depthClearValue = depthClearValue ?? 1; + gpuDepthStencilAttachment.depthLoadOp = depthLoadOp; + gpuDepthStencilAttachment.depthStoreOp = depthStoreOp; + gpuDepthStencilAttachment.depthReadOnly = depthReadOnly; + gpuDepthStencilAttachment.stencilClearValue = stencilClearValue ?? 0; + gpuDepthStencilAttachment.stencilLoadOp = stencilLoadOp; + gpuDepthStencilAttachment.stencilStoreOp = stencilStoreOp; + gpuDepthStencilAttachment.stencilReadOnly = stencilReadOnly; + + return gpuDepthStencilAttachment; + }); + getGPURenderPassDepthStencilAttachmentMap.set(getGPURenderPassDepthStencilAttachmentKey, result); + + return result.value; } +type GetGPURenderPassDepthStencilAttachmentKey = [device: GPUDevice, depthStencilAttachment: RenderPassDepthStencilAttachment]; +const getGPURenderPassDepthStencilAttachmentMap = new ChainMap>; /** * 获取颜色附件完整描述列表。 @@ -249,10 +205,10 @@ function getIGPURenderPassDepthStencilAttachment(depthStencilAttachment: RenderP * @param sampleCount 多重采样次数。 * @returns 颜色附件完整描述列表。 */ -function getIGPURenderPassColorAttachments(device: GPUDevice, descriptor: RenderPassDescriptor) +function getGPURenderPassColorAttachments(device: GPUDevice, descriptor: RenderPassDescriptor) { - const getIGPURenderPassColorAttachmentsKey: GetIGPURenderPassColorAttachmentsKey = [device, descriptor]; - let result = getIGPURenderPassColorAttachmentsMap.get(getIGPURenderPassColorAttachmentsKey); + const getGPURenderPassColorAttachmentsKey: GetGPURenderPassColorAttachmentsKey = [device, descriptor]; + let result = getIGPURenderPassColorAttachmentsMap.get(getGPURenderPassColorAttachmentsKey); if (result) return result.value; const gpuColorAttachments: GPURenderPassColorAttachment[] = []; @@ -276,12 +232,12 @@ function getIGPURenderPassColorAttachments(device: GPUDevice, descriptor: Render return gpuColorAttachments; }); - getIGPURenderPassColorAttachmentsMap.set(getIGPURenderPassColorAttachmentsKey, result); + getIGPURenderPassColorAttachmentsMap.set(getGPURenderPassColorAttachmentsKey, result); return result.value; } -type GetIGPURenderPassColorAttachmentsKey = [device: GPUDevice, descriptor: RenderPassDescriptor]; -const getIGPURenderPassColorAttachmentsMap = new ChainMap>; +type GetGPURenderPassColorAttachmentsKey = [device: GPUDevice, descriptor: RenderPassDescriptor]; +const getIGPURenderPassColorAttachmentsMap = new ChainMap>; /** * 获取颜色附件完整描述。 @@ -292,6 +248,13 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac let result = getGPURenderPassColorAttachmentMap.get(getGPURenderPassColorAttachmentKey); if (result) return result.value; + // 初始化附件尺寸。 + if (!descriptor.attachmentSize) + { + const textureSize = getTextureSize(renderPassColorAttachment.view.texture); + reactive(descriptor).attachmentSize = { width: textureSize[0], height: textureSize[1] }; + } + const attachment: GPURenderPassColorAttachment = {} as any; result = computed(() => { @@ -306,15 +269,8 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac r_descriptor.sampleCount; // - const { depthSlice, clearValue, loadOp, storeOp } = renderPassColorAttachment; let view = renderPassColorAttachment.view; - - // 初始化附件尺寸。 - if (!descriptor.attachmentSize) - { - const textureSize = getTextureSize(view.texture); - reactive(descriptor).attachmentSize = { width: textureSize[0], height: textureSize[1] }; - } + const { depthSlice, clearValue, loadOp, storeOp } = renderPassColorAttachment; const { sampleCount } = descriptor; let resolveTarget: TextureView; @@ -356,19 +312,3 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac type GetGPURenderPassColorAttachmentKey = [device: GPUDevice, renderPassColorAttachment: RenderPassColorAttachment, descriptor: RenderPassDescriptor]; const getGPURenderPassColorAttachmentMap = new ChainMap>; -/** - * 更新渲染通道附件尺寸,使得附件上纹理尺寸一致。 - * - * @param renderPass 渲染通道描述。 - */ -function updateAttachmentSize(renderPass: RenderPassDescriptor) -{ - const attachmentTextures = getAttachmentTextures(renderPass.colorAttachments, renderPass.depthStencilAttachment); - if (!renderPass.attachmentSize) - { - const textureSize = getTextureSize(attachmentTextures[0]); - reactive(renderPass).attachmentSize = { width: textureSize[0], height: textureSize[1] }; - } - attachmentTextures.forEach((v) => setTextureSize(v, renderPass.attachmentSize)); -} - -- Gitee From 21b08562ac66a7ee0a527f0d7fea2142047bcc85 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 10:41:53 +0800 Subject: [PATCH 141/214] =?UTF-8?q?refactor(internal):=20=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E6=9C=AA=E4=BD=BF=E7=94=A8=E7=9A=84=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=92=8C=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 getGPURenderPassDescriptor.ts 中未使用的 NGPURenderPassColorAttachment 接口 - 移除了 internal.ts 中的 RenderPassColorAttachment 和 TextureView 的未使用导入 --- src/caches/getGPURenderPassDescriptor.ts | 1 - src/internal/internal.ts | 14 -------------- 2 files changed, 15 deletions(-) delete mode 100644 src/internal/internal.ts diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index ceaa8d4..1a720ac 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,6 +1,5 @@ import { CanvasTexture, ChainMap, computed, ComputedRef, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; import { MultisampleTexture } from "../internal/MultisampleTexture"; -import { NGPURenderPassColorAttachment } from "../internal/internal"; import { getGPUTextureFormat } from "./getGPUTextureFormat"; import { getGPUTextureView } from "./getGPUTextureView"; import { getTextureSize } from "./getTextureSize"; diff --git a/src/internal/internal.ts b/src/internal/internal.ts deleted file mode 100644 index a1a033a..0000000 --- a/src/internal/internal.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { RenderPassColorAttachment, TextureView } from "@feng3d/render-api"; - -/** - * 内部使用 - */ -export interface NGPURenderPassColorAttachment extends RenderPassColorAttachment -{ - /** - * A {@link GPUTextureView} describing the texture subresource that will receive the resolved - * output for this color attachment if {@link GPURenderPassColorAttachment#view} is - * multisampled. - */ - resolveTarget?: TextureView; -} -- Gitee From bfe8330e27bff159fe2c239dbd0b59433319a7ff Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 11:33:53 +0800 Subject: [PATCH 142/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=87=87=E6=A0=B7=E5=99=A8=E5=8F=82=E6=95=B0=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 updateSamplerResources 函数,改为使用 reactive 和 computed - 优化 sampler descriptor 的创建和管理 - 调整 GUI 控件的事件处理方式 - 重构 getGPUSampler 函数,使用 computed 创建 GPU 采样器 --- .../src/webgpu/samplerParameters/index.ts | 66 +++++-------------- src/caches/getGPUSampler.ts | 63 ++++++++++-------- src/internal/RenderPassFormat.ts | 5 ++ 3 files changed, 60 insertions(+), 74 deletions(-) diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index bf003a1..448703f 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -71,50 +71,44 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => lodMaxClamp: 4, maxAnisotropy: 1, } as const; - const samplerDescriptor: GPUSamplerDescriptor = { ...kInitSamplerDescriptor }; + + const samplerDescriptor: Sampler = { ...kInitSamplerDescriptor }; + const r_samplerDescriptor: Sampler = reactive(samplerDescriptor); { const buttons = { initial() { Object.assign(config, kInitConfig); - Object.assign(samplerDescriptor, kInitSamplerDescriptor); + Object.assign(r_samplerDescriptor, kInitSamplerDescriptor); gui.updateDisplay(); - - updateSamplerResources(); }, checkerboard() { Object.assign(config, { flangeLogSize: 10 }); - Object.assign(samplerDescriptor, { + Object.assign(r_samplerDescriptor, { addressModeU: "repeat", addressModeV: "repeat", }); gui.updateDisplay(); - - updateSamplerResources(); }, smooth() { - Object.assign(samplerDescriptor, { + Object.assign(r_samplerDescriptor, { magFilter: "linear", minFilter: "linear", mipmapFilter: "linear", }); gui.updateDisplay(); - - updateSamplerResources(); }, crunchy() { - Object.assign(samplerDescriptor, { + Object.assign(r_samplerDescriptor, { magFilter: "nearest", minFilter: "nearest", mipmapFilter: "nearest", }); gui.updateDisplay(); - - updateSamplerResources(); }, }; const presets = gui.addFolder("Presets"); @@ -136,28 +130,24 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => folder.open(); const kAddressModes = ["clamp-to-edge", "repeat", "mirror-repeat"]; - folder.add(samplerDescriptor, "addressModeU", kAddressModes).onChange(updateSamplerResources); - folder.add(samplerDescriptor, "addressModeV", kAddressModes).onChange(updateSamplerResources); + folder.add(r_samplerDescriptor, "addressModeU", kAddressModes); + folder.add(r_samplerDescriptor, "addressModeV", kAddressModes); const kFilterModes = ["nearest", "linear"]; - folder.add(samplerDescriptor, "magFilter", kFilterModes).onChange(updateSamplerResources); - folder.add(samplerDescriptor, "minFilter", kFilterModes).onChange(updateSamplerResources); + folder.add(r_samplerDescriptor, "magFilter", kFilterModes); + folder.add(r_samplerDescriptor, "minFilter", kFilterModes); const kMipmapFilterModes = ["nearest", "linear"] as const; - folder.add(samplerDescriptor, "mipmapFilter", kMipmapFilterModes).onChange(updateSamplerResources); + folder.add(r_samplerDescriptor, "mipmapFilter", kMipmapFilterModes); - const ctlMin = folder.add(samplerDescriptor, "lodMinClamp", 0, 4, 0.1); - const ctlMax = folder.add(samplerDescriptor, "lodMaxClamp", 0, 4, 0.1); + const ctlMin = folder.add(r_samplerDescriptor, "lodMinClamp", 0, 4, 0.1); + const ctlMax = folder.add(r_samplerDescriptor, "lodMaxClamp", 0, 4, 0.1); ctlMin.onChange((value: number) => { - if (samplerDescriptor.lodMaxClamp < value) ctlMax.setValue(value); - - updateSamplerResources(); + if (r_samplerDescriptor.lodMaxClamp < value) ctlMax.setValue(value); }); ctlMax.onChange((value: number) => { - if (samplerDescriptor.lodMinClamp > value) ctlMin.setValue(value); - - updateSamplerResources(); + if (r_samplerDescriptor.lodMinClamp > value) ctlMin.setValue(value); }); { @@ -166,29 +156,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ); folder2.open(); const kMaxAnisotropy = 16; - folder2.add(samplerDescriptor, "maxAnisotropy", 1, kMaxAnisotropy, 1).onChange(updateSamplerResources); + folder2.add(r_samplerDescriptor, "maxAnisotropy", 1, kMaxAnisotropy, 1); } } } - /** - * 更新采样资源 - */ - function updateSamplerResources() - { - const sampler: Sampler = { - ...samplerDescriptor, - maxAnisotropy: - samplerDescriptor.minFilter === "linear" - && samplerDescriptor.magFilter === "linear" - && samplerDescriptor.mipmapFilter === "linear" - ? samplerDescriptor.maxAnisotropy - : 1, - }; - - bindingResources0.samp = sampler; - } - // // Canvas setup // @@ -306,12 +278,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const bindingResources0: BindingResources = { config: { bufferView: bufConfig }, matrices: { bufferView: bufMatrices }, - samp: null, // 帧更新中设置 + samp: samplerDescriptor, // 帧更新中设置 tex: { texture: checkerboard }, }; - updateSamplerResources(); - for (let i = 0; i < kViewportGridSize ** 2 - 1; ++i) { const vpX = kViewportGridStride * (i % kViewportGridSize) + 1; diff --git a/src/caches/getGPUSampler.ts b/src/caches/getGPUSampler.ts index 7fb856d..52ff4dc 100644 --- a/src/caches/getGPUSampler.ts +++ b/src/caches/getGPUSampler.ts @@ -1,40 +1,51 @@ -import { anyEmitter } from "@feng3d/event"; -import { ChainMap, Sampler } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; -import { IGPUSampler_changed } from "../eventnames"; +import { ChainMap, computed, ComputedRef, reactive, Sampler } from "@feng3d/render-api"; export function getGPUSampler(device: GPUDevice, sampler: Sampler) { const getGPUSamplerKey: GetGPUSamplerKey = [device, sampler]; - let gSampler = getGPUSamplerMap.get(getGPUSamplerKey); - if (gSampler) return gSampler; + let result = getGPUSamplerMap.get(getGPUSamplerKey); + if (result) return result.value; - // 处理默认值 - sampler.addressModeU = sampler.addressModeU ?? "repeat"; - sampler.addressModeV = sampler.addressModeV ?? "repeat"; - sampler.addressModeW = sampler.addressModeW ?? "repeat"; - sampler.magFilter = sampler.magFilter ?? "nearest"; - sampler.minFilter = sampler.minFilter ?? "nearest"; - sampler.mipmapFilter = sampler.mipmapFilter ?? "nearest"; + result = computed(() => + { + // 监听 + const r_sampler = reactive(sampler); + const { + label, + addressModeU, + addressModeV, + addressModeW, + magFilter, + minFilter, + mipmapFilter, + lodMinClamp, + lodMaxClamp, + compare, + maxAnisotropy, + } = r_sampler; - // - gSampler = device.createSampler(sampler); - getGPUSamplerMap.set(getGPUSamplerKey, gSampler); + const gSampler = device.createSampler({ + label: label, + addressModeU: addressModeU ?? "repeat", + addressModeV: addressModeV ?? "repeat", + addressModeW: addressModeW ?? "repeat", + magFilter: magFilter ?? "nearest", + minFilter: minFilter ?? "nearest", + mipmapFilter: mipmapFilter ?? "nearest", + lodMinClamp: lodMinClamp ?? 0, + lodMaxClamp: lodMaxClamp, + compare: compare, + maxAnisotropy: (minFilter === "linear" && magFilter === "linear" && mipmapFilter === "linear") ? maxAnisotropy : 1, + }); - // - watcher.watchobject(sampler, defaultSampler, () => - { - // 移除监听,删除缓存 - watcher.unwatchobject(sampler, defaultSampler); - getGPUSamplerMap.delete(getGPUSamplerKey); - // - anyEmitter.emit(sampler, IGPUSampler_changed); + return gSampler; }); + getGPUSamplerMap.set(getGPUSamplerKey, result); - return gSampler; + return result.value; } type GetGPUSamplerKey = [device: GPUDevice, sampler: Sampler]; -const getGPUSamplerMap = new ChainMap; +const getGPUSamplerMap = new ChainMap>; /** * GPU采样器默认值。 diff --git a/src/internal/RenderPassFormat.ts b/src/internal/RenderPassFormat.ts index 1d85273..1257fbb 100644 --- a/src/internal/RenderPassFormat.ts +++ b/src/internal/RenderPassFormat.ts @@ -1,3 +1,8 @@ +/** + * 渲染通道格式。 + * + * @private + */ export interface RenderPassFormat { readonly attachmentSize: { readonly width: number, readonly height: number } -- Gitee From 30eb77cea878ea968fe819986c87a9ca5eb06ded Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 11:37:59 +0800 Subject: [PATCH 143/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20getGPUBindGroup=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 computed 函数创建响应式绑定组 - 优化了绑定资源的更新逻辑 - 重构了代码结构,提高了可读性和可维护性 --- src/caches/getGPUBindGroup.ts | 205 +++++++++++++++++----------------- 1 file changed, 105 insertions(+), 100 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 78f2b57..fe50516 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,4 +1,4 @@ -import { BindingResource, BindingResources, BufferBinding, BufferBindingInfo, CanvasTexture, ChainMap, Sampler, TextureView } from "@feng3d/render-api"; +import { BindingResource, BindingResources, BufferBinding, BufferBindingInfo, CanvasTexture, ChainMap, computed, ComputedRef, Sampler, TextureView } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { ResourceType } from "wgsl_reflect"; import { getRealGPUBindGroup } from "../const"; @@ -13,134 +13,139 @@ import { getGBuffer } from "./getIGPUBuffer"; export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) { - const getGPUBindGroupMapKey: GetGPUBindGroupMapKey = [device, bindGroupLayout, bindingResources]; - let gBindGroup = _getGPUBindGroupMap.get(getGPUBindGroupMapKey); - if (gBindGroup) return gBindGroup; + const getGPUBindGroupKey: GetGPUBindGroupKey = [device, bindGroupLayout, bindingResources]; + let result = getGPUBindGroupMap.get(getGPUBindGroupKey); + if (result) return result.value; - // 总是更新函数列表。 - const awaysUpdateFuncs: (() => void)[] = []; - // 执行一次函数列表 - const onceUpdateFuncs: (() => void)[] = []; - - const entries = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map((v) => + let gBindGroup: GPUBindGroup; + result = computed(() => { - const { name, type, resourceType, binding } = v.variableInfo; + // 总是更新函数列表。 + const awaysUpdateFuncs: (() => void)[] = []; + // 执行一次函数列表 + const onceUpdateFuncs: (() => void)[] = []; - const entry: GPUBindGroupEntry = { binding, resource: null }; + const entries = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map((v) => + { + const { name, type, resourceType, binding } = v.variableInfo; - // 更新资源函数。 - let updateResource: () => void; + const entry: GPUBindGroupEntry = { binding, resource: null }; - // 资源变化后更新函数。 - const onResourceChanged = () => - { - onceUpdateFuncs.push(updateResource); + // 更新资源函数。 + let updateResource: () => void; - if (gBindGroup[getRealGPUBindGroup] !== getReal) + // 资源变化后更新函数。 + const onResourceChanged = () => { - gBindGroup[getRealGPUBindGroup] = createBindGroup; - } - }; + onceUpdateFuncs.push(updateResource); - // - if (resourceType === ResourceType.Uniform || resourceType === ResourceType.Storage) - { - updateResource = () => + if (gBindGroup[getRealGPUBindGroup] !== getReal) + { + gBindGroup[getRealGPUBindGroup] = createBindGroup; + } + }; + + // + if (resourceType === ResourceType.Uniform || resourceType === ResourceType.Storage) { - const resource = bindingResources[name] as BufferBinding; - - const bufferBinding = ((typeof resource === "number") ? [resource] : resource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 - const bufferBindingInfo: BufferBindingInfo = type["_bufferBindingInfo"] = type["_bufferBindingInfo"] || getBufferBindingInfo(type); - // 更新缓冲区绑定的数据。 - updateBufferBinding(name, bufferBindingInfo, bufferBinding); - // - const gbuffer = getGBuffer(bufferBinding.bufferView); - (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); - // - const buffer = getGPUBuffer(device, gbuffer); - - const offset = resource.bufferView.byteOffset; - const size = resource.bufferView.byteLength; - - entry.resource = { - buffer, - offset, - size, + updateResource = () => + { + const resource = bindingResources[name] as BufferBinding; + + const bufferBinding = ((typeof resource === "number") ? [resource] : resource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 + const bufferBindingInfo: BufferBindingInfo = type["_bufferBindingInfo"] = type["_bufferBindingInfo"] || getBufferBindingInfo(type); + // 更新缓冲区绑定的数据。 + updateBufferBinding(name, bufferBindingInfo, bufferBinding); + // + const gbuffer = getGBuffer(bufferBinding.bufferView); + (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); + // + const buffer = getGPUBuffer(device, gbuffer); + + const offset = resource.bufferView.byteOffset; + const size = resource.bufferView.byteLength; + + entry.resource = { + buffer, + offset, + size, + }; }; - }; - } - else if (ExternalSampledTextureType[type.name]) // 判断是否为外部纹理 - { - updateResource = () => + } + else if (ExternalSampledTextureType[type.name]) // 判断是否为外部纹理 { - entry.resource = device.importExternalTexture(bindingResources[name] as VideoTexture); - }; + updateResource = () => + { + entry.resource = device.importExternalTexture(bindingResources[name] as VideoTexture); + }; - awaysUpdateFuncs.push(updateResource); - } - else if (resourceType === ResourceType.Texture || resourceType === ResourceType.StorageTexture) - { - updateResource = () => + awaysUpdateFuncs.push(updateResource); + } + else if (resourceType === ResourceType.Texture || resourceType === ResourceType.StorageTexture) { - entry.resource = getGPUTextureView(device, bindingResources[name] as TextureView); - }; + updateResource = () => + { + entry.resource = getGPUTextureView(device, bindingResources[name] as TextureView); + }; - if (((bindingResources[name] as TextureView).texture as CanvasTexture).context) - { - awaysUpdateFuncs.push(updateResource); + if (((bindingResources[name] as TextureView).texture as CanvasTexture).context) + { + awaysUpdateFuncs.push(updateResource); + } } - } - else - { - updateResource = () => + else { - entry.resource = getGPUSampler(device, bindingResources[name] as Sampler); - }; - } + updateResource = () => + { + entry.resource = getGPUSampler(device, bindingResources[name] as Sampler); + }; + } - updateResource(); + updateResource(); - // 监听绑定资源发生改变 - watcher.watch(bindingResources, name, onResourceChanged); + // 监听绑定资源发生改变 + watcher.watch(bindingResources, name, onResourceChanged); - return entry; - }); + return entry; + }); - const getReal = () => - { - awaysUpdateFuncs.forEach((v) => v()); - createBindGroup(); + const getReal = () => + { + awaysUpdateFuncs.forEach((v) => v()); + createBindGroup(); - return gBindGroup; - }; + return gBindGroup; + }; - const createBindGroup = () => - { - onceUpdateFuncs.forEach((v) => v()); + const createBindGroup = () => + { + onceUpdateFuncs.forEach((v) => v()); - gBindGroup = device.createBindGroup({ layout: bindGroupLayout, entries }); + gBindGroup = device.createBindGroup({ layout: bindGroupLayout, entries }); - _getGPUBindGroupMap.set(getGPUBindGroupMapKey, gBindGroup); + // 设置更新外部纹理/画布纹理视图 + if (awaysUpdateFuncs.length > 0) + { + gBindGroup[getRealGPUBindGroup] = getReal; + } + else + { + gBindGroup[getRealGPUBindGroup] = () => gBindGroup; + } - // 设置更新外部纹理/画布纹理视图 - if (awaysUpdateFuncs.length > 0) - { - gBindGroup[getRealGPUBindGroup] = getReal; - } - else - { - gBindGroup[getRealGPUBindGroup] = () => gBindGroup; - } + return gBindGroup; + }; - return gBindGroup; - }; + createBindGroup(); - createBindGroup(); + return gBindGroup; + }); + getGPUBindGroupMap.set(getGPUBindGroupKey, result); - return gBindGroup; + return result.value; } -type GetGPUBindGroupMapKey = [device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; -const _getGPUBindGroupMap = new ChainMap(); +type GetGPUBindGroupKey = [device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; +const getGPUBindGroupMap = new ChainMap>(); /** * GPU 绑定组。 * -- Gitee From 95df9a76acb96aa454045a2ff398c4edc926342d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 11:42:58 +0800 Subject: [PATCH 144/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20bind=20group=20=E7=9A=84=E5=88=9B=E5=BB=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 getGPUBindGroup 中的冗余更新机制 - 简化了 bind group 的创建流程 - 优化了资源更新的处理方式,特别是外部纹理和画布纹理 - 删除了不必要的复杂逻辑和未使用的功能 --- src/WebGPUBase.ts | 2 +- src/caches/getGPUBindGroup.ts | 116 +++++++--------------------------- 2 files changed, 24 insertions(+), 94 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index e099938..c13b88a 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -485,7 +485,7 @@ export class WebGPUBase const layout = getGPUPipelineLayout(device, { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { - const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); + const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources); passEncoder.setBindGroup(group, gpuBindGroup); }); diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index fe50516..94734b6 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -20,123 +20,53 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup let gBindGroup: GPUBindGroup; result = computed(() => { - // 总是更新函数列表。 - const awaysUpdateFuncs: (() => void)[] = []; - // 执行一次函数列表 - const onceUpdateFuncs: (() => void)[] = []; - const entries = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map((v) => { const { name, type, resourceType, binding } = v.variableInfo; const entry: GPUBindGroupEntry = { binding, resource: null }; - // 更新资源函数。 - let updateResource: () => void; - - // 资源变化后更新函数。 - const onResourceChanged = () => - { - onceUpdateFuncs.push(updateResource); - - if (gBindGroup[getRealGPUBindGroup] !== getReal) - { - gBindGroup[getRealGPUBindGroup] = createBindGroup; - } - }; - // if (resourceType === ResourceType.Uniform || resourceType === ResourceType.Storage) { - updateResource = () => - { - const resource = bindingResources[name] as BufferBinding; - - const bufferBinding = ((typeof resource === "number") ? [resource] : resource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 - const bufferBindingInfo: BufferBindingInfo = type["_bufferBindingInfo"] = type["_bufferBindingInfo"] || getBufferBindingInfo(type); - // 更新缓冲区绑定的数据。 - updateBufferBinding(name, bufferBindingInfo, bufferBinding); - // - const gbuffer = getGBuffer(bufferBinding.bufferView); - (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); - // - const buffer = getGPUBuffer(device, gbuffer); - - const offset = resource.bufferView.byteOffset; - const size = resource.bufferView.byteLength; - - entry.resource = { - buffer, - offset, - size, - }; + const resource = bindingResources[name] as BufferBinding; + + const bufferBinding = ((typeof resource === "number") ? [resource] : resource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 + const bufferBindingInfo: BufferBindingInfo = type["_bufferBindingInfo"] = type["_bufferBindingInfo"] || getBufferBindingInfo(type); + // 更新缓冲区绑定的数据。 + updateBufferBinding(name, bufferBindingInfo, bufferBinding); + // + const gbuffer = getGBuffer(bufferBinding.bufferView); + (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); + // + const buffer = getGPUBuffer(device, gbuffer); + + const offset = resource.bufferView.byteOffset; + const size = resource.bufferView.byteLength; + + entry.resource = { + buffer, + offset, + size, }; } else if (ExternalSampledTextureType[type.name]) // 判断是否为外部纹理 { - updateResource = () => - { - entry.resource = device.importExternalTexture(bindingResources[name] as VideoTexture); - }; - - awaysUpdateFuncs.push(updateResource); + entry.resource = device.importExternalTexture(bindingResources[name] as VideoTexture); } else if (resourceType === ResourceType.Texture || resourceType === ResourceType.StorageTexture) { - updateResource = () => - { - entry.resource = getGPUTextureView(device, bindingResources[name] as TextureView); - }; - - if (((bindingResources[name] as TextureView).texture as CanvasTexture).context) - { - awaysUpdateFuncs.push(updateResource); - } + entry.resource = getGPUTextureView(device, bindingResources[name] as TextureView); } else { - updateResource = () => - { - entry.resource = getGPUSampler(device, bindingResources[name] as Sampler); - }; + entry.resource = getGPUSampler(device, bindingResources[name] as Sampler); } - updateResource(); - - // 监听绑定资源发生改变 - watcher.watch(bindingResources, name, onResourceChanged); - return entry; }); - const getReal = () => - { - awaysUpdateFuncs.forEach((v) => v()); - createBindGroup(); - - return gBindGroup; - }; - - const createBindGroup = () => - { - onceUpdateFuncs.forEach((v) => v()); - - gBindGroup = device.createBindGroup({ layout: bindGroupLayout, entries }); - - // 设置更新外部纹理/画布纹理视图 - if (awaysUpdateFuncs.length > 0) - { - gBindGroup[getRealGPUBindGroup] = getReal; - } - else - { - gBindGroup[getRealGPUBindGroup] = () => gBindGroup; - } - - return gBindGroup; - }; - - createBindGroup(); + gBindGroup = device.createBindGroup({ layout: bindGroupLayout, entries }); return gBindGroup; }); -- Gitee From b87f41f9b0c5af70e7f87c1c1c9ac8942721434f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 11:44:23 +0800 Subject: [PATCH 145/214] =?UTF-8?q?refactor(WebGPU):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=20getRealGPUBindGroup=20=E5=B8=B8=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除了 WebGPU 代码中不再使用的 getRealGPUBindGroup 常量。这个常量之前用于从 GPUBindGroup 中获取实际的绑定组,但现在似乎已经不再需要了。移除这个常量有助于简化代码并减少潜在的混淆。 --- src/WebGPUBase.ts | 3 +-- src/WebGPUCache.ts | 3 +-- src/caches/getGPUBindGroup.ts | 4 +--- src/const.ts | 1 - 4 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 src/const.ts diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index c13b88a..75841e9 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -13,7 +13,6 @@ import { getGPURenderTimestampQuery } from "./caches/getGPURenderTimestampQuery" import { getGPUTexture } from "./caches/getGPUTexture"; import { getGBuffer } from "./caches/getIGPUBuffer"; import { getNVertexBuffers } from "./caches/getNGPUVertexBuffers"; -import { getRealGPUBindGroup } from "./const"; import { ComputeObject } from "./data/ComputeObject"; import { ComputePass } from "./data/ComputePass"; import "./data/polyfills/RenderObject"; @@ -374,7 +373,7 @@ export class WebGPUBase const layout = getGPUPipelineLayout(device, { compute: pipeline.compute.code }); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { - const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources)[getRealGPUBindGroup](); + const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources); passEncoder.setBindGroup(group, gpuBindGroup); }); diff --git a/src/WebGPUCache.ts b/src/WebGPUCache.ts index 44fba11..fbd0e37 100644 --- a/src/WebGPUCache.ts +++ b/src/WebGPUCache.ts @@ -2,7 +2,6 @@ import { ChainMap, RenderObject, RenderPassObject } from "@feng3d/render-api"; import { watcher } from "@feng3d/watcher"; import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; -import { getRealGPUBindGroup } from "./const"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { WebGPUBase } from "./WebGPUBase"; @@ -162,7 +161,7 @@ function runCommands(_passEncoder: GPURenderPassEncoder | GPUComputePassEncoder setBindGroupCommands.forEach((v) => { - v[1][1] = v[1][1][getRealGPUBindGroup](); + v[1][1] = v[1][1](); }); commands.forEach((v) => diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 94734b6..dd4804d 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,7 +1,5 @@ -import { BindingResource, BindingResources, BufferBinding, BufferBindingInfo, CanvasTexture, ChainMap, computed, ComputedRef, Sampler, TextureView } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; +import { BindingResource, BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, Sampler, TextureView } from "@feng3d/render-api"; import { ResourceType } from "wgsl_reflect"; -import { getRealGPUBindGroup } from "../const"; import { VideoTexture } from "../data/VideoTexture"; import { ExternalSampledTextureType } from "../types/TextureType"; import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; diff --git a/src/const.ts b/src/const.ts deleted file mode 100644 index 38e90d3..0000000 --- a/src/const.ts +++ /dev/null @@ -1 +0,0 @@ -export const getRealGPUBindGroup = "getRealGPUBindGroup"; \ No newline at end of file -- Gitee From ee6e117d2694f93d2ed9a123bd8620de911257d2 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 11:46:35 +0800 Subject: [PATCH 146/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20getGPUBindGroup=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了不必要的导入项 - 简化了 bindGroupLayout.entries 的处理方式 - 删除了未使用的接口定义 BindGroupDescriptor 和 BindGroupEntry --- src/caches/getGPUBindGroup.ts | 46 ++--------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index dd4804d..789f67d 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,4 +1,4 @@ -import { BindingResource, BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, Sampler, TextureView } from "@feng3d/render-api"; +import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, Sampler, TextureView } from "@feng3d/render-api"; import { ResourceType } from "wgsl_reflect"; import { VideoTexture } from "../data/VideoTexture"; import { ExternalSampledTextureType } from "../types/TextureType"; @@ -18,7 +18,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup let gBindGroup: GPUBindGroup; result = computed(() => { - const entries = (bindGroupLayout.entries as GPUBindGroupLayoutEntry[]).map((v) => + const entries = bindGroupLayout.entries.map((v) => { const { name, type, resourceType, binding } = v.variableInfo; @@ -74,45 +74,3 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup } type GetGPUBindGroupKey = [device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; const getGPUBindGroupMap = new ChainMap>(); -/** - * GPU 绑定组。 - * - * @see GPUBindGroupDescriptor - * @see GPUDevice.createBindGroup - */ -export interface BindGroupDescriptor -{ - /** - * The initial value of {@link GPUObjectBase#label|GPUObjectBase.label}. - */ - label?: string; - - /** - * The {@link IGPUBindGroupLayoutDescriptor} the entries of this bind group will conform to. - */ - layout: GPUBindGroupLayoutDescriptor; - - /** - * A list of entries describing the resources to expose to the shader for each binding - * described by the {@link GPUBindGroupDescriptor#layout}. - * - * {@link GPUBindGroupEntry} - */ - entries: BindGroupEntry[]; -} - -/** - * 绑定资源入口,指定资源绑定的位置。 - * - * @see GPUBindGroupEntry - */ -export interface BindGroupEntry -{ - binding: GPUIndex32; - - /** - * The resource to bind, which may be a {@link GPUSampler}, {@link GPUTextureView}, - * {@link GPUExternalTexture}, or {@link GPUBufferBinding}. - */ - resource: Sampler | TextureView | VideoTexture | BindingResource; -} -- Gitee From c935f0f778ce5f969045af1e6289399fbbcbbb9b Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 13:33:08 +0800 Subject: [PATCH 147/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20getGPUBindGroup=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 getGPUBindingResource 和 getGPUExternalTexture 函数,用于处理不同类型的资源绑定 - 使用 computed 和 reactive 优化性能,避免不必要的重新计算 - 改进缓冲区绑定信息的获取和缓存机制 - 优化统一变量数据的更新逻辑 --- src/caches/getGPUBindGroup.ts | 92 +++++++++++++++++++++++-------- src/utils/getBufferBindingInfo.ts | 23 +++++++- src/utils/updateBufferBinding.ts | 4 +- 3 files changed, 91 insertions(+), 28 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 789f67d..a1cd780 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,6 +1,7 @@ -import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, Sampler, TextureView } from "@feng3d/render-api"; -import { ResourceType } from "wgsl_reflect"; +import { BindingResources, BufferBinding, ChainMap, computed, ComputedRef, reactive, Sampler, TextureView } from "@feng3d/render-api"; +import { ResourceType, TypeInfo } from "wgsl_reflect"; import { VideoTexture } from "../data/VideoTexture"; +import { webgpuEvents } from "../eventnames"; import { ExternalSampledTextureType } from "../types/TextureType"; import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; import { updateBufferBinding } from "../utils/updateBufferBinding"; @@ -27,30 +28,11 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup // if (resourceType === ResourceType.Uniform || resourceType === ResourceType.Storage) { - const resource = bindingResources[name] as BufferBinding; - - const bufferBinding = ((typeof resource === "number") ? [resource] : resource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 - const bufferBindingInfo: BufferBindingInfo = type["_bufferBindingInfo"] = type["_bufferBindingInfo"] || getBufferBindingInfo(type); - // 更新缓冲区绑定的数据。 - updateBufferBinding(name, bufferBindingInfo, bufferBinding); - // - const gbuffer = getGBuffer(bufferBinding.bufferView); - (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); - // - const buffer = getGPUBuffer(device, gbuffer); - - const offset = resource.bufferView.byteOffset; - const size = resource.bufferView.byteLength; - - entry.resource = { - buffer, - offset, - size, - }; + entry.resource = getGPUBindingResource(device, bindingResources, name, type); } else if (ExternalSampledTextureType[type.name]) // 判断是否为外部纹理 { - entry.resource = device.importExternalTexture(bindingResources[name] as VideoTexture); + entry.resource = getGPUExternalTexture(device, bindingResources[name] as VideoTexture); } else if (resourceType === ResourceType.Texture || resourceType === ResourceType.StorageTexture) { @@ -74,3 +56,67 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup } type GetGPUBindGroupKey = [device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; const getGPUBindGroupMap = new ChainMap>(); + +function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo) +{ + const getGPUBindingResourceKey: GetGPUBindingResourceKey = [device, bindingResources, name, type]; + let result = getGPUBindingResourceMap.get(getGPUBindingResourceKey); + if (result) return result.value; + + result = computed(() => + { + // 监听 + const r_bindingResources = reactive(bindingResources); + (r_bindingResources[name] as BufferBinding)?.bufferView; + + // 执行 + const resource = bindingResources[name] as BufferBinding; + const bufferBinding = ((typeof resource === "number") ? [resource] : resource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 + const bufferBindingInfo = getBufferBindingInfo(type); + // 更新缓冲区绑定的数据。 + updateBufferBinding(bufferBindingInfo, bufferBinding); + // + const gbuffer = getGBuffer(bufferBinding.bufferView); + (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); + // + const buffer = getGPUBuffer(device, gbuffer); + + const offset = resource.bufferView.byteOffset; + const size = resource.bufferView.byteLength; + + const gpuBindingResource: GPUBindingResource = { + buffer, + offset, + size, + }; + + return gpuBindingResource; + }); + + getGPUBindingResourceMap.set(getGPUBindingResourceKey, result); + + return result.value; +} +type GetGPUBindingResourceKey = [device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo]; +const getGPUBindingResourceMap = new ChainMap>(); + +function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) +{ + let result = getGPUExternalTextureMap.get(videoTexture); + if (result) return result.value; + + result = computed(() => + { + // 监听 + reactive(webgpuEvents).preSubmit; + + // + const resource = device.importExternalTexture(videoTexture); + + return resource; + }); + getGPUExternalTextureMap.set(videoTexture, result); + + return result.value; +} +const getGPUExternalTextureMap = new WeakMap>(); diff --git a/src/utils/getBufferBindingInfo.ts b/src/utils/getBufferBindingInfo.ts index 821ba5b..0f24703 100644 --- a/src/utils/getBufferBindingInfo.ts +++ b/src/utils/getBufferBindingInfo.ts @@ -1,6 +1,23 @@ import { BufferBindingInfo } from "@feng3d/render-api"; import { ArrayInfo, StructInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; +/** + * 获取缓冲区绑定信息。 + * + * @param type 类型信息。 + * @returns + */ +export function getBufferBindingInfo(type: TypeInfo) +{ + let result = bufferBindingInfoMap.get(type); + if (result) return result; + result = _getBufferBindingInfo(type); + + bufferBindingInfoMap.set(type, result); + return result; +} +const bufferBindingInfoMap = new Map(); + /** * 获取缓冲区绑定信息。 * @@ -10,7 +27,7 @@ import { ArrayInfo, StructInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; * @param bufferBindingInfo 缓冲区绑定信息。 * @returns */ -export function getBufferBindingInfo(type: TypeInfo, paths: string[] = [], offset = 0, bufferBindingInfo: BufferBindingInfo = { size: type.size, items: [] }) +function _getBufferBindingInfo(type: TypeInfo, paths: string[] = [], offset = 0, bufferBindingInfo: BufferBindingInfo = { size: type.size, items: [] }) { if (type.isStruct) { @@ -18,7 +35,7 @@ export function getBufferBindingInfo(type: TypeInfo, paths: string[] = [], offse for (let i = 0; i < structInfo.members.length; i++) { const memberInfo = structInfo.members[i]; - getBufferBindingInfo(memberInfo.type, paths.concat(memberInfo.name), offset + memberInfo.offset, bufferBindingInfo); + _getBufferBindingInfo(memberInfo.type, paths.concat(memberInfo.name), offset + memberInfo.offset, bufferBindingInfo); } } else if (type.isArray) @@ -26,7 +43,7 @@ export function getBufferBindingInfo(type: TypeInfo, paths: string[] = [], offse const arrayInfo = type as ArrayInfo; for (let i = 0; i < arrayInfo.count; i++) { - getBufferBindingInfo(arrayInfo.format, paths.concat(`${i}`), offset + i * arrayInfo.format.size, bufferBindingInfo); + _getBufferBindingInfo(arrayInfo.format, paths.concat(`${i}`), offset + i * arrayInfo.format.size, bufferBindingInfo); } } else if (type.isTemplate) diff --git a/src/utils/updateBufferBinding.ts b/src/utils/updateBufferBinding.ts index 8ffbfa2..48ca33a 100644 --- a/src/utils/updateBufferBinding.ts +++ b/src/utils/updateBufferBinding.ts @@ -11,14 +11,14 @@ import { getGBuffer } from "../caches/getIGPUBuffer"; * @param uniformData * @returns */ -export function updateBufferBinding(resourceName: string, bufferBindingInfo: BufferBindingInfo, uniformData: BufferBinding) +export function updateBufferBinding(bufferBindingInfo: BufferBindingInfo, uniformData: BufferBinding) { if (uniformData["_variableInfo"] !== undefined) { const preVariableInfo = uniformData["_variableInfo"] as any as VariableInfo; if (preVariableInfo.size !== bufferBindingInfo.size) { - console.warn(`updateBufferBinding ${resourceName} 出现一份数据对应多个 variableInfo`, { uniformData, bufferBindingInfo, preVariableInfo }); + console.warn(`updateBufferBinding ${preVariableInfo.name} 出现一份数据对应多个 variableInfo`, { uniformData, bufferBindingInfo, preVariableInfo }); } return; -- Gitee From 363119509972d3efd8a1b32f48758291314a910c Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 13:51:53 +0800 Subject: [PATCH 148/214] =?UTF-8?q?refactor(caches):=20=E5=B0=86=E7=BC=93?= =?UTF-8?q?=E5=86=B2=E5=8C=BA=E7=BB=91=E5=AE=9A=E7=9B=B8=E5=85=B3=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E7=A7=BB=E8=87=B3=20getGPUBindGroup.ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 getBufferBindingInfo 和 updateBufferBinding 函数从 utils 文件夹移至 getGPUBindGroup.ts - 优化了缓冲区绑定的处理逻辑,支持数字类型的资源 - 调整了相关引用和类型定义 --- src/caches/getGPUBindGroup.ts | 240 ++++++++++++++++++++++++++++-- src/utils/getBufferBindingInfo.ts | 138 ----------------- src/utils/updateBufferBinding.ts | 81 ---------- 3 files changed, 230 insertions(+), 229 deletions(-) delete mode 100644 src/utils/getBufferBindingInfo.ts delete mode 100644 src/utils/updateBufferBinding.ts diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index a1cd780..cda9cce 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,10 +1,9 @@ -import { BindingResources, BufferBinding, ChainMap, computed, ComputedRef, reactive, Sampler, TextureView } from "@feng3d/render-api"; -import { ResourceType, TypeInfo } from "wgsl_reflect"; +import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, reactive, Sampler, TextureView, UnReadonly } from "@feng3d/render-api"; +import { watcher } from "@feng3d/watcher"; +import { ArrayInfo, ResourceType, StructInfo, TemplateInfo, TypeInfo, VariableInfo } from "wgsl_reflect"; import { VideoTexture } from "../data/VideoTexture"; import { webgpuEvents } from "../eventnames"; import { ExternalSampledTextureType } from "../types/TextureType"; -import { getBufferBindingInfo } from "../utils/getBufferBindingInfo"; -import { updateBufferBinding } from "../utils/updateBufferBinding"; import { getGPUBuffer } from "./getGPUBuffer"; import { getGPUSampler } from "./getGPUSampler"; import { getGPUTextureView } from "./getGPUTextureView"; @@ -63,6 +62,7 @@ function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResou let result = getGPUBindingResourceMap.get(getGPUBindingResourceKey); if (result) return result.value; + let numberBufferBinding: number[]; result = computed(() => { // 监听 @@ -70,19 +70,25 @@ function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResou (r_bindingResources[name] as BufferBinding)?.bufferView; // 执行 - const resource = bindingResources[name] as BufferBinding; - const bufferBinding = ((typeof resource === "number") ? [resource] : resource) as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 - const bufferBindingInfo = getBufferBindingInfo(type); + let resource = bindingResources[name]; + // 当值为number时,将其视为一个数组。 + if (typeof resource === "number") + { + numberBufferBinding ??= []; + numberBufferBinding[0] = resource; + resource = numberBufferBinding; + } + const bufferBinding = resource as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 // 更新缓冲区绑定的数据。 - updateBufferBinding(bufferBindingInfo, bufferBinding); + updateBufferBinding(type, bufferBinding); // const gbuffer = getGBuffer(bufferBinding.bufferView); (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); // const buffer = getGPUBuffer(device, gbuffer); - const offset = resource.bufferView.byteOffset; - const size = resource.bufferView.byteLength; + const offset = bufferBinding.bufferView.byteOffset; + const size = bufferBinding.bufferView.byteLength; const gpuBindingResource: GPUBindingResource = { buffer, @@ -120,3 +126,217 @@ function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) return result.value; } const getGPUExternalTextureMap = new WeakMap>(); + + +/** + * 初始化缓冲区绑定。 + * + * @param variableInfo + * @param uniformData + * @returns + */ +export function updateBufferBinding(type: TypeInfo, uniformData: BufferBinding) +{ + const bufferBindingInfo = getBufferBindingInfo(type); + if (uniformData["_variableInfo"] !== undefined) + { + const preVariableInfo = uniformData["_variableInfo"] as any as VariableInfo; + if (preVariableInfo.size !== bufferBindingInfo.size) + { + console.warn(`updateBufferBinding ${preVariableInfo.name} 出现一份数据对应多个 variableInfo`, { uniformData, bufferBindingInfo, preVariableInfo }); + } + + return; + } + uniformData["_variableInfo"] = bufferBindingInfo as any; + + const size = bufferBindingInfo.size; + // 是否存在默认值。 + const hasDefautValue = !!uniformData.bufferView; + if (!hasDefautValue) + { + (uniformData as UnReadonly).bufferView = new Uint8Array(size); + } + + const buffer = getGBuffer(uniformData.bufferView); + const offset = uniformData.bufferView.byteOffset; + + for (let i = 0; i < bufferBindingInfo.items.length; i++) + { + const { paths, offset: itemInfoOffset, size: itemInfoSize, Cls } = bufferBindingInfo.items[i]; + const update = () => + { + let value: any = uniformData; + for (let i = 0; i < paths.length; i++) + { + value = value[paths[i]]; + if (value === undefined) + { + if (!hasDefautValue) + { + console.warn(`没有找到 统一块变量属性 ${paths.join(".")} 的值!`); + } + + return; + } + } + + let data: Float32Array | Int32Array | Uint32Array | Int16Array; + if (typeof value === "number") + { + data = new Cls([value]); + } + else if (value.constructor.name !== Cls.name) + { + data = new Cls(value as ArrayLike); + } + else + { + data = value as any; + } + + const writeBuffers = buffer.writeBuffers ?? []; + writeBuffers.push({ bufferOffset: offset + itemInfoOffset, data: data.buffer, dataOffset: data.byteOffset, size: Math.min(itemInfoSize, data.byteLength) }); + reactive(buffer).writeBuffers = writeBuffers; + }; + + update(); + watcher.watchchain(uniformData, paths.join("."), update, undefined, false); + } +} + +/** + * 获取缓冲区绑定信息。 + * + * @param type 类型信息。 + * @returns + */ +function getBufferBindingInfo(type: TypeInfo) +{ + let result = bufferBindingInfoMap.get(type); + if (result) return result; + result = _getBufferBindingInfo(type); + + bufferBindingInfoMap.set(type, result); + return result; +} +const bufferBindingInfoMap = new Map(); + +/** + * 获取缓冲区绑定信息。 + * + * @param type 类型信息。 + * @param paths 当前路径。 + * @param offset 当前编译。 + * @param bufferBindingInfo 缓冲区绑定信息。 + * @returns + */ +function _getBufferBindingInfo(type: TypeInfo, paths: string[] = [], offset = 0, bufferBindingInfo: BufferBindingInfo = { size: type.size, items: [] }) +{ + if (type.isStruct) + { + const structInfo = type as StructInfo; + for (let i = 0; i < structInfo.members.length; i++) + { + const memberInfo = structInfo.members[i]; + _getBufferBindingInfo(memberInfo.type, paths.concat(memberInfo.name), offset + memberInfo.offset, bufferBindingInfo); + } + } + else if (type.isArray) + { + const arrayInfo = type as ArrayInfo; + for (let i = 0; i < arrayInfo.count; i++) + { + _getBufferBindingInfo(arrayInfo.format, paths.concat(`${i}`), offset + i * arrayInfo.format.size, bufferBindingInfo); + } + } + else if (type.isTemplate) + { + const templateInfo = type as TemplateInfo; + const templateFormatName = templateInfo.format?.name; + bufferBindingInfo.items.push({ + paths: paths.concat(), + offset, + size: templateInfo.size, + Cls: getTemplateDataCls(templateFormatName as any), + }); + } + else + { + bufferBindingInfo.items.push({ + paths: paths.concat(), + offset, + size: type.size, + Cls: getBaseTypeDataCls(type.name), + }); + } + + return bufferBindingInfo; +} + +function getBaseTypeDataCls(baseTypeName: string) +{ + const dataCls = baseTypeDataCls[baseTypeName]; + + console.assert(!!dataCls, `baseTypeName必须为以下值 ${Object.keys(baseTypeDataCls)}`); + + return dataCls; +} + +/** + * @see https://gpuweb.github.io/gpuweb/wgsl/#vec2i + */ +const baseTypeDataCls: { [key: string]: DataCls } = { + i32: Int32Array, + u32: Uint32Array, + f32: Float32Array, + f16: Int16Array, + vec2i: Int32Array, + vec3i: Int32Array, + vec4i: Int32Array, + vec2u: Uint32Array, + vec3u: Uint32Array, + vec4u: Uint32Array, + vec2f: Float32Array, + vec3f: Float32Array, + vec4f: Float32Array, + vec2h: Int16Array, + vec3h: Int16Array, + vec4h: Int16Array, + mat2x2f: Float32Array, + mat2x3f: Float32Array, + mat2x4f: Float32Array, + mat3x2f: Float32Array, + mat3x3f: Float32Array, + mat3x4f: Float32Array, + mat4x2f: Float32Array, + mat4x3f: Float32Array, + mat4x4f: Float32Array, + mat2x2h: Float32Array, + mat2x3h: Float32Array, + mat2x4h: Float32Array, + mat3x2h: Float32Array, + mat3x3h: Float32Array, + mat3x4h: Float32Array, + mat4x2h: Float32Array, + mat4x3h: Float32Array, + mat4x4h: Float32Array, +}; + +function getTemplateDataCls(templateFormatName: "i32" | "u32" | "f32" | "f16") +{ + const dataCls = templateFormatDataCls[templateFormatName]; + + console.assert(!!dataCls, `templateFormatName必须为以下值 ${Object.keys(templateFormatDataCls)}`); + + return dataCls; +} +const templateFormatDataCls: { [key: string]: DataCls } = { + i32: Int32Array, + u32: Uint32Array, + f32: Float32Array, + f16: Int16Array, +}; + +type DataCls = Float32ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Int16ArrayConstructor; + diff --git a/src/utils/getBufferBindingInfo.ts b/src/utils/getBufferBindingInfo.ts deleted file mode 100644 index 0f24703..0000000 --- a/src/utils/getBufferBindingInfo.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { BufferBindingInfo } from "@feng3d/render-api"; -import { ArrayInfo, StructInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; - -/** - * 获取缓冲区绑定信息。 - * - * @param type 类型信息。 - * @returns - */ -export function getBufferBindingInfo(type: TypeInfo) -{ - let result = bufferBindingInfoMap.get(type); - if (result) return result; - result = _getBufferBindingInfo(type); - - bufferBindingInfoMap.set(type, result); - return result; -} -const bufferBindingInfoMap = new Map(); - -/** - * 获取缓冲区绑定信息。 - * - * @param type 类型信息。 - * @param paths 当前路径。 - * @param offset 当前编译。 - * @param bufferBindingInfo 缓冲区绑定信息。 - * @returns - */ -function _getBufferBindingInfo(type: TypeInfo, paths: string[] = [], offset = 0, bufferBindingInfo: BufferBindingInfo = { size: type.size, items: [] }) -{ - if (type.isStruct) - { - const structInfo = type as StructInfo; - for (let i = 0; i < structInfo.members.length; i++) - { - const memberInfo = structInfo.members[i]; - _getBufferBindingInfo(memberInfo.type, paths.concat(memberInfo.name), offset + memberInfo.offset, bufferBindingInfo); - } - } - else if (type.isArray) - { - const arrayInfo = type as ArrayInfo; - for (let i = 0; i < arrayInfo.count; i++) - { - _getBufferBindingInfo(arrayInfo.format, paths.concat(`${i}`), offset + i * arrayInfo.format.size, bufferBindingInfo); - } - } - else if (type.isTemplate) - { - const templateInfo = type as TemplateInfo; - const templateFormatName = templateInfo.format?.name; - bufferBindingInfo.items.push({ - paths: paths.concat(), - offset, - size: templateInfo.size, - Cls: getTemplateDataCls(templateFormatName as any), - }); - } - else - { - bufferBindingInfo.items.push({ - paths: paths.concat(), - offset, - size: type.size, - Cls: getBaseTypeDataCls(type.name), - }); - } - - return bufferBindingInfo; -} - -function getBaseTypeDataCls(baseTypeName: string) -{ - const dataCls = baseTypeDataCls[baseTypeName]; - - console.assert(!!dataCls, `baseTypeName必须为以下值 ${Object.keys(baseTypeDataCls)}`); - - return dataCls; -} - -/** - * @see https://gpuweb.github.io/gpuweb/wgsl/#vec2i - */ -const baseTypeDataCls: { [key: string]: DataCls } = { - i32: Int32Array, - u32: Uint32Array, - f32: Float32Array, - f16: Int16Array, - vec2i: Int32Array, - vec3i: Int32Array, - vec4i: Int32Array, - vec2u: Uint32Array, - vec3u: Uint32Array, - vec4u: Uint32Array, - vec2f: Float32Array, - vec3f: Float32Array, - vec4f: Float32Array, - vec2h: Int16Array, - vec3h: Int16Array, - vec4h: Int16Array, - mat2x2f: Float32Array, - mat2x3f: Float32Array, - mat2x4f: Float32Array, - mat3x2f: Float32Array, - mat3x3f: Float32Array, - mat3x4f: Float32Array, - mat4x2f: Float32Array, - mat4x3f: Float32Array, - mat4x4f: Float32Array, - mat2x2h: Float32Array, - mat2x3h: Float32Array, - mat2x4h: Float32Array, - mat3x2h: Float32Array, - mat3x3h: Float32Array, - mat3x4h: Float32Array, - mat4x2h: Float32Array, - mat4x3h: Float32Array, - mat4x4h: Float32Array, -}; - -function getTemplateDataCls(templateFormatName: "i32" | "u32" | "f32" | "f16") -{ - const dataCls = templateFormatDataCls[templateFormatName]; - - console.assert(!!dataCls, `templateFormatName必须为以下值 ${Object.keys(templateFormatDataCls)}`); - - return dataCls; -} -const templateFormatDataCls: { [key: string]: DataCls } = { - i32: Int32Array, - u32: Uint32Array, - f32: Float32Array, - f16: Int16Array, -}; - -type DataCls = Float32ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Int16ArrayConstructor; - diff --git a/src/utils/updateBufferBinding.ts b/src/utils/updateBufferBinding.ts deleted file mode 100644 index 48ca33a..0000000 --- a/src/utils/updateBufferBinding.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { BufferBinding, BufferBindingInfo, reactive, UnReadonly } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; -import { VariableInfo } from "wgsl_reflect"; - -import { getGBuffer } from "../caches/getIGPUBuffer"; - -/** - * 初始化缓冲区绑定。 - * - * @param variableInfo - * @param uniformData - * @returns - */ -export function updateBufferBinding(bufferBindingInfo: BufferBindingInfo, uniformData: BufferBinding) -{ - if (uniformData["_variableInfo"] !== undefined) - { - const preVariableInfo = uniformData["_variableInfo"] as any as VariableInfo; - if (preVariableInfo.size !== bufferBindingInfo.size) - { - console.warn(`updateBufferBinding ${preVariableInfo.name} 出现一份数据对应多个 variableInfo`, { uniformData, bufferBindingInfo, preVariableInfo }); - } - - return; - } - uniformData["_variableInfo"] = bufferBindingInfo as any; - - const size = bufferBindingInfo.size; - // 是否存在默认值。 - const hasDefautValue = !!uniformData.bufferView; - if (!hasDefautValue) - { - (uniformData as UnReadonly).bufferView = new Uint8Array(size); - } - - const buffer = getGBuffer(uniformData.bufferView); - const offset = uniformData.bufferView.byteOffset; - - for (let i = 0; i < bufferBindingInfo.items.length; i++) - { - const { paths, offset: itemInfoOffset, size: itemInfoSize, Cls } = bufferBindingInfo.items[i]; - const update = () => - { - let value: any = uniformData; - for (let i = 0; i < paths.length; i++) - { - value = value[paths[i]]; - if (value === undefined) - { - if (!hasDefautValue) - { - console.warn(`没有找到 统一块变量属性 ${paths.join(".")} 的值!`); - } - - return; - } - } - - let data: Float32Array | Int32Array | Uint32Array | Int16Array; - if (typeof value === "number") - { - data = new Cls([value]); - } - else if (value.constructor.name !== Cls.name) - { - data = new Cls(value as ArrayLike); - } - else - { - data = value as any; - } - - const writeBuffers = buffer.writeBuffers ?? []; - writeBuffers.push({ bufferOffset: offset + itemInfoOffset, data: data.buffer, dataOffset: data.byteOffset, size: Math.min(itemInfoSize, data.byteLength) }); - reactive(buffer).writeBuffers = writeBuffers; - }; - - update(); - watcher.watchchain(uniformData, paths.join("."), update, undefined, false); - } -} -- Gitee From 88c6528e8167710a5d36da05817fe9c04f3d833d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 15:05:03 +0800 Subject: [PATCH 149/214] =?UTF-8?q?feat(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BB=91=E5=AE=9A=E5=92=8C=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新了 RenderObjectChanges 示例中的顶点和片段着色器代码 - 改进了 bitonicSort 示例中的数据绑定方式 - 优化了 getGPUBindGroup 中的缓冲区绑定更新逻辑 --- .../src/webgpu/RenderObjectChanges/index.ts | 52 +++++++++---------- .../src/webgpu/bitonicSort/bitonicDisplay.ts | 4 +- src/caches/getGPUBindGroup.ts | 19 +++---- 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index 1d2f367..ff24f4a 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -70,34 +70,34 @@ const init = async (canvas: HTMLCanvasElement) => reactive(renderObject.geometry.vertices.position).stepMode = "instance"; reactive(renderObject.geometry.vertices.position).stepMode = "vertex"; reactive(renderObject.geometry.vertices.position).data = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -1]); - // reactive(renderObject.geometry.vertices.position).format = "float32x3"; - // reactive(renderObject.geometry.vertices.position).data = new Float32Array([0.0, 0.5,1.0, -0.5, -0.5,1.0, 0.5, -1,1.0]); + reactive(renderObject.geometry.vertices.position).format = "float32x3"; + reactive(renderObject.geometry.vertices.position).data = new Float32Array([1.0, 0.5, 1.0, -0.5, -0.5, 1.0, 0.5, -1, 1.0]); // 修改顶点着色器代码 - // reactive(renderObject.pipeline.vertex).code = ` - // @vertex - // fn main( - // @location(0) position: vec2, - // ) -> @builtin(position) vec4 { - // var pos = position; - // pos.x = pos.x + 0.5; - // return vec4(pos, 0.0, 1.0); - // } - // `; + reactive(renderObject.pipeline.vertex).code = ` + @vertex + fn main( + @location(0) position: vec2, + ) -> @builtin(position) vec4 { + var pos = position; + pos.x = pos.x + 0.5; + return vec4(pos, 0.0, 1.0); + } + `; + + // 修改片段着色器代码 + reactive(renderObject.pipeline.fragment).code = ` + @binding(0) @group(0) var color : vec4; + @fragment + fn main() -> @location(0) vec4f { + var col = color; + col.x = 0.5; + col.y = 0.6; + col.z = 0.7; + return col; + } + `; - // // 修改片段着色器代码 - // reactive(renderObject.pipeline.fragment).code = ` - // @binding(0) @group(0) var color : vec4; - // @fragment - // fn main() -> @location(0) vec4f { - // var col = color; - // col.x = 0.5; - // col.y = 0.6; - // col.z = 0.7; - // return col; - // } - // `; - // - // renderObject.uniforms.color = [0, 1, 0, 1]; + reactive(renderObject.bindingResources).color = [0, 1, 0, 1]; }; }; diff --git a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts index e564e18..899e052 100644 --- a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts +++ b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts @@ -1,4 +1,4 @@ -import { BindingResources, BufferBinding, CommandEncoder, RenderPassDescriptor } from "@feng3d/render-api"; +import { BindingResources, BufferBinding, CommandEncoder, reactive, RenderPassDescriptor } from "@feng3d/render-api"; import bitonicDisplay from "./bitonicDisplay.frag.wgsl"; import { Base2DRendererClass } from "./utils"; @@ -28,7 +28,7 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass highlight: undefined, }; - computeBGDescript.fragment_uniforms = fragment_uniforms; + reactive(computeBGDescript).fragment_uniforms = fragment_uniforms; this.pipeline = super.create2DRenderPipeline( label, diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index cda9cce..faed7f0 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -145,10 +145,11 @@ export function updateBufferBinding(type: TypeInfo, uniformData: BufferBinding) { console.warn(`updateBufferBinding ${preVariableInfo.name} 出现一份数据对应多个 variableInfo`, { uniformData, bufferBindingInfo, preVariableInfo }); } - - return; } - uniformData["_variableInfo"] = bufferBindingInfo as any; + else + { + uniformData["_variableInfo"] = bufferBindingInfo as any; + } const size = bufferBindingInfo.size; // 是否存在默认值。 @@ -164,9 +165,11 @@ export function updateBufferBinding(type: TypeInfo, uniformData: BufferBinding) for (let i = 0; i < bufferBindingInfo.items.length; i++) { const { paths, offset: itemInfoOffset, size: itemInfoSize, Cls } = bufferBindingInfo.items[i]; - const update = () => + // 更新数据 + computed(() => { - let value: any = uniformData; + // 监听 + let value: any = reactive(uniformData); for (let i = 0; i < paths.length; i++) { value = value[paths[i]]; @@ -181,6 +184,7 @@ export function updateBufferBinding(type: TypeInfo, uniformData: BufferBinding) } } + // 更新数据 let data: Float32Array | Int32Array | Uint32Array | Int16Array; if (typeof value === "number") { @@ -198,10 +202,7 @@ export function updateBufferBinding(type: TypeInfo, uniformData: BufferBinding) const writeBuffers = buffer.writeBuffers ?? []; writeBuffers.push({ bufferOffset: offset + itemInfoOffset, data: data.buffer, dataOffset: data.byteOffset, size: Math.min(itemInfoSize, data.byteLength) }); reactive(buffer).writeBuffers = writeBuffers; - }; - - update(); - watcher.watchchain(uniformData, paths.join("."), update, undefined, false); + }).value; } } -- Gitee From 199446c9967027ced96a88a7a3fca75d4a5c8f90 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 15:16:46 +0800 Subject: [PATCH 150/214] =?UTF-8?q?refactor(src):=20=E9=87=8D=E6=9E=84=20u?= =?UTF-8?q?pdateBufferBinding=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整函数参数顺序,提高可读性 - 引入缓存机制,避免重复计算 - 优化内部逻辑,提高执行效率 - 修复了一些潜在的 bug 和警告 --- src/caches/getGPUBindGroup.ts | 110 +++++++++++++++++----------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index faed7f0..7dba13b 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -80,7 +80,7 @@ function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResou } const bufferBinding = resource as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 // 更新缓冲区绑定的数据。 - updateBufferBinding(type, bufferBinding); + updateBufferBinding(bufferBinding, type); // const gbuffer = getGBuffer(bufferBinding.bufferView); (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); @@ -135,76 +135,76 @@ const getGPUExternalTextureMap = new WeakMap { - const preVariableInfo = uniformData["_variableInfo"] as any as VariableInfo; - if (preVariableInfo.size !== bufferBindingInfo.size) + const bufferBindingInfo = getBufferBindingInfo(type); + + const size = bufferBindingInfo.size; + // 是否存在默认值。 + const hasDefautValue = !!uniformData.bufferView; + if (!hasDefautValue) { - console.warn(`updateBufferBinding ${preVariableInfo.name} 出现一份数据对应多个 variableInfo`, { uniformData, bufferBindingInfo, preVariableInfo }); + (uniformData as UnReadonly).bufferView = new Uint8Array(size); } - } - else - { - uniformData["_variableInfo"] = bufferBindingInfo as any; - } - const size = bufferBindingInfo.size; - // 是否存在默认值。 - const hasDefautValue = !!uniformData.bufferView; - if (!hasDefautValue) - { - (uniformData as UnReadonly).bufferView = new Uint8Array(size); - } - - const buffer = getGBuffer(uniformData.bufferView); - const offset = uniformData.bufferView.byteOffset; + const buffer = getGBuffer(uniformData.bufferView); + const offset = uniformData.bufferView.byteOffset; - for (let i = 0; i < bufferBindingInfo.items.length; i++) - { - const { paths, offset: itemInfoOffset, size: itemInfoSize, Cls } = bufferBindingInfo.items[i]; - // 更新数据 - computed(() => + for (let i = 0; i < bufferBindingInfo.items.length; i++) { - // 监听 - let value: any = reactive(uniformData); - for (let i = 0; i < paths.length; i++) + const { paths, offset: itemInfoOffset, size: itemInfoSize, Cls } = bufferBindingInfo.items[i]; + // 更新数据 + computed(() => { - value = value[paths[i]]; - if (value === undefined) + // 监听 + let value: any = reactive(uniformData); + for (let i = 0; i < paths.length; i++) { - if (!hasDefautValue) + value = value[paths[i]]; + if (value === undefined) { - console.warn(`没有找到 统一块变量属性 ${paths.join(".")} 的值!`); + if (!hasDefautValue) + { + console.warn(`没有找到 统一块变量属性 ${paths.join(".")} 的值!`); + } + + return; } + } - return; + // 更新数据 + let data: Float32Array | Int32Array | Uint32Array | Int16Array; + if (typeof value === "number") + { + data = new Cls([value]); + } + else if (value.constructor.name !== Cls.name) + { + data = new Cls(value as ArrayLike); + } + else + { + data = value as any; } - } - // 更新数据 - let data: Float32Array | Int32Array | Uint32Array | Int16Array; - if (typeof value === "number") - { - data = new Cls([value]); - } - else if (value.constructor.name !== Cls.name) - { - data = new Cls(value as ArrayLike); - } - else - { - data = value as any; - } + const writeBuffers = buffer.writeBuffers ?? []; + writeBuffers.push({ bufferOffset: offset + itemInfoOffset, data: data.buffer, dataOffset: data.byteOffset, size: Math.min(itemInfoSize, data.byteLength) }); + reactive(buffer).writeBuffers = writeBuffers; + }).value; + } + }); + updateBufferBindingMap.set(updateBufferBindingKey, result); - const writeBuffers = buffer.writeBuffers ?? []; - writeBuffers.push({ bufferOffset: offset + itemInfoOffset, data: data.buffer, dataOffset: data.byteOffset, size: Math.min(itemInfoSize, data.byteLength) }); - reactive(buffer).writeBuffers = writeBuffers; - }).value; - } + return result.value; } +type UpdateBufferBindingKey = [uniformData: BufferBinding, type: TypeInfo]; +const updateBufferBindingMap = new ChainMap>(); /** * 获取缓冲区绑定信息。 -- Gitee From c09e76519161cf2279d84f24cfc0fc2c0b4ee8f9 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 16:29:43 +0800 Subject: [PATCH 151/214] =?UTF-8?q?refactor(webgpu):=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20reactive=20=E5=87=BD=E6=95=B0=E6=94=B9=E8=BF=9B=20uniform=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在多个示例中,将直接赋值改为使用 reactive 函数更新 uniforms - 优化了 uniform 数据的上传逻辑,提高性能 - 统一了 uniform 更新的代码风格,提高可维护性 --- examples/src/webgpu/a-buffer/index.ts | 8 +- examples/src/webgpu/animometer/index.ts | 4 +- .../src/webgpu/bitonicSort/bitonicDisplay.ts | 2 +- examples/src/webgpu/blending/index.ts | 38 ++++----- examples/src/webgpu/cameras/camera.ts | 77 ++++++++++--------- examples/src/webgpu/cameras/index.ts | 6 +- examples/src/webgpu/cubemap/index.ts | 4 +- examples/src/webgpu/fractalCube/index.ts | 4 +- examples/src/webgpu/instancedCube/index.ts | 5 +- examples/src/webgpu/normalMap/index.ts | 8 +- examples/src/webgpu/points/index.ts | 49 ++++++------ .../src/webgpu/resizeObserverHDDPI/index.ts | 76 +++++++++--------- examples/src/webgpu/reversedZ/index.ts | 4 +- examples/src/webgpu/rotatingCube/index.ts | 7 +- examples/src/webgpu/texturedCube/index.ts | 5 +- examples/src/webgpu/timestampQuery/index.ts | 4 +- .../src/webgpu/transparentCanvas/index.ts | 38 ++++----- examples/src/webgpu/twoCubes/index.ts | 7 +- .../webgpu/volumeRenderingTexture3D/index.ts | 35 +++++---- examples/src/webgpu/wireframe/index.ts | 6 +- examples/src/webgpu/worker/worker.ts | 4 +- src/caches/getGPUTexture.ts | 4 +- 22 files changed, 203 insertions(+), 192 deletions(-) diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 27d3e89..95948fb 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, CanvasContext, PassEncoder, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; +import { BufferBinding, CanvasContext, PassEncoder, reactive, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, TextureView, VertexAttributes } from "@feng3d/render-api"; import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -365,14 +365,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }; // update the uniform buffer - uniforms.maxStorableFragments = averageLayersPerFragment * canvas.width * sliceHeight; - uniforms.targetWidth = canvas.width; + reactive(uniforms).maxStorableFragments = averageLayersPerFragment * canvas.width * sliceHeight; + reactive(uniforms).targetWidth = canvas.width; return function doDraw() { // update the uniform buffer { - uniforms.modelViewProjectionMatrix = getCameraViewProjMatrix(); + reactive(uniforms).modelViewProjectionMatrix = getCameraViewProjMatrix(); } webgpu.submit(submit); diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index 530908c..7841d72 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import animometerWGSL from "./animometer.wgsl"; -import { RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; +import { reactive, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; import { RenderBundle, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -154,7 +154,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } uniformTime[0] = (timestamp - startTime) / 1000; - time.value = uniformTime[0]; + reactive(time).value = uniformTime[0]; if (settings.renderBundles) { diff --git a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts index 899e052..d7e7960 100644 --- a/examples/src/webgpu/bitonicSort/bitonicDisplay.ts +++ b/examples/src/webgpu/bitonicSort/bitonicDisplay.ts @@ -37,7 +37,7 @@ export default class BitonicDisplayRenderer extends Base2DRendererClass this.setArguments = (args: BitonicDisplayRenderArgs) => { - fragment_uniforms.highlight = args.highlight; + reactive(fragment_uniforms).highlight = args.highlight; }; } diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 1d5ef6e..7055528 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -370,7 +370,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ); } } - + const constantColor: Color = [0, 0, 0, 0]; const srcPipeline: RenderPipeline = { label: "hardcoded textured quad pipeline", vertex: { @@ -381,7 +381,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => targets: [ { blend: { - constantColor: [0, 0, 0, 0], + constantColor: constantColor, color: { operation: "add", srcFactor: "one", @@ -410,46 +410,43 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gui .add(settings, "alphaMode", ["opaque", "premultiplied"]) - .name("canvas alphaMode") - .onChange(render); + .name("canvas alphaMode"); gui .add(settings, "textureSet", [ "premultiplied alpha", "un-premultiplied alpha", ]) - .name("texture data") - .onChange(render); + .name("texture data"); gui.add(settings, "preset", [...Object.keys(presets)]).onChange(() => { applyPreset(); - render(); }); const colorFolder = gui.addFolder("color"); colorFolder.open(); - colorFolder.add(r_color, "operation", operations).onChange(render); - colorFolder.add(r_color, "srcFactor", factors).onChange(render); - colorFolder.add(r_color, "dstFactor", factors).onChange(render); + colorFolder.add(r_color, "operation", operations); + colorFolder.add(r_color, "srcFactor", factors); + colorFolder.add(r_color, "dstFactor", factors); const alphaFolder = gui.addFolder("alpha"); alphaFolder.open(); - alphaFolder.add(r_alpha, "operation", operations).onChange(render); - alphaFolder.add(r_alpha, "srcFactor", factors).onChange(render); - alphaFolder.add(r_alpha, "dstFactor", factors).onChange(render); + alphaFolder.add(r_alpha, "operation", operations); + alphaFolder.add(r_alpha, "srcFactor", factors); + alphaFolder.add(r_alpha, "dstFactor", factors); const constantFolder = gui.addFolder("constant"); constantFolder.open(); constantFolder .addColor(new GUIColorHelper(constant.color), "value") .name("color") - .onChange(render); - constantFolder.add(constant, "alpha", 0, 1).onChange(render); + ; + constantFolder.add(constant, "alpha", 0, 1); const clearFolder = gui.addFolder("clear color"); clearFolder.open(); - clearFolder.add(clear, "premultiply").onChange(render); - clearFolder.add(clear, "alpha", 0, 1).onChange(render); - clearFolder.addColor(new GUIColorHelper(clear.color), "value").onChange(render); + clearFolder.add(clear, "premultiply"); + clearFolder.add(clear, "alpha", 0, 1); + clearFolder.addColor(new GUIColorHelper(clear.color), "value"); const dstPipeline: RenderPipeline = { label: "hardcoded textured quad pipeline", @@ -536,6 +533,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => clearValue[3] = alpha; } + constantColor[0] = constant.color[0]; + constantColor[1] = constant.color[1]; + constantColor[2] = constant.color[2]; + constantColor[3] = constant.alpha; + updateUniforms(srcUniform, canvas, srcTexture); updateUniforms(dstUniform, canvas, dstTexture); diff --git a/examples/src/webgpu/cameras/camera.ts b/examples/src/webgpu/cameras/camera.ts index bfbce41..ad9d7da 100644 --- a/examples/src/webgpu/cameras/camera.ts +++ b/examples/src/webgpu/cameras/camera.ts @@ -5,7 +5,8 @@ import { Mat4, Vec3, Vec4, mat4, vec3 } from "wgpu-matrix"; import Input from "./input"; // Common interface for camera implementations -export default interface Camera { +export default interface Camera +{ // update updates the camera using the user-input and returns the view matrix. update(delta_time: number, input: Input): Mat4; @@ -41,67 +42,67 @@ class CameraBase // Returns the camera matrix get matrix() -{ + { return this.matrix_; } // Assigns `mat` to the camera matrix set matrix(mat: Mat4) -{ + { mat4.copy(mat, this.matrix_); } // Returns the camera view matrix get view() -{ + { return this.view_; } // Assigns `mat` to the camera view set view(mat: Mat4) -{ + { mat4.copy(mat, this.view_); } // Returns column vector 0 of the camera matrix get right() -{ + { return this.right_; } // Assigns `vec` to the first 3 elements of column vector 0 of the camera matrix set right(vec: Vec3) -{ + { vec3.copy(vec, this.right_); } // Returns column vector 1 of the camera matrix get up() -{ + { return this.up_; } // Assigns `vec` to the first 3 elements of column vector 1 of the camera matrix set up(vec: Vec3) -{ + { vec3.copy(vec, this.up_); } // Returns column vector 2 of the camera matrix get back() -{ + { return this.back_; } // Assigns `vec` to the first 3 elements of column vector 2 of the camera matrix set back(vec: Vec3) -{ + { vec3.copy(vec, this.back_); } // Returns column vector 3 of the camera matrix get position() -{ + { return this.position_; } // Assigns `vec` to the first 3 elements of column vector 3 of the camera matrix set position(vec: Vec3) -{ + { vec3.copy(vec, this.position_); } } @@ -130,12 +131,12 @@ export class WASDCamera extends CameraBase implements Camera // Returns velocity vector get velocity() -{ + { return this.velocity_; } // Assigns `vec` to the velocity vector set velocity(vec: Vec3) -{ + { vec3.copy(vec, this.velocity_); } @@ -146,10 +147,10 @@ export class WASDCamera extends CameraBase implements Camera // The initial target of the camera target?: Vec3; }) -{ + { super(); if (options && (options.position || options.target)) -{ + { const position = options.position ?? vec3.create(0, 0, -5); const target = options.target ?? vec3.create(0, 0, 0); const back = vec3.normalize(vec3.sub(position, target)); @@ -160,19 +161,19 @@ export class WASDCamera extends CameraBase implements Camera // Returns the camera matrix get matrix() -{ + { return super.matrix; } // Assigns `mat` to the camera matrix, and recalcuates the camera angles set matrix(mat: Mat4) -{ + { super.matrix = mat; this.recalculateAngles(this.back); } update(deltaTime: number, input: Input): Mat4 -{ + { const sign = (positive: boolean, negative: boolean) => (positive ? 1 : 0) - (negative ? 1 : 0); @@ -216,12 +217,12 @@ export class WASDCamera extends CameraBase implements Camera // Invert the camera matrix to build the view matrix this.view = mat4.invert(this.matrix); -return this.view; + return this.view; } // Recalculates the yaw and pitch values from a directional vector recalculateAngles(dir: Vec3) -{ + { this.yaw = Math.atan2(dir[0], dir[2]); this.pitch = -Math.asin(dir[1]); } @@ -241,12 +242,12 @@ export class ArcballCamera extends CameraBase implements Camera // Returns the rotation axis get axis() -{ + { return this.axis_; } // Assigns `vec` to the rotation axis set axis(vec: Vec3) -{ + { vec3.copy(vec, this.axis_); } @@ -266,10 +267,10 @@ export class ArcballCamera extends CameraBase implements Camera // The initial position of the camera position?: Vec3; }) -{ + { super(); if (options && options.position) -{ + { this.position = options.position; this.distance = vec3.len(this.position); this.back = vec3.normalize(this.position); @@ -280,28 +281,28 @@ export class ArcballCamera extends CameraBase implements Camera // Returns the camera matrix get matrix() -{ + { return super.matrix; } // Assigns `mat` to the camera matrix, and recalcuates the distance set matrix(mat: Mat4) -{ + { super.matrix = mat; this.distance = vec3.len(this.position); } update(deltaTime: number, input: Input): Mat4 -{ + { const epsilon = 0.0000001; if (input.analog.touching) -{ + { // Currently being dragged. this.angularVelocity = 0; } - else -{ + else + { // Dampen any existing angular velocity this.angularVelocity *= Math.pow(1 - this.frictionCoefficient, deltaTime); } @@ -318,7 +319,7 @@ export class ArcballCamera extends CameraBase implements Camera const magnitude = vec3.len(crossProduct); if (magnitude > epsilon) -{ + { // Normalize the crossProduct to get the rotation axis this.axis = vec3.scale(crossProduct, 1 / magnitude); @@ -329,7 +330,7 @@ export class ArcballCamera extends CameraBase implements Camera // The rotation around this.axis to apply to the camera matrix this update const rotationAngle = this.angularVelocity * deltaTime; if (rotationAngle > epsilon) -{ + { // Rotate the matrix around axis // Note: The rotation is not done as a matrix-matrix multiply as the repeated multiplications // will quickly introduce substantial error into the matrix. @@ -340,7 +341,7 @@ export class ArcballCamera extends CameraBase implements Camera // recalculate `this.position` from `this.back` considering zoom if (input.analog.zoom !== 0) -{ + { this.distance *= 1 + input.analog.zoom * this.zoomSpeed; } this.position = vec3.scale(this.back, this.distance); @@ -348,18 +349,18 @@ export class ArcballCamera extends CameraBase implements Camera // Invert the camera matrix to build the view matrix this.view = mat4.invert(this.matrix); -return this.view; + return this.view; } // Assigns `this.right` with the cross product of `this.up` and `this.back` recalcuateRight() -{ + { this.right = vec3.normalize(vec3.cross(this.up, this.back)); } // Assigns `this.up` with the cross product of `this.back` and `this.right` recalcuateUp() -{ + { this.up = vec3.normalize(vec3.cross(this.back, this.right)); } } diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index 8d45f99..2f4438c 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -5,7 +5,7 @@ import { ArcballCamera, WASDCamera } from "./camera"; import cubeWGSL from "./cube.wgsl"; import { createInputHandler } from "./input"; -import { RenderObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; +import { reactive, RenderObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -99,7 +99,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: RenderObject = { pipeline: pipeline, bindingResources: bindingResources, - geometry:{ + geometry: { vertices, draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, } @@ -156,7 +156,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => lastFrameMS = now; const modelViewProjection = getModelViewProjectionMatrix(deltaTime); - bindingResources.uniforms.modelViewProjectionMatrix = new Float32Array(modelViewProjection); // 使用 new Float32Array 是因为赋值不同的对象才会触发数据改变重新上传数据到GPU + reactive(bindingResources.uniforms).modelViewProjectionMatrix = new Float32Array(modelViewProjection); // 使用 new Float32Array 是因为赋值不同的对象才会触发数据改变重新上传数据到GPU webgpu.submit(data); diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index 2180b65..9ea115f 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, TextureImageSource, RenderObject } from "@feng3d/render-api"; +import { BufferBinding, RenderPassDescriptor, Sampler, Submit, Texture, TextureImageSource, RenderObject, reactive } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -146,7 +146,7 @@ const init = async (canvas: HTMLCanvasElement) => { updateTransformationMatrix(); - (renderObject.bindingResources.uniforms as BufferBinding).modelViewProjectionMatrix = modelViewProjectionMatrix; + reactive(renderObject.bindingResources.uniforms as BufferBinding).modelViewProjectionMatrix = modelViewProjectionMatrix.subarray(); const data: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 4df0ca2..8c9ba9d 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, CanvasContext, CopyTextureToTexture, RenderObject, RenderPassDescriptor, Sampler, Submit, Texture } from "@feng3d/render-api"; +import { BufferBinding, CanvasContext, CopyTextureToTexture, reactive, RenderObject, RenderPassDescriptor, Sampler, Submit, Texture } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -110,7 +110,7 @@ const init = async (canvas: HTMLCanvasElement) => { const transformationMatrix = getTransformationMatrix(); - (renderObject.bindingResources.uniforms as BufferBinding).modelViewProjectionMatrix = transformationMatrix; + reactive(renderObject.bindingResources.uniforms as BufferBinding).modelViewProjectionMatrix = transformationMatrix.subarray(); const data: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 29a0847..465f257 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, Submit, RenderObject } from "@feng3d/render-api"; +import { RenderPassDescriptor, Submit, RenderObject, reactive } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { Mat4, mat4, vec3 } from "wgpu-matrix"; @@ -79,7 +79,8 @@ const init = async (canvas: HTMLCanvasElement) => mat4.multiply(viewMatrix, tmpMat4, tmpMat4); mat4.multiply(projectionMatrix, tmpMat4, tmpMat4); - mvpMatricesData[i] = tmpMat4.slice(); + // Update the matrix data. + reactive(mvpMatricesData)[i] = tmpMat4.slice(); i++; m += matrixFloatCount; diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index e8cdc19..feebf04 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, BindingResources } from "@feng3d/render-api"; +import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, BindingResources, reactive } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4, vec3 } from "wgpu-matrix"; @@ -288,8 +288,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const worldViewMatrix = mat4.mul(viewMatrix, getModelMatrix()); const worldViewProjMatrix = mat4.mul(projectionMatrix, worldViewMatrix); - spaceTransform.worldViewMatrix = worldViewMatrix; - spaceTransform.worldViewProjMatrix = worldViewProjMatrix; + reactive(spaceTransform).worldViewMatrix = worldViewMatrix; + reactive(spaceTransform).worldViewProjMatrix = worldViewProjMatrix; // Update mapInfoBuffer const lightPosWS = vec3.create( @@ -343,7 +343,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => requestAnimationFrame(frame); } - requestAnimationFrame(frame); + frame(); }; const panel = new GUI(); diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index cd80ed0..3cc17c3 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; +import { reactive, RenderObject, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; @@ -161,6 +161,26 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gui.add(settings, "textured"); gui.add(settings, "size", 0, 80); + const ro: RenderObject = { + pipeline: undefined, + bindingResources: bindingResources, + geometry: { + vertices, + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, + } + }; + // + const submit: Submit = { + commandEncoders: [{ + passEncoders: [ + { + descriptor: renderPassDescriptor, + renderObjects: [ro] + } + ] + }] + }; + function render(time: number) { // Convert to seconds. @@ -168,10 +188,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const { size, fixedSize, textured } = settings; - const pipeline = pipelines[fixedSize ? 1 : 0][textured ? 1 : 0]; + ro.pipeline = pipelines[fixedSize ? 1 : 0][textured ? 1 : 0]; // Set the size in the uniform values - bindingResources.uni.size = size; + reactive(bindingResources.uni).size = size; const fov = (90 * Math.PI) / 180; const aspect = canvas.clientWidth / canvas.clientHeight; @@ -186,29 +206,10 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => mat4.rotateY(viewProjection, time, matrixValue); mat4.rotateX(matrixValue, time * 0.1, matrixValue); // Copy the uniform values to the GPU - bindingResources.uni.matrix = matrixValue; + reactive(bindingResources.uni).matrix = matrixValue; // Update the resolution in the uniform values - bindingResources.uni.resolution = [canvas.width, canvas.height]; - - // - const submit: Submit = { - commandEncoders: [{ - passEncoders: [ - { - descriptor: renderPassDescriptor, - renderObjects: [{ - pipeline: pipeline, - bindingResources: bindingResources, - geometry: { - vertices, - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, - } - }] - } - ] - }] - }; + reactive(bindingResources.uni).resolution = [canvas.width, canvas.height]; webgpu.submit(submit); diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index 56a583a..3043a10 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -1,7 +1,7 @@ import { GUI } from "dat.gui"; import checkerWGSL from "./checker.wgsl"; -import { BindingResources, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; +import { BindingResources, reactive, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement) => @@ -21,7 +21,7 @@ const init = async (canvas: HTMLCanvasElement) => size: undefined, }; - const bindGroup: BindingResources = { + const bindGroup: BindingResources = { uni, }; @@ -36,7 +36,7 @@ const init = async (canvas: HTMLCanvasElement) => { document.exitFullscreen(); } - else + else { document.body.requestFullscreen(); } @@ -72,47 +72,47 @@ const init = async (canvas: HTMLCanvasElement) => willReadFrequently: true, }); -return function (color: string) + return function (color: string) { ctx.clearRect(0, 0, 1, 1); ctx.fillStyle = color; ctx.fillRect(0, 0, 1, 1); -return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); + return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); }; })(); - function frame() - { - uni.color0 = cssColorToRGBA(settings.color0); - uni.color1 = cssColorToRGBA(settings.color1); - uni.size = settings.size; - - const renderPassDescriptor: RenderPassDescriptor = { - colorAttachments: [ - { - view: { texture: { context: { canvasId: canvas.id } } }, - clearValue: [0.2, 0.2, 0.2, 1.0], - loadOp: "clear", - storeOp: "store", - }, - ], - }; + const renderPassDescriptor: RenderPassDescriptor = { + colorAttachments: [ + { + view: { texture: { context: { canvasId: canvas.id } } }, + clearValue: [0.2, 0.2, 0.2, 1.0], + loadOp: "clear", + storeOp: "store", + }, + ], + }; - const submit: Submit = { - commandEncoders: [{ - passEncoders: [{ - descriptor: renderPassDescriptor, - renderObjects: [{ - pipeline: pipeline, - bindingResources: bindGroup, - geometry:{ - draw: { __type__: "DrawVertex", vertexCount: 3 }, - } - }] + const submit: Submit = { + commandEncoders: [{ + passEncoders: [{ + descriptor: renderPassDescriptor, + renderObjects: [{ + pipeline: pipeline, + bindingResources: bindGroup, + geometry: { + draw: { __type__: "DrawVertex", vertexCount: 3 }, + } }] }] - }; + }] + }; + function frame() + { + reactive(uni).color0 = cssColorToRGBA(settings.color0); + reactive(uni).color1 = cssColorToRGBA(settings.color1); + reactive(uni).size = settings.size; + webgpu.submit(submit); } @@ -126,11 +126,11 @@ return [...ctx.getImageData(0, 0, 1, 1).data].map((v) => v / 255); height: entry.devicePixelContentBoxSize[0].blockSize, }; } - // These values not correct but they're as close as you can get in Safari - return { - width: entry.contentBoxSize[0].inlineSize * devicePixelRatio, - height: entry.contentBoxSize[0].blockSize * devicePixelRatio, - }; + // These values not correct but they're as close as you can get in Safari + return { + width: entry.contentBoxSize[0].inlineSize * devicePixelRatio, + height: entry.contentBoxSize[0].blockSize * devicePixelRatio, + }; } const { maxTextureDimension2D } = webgpu.device.limits; diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 5986c04..7f69b38 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -10,7 +10,7 @@ import vertexDepthPrePassWGSL from "./vertexDepthPrePass.wgsl"; import vertexPrecisionErrorPassWGSL from "./vertexPrecisionErrorPass.wgsl"; import vertexTextureQuadWGSL from "./vertexTextureQuad.wgsl"; -import { BindingResources, CanvasContext, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, CanvasContext, reactive, RenderPass, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; // Two planes close to each other for depth precision test @@ -351,7 +351,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => (Math.PI / 180) * 30, tmpMat4 ); - mvpMatricesData[i] = tmpMat4.slice(); + reactive(mvpMatricesData)[i] = tmpMat4.slice(); } } diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index 1dcc562..7c3fedf 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, RenderObject, RenderPassDescriptor, Submit } from "@feng3d/render-api"; +import { BufferBinding, reactive, RenderObject, RenderPassDescriptor, Submit } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -40,7 +40,7 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, }, - geometry:{ + geometry: { vertices: { position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, @@ -82,7 +82,8 @@ const init = async (canvas: HTMLCanvasElement) => { const transformationMatrix = getTransformationMatrix(); - uniforms.modelViewProjectionMatrix = new Float32Array(transformationMatrix); // 使用 new Float32Array 是因为赋值不同的对象才会触发数据改变重新上传数据到GPU + // 更新uniforms + reactive(uniforms).modelViewProjectionMatrix = transformationMatrix.subarray(); const data: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index 0e93302..21bb1b7 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -1,4 +1,4 @@ -import { RenderObject, RenderPassDescriptor, Sampler, Submit, Texture } from "@feng3d/render-api"; +import { reactive, RenderObject, RenderPassDescriptor, Sampler, Submit, Texture } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -103,7 +103,8 @@ const init = async (canvas: HTMLCanvasElement) => { const transformationMatrix = getTransformationMatrix(); - uniforms.modelViewProjectionMatrix = transformationMatrix.slice(); // 使用 new Float32Array 是因为赋值不同的对象才会触发数据改变重新上传数据到GPU + // 重新设置uniforms + reactive(uniforms).modelViewProjectionMatrix = transformationMatrix.subarray(); const data: Submit = { commandEncoders: [ diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index f7c9dfc..330ce20 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -1,4 +1,4 @@ -import { CanvasContext, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; +import { CanvasContext, reactive, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { TimestampQuery, WebGPU } from "@feng3d/webgpu"; import { mat4, vec3 } from "wgpu-matrix"; @@ -152,7 +152,7 @@ const init = async (canvas: HTMLCanvasElement) => function frame() { const transformationMatrix = getTransformationMatrix(); - uniforms.modelViewProjectionMatrix = new Float32Array(transformationMatrix); + reactive(uniforms).modelViewProjectionMatrix = transformationMatrix.subarray(); webgpu.submit(submit); diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 1b453ca..1fd2fd6 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { CanvasContext, RenderPassDescriptor, RenderPipeline, Texture, VertexAttributes } from "@feng3d/render-api"; +import { CanvasContext, reactive, RenderPassDescriptor, RenderPipeline, Submit, Texture, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -96,25 +96,27 @@ const init = async (canvas: HTMLCanvasElement) => return modelViewProjectionMatrix; } - function frame() - { - uniformBindGroup.uniforms.modelViewProjectionMatrix = getTransformationMatrix().slice(); - - webgpu.submit({ - commandEncoders: [{ - passEncoders: [{ - descriptor: renderPassDescriptor, - renderObjects: [{ - pipeline: pipeline, - bindingResources: uniformBindGroup, - geometry: { - vertices: verticesBuffer, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, - } - }] + const submit: Submit = { + commandEncoders: [{ + passEncoders: [{ + descriptor: renderPassDescriptor, + renderObjects: [{ + pipeline: pipeline, + bindingResources: uniformBindGroup, + geometry: { + vertices: verticesBuffer, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, + } }] }] - }); + }] + } + + function frame() + { + reactive(uniformBindGroup.uniforms).modelViewProjectionMatrix = getTransformationMatrix().slice(); + + webgpu.submit(submit); requestAnimationFrame(frame); } diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index e6b6909..36cc990 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { BufferBinding, RenderObject, RenderPassDescriptor, Submit } from "@feng3d/render-api"; +import { BufferBinding, reactive, RenderObject, RenderPassDescriptor, Submit } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -135,8 +135,9 @@ const init = async (canvas: HTMLCanvasElement) => { updateTransformationMatrix(); - uniforms.modelViewProjectionMatrix = modelViewProjectionMatrix1; - uniforms1.modelViewProjectionMatrix = modelViewProjectionMatrix2; + // 使用 subarray 是因为赋值不同的对象才会触发数据改变重新上传数据到GPU + reactive(uniforms).modelViewProjectionMatrix = modelViewProjectionMatrix1.subarray(); + reactive(uniforms1).modelViewProjectionMatrix = modelViewProjectionMatrix2.subarray(); webgpu.submit(data); diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index 2df655d..760bf47 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -2,7 +2,7 @@ import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; import volumeWGSL from "./volume.wgsl"; -import { BindingResources, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture } from "@feng3d/render-api"; +import { BindingResources, reactive, RenderPassDescriptor, RenderPipeline, Sampler, Submit, Texture } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; const gui = new GUI(); @@ -145,6 +145,21 @@ const init = async (canvas: HTMLCanvasElement) => let lastFrameMS = Date.now(); + const submit: Submit = { + commandEncoders: [{ + passEncoders: [{ + descriptor: renderPassDescriptor, + renderObjects: [{ + pipeline, + bindingResources: uniformBindGroup, + geometry: { + draw: { __type__: "DrawVertex", vertexCount: 3 }, + } + }], + }] + }] + }; + function frame() { const now = Date.now(); @@ -154,22 +169,8 @@ const init = async (canvas: HTMLCanvasElement) => const inverseModelViewProjection = getInverseModelViewProjectionMatrix(deltaTime); - uniformBuffer.inverseModelViewProjectionMatrix = inverseModelViewProjection; - - const submit: Submit = { - commandEncoders: [{ - passEncoders: [{ - descriptor: renderPassDescriptor, - renderObjects: [{ - pipeline, - bindingResources: uniformBindGroup, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 3 }, - } - }], - }] - }] - }; + reactive(uniformBuffer).inverseModelViewProjectionMatrix = inverseModelViewProjection; + webgpu.submit(submit); requestAnimationFrame(frame); diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 4e6b8c7..d2ceb18 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -1,4 +1,4 @@ -import { BindingResources, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; +import { BindingResources, reactive, RenderObject, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -321,8 +321,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => mat4.multiply(viewProjection, world, worldViewProjectionMatrixValue); // Upload our uniform values. - uniformBuffer.worldViewProjectionMatrix = worldViewProjectionMatrixValue; - uniformBuffer.worldMatrix = world; + reactive(uniformBuffer).worldViewProjectionMatrix = worldViewProjectionMatrixValue.subarray(); + reactive(uniformBuffer).worldMatrix = world; if (settings.models) { diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 8971cbd..9cea480 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -1,6 +1,6 @@ import { mat4, vec3 } from "wgpu-matrix"; -import { CanvasContext, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; +import { CanvasContext, reactive, RenderPassDescriptor, RenderPipeline, Submit, VertexAttributes } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import { cubePositionOffset, cubeUVOffset, cubeVertexArray, cubeVertexCount, cubeVertexSize } from "../../meshes/cube"; @@ -168,7 +168,7 @@ async function init(canvas: OffscreenCanvas) function frame() { const transformationMatrix = getTransformationMatrix(); - uniformBindGroup.uniforms.modelViewProjectionMatrix = transformationMatrix.slice(); + reactive(uniformBindGroup.uniforms).modelViewProjectionMatrix = transformationMatrix.slice(); webgpu.submit(submit); diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 93c4d52..e3d331f 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -163,8 +163,8 @@ function updateWriteTextures(device: GPUDevice, gpuTexture: GPUTexture, texture: // 转换为WebGPU翻转模式 if (flipY) { - const x = imageOrigin?.[0]; - let y = imageOrigin?.[1]; + const x = imageOrigin?.[0] ?? 0; + let y = imageOrigin?.[1] ?? 0; y = imageSize[1] - y - copySize[1]; -- Gitee From 10545d22ad23959cb6d5d0741fb9e3869a71d785 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 17:43:48 +0800 Subject: [PATCH 152/214] =?UTF-8?q?feat(caches):=20=E4=BC=98=E5=8C=96=20bi?= =?UTF-8?q?ndGroup=20=E5=92=8C=20GPUBuffer=20=E5=88=9B=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 gpuBindGroupMap 缓存 GPUBindGroup 对象 - 新增 gpuBindingResourceMap 缓存 GPUBindingResource 对象 - 优化 getGPUBindGroup 和 getGPUBindingResource 函数的缓存逻辑 - 重构代码,提高可读性和性能 --- src/caches/getGPUBindGroup.ts | 68 ++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 7dba13b..98edddb 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,6 +1,5 @@ -import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, reactive, Sampler, TextureView, UnReadonly } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; -import { ArrayInfo, ResourceType, StructInfo, TemplateInfo, TypeInfo, VariableInfo } from "wgsl_reflect"; +import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, reactive, Sampler, TextureView, TypedArray, UnReadonly } from "@feng3d/render-api"; +import { ArrayInfo, ResourceType, StructInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; import { VideoTexture } from "../data/VideoTexture"; import { webgpuEvents } from "../eventnames"; import { ExternalSampledTextureType } from "../types/TextureType"; @@ -45,14 +44,26 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup return entry; }); + // + const resources = entries.map((v) => v.resource); + const gpuBindGroupKey: GPUBindGroupKey = [bindGroupLayout, ...resources]; + const cache = gpuBindGroupMap.get(gpuBindGroupKey); + if (cache) return cache; + gBindGroup = device.createBindGroup({ layout: bindGroupLayout, entries }); + gpuBindGroupMap.set(gpuBindGroupKey, gBindGroup); + return gBindGroup; }); getGPUBindGroupMap.set(getGPUBindGroupKey, result); return result.value; } + +type GPUBindGroupKey = [bindGroupLayout: GPUBindGroupLayout, ...resources: GPUBindingResource[]]; +const gpuBindGroupMap = new ChainMap(); + type GetGPUBindGroupKey = [device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; const getGPUBindGroupMap = new ChainMap>(); @@ -82,20 +93,7 @@ function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResou // 更新缓冲区绑定的数据。 updateBufferBinding(bufferBinding, type); // - const gbuffer = getGBuffer(bufferBinding.bufferView); - (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); - // - const buffer = getGPUBuffer(device, gbuffer); - - const offset = bufferBinding.bufferView.byteOffset; - const size = bufferBinding.bufferView.byteLength; - - const gpuBindingResource: GPUBindingResource = { - buffer, - offset, - size, - }; - + const gpuBindingResource = _getGPUBindingResource(device, bufferBinding.bufferView); return gpuBindingResource; }); @@ -106,9 +104,37 @@ function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResou type GetGPUBindingResourceKey = [device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo]; const getGPUBindingResourceMap = new ChainMap>(); +function _getGPUBindingResource(device: GPUDevice, bufferView: TypedArray) +{ + // + const gpuBindingResourceKey: GPUBindingResourceKey = [device, bufferView]; + const cache = gpuBindingResourceMap.get(gpuBindingResourceKey); + if (cache) return cache; + + const gbuffer = getGBuffer(bufferView); + (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); + // + const buffer = getGPUBuffer(device, gbuffer); + + const offset = bufferView.byteOffset; + const size = bufferView.byteLength; + + const gpuBindingResource: GPUBindingResource = { + buffer, + offset, + size, + }; + gpuBindingResourceMap.set(gpuBindingResourceKey, gpuBindingResource); + + return gpuBindingResource; +} +type GPUBindingResourceKey = [device: GPUDevice, bufferView: TypedArray]; +const gpuBindingResourceMap = new ChainMap(); + function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) { - let result = getGPUExternalTextureMap.get(videoTexture); + const getGPUExternalTextureKey: GetGPUExternalTextureKey = [device, videoTexture]; + let result = getGPUExternalTextureMap.get(getGPUExternalTextureKey); if (result) return result.value; result = computed(() => @@ -121,12 +147,12 @@ function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) return resource; }); - getGPUExternalTextureMap.set(videoTexture, result); + getGPUExternalTextureMap.set(getGPUExternalTextureKey, result); return result.value; } -const getGPUExternalTextureMap = new WeakMap>(); - +type GetGPUExternalTextureKey = [device: GPUDevice, videoTexture: VideoTexture]; +const getGPUExternalTextureMap = new ChainMap>(); /** * 初始化缓冲区绑定。 -- Gitee From b398534076a5c9544fdbf3b6578861abd64dc812 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 18:23:22 +0800 Subject: [PATCH 153/214] =?UTF-8?q?refactor(WebGPUBase):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=B8=B2=E6=9F=93=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将渲染流程拆分为多个独立的方法 - 优化了视口和剪裁矩形的设置 - 改进了渲染管道、绑定资源和顶点属性的处理 - 提高了代码的可读性和可维护性 --- src/WebGPUBase.ts | 190 +++++++++++++++++++++++++--------------------- 1 file changed, 104 insertions(+), 86 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 75841e9..90c602a 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BlendState, ChainMap, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; +import { BindingResources, BlendState, ChainMap, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, Geometry, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, TextureLike, UnReadonly, Viewport } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -391,57 +391,93 @@ export class WebGPUBase protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) { const device = this._device; - const { viewport, scissorRect, pipeline, bindingResources: bindingResources, geometry } = renderObject; - const attachmentSize = renderPassFormat.attachmentSize; + const { viewport, scissorRect, pipeline, bindingResources, geometry } = renderObject; + + this.runviewport(passEncoder, viewport, renderPassFormat); + this.runScissorRect(passEncoder, scissorRect, renderPassFormat); + this.runRenderPipeline(passEncoder, pipeline, renderPassFormat, geometry); + this.runBindingResources(passEncoder, pipeline, bindingResources); + this.runVertexAttributes(passEncoder, pipeline, geometry); + + // this.run + const { indices, draw } = geometry; - if ("setViewport" in passEncoder) + if (indices) { - if (viewport) - { - const isYup = viewport.isYup ?? true; - const x = viewport.x ?? 0; - let y = viewport.y ?? 0; - const width = viewport.width ?? attachmentSize.width; - const height = viewport.height ?? attachmentSize.height; - const minDepth = viewport.minDepth ?? 0; - const maxDepth = viewport.maxDepth ?? 0; - - if (isYup) - { - y = attachmentSize.height - y - height; - } - passEncoder.setViewport(x, y, width, height, minDepth, maxDepth); - } - else - { - passEncoder.setViewport(0, 0, attachmentSize.width, attachmentSize.height, 0, 1); - } + const buffer = getGBuffer(indices); + (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); + + const gBuffer = getGPUBuffer(device, buffer); + + // + passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); + } + + if (draw.__type__ === 'DrawVertex') + { + passEncoder.draw(draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance); + } + else + { + passEncoder.drawIndexed(draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance); } - if ("setScissorRect" in passEncoder) + } + + protected runviewport(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, viewport: Viewport, renderPassFormat: RenderPassFormat) + { + if (!("setViewport" in passEncoder)) return; + const attachmentSize = renderPassFormat.attachmentSize; + if (viewport) { - if (scissorRect) + const isYup = viewport.isYup ?? true; + const x = viewport.x ?? 0; + let y = viewport.y ?? 0; + const width = viewport.width ?? attachmentSize.width; + const height = viewport.height ?? attachmentSize.height; + const minDepth = viewport.minDepth ?? 0; + const maxDepth = viewport.maxDepth ?? 0; + + if (isYup) { - const isYup = scissorRect.isYup ?? true; - const x = scissorRect.x ?? 0; - let y = scissorRect.y ?? 0; - const width = scissorRect.width ?? attachmentSize.width; - const height = scissorRect.height ?? attachmentSize.height; - - if (isYup) - { - y = attachmentSize.height - y - height; - } - - passEncoder.setScissorRect(x, y, width, height); + y = attachmentSize.height - y - height; } - else + passEncoder.setViewport(x, y, width, height, minDepth, maxDepth); + } + else + { + passEncoder.setViewport(0, 0, attachmentSize.width, attachmentSize.height, 0, 1); + } + } + + protected runScissorRect(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, scissorRect: ScissorRect, renderPassFormat: RenderPassFormat) + { + if (!("setScissorRect" in passEncoder)) return; + const attachmentSize = renderPassFormat.attachmentSize; + if (scissorRect) + { + const isYup = scissorRect.isYup ?? true; + const x = scissorRect.x ?? 0; + let y = scissorRect.y ?? 0; + const width = scissorRect.width ?? attachmentSize.width; + const height = scissorRect.height ?? attachmentSize.height; + + if (isYup) { - passEncoder.setScissorRect(0, 0, attachmentSize.width, attachmentSize.height); + y = attachmentSize.height - y - height; } - } - const { vertices, indices, draw } = geometry; + passEncoder.setScissorRect(x, y, width, height); + } + else + { + passEncoder.setScissorRect(0, 0, attachmentSize.width, attachmentSize.height); + } + } + protected runRenderPipeline(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, renderPassFormat: RenderPassFormat, geometry: Geometry) + { + const device = this._device; + const { vertices, indices } = geometry; // const indexFormat: GPUIndexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; const nPipeline = getGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indexFormat); @@ -449,37 +485,34 @@ export class WebGPUBase // passEncoder.setPipeline(nPipeline); + // + this.runStencilReference(passEncoder, pipeline); + this.runBlendConstant(passEncoder, pipeline); + } + + protected runStencilReference(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline) + { + if (!("setStencilReference" in passEncoder)) return; // const stencilReference = getStencilReference(pipeline.depthStencil); + if (stencilReference === undefined) return; + + passEncoder.setStencilReference(stencilReference); + } + protected runBlendConstant(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline) + { + if (!("setBlendConstant" in passEncoder)) return; // const blendConstantColor = BlendState.getBlendConstantColor(pipeline.fragment?.targets?.[0]?.blend); + if (blendConstantColor === undefined) return; - // 设置模板测试替换值 - if (stencilReference !== undefined) - { - if ("setStencilReference" in passEncoder) - { - passEncoder.setStencilReference(stencilReference); - } - else - { - console.warn(`不支持在 ${passEncoder.constructor.name} 中设置 stencilReference 值!`); - } - } - - if (blendConstantColor !== undefined) - { - if ("setBlendConstant" in passEncoder) - { - passEncoder.setBlendConstant(blendConstantColor); - } - else - { - console.warn(`不支持在 ${passEncoder.constructor.name} 中设置 setBlendConstant 值!`); - } - } + passEncoder.setBlendConstant(blendConstantColor); + } + protected runBindingResources(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, bindingResources: BindingResources) + { + const device = this._device; // 计算 bindGroups const layout = getGPUPipelineLayout(device, { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => @@ -487,7 +520,12 @@ export class WebGPUBase const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources); passEncoder.setBindGroup(group, gpuBindGroup); }); + } + protected runVertexAttributes(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, geometry: Geometry) + { + const device = this._device; + const { vertices } = geometry; // const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) vertexBuffers?.forEach((vertexBuffer, index) => @@ -499,26 +537,6 @@ export class WebGPUBase passEncoder.setVertexBuffer(index, gBuffer, vertexBuffer.offset, vertexBuffer.size); }); - - if (indices) - { - const buffer = getGBuffer(indices); - (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); - - const gBuffer = getGPUBuffer(device, buffer); - - // - passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); - } - - if (draw.__type__ === 'DrawVertex') - { - passEncoder.draw(draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance); - } - else - { - passEncoder.drawIndexed(draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance); - } } } -- Gitee From f3dbd2224efabb074fed818d146a1d0e56868732 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 18:52:11 +0800 Subject: [PATCH 154/214] =?UTF-8?q?refactor(WebGPUBase):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=B8=B2=E6=9F=93=E6=B5=81=E7=A8=8B=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将渲染流程中的索引设置和绘制逻辑拆分为独立的方法 - 新增 runIndices 和 runDraw 方法,提高代码可读性和可维护性 - 优化了原有 runRenderObject 方法的结构,使其更加清晰 --- src/WebGPUBase.ts | 56 +++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 90c602a..208e5c5 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -390,7 +390,6 @@ export class WebGPUBase */ protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) { - const device = this._device; const { viewport, scissorRect, pipeline, bindingResources, geometry } = renderObject; this.runviewport(passEncoder, viewport, renderPassFormat); @@ -398,29 +397,8 @@ export class WebGPUBase this.runRenderPipeline(passEncoder, pipeline, renderPassFormat, geometry); this.runBindingResources(passEncoder, pipeline, bindingResources); this.runVertexAttributes(passEncoder, pipeline, geometry); - - // this.run - const { indices, draw } = geometry; - - if (indices) - { - const buffer = getGBuffer(indices); - (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); - - const gBuffer = getGPUBuffer(device, buffer); - - // - passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); - } - - if (draw.__type__ === 'DrawVertex') - { - passEncoder.draw(draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance); - } - else - { - passEncoder.drawIndexed(draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance); - } + this.runIndices(passEncoder, geometry); + this.runDraw(passEncoder, geometry); } protected runviewport(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, viewport: Viewport, renderPassFormat: RenderPassFormat) @@ -538,6 +516,36 @@ export class WebGPUBase passEncoder.setVertexBuffer(index, gBuffer, vertexBuffer.offset, vertexBuffer.size); }); } + + protected runIndices(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: Geometry) + { + const { indices } = geometry; + if (!indices) return; + + const device = this._device; + + const buffer = getGBuffer(indices); + (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); + + const gBuffer = getGPUBuffer(device, buffer); + + // + passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); + } + + protected runDraw(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: Geometry) + { + const { draw } = geometry; + + if (draw.__type__ === 'DrawVertex') + { + passEncoder.draw(draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance); + } + else + { + passEncoder.drawIndexed(draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance); + } + } } let autoIndex = 0; -- Gitee From a045233d040327c052407145bfd769d5ec888a23 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 19:06:09 +0800 Subject: [PATCH 155/214] =?UTF-8?q?refactor(webgpu):=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=20RenderObject=20=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 geometry 属性,将 vertices、indices 和 draw 直接放在 RenderObject 中 - 更新多个示例文件以适应新的结构 - 优化代码可读性和减少嵌套层次 --- .../src/webgpu/RenderObjectChanges/index.ts | 20 +++++----- examples/src/webgpu/a-buffer/index.ts | 20 ++++------ examples/src/webgpu/animometer/index.ts | 10 ++--- examples/src/webgpu/bitonicSort/utils.ts | 4 +- examples/src/webgpu/blending/index.ts | 8 +--- examples/src/webgpu/cameras/index.ts | 6 +-- examples/src/webgpu/computeBoids/index.ts | 39 ++++++++----------- examples/src/webgpu/cornell/rasterizer.ts | 8 ++-- examples/src/webgpu/cubemap/index.ts | 12 +++--- .../src/webgpu/deferredRendering/index.ts | 16 +++----- examples/src/webgpu/fractalCube/index.ts | 10 ++--- examples/src/webgpu/gameOfLife/index.ts | 6 +-- examples/src/webgpu/helloTriangle/index.ts | 10 ++--- .../src/webgpu/helloTriangleMSAA/index.ts | 4 +- examples/src/webgpu/imageBlur/index.ts | 4 +- examples/src/webgpu/instancedCube/index.ts | 10 ++--- examples/src/webgpu/multipleCanvases/index.ts | 8 ++-- examples/src/webgpu/normalMap/index.ts | 20 +++++----- examples/src/webgpu/occlusionQuery/index.ts | 12 +++--- examples/src/webgpu/particles/index.ts | 6 +-- examples/src/webgpu/points/index.ts | 6 +-- examples/src/webgpu/renderBundles/index.ts | 8 ++-- examples/src/webgpu/resizeCanvas/index.ts | 6 +-- .../src/webgpu/resizeObserverHDDPI/index.ts | 4 +- examples/src/webgpu/reversedZ/index.ts | 28 +++++-------- examples/src/webgpu/rotatingCube/index.ts | 10 ++--- .../src/webgpu/samplerParameters/index.ts | 20 +++------- examples/src/webgpu/shadowMapping/index.ts | 16 +++----- examples/src/webgpu/skinnedMesh/glbUtils.ts | 8 ++-- examples/src/webgpu/skinnedMesh/index.ts | 8 ++-- .../src/webgpu/textRenderingMsdf/index.ts | 6 +-- .../src/webgpu/textRenderingMsdf/msdfText.ts | 4 +- examples/src/webgpu/texturedCube/index.ts | 12 +++--- examples/src/webgpu/timestampQuery/index.ts | 6 +-- .../src/webgpu/transparentCanvas/index.ts | 6 +-- examples/src/webgpu/twoCubes/index.ts | 12 +++--- examples/src/webgpu/videoUploading/index.ts | 4 +- .../webgpu/volumeRenderingTexture3D/index.ts | 4 +- examples/src/webgpu/wireframe/index.ts | 12 ++---- examples/src/webgpu/worker/worker.ts | 6 +-- src/WebGPUBase.ts | 39 ++++++++++--------- 41 files changed, 173 insertions(+), 285 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index ff24f4a..acbc9a8 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -29,13 +29,11 @@ const init = async (canvas: HTMLCanvasElement) => } ` }, }, - geometry: { - vertices: { - position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 - }, - indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 - draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 + vertices: { + position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 }, + indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 + draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 bindingResources: { color: [1, 0, 0, 0] as any }, // Uniform 颜色值。 }; @@ -67,11 +65,11 @@ const init = async (canvas: HTMLCanvasElement) => window.onclick = () => { - reactive(renderObject.geometry.vertices.position).stepMode = "instance"; - reactive(renderObject.geometry.vertices.position).stepMode = "vertex"; - reactive(renderObject.geometry.vertices.position).data = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -1]); - reactive(renderObject.geometry.vertices.position).format = "float32x3"; - reactive(renderObject.geometry.vertices.position).data = new Float32Array([1.0, 0.5, 1.0, -0.5, -0.5, 1.0, 0.5, -1, 1.0]); + reactive(renderObject.vertices.position).stepMode = "instance"; + reactive(renderObject.vertices.position).stepMode = "vertex"; + reactive(renderObject.vertices.position).data = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -1]); + reactive(renderObject.vertices.position).format = "float32x3"; + reactive(renderObject.vertices.position).data = new Float32Array([1.0, 0.5, 1.0, -0.5, -0.5, 1.0, 0.5, -1, 1.0]); // 修改顶点着色器代码 reactive(renderObject.pipeline.vertex).code = ` @vertex diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 95948fb..183e411 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -288,11 +288,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [{ pipeline: opaquePipeline, bindingResources: bindingResources, - geometry: { - vertices, - indices, - draw: { __type__: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, - } + vertices, + indices, + draw: { __type__: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, }] }; passEncoders.push(opaquePassEncoder); @@ -326,11 +324,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...bindingResources, sliceInfo: sliceInfoBuffer[slice], }, - geometry: { - vertices, - indices, - draw: { __type__: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, - } + vertices, + indices, + draw: { __type__: "DrawIndexed", indexCount: mesh.triangles.length * 3, instanceCount: 8 }, } ], }; @@ -349,9 +345,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...bindingResources, sliceInfo: sliceInfoBuffer[slice] }, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6 }, - } + draw: { __type__: "DrawVertex", vertexCount: 6 }, } ] }; diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index 7841d72..bf0d755 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -59,13 +59,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: RenderObject = { pipeline: pipeline, bindingResources: {}, - geometry: { - vertices: { - position: { data: vertexBuffer, format: "float32x4", offset: 0, arrayStride: 2 * vec4Size }, - color: { data: vertexBuffer, format: "float32x4", offset: vec4Size, arrayStride: 2 * vec4Size }, - }, - draw: { __type__: "DrawVertex", vertexCount: 3, instanceCount: 1 }, + vertices: { + position: { data: vertexBuffer, format: "float32x4", offset: 0, arrayStride: 2 * vec4Size }, + color: { data: vertexBuffer, format: "float32x4", offset: vec4Size, arrayStride: 2 * vec4Size }, }, + draw: { __type__: "DrawVertex", vertexCount: 3, instanceCount: 1 }, }; const uniformBytes = 5 * Float32Array.BYTES_PER_ELEMENT; diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index ab9c79a..1730169 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -59,9 +59,7 @@ export abstract class Base2DRendererClass renderObjects: [{ pipeline: pipeline, bindingResources: bindingResources, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1 } - } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1 }, }], }; commandEncoder.passEncoders.push(passEncoder); diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 7055528..44ad0f3 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -485,16 +485,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const ro: RenderObject = { pipeline: dstPipeline, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6 }, - } + draw: { __type__: "DrawVertex", vertexCount: 6 }, }; const ro1: RenderObject = { pipeline: srcPipeline, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6 }, - } + draw: { __type__: "DrawVertex", vertexCount: 6 }, }; const renderObjects: RenderPassObject[] = [ diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index 2f4438c..e2a398c 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -99,10 +99,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: RenderObject = { pipeline: pipeline, bindingResources: bindingResources, - geometry: { - vertices, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, - } + vertices, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }; const renderPassDescriptor: RenderPassDescriptor = { diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index abac7ea..56a3ec0 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -97,33 +97,28 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => cullFace: "back", }, }, - geometry: { - vertices: { - a_particlePos: { data: particleBuffers[0], format: "float32x2", offset: 0, arrayStride: 4 * 4, stepMode: "instance" }, - a_particleVel: { data: particleBuffers[0], format: "float32x2", offset: 2 * 4, arrayStride: 4 * 4, stepMode: "instance" }, - a_pos: { data: vertexBufferData, format: "float32x2" }, - }, - draw: { __type__: "DrawVertex", vertexCount: 3, instanceCount: numParticles } - } + vertices: { + a_particlePos: { data: particleBuffers[0], format: "float32x2", offset: 0, arrayStride: 4 * 4, stepMode: "instance" }, + a_particleVel: { data: particleBuffers[0], format: "float32x2", offset: 2 * 4, arrayStride: 4 * 4, stepMode: "instance" }, + a_pos: { data: vertexBufferData, format: "float32x2" }, + }, + draw: { __type__: "DrawVertex", vertexCount: 3, instanceCount: numParticles } }; const renderObject1: RenderObject = { ...renderObject, - geometry: { - ...renderObject.geometry, - draw: renderObject.geometry.draw, - vertices: { - ...renderObject.geometry.vertices, - a_particlePos: { - ...renderObject.geometry.vertices.a_particlePos, - data: particleBuffers[1], - }, - a_particleVel: { - ...renderObject.geometry.vertices.a_particleVel, - data: particleBuffers[1], - }, + draw: renderObject.draw, + vertices: { + ...renderObject.vertices, + a_particlePos: { + ...renderObject.vertices.a_particlePos, + data: particleBuffers[1], }, - } + a_particleVel: { + ...renderObject.vertices.a_particleVel, + data: particleBuffers[1], + }, + }, }; let t = 0; diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index aae2ba6..15464d3 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -83,11 +83,9 @@ export default class Rasterizer ...this.common.uniforms.bindGroup, ...this.bindGroup, }, - geometry: { - vertices: this.scene.vertexAttributes, - indices: this.scene.indices, - draw: { __type__: "DrawIndexed", indexCount: this.scene.indexCount }, - }, + vertices: this.scene.vertexAttributes, + indices: this.scene.indices, + draw: { __type__: "DrawIndexed", indexCount: this.scene.indexCount }, }], }; } diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index 9ea115f..f6478d3 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -133,13 +133,11 @@ const init = async (canvas: HTMLCanvasElement) => mySampler: sampler, myTexture: { texture: cubemapTexture }, }, - geometry: { - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, - }, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, - } + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }; function frame() diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 9824f7a..4049da7 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -334,11 +334,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => bindingResources: { ...sceneUniformBindGroup, }, - geometry: { - vertices, - indices: indexBuffer, - draw: { __type__: "DrawIndexed", indexCount }, - } + vertices, + indices: indexBuffer, + draw: { __type__: "DrawIndexed", indexCount }, }, ] }); @@ -365,9 +363,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => bindingResources: { ...gBufferTexturesBindGroup, }, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6 }, - } + draw: { __type__: "DrawVertex", vertexCount: 6 }, }, ] }); @@ -381,9 +377,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...gBufferTexturesBindGroup, ...lightsBufferBindGroup, }, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6 }, - }, + draw: { __type__: "DrawVertex", vertexCount: 6 }, }, ] }); diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index 8c9ba9d..ea4ea78 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -83,13 +83,11 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, }, - geometry: { - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, - }, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, bindingResources: { uniforms: { modelViewProjectionMatrix: new Float32Array(16) diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 973cc8b..5d40d20 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -138,10 +138,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { pipeline: renderPipeline, bindingResources: uniformBindGroup, - geometry: { - vertices: vertices1, - draw: { __type__: "DrawVertex", vertexCount: 4, instanceCount: length }, - } + vertices: vertices1, + draw: { __type__: "DrawVertex", vertexCount: 4, instanceCount: length }, } ], } diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index d9037e7..7111c79 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -40,13 +40,11 @@ const init = async (canvas: HTMLCanvasElement) => } ` }, }, - geometry: { - vertices: { - position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 - }, - indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 - draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 + vertices: { + position: { data: new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]), format: "float32x2" }, // 顶点坐标数据 }, + indices: new Uint16Array([0, 1, 2]), // 顶点索引数据 + draw: { __type__: "DrawIndexed", indexCount: 3 }, // 绘制命令 bindingResources: { color: [1, 0, 0, 0] }, // Uniform 颜色值。 }] }, diff --git a/examples/src/webgpu/helloTriangleMSAA/index.ts b/examples/src/webgpu/helloTriangleMSAA/index.ts index 47ed4b3..ca6e5b9 100644 --- a/examples/src/webgpu/helloTriangleMSAA/index.ts +++ b/examples/src/webgpu/helloTriangleMSAA/index.ts @@ -24,9 +24,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 3 }, - }, + draw: { __type__: "DrawVertex", vertexCount: 3 }, }; function frame() diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index b4743cb..6c96d3e 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -145,9 +145,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [{ pipeline: fullscreenQuadPipeline1, bindingResources: showResultBindGroup1, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, - }, + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, }], }; diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 465f257..9b20d02 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -109,13 +109,11 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, }, - geometry: { - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, - }, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: numInstances } + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: numInstances }, bindingResources: { uniforms: { modelViewProjectionMatrix: mvpMatricesData diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index 0018032..744e47c 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -320,11 +320,9 @@ const init = async () => renderObjects: [{ pipeline: pipeline, bindingResources: bindGroup, - geometry: { - vertices: vertexAttributes, - indices, - draw: { __type__: "DrawIndexed", indexCount: indices.length }, - }, + vertices: vertexAttributes, + indices, + draw: { __type__: "DrawIndexed", indexCount: indices.length }, }], }); }); diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index feebf04..fcd5e17 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -324,17 +324,15 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // * uv : float32x2 // * tangent : float32x3 // * bitangent : float32x3 - geometry: { - vertices: { - position: { data: box.vertices, offset: 0, format: "float32x3", arrayStride: box.vertexStride }, - normal: { data: box.vertices, offset: 12, format: "float32x3", arrayStride: box.vertexStride }, - uv: { data: box.vertices, offset: 24, format: "float32x2", arrayStride: box.vertexStride }, - vert_tan: { data: box.vertices, offset: 32, format: "float32x3", arrayStride: box.vertexStride }, - vert_bitan: { data: box.vertices, offset: 44, format: "float32x3", arrayStride: box.vertexStride }, - }, - indices: box.indices, - draw: { __type__: "DrawIndexed", indexCount: box.indices.length }, - } + vertices: { + position: { data: box.vertices, offset: 0, format: "float32x3", arrayStride: box.vertexStride }, + normal: { data: box.vertices, offset: 12, format: "float32x3", arrayStride: box.vertexStride }, + uv: { data: box.vertices, offset: 24, format: "float32x2", arrayStride: box.vertexStride }, + vert_tan: { data: box.vertices, offset: 32, format: "float32x3", arrayStride: box.vertexStride }, + vert_bitan: { data: box.vertices, offset: 44, format: "float32x3", arrayStride: box.vertexStride }, + }, + indices: box.indices, + draw: { __type__: "DrawIndexed", indexCount: box.indices.length }, }], }] }] diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 8da2f11..a5d5cca 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -126,14 +126,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderObject: RenderObject = { pipeline: pipeline, - geometry: { - vertices: { - position: { data: vertexBuf, offset: 0, arrayStride: 6 * 4, format: "float32x3" }, - normal: { data: vertexBuf, offset: 12, arrayStride: 6 * 4, format: "float32x3" }, - }, - indices, - draw: { __type__: "DrawIndexed", indexCount: indices.length }, + vertices: { + position: { data: vertexBuf, offset: 0, arrayStride: 6 * 4, format: "float32x3" }, + normal: { data: vertexBuf, offset: 12, arrayStride: 6 * 4, format: "float32x3" }, }, + indices, + draw: { __type__: "DrawIndexed", indexCount: indices.length }, bindingResources: { uni: { bufferView: undefined, diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index f4dd629..d496924 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -291,10 +291,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects: [{ pipeline: renderPipeline, bindingResources: { ...uniformBindGroup }, - geometry: { - vertices: { ...particlesVertices, ...quadVertices }, - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: numParticles, firstVertex: 0, firstInstance: 0 }, - }, + vertices: { ...particlesVertices, ...quadVertices }, + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: numParticles, firstVertex: 0, firstInstance: 0 }, }], } ); diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 3cc17c3..d19a93d 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -164,10 +164,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const ro: RenderObject = { pipeline: undefined, bindingResources: bindingResources, - geometry: { - vertices, - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, - } + vertices, + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: kNumPoints }, }; // const submit: Submit = { diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index f5514f5..1e6cf70 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -258,11 +258,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => renderable.renderObject = { pipeline: pipeline, bindingResources: { ...frameBindGroup, ...renderable.bindGroup }, - geometry: { - vertices: renderable.vertexAttributes, - indices: renderable.indices, - draw: { __type__: "DrawIndexed", indexCount: renderable.indexCount }, - } + vertices: renderable.vertexAttributes, + indices: renderable.indices, + draw: { __type__: "DrawIndexed", indexCount: renderable.indexCount }, }; } diff --git a/examples/src/webgpu/resizeCanvas/index.ts b/examples/src/webgpu/resizeCanvas/index.ts index de1a2f8..ef17f10 100644 --- a/examples/src/webgpu/resizeCanvas/index.ts +++ b/examples/src/webgpu/resizeCanvas/index.ts @@ -1,4 +1,4 @@ -import { RenderPassDescriptor, Submit, RenderObject, reactive } from "@feng3d/render-api"; +import { RenderObject, RenderPassDescriptor, Submit, reactive } from "@feng3d/render-api"; import { WebGPU } from "@feng3d/webgpu"; import redFragWGSL from "../../shaders/red.frag.wgsl"; @@ -22,9 +22,7 @@ const init = async (canvas: HTMLCanvasElement) => pipeline: { vertex: { code: triangleVertWGSL }, fragment: { code: redFragWGSL }, }, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 3 }, - } + draw: { __type__: "DrawVertex", vertexCount: 3 }, }; canvas.classList.add(styles.animatedCanvasSize); diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index 3043a10..0dcced4 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -100,9 +100,7 @@ const init = async (canvas: HTMLCanvasElement) => renderObjects: [{ pipeline: pipeline, bindingResources: bindGroup, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 3 }, - } + draw: { __type__: "DrawVertex", vertexCount: 3 }, }] }] }] diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index 7f69b38..b86cda8 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -377,10 +377,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: colorPassPipelines[m], bindingResources: { ...uniformBindGroups[m] }, - geometry: { - vertices, - draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, - } + vertices, + draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, }] }); } @@ -401,10 +399,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], bindingResources: { ...uniformBindGroups[m] }, - geometry: { - vertices, - draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, - } + vertices, + draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, }] }); precisionErrorPassEncoders.push({ @@ -420,10 +416,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: precisionPassPipelines[m], bindingResources: { ...uniformBindGroups[m], ...depthTextureBindGroup }, - geometry: { - vertices, - draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, - } + vertices, + draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, }] }); } @@ -444,10 +438,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], bindingResources: { ...uniformBindGroups[m] }, - geometry: { - vertices, - draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, - } + vertices, + draw: { __type__: "DrawVertex", vertexCount: geometryDrawCount, instanceCount: numInstances, firstVertex: 0, firstInstance: 0 }, }] }); depthBufferPassEncoders.push({ @@ -457,9 +449,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: textureQuadPassPipline, bindingResources: { ...depthTextureBindGroup }, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, - } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, }] }); } diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index 7c3fedf..4a3ecaf 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -40,13 +40,11 @@ const init = async (canvas: HTMLCanvasElement) => cullFace: "back", }, }, - geometry: { - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, - }, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, bindingResources: { uniforms, }, diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index 448703f..81bd8c7 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -292,9 +292,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: vpX, y: vpY, width: kViewportSize, height: kViewportSize, minDepth: 0, maxDepth: 1 }, pipeline: texturedSquarePipeline, bindingResources: bindingResources0, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } - } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: i } } ); } @@ -308,9 +306,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: kLastViewport, y: kLastViewport, width: 32, height: 32, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, bindingResources: bindingResources1, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } - } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 } } ); renderObjects.push( @@ -318,9 +314,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: kLastViewport + 32, y: kLastViewport, width: 16, height: 16, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, bindingResources: bindingResources1, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } - } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 1 } } ); renderObjects.push( @@ -328,9 +322,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: kLastViewport + 32, y: kLastViewport + 16, width: 8, height: 8, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, bindingResources: bindingResources1, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } - } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 3 } } ); renderObjects.push( @@ -338,9 +330,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => viewport: { isYup: false, x: kLastViewport + 32, y: kLastViewport + 24, width: 4, height: 4, minDepth: 0, maxDepth: 1 }, pipeline: showTexturePipeline, bindingResources: bindingResources1, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } - } + draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 2 } } ); diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index cabfc28..74def59 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -225,11 +225,9 @@ const init = async (canvas: HTMLCanvasElement) => ...sceneBindGroupForShadow, ...modelBindGroup, }, - geometry: { - vertices, - indices: indexBuffer, - draw: { __type__: "DrawIndexed", indexCount }, - } + vertices, + indices: indexBuffer, + draw: { __type__: "DrawIndexed", indexCount }, }, ] }, @@ -242,11 +240,9 @@ const init = async (canvas: HTMLCanvasElement) => ...sceneBindGroupForRender, ...modelBindGroup, }, - geometry: { - vertices, - indices: indexBuffer, - draw: { __type__: "DrawIndexed", indexCount }, - } + vertices, + indices: indexBuffer, + draw: { __type__: "DrawIndexed", indexCount }, } ], } diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index da64c59..519878d 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -472,11 +472,9 @@ export class GLTFPrimitive pipeline: this.renderPipeline, bindingResources: bindingResources, //if skin do something with bone bind group - geometry: { - vertices: this.vertices, - indices: this.indices, - draw, - } + vertices: this.vertices, + indices: this.indices, + draw, }; renderObjects.push(renderObject); } diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index cdb5002..95a3dde 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -515,11 +515,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ...generalUniformsBGCLuster, ...skinnedGridBoneBGCluster, }, - geometry: { - vertices: skinnedGridVertexBuffers.vertices, - indices: skinnedGridVertexBuffers.indices, - draw: { __type__: "DrawIndexed", indexCount: gridIndices.length }, - } + vertices: skinnedGridVertexBuffers.vertices, + indices: skinnedGridVertexBuffers.indices, + draw: { __type__: "DrawIndexed", indexCount: gridIndices.length }, }; // passEncoders.push({ diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index 4f594c7..6f1399e 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -260,10 +260,8 @@ setBlendConstant().`, renderObjects.push({ pipeline: pipeline, bindingResources: uniformBindGroup, - geometry: { - vertices: verticesBuffer, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: 1 }, - } + vertices: verticesBuffer, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount, instanceCount: 1 }, }); textRenderer.render(renderObjects, ...text); diff --git a/examples/src/webgpu/textRenderingMsdf/msdfText.ts b/examples/src/webgpu/textRenderingMsdf/msdfText.ts index 66b3704..0e4be94 100644 --- a/examples/src/webgpu/textRenderingMsdf/msdfText.ts +++ b/examples/src/webgpu/textRenderingMsdf/msdfText.ts @@ -347,9 +347,7 @@ export class MsdfTextRenderer ...font.bindGroup, ...bindGroup, }, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 4, instanceCount: measurements.printedCharCount }, - } + draw: { __type__: "DrawVertex", vertexCount: 4, instanceCount: measurements.printedCharCount }, } ], }; diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index 21bb1b7..6741dcc 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -64,13 +64,11 @@ const init = async (canvas: HTMLCanvasElement) => mySampler: sampler, myTexture: { texture: cubeTexture }, }, - geometry: { - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, - }, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, - } + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }; const aspect = canvas.width / canvas.height; diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 330ce20..2670812 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -108,10 +108,8 @@ const init = async (canvas: HTMLCanvasElement) => bindingResources: { uniforms, }, - geometry: { - vertices, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, - } + vertices, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }; const submit: Submit = { diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 1fd2fd6..2740dac 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -103,10 +103,8 @@ const init = async (canvas: HTMLCanvasElement) => renderObjects: [{ pipeline: pipeline, bindingResources: uniformBindGroup, - geometry: { - vertices: verticesBuffer, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, - } + vertices: verticesBuffer, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }] }] }] diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index 36cc990..4d523c1 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -52,13 +52,11 @@ const init = async (canvas: HTMLCanvasElement) => bindingResources: { uniforms, }, - geometry: { - vertices: { - position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, - uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, - }, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, - } + vertices: { + position: { data: cubeVertexArray, format: "float32x4", offset: cubePositionOffset, arrayStride: cubeVertexSize }, + uv: { data: cubeVertexArray, format: "float32x2", offset: cubeUVOffset, arrayStride: cubeVertexSize }, + }, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount }, }; const uniforms1: BufferBinding = { diff --git a/examples/src/webgpu/videoUploading/index.ts b/examples/src/webgpu/videoUploading/index.ts index 7464efe..743ad39 100644 --- a/examples/src/webgpu/videoUploading/index.ts +++ b/examples/src/webgpu/videoUploading/index.ts @@ -47,9 +47,7 @@ const init = async (canvas: HTMLCanvasElement) => source: video, }, }, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 6 }, - } + draw: { __type__: "DrawVertex", vertexCount: 6 }, }; function frame() diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index 760bf47..ddbe76c 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -152,9 +152,7 @@ const init = async (canvas: HTMLCanvasElement) => renderObjects: [{ pipeline, bindingResources: uniformBindGroup, - geometry: { - draw: { __type__: "DrawVertex", vertexCount: 3 }, - } + draw: { __type__: "DrawVertex", vertexCount: 3 }, }], }] }] diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index d2ceb18..93e100b 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -329,11 +329,9 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push({ pipeline: litPipeline, bindingResources: litBindGroup, - geometry: { - vertices: vertexAttributes, - indices, - draw: { __type__: "DrawIndexed", indexCount: indices.length }, - } + vertices: vertexAttributes, + indices, + draw: { __type__: "DrawIndexed", indexCount: indices.length }, }); } } @@ -353,9 +351,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => renderObjects.push({ pipeline, bindingResources: wireframeBindGroups[bindGroupNdx], - geometry: { - draw: { __type__: "DrawVertex", vertexCount: indices.length * countMult }, - } + draw: { __type__: "DrawVertex", vertexCount: indices.length * countMult }, }); }); } diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index 9cea480..c0f17f7 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -156,10 +156,8 @@ async function init(canvas: OffscreenCanvas) renderObjects: [{ pipeline, bindingResources: uniformBindGroup, - geometry: { - vertices: verticesBuffer, - draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount } - } + vertices: verticesBuffer, + draw: { __type__: "DrawVertex", vertexCount: cubeVertexCount } }] }] }] diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 208e5c5..4221767 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BindingResources, BlendState, ChainMap, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, Geometry, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, ScissorRect, Submit, TextureLike, UnReadonly, Viewport } from "@feng3d/render-api"; +import { BlendState, ChainMap, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -390,21 +390,20 @@ export class WebGPUBase */ protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) { - const { viewport, scissorRect, pipeline, bindingResources, geometry } = renderObject; - - this.runviewport(passEncoder, viewport, renderPassFormat); - this.runScissorRect(passEncoder, scissorRect, renderPassFormat); - this.runRenderPipeline(passEncoder, pipeline, renderPassFormat, geometry); - this.runBindingResources(passEncoder, pipeline, bindingResources); - this.runVertexAttributes(passEncoder, pipeline, geometry); - this.runIndices(passEncoder, geometry); - this.runDraw(passEncoder, geometry); + this.runviewport(passEncoder, renderObject, renderPassFormat); + this.runScissorRect(passEncoder, renderObject, renderPassFormat); + this.runRenderPipeline(passEncoder, renderPassFormat, renderObject); + this.runBindingResources(passEncoder, renderObject); + this.runVertexAttributes(passEncoder, renderObject); + this.runIndices(passEncoder, renderObject); + this.runDraw(passEncoder, renderObject); } - protected runviewport(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, viewport: Viewport, renderPassFormat: RenderPassFormat) + protected runviewport(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderPassFormat: RenderPassFormat) { if (!("setViewport" in passEncoder)) return; const attachmentSize = renderPassFormat.attachmentSize; + const viewport = renderObject.viewport; if (viewport) { const isYup = viewport.isYup ?? true; @@ -427,10 +426,11 @@ export class WebGPUBase } } - protected runScissorRect(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, scissorRect: ScissorRect, renderPassFormat: RenderPassFormat) + protected runScissorRect(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderPassFormat: RenderPassFormat) { if (!("setScissorRect" in passEncoder)) return; const attachmentSize = renderPassFormat.attachmentSize; + const scissorRect = renderObject.scissorRect; if (scissorRect) { const isYup = scissorRect.isYup ?? true; @@ -452,10 +452,10 @@ export class WebGPUBase } } - protected runRenderPipeline(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, renderPassFormat: RenderPassFormat, geometry: Geometry) + protected runRenderPipeline(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, geometry: RenderObject) { const device = this._device; - const { vertices, indices } = geometry; + const { pipeline, vertices, indices } = geometry; // const indexFormat: GPUIndexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; const nPipeline = getGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indexFormat); @@ -488,9 +488,10 @@ export class WebGPUBase passEncoder.setBlendConstant(blendConstantColor); } - protected runBindingResources(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, bindingResources: BindingResources) + protected runBindingResources(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject) { const device = this._device; + const { pipeline, bindingResources } = renderObject; // 计算 bindGroups const layout = getGPUPipelineLayout(device, { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => @@ -500,10 +501,10 @@ export class WebGPUBase }); } - protected runVertexAttributes(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, geometry: Geometry) + protected runVertexAttributes(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject) { const device = this._device; - const { vertices } = geometry; + const { vertices, pipeline } = geometry; // const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) vertexBuffers?.forEach((vertexBuffer, index) => @@ -517,7 +518,7 @@ export class WebGPUBase }); } - protected runIndices(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: Geometry) + protected runIndices(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject) { const { indices } = geometry; if (!indices) return; @@ -533,7 +534,7 @@ export class WebGPUBase passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); } - protected runDraw(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: Geometry) + protected runDraw(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject) { const { draw } = geometry; -- Gitee From 6825799b22bcca1fb117851772be7d64b5cb5b28 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Thu, 20 Mar 2025 19:10:30 +0800 Subject: [PATCH 156/214] =?UTF-8?q?refactor(caches):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E7=BB=B4=E5=BA=A6=E8=8E=B7=E5=8F=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 getGPUTextureDimension 函数 - 直接使用 dimensionMap 获取纹理维度 - 简化了代码结构,提高了执行效率 --- src/caches/getGPUTexture.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index e3d331f..29f111c 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -72,7 +72,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC label = `GPUTexture ${autoIndex++}`; } - const textureDimension = getGPUTextureDimension(dimension); + const textureDimension = dimensionMap[dimension]; // 创建纹理 const gpuTexture = device.createTexture({ @@ -242,13 +242,6 @@ function updateWriteTextures(device: GPUDevice, gpuTexture: GPUTexture, texture: }).value; }; -function getGPUTextureDimension(dimension: TextureDimension) -{ - const textureDimension = dimensionMap[dimension]; - - return textureDimension; -} - const dimensionMap: Record = { "1d": "1d", "2d": "2d", -- Gitee From a23ac8679b2e96357b38771add031d9a59db8819 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 10:41:37 +0800 Subject: [PATCH 157/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E5=8C=BA=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 GBuffer 接口改名为 Buffer,以更好地与 GPUBuffer 对应 - 优化了 getGPUBuffer 函数的实现,提高了缓冲区的创建和更新效率 - 调整了部分代码结构,以适应新的 Buffer 接口 - 删除了不再使用的 GBuffer 相关的 polyfill --- examples/src/webgpu/bitonicSort/index.ts | 6 +- examples/src/webgpu/renderBundles/index.ts | 31 ++-- examples/src/webgpu/skinnedMesh/glbUtils.ts | 6 +- src/WebGPUBase.ts | 43 ++++-- src/caches/getGPUBuffer.ts | 151 ++++++++++--------- src/caches/getIGPUBuffer.ts | 4 +- src/data/RenderBundle.ts | 4 +- src/data/polyfills/{GBuffer.ts => Buffer.ts} | 6 +- src/index.ts | 2 +- 9 files changed, 137 insertions(+), 116 deletions(-) rename src/data/polyfills/{GBuffer.ts => Buffer.ts} (82%) diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 74b75b5..bff3ebf 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -1,4 +1,4 @@ -import { BindingResources, BufferBinding, CommandEncoder, GBuffer, RenderPassDescriptor, Submit, reactive } from "@feng3d/render-api"; +import { BindingResources, BufferBinding, CommandEncoder, Buffer, RenderPassDescriptor, Submit, reactive } from "@feng3d/render-api"; import { ComputePass, ComputePipeline, TimestampQuery, WebGPU, getGBuffer } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; @@ -261,7 +261,7 @@ async function init( const elementsOutputBuffer: BufferBinding = { bufferView: new Uint8Array(elementsBufferSize) }; - const elementsStagingBuffer: GBuffer = { + const elementsStagingBuffer: Buffer = { size: elementsBufferSize, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, }; @@ -271,7 +271,7 @@ async function init( const atomicSwapsOutputBuffer: BufferBinding = { bufferView: new Uint32Array(1) }; - const atomicSwapsStagingBuffer: GBuffer = { + const atomicSwapsStagingBuffer: Buffer = { size: Uint32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, }; diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 1e6cf70..d8f3ca8 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -302,6 +302,19 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => } updateRenderBundle(); + const renderPass: RenderPass = { + descriptor: renderPassDescriptor, + renderObjects: [], + }; + + const submit: Submit = { + commandEncoders: [ + { + passEncoders: [renderPass], + } + ] + }; + function frame() { stats.begin(); @@ -310,34 +323,20 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => reactive(getGBuffer(uniformBuffer)).writeBuffers = [{ data: transformationMatrix }]; - let renderObjects: RenderPassObject[] = []; if (settings.useRenderBundles) { // Executing a bundle is equivalent to calling all of the commands encoded // in the render bundle as part of the current render pass. - renderObjects.push(renderBundle); + reactive(renderPass).renderObjects = [renderBundle]; } else { // Alternatively, the same render commands can be encoded manually, which // can take longer since each command needs to be interpreted by the // JavaScript virtual machine and re-validated each time. - renderObjects = renderBundle.renderObjects as any; + reactive(renderPass).renderObjects = renderBundle.renderObjects; } - const renderPass: RenderPass = { - descriptor: renderPassDescriptor, - renderObjects, - }; - - const submit: Submit = { - commandEncoders: [ - { - passEncoders: [renderPass], - } - ] - }; - webgpu.submit(submit); stats.end(); diff --git a/examples/src/webgpu/skinnedMesh/glbUtils.ts b/examples/src/webgpu/skinnedMesh/glbUtils.ts index 519878d..535df79 100644 --- a/examples/src/webgpu/skinnedMesh/glbUtils.ts +++ b/examples/src/webgpu/skinnedMesh/glbUtils.ts @@ -1,7 +1,7 @@ import { Mat4, mat4, Quatn, Vec3n } from "wgpu-matrix"; import { Accessor, BufferView, GlTf, Scene } from "./gltf"; -import { BindingResources, FragmentState, GBuffer, IDraw, PrimitiveState, reactive, RenderObject, RenderPipeline, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; +import { BindingResources, FragmentState, Buffer, IDraw, PrimitiveState, reactive, RenderObject, RenderPipeline, VertexAttributes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { getGBuffer } from "@feng3d/webgpu"; //NOTE: GLTF code is not generally extensible to all gltf models @@ -245,7 +245,7 @@ export class GLTFBufferView byteStride: number; view: Uint8Array; needsUpload: boolean; - gpuBuffer: GBuffer; + gpuBuffer: Buffer; usage: number; constructor(buffer: GLTFBuffer, view: BufferView) { @@ -285,7 +285,7 @@ export class GLTFBufferView upload() { // Note: must align to 4 byte size when mapped at creation is true - const buf: GBuffer = { + const buf: Buffer = { size: alignTo(this.view.byteLength, 4), usage: this.usage, data: this.view, diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 4221767..61cde3a 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { BlendState, ChainMap, CommandEncoder, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, GBuffer, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; +import { BlendState, Buffer, ChainMap, CommandEncoder, computed, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -125,7 +125,7 @@ export class WebGPUBase return result; } - async readBuffer(buffer: GBuffer, offset?: GPUSize64, size?: GPUSize64) + async readBuffer(buffer: Buffer, offset?: GPUSize64, size?: GPUSize64) { const device = this._device; const gpuBuffer = getGPUBuffer(device, buffer); @@ -326,11 +326,27 @@ export class WebGPUBase protected runRenderBundle(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) { const device = this._device; - // - const gpuRenderBundleKey: GPURenderBundleKey = [renderBundleObject, renderPassFormat]; - let gpuRenderBundle = gpuRenderBundleMap.get(gpuRenderBundleKey); - if (!gpuRenderBundle) + + const gpuRenderBundle = this.getGPURenderBundle(device, renderBundleObject, renderPassFormat); + + passEncoder.executeBundles([gpuRenderBundle]); + } + + private getGPURenderBundle(device: GPUDevice, renderBundleObject: RenderBundle, renderPassFormat: RenderPassFormat) + { + const gpuRenderBundleKey: GPURenderBundleKey = [device, renderBundleObject, renderPassFormat]; + let result = gpuRenderBundleMap.get(gpuRenderBundleKey); + if (result) return result.value; + + result = computed(() => { + // 监听 + const r_renderBundleObject = reactive(renderBundleObject); + r_renderBundleObject.renderObjects; + r_renderBundleObject.descriptor?.depthReadOnly; + r_renderBundleObject.descriptor?.stencilReadOnly; + + // 执行 const descriptor: GPURenderBundleEncoderDescriptor = { ...renderBundleObject.descriptor, ...renderPassFormat }; // @@ -338,11 +354,12 @@ export class WebGPUBase this.runRenderBundleObjects(renderBundleEncoder, renderPassFormat, renderBundleObject.renderObjects); - gpuRenderBundle = renderBundleEncoder.finish(); - gpuRenderBundleMap.set(gpuRenderBundleKey, gpuRenderBundle); - } + const gpuRenderBundle = renderBundleEncoder.finish(); + return gpuRenderBundle; + }); + gpuRenderBundleMap.set(gpuRenderBundleKey, result); - passEncoder.executeBundles([gpuRenderBundle]); + return result.value; } protected runRenderBundleObjects(passEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: readonly RenderObject[]) @@ -526,7 +543,7 @@ export class WebGPUBase const device = this._device; const buffer = getGBuffer(indices); - (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); + (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); const gBuffer = getGPUBuffer(device, buffer); @@ -586,5 +603,5 @@ function getStencilReference(depthStencil?: DepthStencilState) return stencilReference; } -type GPURenderBundleKey = [renderBundle: RenderBundle, renderPassFormat: RenderPassFormat]; -const gpuRenderBundleMap = new ChainMap(); \ No newline at end of file +type GPURenderBundleKey = [device: GPUDevice, renderBundle: RenderBundle, renderPassFormat: RenderPassFormat]; +const gpuRenderBundleMap = new ChainMap>(); \ No newline at end of file diff --git a/src/caches/getGPUBuffer.ts b/src/caches/getGPUBuffer.ts index 9f9c96b..ac4e2ed 100644 --- a/src/caches/getGPUBuffer.ts +++ b/src/caches/getGPUBuffer.ts @@ -1,5 +1,4 @@ -import { ChainMap, computed, ComputedRef, effect, GBuffer, reactive, UnReadonly } from "@feng3d/render-api"; -import { watcher } from "@feng3d/watcher"; +import { ChainMap, computed, ComputedRef, Buffer, reactive } from "@feng3d/render-api"; /** * 除了GPU与CPU数据交换的`MAP_READ`与`MAP_WRITE`除外。 @@ -24,42 +23,92 @@ const defaultGPUBufferUsage = 0 * @param buffer * @returns */ -export function getGPUBuffer(device: GPUDevice, buffer: GBuffer) +export function getGPUBuffer(device: GPUDevice, buffer: Buffer) { const getGPUBufferKey: GetGPUBufferKey = [device, buffer]; let result = getGPUBufferMap.get(getGPUBufferKey); if (result) return result.value; - const size = buffer.size; - console.assert(size && (size % 4 === 0), `初始化缓冲区时必须设置缓冲区尺寸且必须为4的倍数!`); - - (buffer as UnReadonly).usage = buffer.usage ?? defaultGPUBufferUsage; + let gpuBuffer: GPUBuffer; + result = computed(() => + { + // 监听 + const r_buffer = reactive(buffer); + r_buffer.size; + r_buffer.usage; - const label = buffer.label; - const usage = buffer.usage; + // 执行 + const { label, size, usage } = buffer; + console.assert(size && (size % 4 === 0), `初始化缓冲区时必须设置缓冲区尺寸且必须为4的倍数!`); - // 初始化时存在数据,则使用map方式上传第一次数据。 - const mappedAtCreation = buffer.data !== undefined; + // 初始化时存在数据,则使用map方式上传第一次数据。 + const mappedAtCreation = buffer.data !== undefined; - const gBuffer = device.createBuffer({ label, size, usage, mappedAtCreation }); + // 销毁旧的缓冲区 + if (gpuBuffer) gpuBuffer.destroy(); + gpuBuffer = device.createBuffer({ label, size, usage: usage ?? defaultGPUBufferUsage, mappedAtCreation }); - if (mappedAtCreation) - { - const bufferData = buffer.data; - if (ArrayBuffer.isView(bufferData)) - { - new Int8Array(gBuffer.getMappedRange()).set(new Int8Array(bufferData.buffer)); - } - else + // 初始化时存在数据,则使用map方式上传第一次数据。 + if (mappedAtCreation) { - new Int8Array(gBuffer.getMappedRange()).set(new Int8Array(bufferData)); + const bufferData = buffer.data; + if (ArrayBuffer.isView(bufferData)) + { + new Int8Array(gpuBuffer.getMappedRange()).set(new Int8Array(bufferData.buffer)); + } + else + { + new Int8Array(gpuBuffer.getMappedRange()).set(new Int8Array(bufferData)); + } + + gpuBuffer.unmap(); } - gBuffer.unmap(); - } + // 更新数据 + dataChange(buffer); - const writeBuffer = () => + // 写入数据 + writeBuffer(device, buffer, gpuBuffer); + + return gpuBuffer; + }); + getGPUBufferMap.set(getGPUBufferKey, result); + + return result.value; +} +type GetGPUBufferKey = [device: GPUDevice, buffer: Buffer]; +const getGPUBufferMap = new ChainMap>; + +function dataChange(buffer: Buffer) +{ + let isInitData = true; + computed(() => + { + // 监听数据变化 + const rb = reactive(buffer); + rb.data; + + // 第一次初始存在数据,则不再处理。 + if (isInitData) { isInitData = false; return } + + // 处理数据写入GPU缓冲 + const { data } = buffer; + const writeBuffers = buffer.writeBuffers || []; + writeBuffers.push({ data }); + + // 触发下次写入数据 + rb.writeBuffers = writeBuffers; + }).value; +}; + +function writeBuffer(device: GPUDevice, buffer: Buffer, gBuffer: GPUBuffer) +{ + computed(() => { + // 监听 + const rb = reactive(buffer); + rb.writeBuffers?.forEach(() => { }); + // 处理数据写入GPU缓冲 if (!buffer.writeBuffers) return; buffer.writeBuffers.forEach((writeBuffer) => @@ -101,54 +150,8 @@ export function getGPUBuffer(device: GPUDevice, buffer: GBuffer) sizeByte, ); }); - rb.writeBuffers = null; - }; - - const rb = reactive(buffer); - // 处理数据写入GPU缓冲 - result = computed(() => - { - // 监听 - rb.writeBuffers?.forEach(() => { }); - - // 执行 - writeBuffer(); - - return gBuffer; - }); - - // 这行是不是可以删掉? - effect(() => - { - result.value; - }) - const dataChange = () => - { - const writeBuffers = buffer.writeBuffers || []; - writeBuffers.push({ data: buffer.data }); - rb.writeBuffers = writeBuffers; - }; - - watcher.watch(buffer, "data", dataChange); - - // - ((oldDestroy) => - { - gBuffer.destroy = () => - { - oldDestroy.apply(gBuffer); - - getGPUBufferMap.delete(getGPUBufferKey); - - // - watcher.unwatch(buffer, "data", dataChange); - }; - })(gBuffer.destroy); - - getGPUBufferMap.set(getGPUBufferKey, result); - - return result.value; -} -type GetGPUBufferKey = [device: GPUDevice, buffer: GBuffer]; -const getGPUBufferMap = new ChainMap>; \ No newline at end of file + // 清空写入数据 + rb.writeBuffers = null; + }).value; +}; \ No newline at end of file diff --git a/src/caches/getIGPUBuffer.ts b/src/caches/getIGPUBuffer.ts index e279824..19c8eaf 100644 --- a/src/caches/getIGPUBuffer.ts +++ b/src/caches/getIGPUBuffer.ts @@ -1,4 +1,4 @@ -import { GBuffer, TypedArray } from "@feng3d/render-api"; +import { Buffer, TypedArray } from "@feng3d/render-api"; export function getGBuffer(bufferSource: TypedArray) { @@ -8,7 +8,7 @@ export function getGBuffer(bufferSource: TypedArray) arrayBuffer = (bufferSource as ArrayBufferView).buffer; } - const gpuBuffer: GBuffer = arrayBuffer["_IGPUBuffer"] = arrayBuffer["_IGPUBuffer"] || { + const gpuBuffer: Buffer = arrayBuffer["_IGPUBuffer"] = arrayBuffer["_IGPUBuffer"] || { size: Math.ceil(arrayBuffer.byteLength / 4) * 4, data: arrayBuffer, }; diff --git a/src/data/RenderBundle.ts b/src/data/RenderBundle.ts index 8e46846..5432fb0 100644 --- a/src/data/RenderBundle.ts +++ b/src/data/RenderBundle.ts @@ -22,9 +22,7 @@ export interface RenderBundle /** * GPU渲染对象列表。 */ - renderObjects: readonly RenderObject[]; - - _version?: number; + readonly renderObjects: readonly RenderObject[]; } /** diff --git a/src/data/polyfills/GBuffer.ts b/src/data/polyfills/Buffer.ts similarity index 82% rename from src/data/polyfills/GBuffer.ts rename to src/data/polyfills/Buffer.ts index 71aa2d3..9063485 100644 --- a/src/data/polyfills/GBuffer.ts +++ b/src/data/polyfills/Buffer.ts @@ -8,7 +8,7 @@ declare module "@feng3d/render-api" * {@link GPUBufferDescriptor} * {@link GPUBuffer} */ - export interface GBuffer + export interface Buffer { /** * The allowed usages for the buffer. @@ -21,8 +21,12 @@ declare module "@feng3d/render-api" | GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT | GPUBufferUsage.QUERY_RESOLVE 。 + + * 注:修改允许缓冲区使用的用途时,会重新创建缓冲区。 + * */ readonly usage?: GPUBufferUsageFlags; } } +GPUBufferUsage \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 7a9f1c7..62598ca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,7 +8,7 @@ export * from "./data/polyfills/TextureView"; export * from "./data/RenderBundle"; export * from "./data/TimestampQuery"; -export * from "./data/polyfills/GBuffer"; +export * from "./data/polyfills/Buffer"; export * from "./data/polyfills/CanvasContext"; export * from "./data/polyfills/CommandEncoder"; export * from "./data/polyfills/PrimitiveState"; -- Gitee From c2b133929507dcd3e1bd72b623131bcfddd45cb3 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 11:37:43 +0800 Subject: [PATCH 158/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=20WebGPU=20=E7=A4=BA=E4=BE=8B=E5=92=8C?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整灯光缓冲区的创建和填充方式 - 优化渲染对象的处理方法 - 修改缓存绑定组的键值生成逻辑 - 修正矩阵计算相关代码 --- examples/src/webgpu/deferredRendering/index.ts | 9 +++------ examples/src/webgpu/occlusionQuery/index.ts | 4 ++-- examples/src/webgpu/renderBundles/index.ts | 6 ++---- src/caches/getGPUBindGroup.ts | 4 ++-- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 4049da7..3702117 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -199,13 +199,11 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // which could be updated/culled/etc. with a compute shader const extent = vec3.sub(lightExtentMax, lightExtentMin); const lightDataStride = 8; - const bufferSizeInByte = Float32Array.BYTES_PER_ELEMENT * lightDataStride * kMaxNumLights; - const lightsBuffer = new Uint8Array(bufferSizeInByte); // We randomaly populate lights randomly in a box range // And simply move them along y-axis per frame to show they are // dynamic lightings - const lightData = new Float32Array(lightDataStride * kMaxNumLights); + const lightsBuffer = new Float32Array(lightDataStride * kMaxNumLights); const tmpVec4 = vec4.create(); let offset = 0; for (let i = 0; i < kMaxNumLights; i++) @@ -217,16 +215,15 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => tmpVec4[i] = Math.random() * extent[i] + lightExtentMin[i]; } tmpVec4[3] = 1; - lightData.set(tmpVec4, offset); + lightsBuffer.set(tmpVec4, offset); // color tmpVec4[0] = Math.random() * 2; tmpVec4[1] = Math.random() * 2; tmpVec4[2] = Math.random() * 2; // radius tmpVec4[3] = 20.0; - lightData.set(tmpVec4, offset + 4); + lightsBuffer.set(tmpVec4, offset + 4); } - getGBuffer(lightsBuffer).data = lightData; const lightExtentBuffer = new Uint8Array(4 * 8); const lightExtentData = new Float32Array(8); diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index a5d5cca..87dbe34 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -1,4 +1,4 @@ -import { BufferBinding, OcclusionQuery, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; +import { BufferBinding, OcclusionQuery, reactive, RenderObject, RenderPass, RenderPassDescriptor, RenderPipeline, Submit } from "@feng3d/render-api"; import { getGBuffer, WebGPU } from "@feng3d/webgpu"; import { GUI } from "dat.gui"; import { mat4 } from "wgpu-matrix"; @@ -228,7 +228,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => mat4.multiply(viewProjection, world, worldViewProjection); const buffer = (renderObjects[i].bindingResources.uni as BufferBinding).bufferView; - getGBuffer(buffer).data = uniformValues.slice(); + reactive(getGBuffer(buffer)).data = uniformValues.subarray(); } ); diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index d8f3ca8..079b3da 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -288,16 +288,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => // using render bundles as much. let renderBundle: RenderBundle = { __type__: "RenderBundle", - renderObjects: [], + renderObjects: renderScene(), }; - renderBundle.renderObjects = renderScene(); function updateRenderBundle() { const renderBundleEncoder: RenderBundle = { __type__: "RenderBundle", - renderObjects: [], + renderObjects: renderScene(), }; - renderBundleEncoder.renderObjects = renderScene(); renderBundle = renderBundleEncoder; } updateRenderBundle(); diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 98edddb..779e377 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -10,7 +10,7 @@ import { getGBuffer } from "./getIGPUBuffer"; export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources) { - const getGPUBindGroupKey: GetGPUBindGroupKey = [device, bindGroupLayout, bindingResources]; + const getGPUBindGroupKey: GetGPUBindGroupKey = [bindGroupLayout, bindingResources]; let result = getGPUBindGroupMap.get(getGPUBindGroupKey); if (result) return result.value; @@ -64,7 +64,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup type GPUBindGroupKey = [bindGroupLayout: GPUBindGroupLayout, ...resources: GPUBindingResource[]]; const gpuBindGroupMap = new ChainMap(); -type GetGPUBindGroupKey = [device: GPUDevice, bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; +type GetGPUBindGroupKey = [bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; const getGPUBindGroupMap = new ChainMap>(); function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo) -- Gitee From d0924b4d0eeaa1c3e6c6a4ed38cd78936d403d40 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 12:00:48 +0800 Subject: [PATCH 159/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20getGPUBindGroup=20=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加监听逻辑,使用 reactive 包装 bindingResources - 优化 getGPUBindingResource 函数,引入 computed 计算属性 - 调整 _getGPUBindingResource 函数,返回 ComputedRef 类型 - 更新 gpuBindingResourceMap 存储结构,适应新的计算属性 --- src/caches/getGPUBindGroup.ts | 46 +++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 779e377..3950fd3 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -21,6 +21,11 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup { const { name, type, resourceType, binding } = v.variableInfo; + // 监听 + const r_bindingResources = reactive(bindingResources); + r_bindingResources[name]; + + // 执行 const entry: GPUBindGroupEntry = { binding, resource: null }; // @@ -93,7 +98,7 @@ function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResou // 更新缓冲区绑定的数据。 updateBufferBinding(bufferBinding, type); // - const gpuBindingResource = _getGPUBindingResource(device, bufferBinding.bufferView); + const gpuBindingResource = _getGPUBindingResource(device, bufferBinding.bufferView, name); return gpuBindingResource; }); @@ -104,32 +109,37 @@ function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResou type GetGPUBindingResourceKey = [device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo]; const getGPUBindingResourceMap = new ChainMap>(); -function _getGPUBindingResource(device: GPUDevice, bufferView: TypedArray) +function _getGPUBindingResource(device: GPUDevice, bufferView: TypedArray, name: string) { // const gpuBindingResourceKey: GPUBindingResourceKey = [device, bufferView]; - const cache = gpuBindingResourceMap.get(gpuBindingResourceKey); - if (cache) return cache; + let cache = gpuBindingResourceMap.get(gpuBindingResourceKey); + if (cache) return cache.value; - const gbuffer = getGBuffer(bufferView); - (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); - // - const buffer = getGPUBuffer(device, gbuffer); + cache = computed(() => + { + const gbuffer = getGBuffer(bufferView); + (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); + // + const buffer = getGPUBuffer(device, gbuffer); - const offset = bufferView.byteOffset; - const size = bufferView.byteLength; + const offset = bufferView.byteOffset; + const size = bufferView.byteLength; - const gpuBindingResource: GPUBindingResource = { - buffer, - offset, - size, - }; - gpuBindingResourceMap.set(gpuBindingResourceKey, gpuBindingResource); + const gpuBindingResource: GPUBindingResource = { + buffer, + offset, + size, + }; + + return gpuBindingResource; + }); + gpuBindingResourceMap.set(gpuBindingResourceKey, cache); - return gpuBindingResource; + return cache.value; } type GPUBindingResourceKey = [device: GPUDevice, bufferView: TypedArray]; -const gpuBindingResourceMap = new ChainMap(); +const gpuBindingResourceMap = new ChainMap>(); function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) { -- Gitee From 67d1904865eb838093a33a069b239c162b6e26e7 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 12:34:05 +0800 Subject: [PATCH 160/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20uniform=20=E5=92=8C=20storage=20=E7=B1=BB=E5=9E=8B=E7=9A=84?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E8=B5=84=E6=BA=90=E8=8E=B7=E5=8F=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 getGPUBindingResource 函数重命名为 getGPUBufferBinding,以更准确地反映其功能 - 移除了不必要的 _getGPUBindingResource 函数,简化了资源获取流程 - 优化了 GPU buffer binding 的创建和缓存逻辑 - 调整了相关类型和变量名称,提高了代码可读性 --- src/caches/getGPUBindGroup.ts | 38 +++++++++-------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 3950fd3..b1c50c2 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -31,7 +31,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup // if (resourceType === ResourceType.Uniform || resourceType === ResourceType.Storage) { - entry.resource = getGPUBindingResource(device, bindingResources, name, type); + entry.resource = getGPUBufferBinding(device, bindingResources, name, type); } else if (ExternalSampledTextureType[type.name]) // 判断是否为外部纹理 { @@ -72,7 +72,7 @@ const gpuBindGroupMap = new ChainMap(); type GetGPUBindGroupKey = [bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; const getGPUBindGroupMap = new ChainMap>(); -function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo) +function getGPUBufferBinding(device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo) { const getGPUBindingResourceKey: GetGPUBindingResourceKey = [device, bindingResources, name, type]; let result = getGPUBindingResourceMap.get(getGPUBindingResourceKey); @@ -97,27 +97,8 @@ function getGPUBindingResource(device: GPUDevice, bindingResources: BindingResou const bufferBinding = resource as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 // 更新缓冲区绑定的数据。 updateBufferBinding(bufferBinding, type); + const bufferView = bufferBinding.bufferView; // - const gpuBindingResource = _getGPUBindingResource(device, bufferBinding.bufferView, name); - return gpuBindingResource; - }); - - getGPUBindingResourceMap.set(getGPUBindingResourceKey, result); - - return result.value; -} -type GetGPUBindingResourceKey = [device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo]; -const getGPUBindingResourceMap = new ChainMap>(); - -function _getGPUBindingResource(device: GPUDevice, bufferView: TypedArray, name: string) -{ - // - const gpuBindingResourceKey: GPUBindingResourceKey = [device, bufferView]; - let cache = gpuBindingResourceMap.get(gpuBindingResourceKey); - if (cache) return cache.value; - - cache = computed(() => - { const gbuffer = getGBuffer(bufferView); (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); // @@ -126,20 +107,21 @@ function _getGPUBindingResource(device: GPUDevice, bufferView: TypedArray, name: const offset = bufferView.byteOffset; const size = bufferView.byteLength; - const gpuBindingResource: GPUBindingResource = { + const gpuBufferBinding: GPUBufferBinding = { buffer, offset, size, }; - return gpuBindingResource; + return gpuBufferBinding; }); - gpuBindingResourceMap.set(gpuBindingResourceKey, cache); - return cache.value; + getGPUBindingResourceMap.set(getGPUBindingResourceKey, result); + + return result.value; } -type GPUBindingResourceKey = [device: GPUDevice, bufferView: TypedArray]; -const gpuBindingResourceMap = new ChainMap>(); +type GetGPUBindingResourceKey = [device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo]; +const getGPUBindingResourceMap = new ChainMap>(); function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) { -- Gitee From ea5fb433a4f0fd714e4bfaf770e68d64e6ed5101 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 12:52:06 +0800 Subject: [PATCH 161/214] =?UTF-8?q?perf(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E5=8C=BA=E7=BB=91=E5=AE=9A=E7=9A=84=E6=80=A7?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 getGPUBindGroup 中引入 numberBufferBinding 对象,用于处理数字类型的资源 - 重构 getGPUBufferBinding 函数,使用 BufferBinding 类型的参数 - 在 getGPUBufferBinding 中增加缓存机制,避免重复创建 GPUBufferBinding - 优化 getGBuffer 函数,使用 WeakMap 缓存 GBuffer 对象 --- src/caches/getGPUBindGroup.ts | 47 ++++++++++++++++++++--------------- src/caches/getIGPUBuffer.ts | 9 +++++-- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index b1c50c2..b76c4b9 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,4 +1,4 @@ -import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, reactive, Sampler, TextureView, TypedArray, UnReadonly } from "@feng3d/render-api"; +import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, reactive, Sampler, TextureView, UnReadonly } from "@feng3d/render-api"; import { ArrayInfo, ResourceType, StructInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; import { VideoTexture } from "../data/VideoTexture"; import { webgpuEvents } from "../eventnames"; @@ -15,6 +15,7 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup if (result) return result.value; let gBindGroup: GPUBindGroup; + let numberBufferBinding: { [name: string]: number[] } = {}; result = computed(() => { const entries = bindGroupLayout.entries.map((v) => @@ -31,7 +32,17 @@ export function getGPUBindGroup(device: GPUDevice, bindGroupLayout: GPUBindGroup // if (resourceType === ResourceType.Uniform || resourceType === ResourceType.Storage) { - entry.resource = getGPUBufferBinding(device, bindingResources, name, type); + // 执行 + let resource = bindingResources[name]; + // 当值为number时,将其视为一个数组。 + if (typeof resource === "number") + { + numberBufferBinding[name] ??= []; + numberBufferBinding[name][0] = resource; + resource = numberBufferBinding[name]; + } + const bufferBinding = resource as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 + entry.resource = getGPUBufferBinding(device, bufferBinding, type); } else if (ExternalSampledTextureType[type.name]) // 判断是否为外部纹理 { @@ -72,35 +83,24 @@ const gpuBindGroupMap = new ChainMap(); type GetGPUBindGroupKey = [bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; const getGPUBindGroupMap = new ChainMap>(); -function getGPUBufferBinding(device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo) +function getGPUBufferBinding(device: GPUDevice, bufferBinding: BufferBinding, type: TypeInfo) { - const getGPUBindingResourceKey: GetGPUBindingResourceKey = [device, bindingResources, name, type]; + const getGPUBindingResourceKey: GetGPUBindingResourceKey = [device, bufferBinding, type]; let result = getGPUBindingResourceMap.get(getGPUBindingResourceKey); if (result) return result.value; - let numberBufferBinding: number[]; result = computed(() => { // 监听 - const r_bindingResources = reactive(bindingResources); - (r_bindingResources[name] as BufferBinding)?.bufferView; + const r_bufferBinding = reactive(bufferBinding); + r_bufferBinding?.bufferView; - // 执行 - let resource = bindingResources[name]; - // 当值为number时,将其视为一个数组。 - if (typeof resource === "number") - { - numberBufferBinding ??= []; - numberBufferBinding[0] = resource; - resource = numberBufferBinding; - } - const bufferBinding = resource as BufferBinding; // 值为number且不断改变时将可能会产生无数细碎gpu缓冲区。 // 更新缓冲区绑定的数据。 updateBufferBinding(bufferBinding, type); const bufferView = bufferBinding.bufferView; // const gbuffer = getGBuffer(bufferView); - (gbuffer as any).label = gbuffer.label || (`BufferBinding ${name}`); + (gbuffer as any).label = gbuffer.label || (`BufferBinding ${type.name}`); // const buffer = getGPUBuffer(device, gbuffer); @@ -112,6 +112,10 @@ function getGPUBufferBinding(device: GPUDevice, bindingResources: BindingResourc offset, size, }; + const gpuBufferBindingKey: GPUBufferBindingKey = [buffer, offset, size]; + const cache = gpuBufferBindingMap.get(gpuBufferBindingKey); + if (cache) return cache; + gpuBufferBindingMap.set(gpuBufferBindingKey, gpuBufferBinding); return gpuBufferBinding; }); @@ -120,8 +124,11 @@ function getGPUBufferBinding(device: GPUDevice, bindingResources: BindingResourc return result.value; } -type GetGPUBindingResourceKey = [device: GPUDevice, bindingResources: BindingResources, name: string, type: TypeInfo]; -const getGPUBindingResourceMap = new ChainMap>(); +type GPUBufferBindingKey = [buffer: GPUBuffer, offset: number, size: number]; +const gpuBufferBindingMap = new ChainMap(); + +type GetGPUBindingResourceKey = [device: GPUDevice, bufferBinding: BufferBinding, type: TypeInfo]; +const getGPUBindingResourceMap = new ChainMap>(); function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) { diff --git a/src/caches/getIGPUBuffer.ts b/src/caches/getIGPUBuffer.ts index 19c8eaf..f3f924e 100644 --- a/src/caches/getIGPUBuffer.ts +++ b/src/caches/getIGPUBuffer.ts @@ -8,11 +8,16 @@ export function getGBuffer(bufferSource: TypedArray) arrayBuffer = (bufferSource as ArrayBufferView).buffer; } - const gpuBuffer: Buffer = arrayBuffer["_IGPUBuffer"] = arrayBuffer["_IGPUBuffer"] || { + let gpuBuffer = bufferMap.get(arrayBuffer); + if (gpuBuffer) return gpuBuffer; + + gpuBuffer = { size: Math.ceil(arrayBuffer.byteLength / 4) * 4, - data: arrayBuffer, + data: bufferSource, }; + bufferMap.set(arrayBuffer, gpuBuffer); return gpuBuffer; } +const bufferMap = new WeakMap(); \ No newline at end of file -- Gitee From 0d4624ff461469ec4554b83d2d60072657920431 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 13:13:23 +0800 Subject: [PATCH 162/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E9=80=BB=E8=BE=91=E4=BB=A5=E6=8F=90=E9=AB=98?= =?UTF-8?q?=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 提前创建并复用 RenderPass 对象,减少每帧创建的开销 - 使用 Submit 对象统一管理命令编码器,简化提交逻辑 - 通过预计算和缓存渲染对象,提高渲染效率 --- examples/src/webgpu/skinnedMesh/index.ts | 88 ++++++++++++++---------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index 95a3dde..f4aabc3 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -7,7 +7,7 @@ import gridWGSL from "./grid.wgsl"; import { gridIndices } from "./gridData"; import { createSkinnedGridBuffers, createSkinnedGridRenderPipeline } from "./gridUtils"; -import { BindingResources, PassEncoder, reactive, RenderObject, RenderPass, RenderPassDescriptor, Texture } from "@feng3d/render-api"; +import { BindingResources, PassEncoder, reactive, RenderObject, RenderPass, RenderPassDescriptor, Submit, Texture } from "@feng3d/render-api"; import { getGBuffer, WebGPU } from "@feng3d/webgpu"; const init = async (canvas: HTMLCanvasElement, gui: GUI) => @@ -424,6 +424,51 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } }; + const passEncoders: PassEncoder[] = []; + const submit: Submit = { commandEncoders: [{ passEncoders }] }; + + const whaleRenderPass = (() => + { + const renderObjects: RenderObject[] = []; + const bindingResources: BindingResources = { + ...cameraBGCluster, + ...generalUniformsBGCLuster, + }; + for (const scene of whaleScene.scenes) + { + scene.root.renderDrawables(renderObjects, bindingResources); + } + const passEncoder: RenderPass = { + descriptor: gltfRenderPassDescriptor, + renderObjects + }; + return passEncoder; + })(); + const skinnedGridRenderPass = (() => + { + // Our skinned grid isn't checking for depth, so we pass it + // a separate render descriptor that does not take in a depth texture + // Pass in vertex and index buffers generated from our static skinned grid + // data at ./gridData.ts + const renderObject: RenderObject = { + pipeline: skinnedGridPipeline, + bindingResources: { + ...cameraBGCluster, + ...generalUniformsBGCLuster, + ...skinnedGridBoneBGCluster, + }, + vertices: skinnedGridVertexBuffers.vertices, + indices: skinnedGridVertexBuffers.indices, + draw: { __type__: "DrawIndexed", indexCount: gridIndices.length }, + }; + // + const passEncoder: RenderPass = { + descriptor: gltfRenderPassDescriptor, + renderObjects: [renderObject], + }; + return passEncoder; + })(); + function frame() { // Calculate camera matrices @@ -483,50 +528,17 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Node 6 should be the only node with a drawable mesh so hopefully this works fine whaleScene.skins[0].update(6, whaleScene.nodes); - const passEncoders: PassEncoder[] = []; - + passEncoders.length = 0; if (settings.object === "Whale") { - const renderObjects: RenderObject[] = []; - const bindingResources: BindingResources = { - ...cameraBGCluster, - ...generalUniformsBGCLuster, - }; - for (const scene of whaleScene.scenes) - { - scene.root.renderDrawables(renderObjects, bindingResources); - } - const passEncoder: RenderPass = { - descriptor: gltfRenderPassDescriptor, - renderObjects - }; - passEncoders.push(passEncoder); + passEncoders.push(whaleRenderPass); } else { - // Our skinned grid isn't checking for depth, so we pass it - // a separate render descriptor that does not take in a depth texture - // Pass in vertex and index buffers generated from our static skinned grid - // data at ./gridData.ts - const renderObject: RenderObject = { - pipeline: skinnedGridPipeline, - bindingResources: { - ...cameraBGCluster, - ...generalUniformsBGCLuster, - ...skinnedGridBoneBGCluster, - }, - vertices: skinnedGridVertexBuffers.vertices, - indices: skinnedGridVertexBuffers.indices, - draw: { __type__: "DrawIndexed", indexCount: gridIndices.length }, - }; - // - passEncoders.push({ - descriptor: skinnedGridRenderPassDescriptor, - renderObjects: [renderObject], - }); + passEncoders.push(skinnedGridRenderPass); } - webgpu.submit({ commandEncoders: [{ passEncoders }] }); + webgpu.submit(submit); requestAnimationFrame(frame); } -- Gitee From 4221c9fdb106385647921e831eb0d18a9a56452d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 13:54:00 +0800 Subject: [PATCH 163/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E7=BC=93=E5=AD=98=E7=9A=84=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E5=89=8D=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 getGPUBindGroup.ts 中,将"监听"修改为"在提交前确保收集到正确的外部纹理" - 在 getGPUTexture.ts 中,将"//"修改为"确保在提交之前使用正确的画布纹理" - 这些修改提高了代码的可读性和准确性,更好地描述了预提交处理的目的 --- src/caches/getGPUBindGroup.ts | 2 +- src/caches/getGPUTexture.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index b76c4b9..74b7cc4 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -138,7 +138,7 @@ function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) result = computed(() => { - // 监听 + // 在提交前确保收集到正确的外部纹理。 reactive(webgpuEvents).preSubmit; // diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 29f111c..f033698 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -24,7 +24,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC { if ("context" in textureLike) { - // + // 确保在提交之前使用正确的画布纹理。 reactive(webgpuEvents).preSubmit; const canvasTexture = textureLike; -- Gitee From 001eb3af3e52d8140c1f21aa2053f316dceca2f9 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 14:31:26 +0800 Subject: [PATCH 164/214] =?UTF-8?q?fix(WebGPU):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E8=A7=86=E5=8F=A3=E6=9C=80=E5=A4=A7=E6=B7=B1=E5=BA=A6=E5=80=BC?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将视口最大深度值的默认值从 0 修改为 1 - 这个修改符合 WebGPU 规范,确保深度测试在默认设置下能正常工作 --- src/WebGPUBase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 61cde3a..fe93ba6 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -429,7 +429,7 @@ export class WebGPUBase const width = viewport.width ?? attachmentSize.width; const height = viewport.height ?? attachmentSize.height; const minDepth = viewport.minDepth ?? 0; - const maxDepth = viewport.maxDepth ?? 0; + const maxDepth = viewport.maxDepth ?? 1; if (isYup) { -- Gitee From 09340fcd82e9940c227fe910d7c82a373b131074 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 15:17:43 +0800 Subject: [PATCH 165/214] =?UTF-8?q?feat(WebGPU):=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E5=9F=BA=E4=BA=8E=20computed=20=E7=9A=84=20renderObject=20?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构了 WebGPUBase 类中的 runRenderObject 方法,引入了 RenderObjectCache - 新增 renderObjectCacheMap 用于缓存 renderObject 相关的命令 - 优化了渲染命令的生成和执行流程,提高了性能 - 暂时移除了 WebGPUCache 类中的冗余代码 --- src/WebGPU.ts | 1 - src/WebGPUBase.ts | 85 +++-- src/WebGPUCache.ts | 542 +++++++++++++++--------------- src/internal/RenderObjectCache.ts | 65 ++++ 4 files changed, 398 insertions(+), 295 deletions(-) create mode 100644 src/internal/RenderObjectCache.ts diff --git a/src/WebGPU.ts b/src/WebGPU.ts index 570b057..25ff4bf 100644 --- a/src/WebGPU.ts +++ b/src/WebGPU.ts @@ -1,5 +1,4 @@ import { WebGPUBase } from "./WebGPUBase"; -import { WebGPUCache } from "./WebGPUCache"; /** * WebGPU 对象。 diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index fe93ba6..183cbd4 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -19,6 +19,7 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit, webgpuEvents } from "./eventnames"; +import { RenderObjectCache } from "./internal/RenderObjectCache"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; @@ -407,16 +408,35 @@ export class WebGPUBase */ protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) { - this.runviewport(passEncoder, renderObject, renderPassFormat); - this.runScissorRect(passEncoder, renderObject, renderPassFormat); - this.runRenderPipeline(passEncoder, renderPassFormat, renderObject); - this.runBindingResources(passEncoder, renderObject); - this.runVertexAttributes(passEncoder, renderObject); - this.runIndices(passEncoder, renderObject); - this.runDraw(passEncoder, renderObject); + const device = this._device; + const renderObjectCacheKey: RenderObjectCacheKey = [device, renderObject, renderPassFormat]; + let result = renderObjectCacheMap.get(renderObjectCacheKey); + if (result) + { + RenderObjectCache.run(result.value, passEncoder); + + return result.value; + } + + const renderObjectCache: RenderObjectCache = {} as any; + result = computed(() => + { + this.runviewport(passEncoder, renderObject, renderPassFormat, renderObjectCache); + this.runScissorRect(passEncoder, renderObject, renderPassFormat, renderObjectCache); + this.runRenderPipeline(passEncoder, renderPassFormat, renderObject, renderObjectCache); + this.runBindingResources(passEncoder, renderObject, renderObjectCache); + this.runVertexAttributes(passEncoder, renderObject, renderObjectCache); + this.runIndices(passEncoder, renderObject, renderObjectCache); + this.runDraw(passEncoder, renderObject, renderObjectCache); + + return renderObjectCache; + }); + renderObjectCacheMap.set(renderObjectCacheKey, result); + + return result.value; } - protected runviewport(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderPassFormat: RenderPassFormat) + protected runviewport(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderPassFormat: RenderPassFormat, renderObjectCache: RenderObjectCache) { if (!("setViewport" in passEncoder)) return; const attachmentSize = renderPassFormat.attachmentSize; @@ -436,14 +456,18 @@ export class WebGPUBase y = attachmentSize.height - y - height; } passEncoder.setViewport(x, y, width, height, minDepth, maxDepth); + // + renderObjectCache.setViewport = [x, y, width, height, minDepth, maxDepth]; } else { passEncoder.setViewport(0, 0, attachmentSize.width, attachmentSize.height, 0, 1); + // + renderObjectCache.setViewport = [0, 0, attachmentSize.width, attachmentSize.height, 0, 1]; } } - protected runScissorRect(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderPassFormat: RenderPassFormat) + protected runScissorRect(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderPassFormat: RenderPassFormat, renderObjectCache: RenderObjectCache) { if (!("setScissorRect" in passEncoder)) return; const attachmentSize = renderPassFormat.attachmentSize; @@ -462,30 +486,33 @@ export class WebGPUBase } passEncoder.setScissorRect(x, y, width, height); + renderObjectCache.setScissorRect = [x, y, width, height]; } else { passEncoder.setScissorRect(0, 0, attachmentSize.width, attachmentSize.height); + renderObjectCache.setScissorRect = [0, 0, attachmentSize.width, attachmentSize.height]; } } - protected runRenderPipeline(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, geometry: RenderObject) + protected runRenderPipeline(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject, renderObjectCache: RenderObjectCache) { const device = this._device; - const { pipeline, vertices, indices } = geometry; + const { pipeline, vertices, indices } = renderObject; // const indexFormat: GPUIndexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; - const nPipeline = getGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indexFormat); + const gpuRenderPipeline = getGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indexFormat); // - passEncoder.setPipeline(nPipeline); + passEncoder.setPipeline(gpuRenderPipeline); + renderObjectCache.setPipeline = [gpuRenderPipeline]; // - this.runStencilReference(passEncoder, pipeline); - this.runBlendConstant(passEncoder, pipeline); + this.runStencilReference(passEncoder, pipeline, renderObjectCache); + this.runBlendConstant(passEncoder, pipeline, renderObjectCache); } - protected runStencilReference(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline) + protected runStencilReference(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, renderObjectCache: RenderObjectCache) { if (!("setStencilReference" in passEncoder)) return; // @@ -493,9 +520,10 @@ export class WebGPUBase if (stencilReference === undefined) return; passEncoder.setStencilReference(stencilReference); + renderObjectCache.setStencilReference = [stencilReference]; } - protected runBlendConstant(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline) + protected runBlendConstant(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, renderObjectCache: RenderObjectCache) { if (!("setBlendConstant" in passEncoder)) return; // @@ -503,9 +531,10 @@ export class WebGPUBase if (blendConstantColor === undefined) return; passEncoder.setBlendConstant(blendConstantColor); + renderObjectCache.setBlendConstant = [blendConstantColor]; } - protected runBindingResources(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject) + protected runBindingResources(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderObjectCache: RenderObjectCache) { const device = this._device; const { pipeline, bindingResources } = renderObject; @@ -515,13 +544,15 @@ export class WebGPUBase { const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources); passEncoder.setBindGroup(group, gpuBindGroup); + renderObjectCache.setBindGroup ??= [] + renderObjectCache.setBindGroup[group] = [group, gpuBindGroup]; }); } - protected runVertexAttributes(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject) + protected runVertexAttributes(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderObjectCache: RenderObjectCache) { const device = this._device; - const { vertices, pipeline } = geometry; + const { vertices, pipeline } = renderObject; // const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) vertexBuffers?.forEach((vertexBuffer, index) => @@ -532,10 +563,12 @@ export class WebGPUBase const gBuffer = getGPUBuffer(device, buffer); passEncoder.setVertexBuffer(index, gBuffer, vertexBuffer.offset, vertexBuffer.size); + renderObjectCache.setVertexBuffer ??= []; + renderObjectCache.setVertexBuffer[index] = [index, gBuffer, vertexBuffer.offset, vertexBuffer.size]; }); } - protected runIndices(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject) + protected runIndices(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject, renderObjectCache: RenderObjectCache) { const { indices } = geometry; if (!indices) return; @@ -549,19 +582,22 @@ export class WebGPUBase // passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); + renderObjectCache.setIndexBuffer = [gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength]; } - protected runDraw(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject) + protected runDraw(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject, renderObjectCache: RenderObjectCache) { const { draw } = geometry; if (draw.__type__ === 'DrawVertex') { passEncoder.draw(draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance); + renderObjectCache.draw = [draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance]; } else { passEncoder.drawIndexed(draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance); + renderObjectCache.drawIndexed = [draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance]; } } } @@ -604,4 +640,7 @@ function getStencilReference(depthStencil?: DepthStencilState) } type GPURenderBundleKey = [device: GPUDevice, renderBundle: RenderBundle, renderPassFormat: RenderPassFormat]; -const gpuRenderBundleMap = new ChainMap>(); \ No newline at end of file +const gpuRenderBundleMap = new ChainMap>(); + +type RenderObjectCacheKey = [device: GPUDevice, renderObject: RenderObject, renderPassFormat: RenderPassFormat]; +const renderObjectCacheMap = new ChainMap>(); \ No newline at end of file diff --git a/src/WebGPUCache.ts b/src/WebGPUCache.ts index fbd0e37..242d567 100644 --- a/src/WebGPUCache.ts +++ b/src/WebGPUCache.ts @@ -1,271 +1,271 @@ -import { ChainMap, RenderObject, RenderPassObject } from "@feng3d/render-api"; - -import { watcher } from "@feng3d/watcher"; -import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; -import { RenderPassFormat } from "./internal/RenderPassFormat"; -import { WebGPUBase } from "./WebGPUBase"; - -/** - * 缓存命令,优化性能。 - */ -export class WebGPUCache extends WebGPUBase -{ - protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) - { - const device = this._device; - const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat, renderObjects]; - let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); - if (!caches) - { - // 收集命令 - const renderPassRecord = new GPURenderPassRecord(); - const commands = renderPassRecord["_commands"] = []; - - super.runRenderPassObjects(renderPassRecord, renderPassFormat, renderObjects, occlusionQuery); - - // 排除无效命令 - paichuWuxiaoCommands(renderPassFormat.attachmentSize, commands); - - // - const setBindGroupCommands = commands.filter((v) => v[0] === "setBindGroup"); - - caches = { commands, setBindGroupCommands }; - - _renderPassObjectsCommandMap.set(renderPassObjectsCommandKey, caches); - - // 监听变化 - const onchanged = () => - { - _renderPassObjectsCommandMap.delete(renderPassObjectsCommandKey); - // - renderObjects.forEach((v) => { watcher.unwatch(v, "_version" as any, onchanged); }); - }; - renderObjects.forEach((v) => { watcher.watch(v, "_version" as any, onchanged); }); - } - - // 执行命令 - runCommands(passEncoder, caches); - } - - protected runRenderBundleObjects(bundleEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: RenderObject[]) - { - const device = this._device; - const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat, renderObjects]; - let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); - if (!caches) - { - // 收集命令 - // const renderBundleRecord = new GPURenderBundleRecord(); - const renderBundleRecord = new GPURenderPassRecord(); - const commands = renderBundleRecord["_commands"] = []; - - super.runRenderBundleObjects(renderBundleRecord as any, renderPassFormat, renderObjects); - - // 排除无效命令 - paichuWuxiaoCommands(renderPassFormat.attachmentSize, commands); - // - const setBindGroupCommands = commands.filter((v) => v[0] === "setBindGroup"); - - caches = { commands, setBindGroupCommands }; - - _renderPassObjectsCommandMap.set(renderPassObjectsCommandKey, caches); - - // 监听变化 - const onchanged = () => - { - _renderPassObjectsCommandMap.delete(renderPassObjectsCommandKey); - // - renderObjects.forEach((v) => { watcher.unwatch(v, "_version", onchanged); }); - }; - renderObjects.forEach((v) => { watcher.watch(v, "_version", onchanged); }); - } - - // 排除在 GPURenderBundleEncoder 中不支持的命令 - const commands = caches.commands.filter((v) => (v[0] in bundleEncoder)); - - // 执行命令 - runCommands(bundleEncoder, { ...caches, commands }); - } - - protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) - { - const device = this._device; - const _commands = passEncoder["_commands"] as any[]; - - const renderObjectCommandKey: RenderObjectCommandKey = [device, renderPassFormat, renderObject]; - const commands = renderObjectCommandMap.get(renderObjectCommandKey); - if (commands) - { - commands.forEach((v) => _commands.push(v)); - - return; - } - - const start = _commands.length; - - super.runRenderObject(passEncoder, renderPassFormat, renderObject); - - renderObjectCommandMap.set(renderObjectCommandKey, _commands.slice(start)); - - // - const onchanged = () => - { - renderObjectCommandMap.delete(renderObjectCommandKey); - // - renderObject._version = ~~renderObject._version + 1; - watcher.unwatch(renderObject.pipeline, '_version', onchanged); - } - watcher.watch(renderObject.pipeline, '_version', onchanged); - } -} -type RenderObjectCommandKey = [device: GPUDevice, renderPassFormat: RenderPassFormat, renderObject: RenderObject]; -const renderObjectCommandMap = new ChainMap>(); - -class GPURenderPassRecord implements GPURenderPassEncoder -{ - __brand: "GPURenderPassEncoder" = "GPURenderPassEncoder"; - label: string; - // - setViewport(...args: any): undefined { this["_commands"].push(["setViewport", args]); } - setScissorRect(...args: any): undefined { this["_commands"].push(["setScissorRect", args]); } - setBlendConstant(...args: any): undefined { this["_commands"].push(["setBlendConstant", args]); } - setStencilReference(...args: any): undefined { this["_commands"].push(["setStencilReference", args]); } - // - setPipeline(...args: any): undefined { this["_commands"].push(["setPipeline", args]); } - setVertexBuffer(...args: any): undefined { this["_commands"].push(["setVertexBuffer", args]); } - setIndexBuffer(...args: any): undefined { this["_commands"].push(["setIndexBuffer", args]); } - setBindGroup(...args: any): undefined { this["_commands"].push(["setBindGroup", args]); } - draw(...args: any): undefined { this["_commands"].push(["draw", args]); } - drawIndexed(...args: any): undefined { this["_commands"].push(["drawIndexed", args]); } - drawIndirect(...args: any): undefined { this["_commands"].push(["drawIndirect", args]); } - drawIndexedIndirect(...args: any): undefined { this["_commands"].push(["drawIndexedIndirect", args]); } - // - beginOcclusionQuery(...args: any): undefined { this["_commands"].push(["beginOcclusionQuery", args]); } - endOcclusionQuery(...args: any): undefined { this["_commands"].push(["endOcclusionQuery", args]); } - // - executeBundles(...args: any): undefined { this["_commands"].push(["executeBundles", args]); } - // - end(...args: any): undefined { this["_commands"].push(["end", args]); } - // - pushDebugGroup(...args: any): undefined { this["_commands"].push(["pushDebugGroup", args]); } - popDebugGroup(...args: any): undefined { this["_commands"].push(["popDebugGroup", args]); } - insertDebugMarker(...args: any): undefined { this["_commands"].push(["insertDebugMarker", args]); } -} - -function runCommands(_passEncoder: GPURenderPassEncoder | GPUComputePassEncoder | GPURenderBundleEncoder, caches: { - commands: Array; - setBindGroupCommands: Array; -}) -{ - const { commands, setBindGroupCommands } = caches; - - setBindGroupCommands.forEach((v) => - { - v[1][1] = v[1][1](); - }); - - commands.forEach((v) => - { - _passEncoder[v[0]].apply(_passEncoder, v[1]); - }); -} - -/** - * 排除无效命令 - * - * @param attachmentSize - */ -function paichuWuxiaoCommands(attachmentSize: { readonly width: number; readonly height: number; }, commands: any[]) -{ - const _obj = { - setBindGroup: [], setVertexBuffer: [], - setViewport: [0, 0, attachmentSize.width, attachmentSize.height, 0, 1], - setScissorRect: [0, 0, attachmentSize.width, attachmentSize.height], - }; - // - let length = 0; - commands.concat().forEach((v) => - { - // 排除重复的无效命令 - if (v[0] === "setBindGroup" || v[0] === "setVertexBuffer") - { - if (!arrayEq1(_obj, v[0], v[1][0], v[1])) - { - commands[length++] = v; - } - } - else if (0 - || v[0] === "setPipeline" - || v[0] === "setIndexBuffer" - || v[0] === "setViewport" - || v[0] === "setScissorRect" - || v[0] === "setBlendConstant" - || v[0] === "setStencilReference" - ) - { - if (!arrayEq0(_obj, v[0], v[1])) - { - commands[length++] = v; - } - } - else - { - commands[length++] = v; - } - }); - commands.length = length; -} - -function arrayEq0(_obj: any, name: string, args: any[]) -{ - const obj = _obj; - const oldArgs: any[] = obj[name]; - if (!oldArgs) - { - obj[name] = args; - - return false; - } - - for (let i = 0, n = oldArgs.length; i < n; i++) - { - if (oldArgs[i] !== args[i]) - { - obj[name] = args; - - return false; - } - } - - return true; -} - -function arrayEq1(_obj: any, name: string, index: number, args: any[]) -{ - const obj = _obj[name]; - const oldArgs: any[] = obj[index]; - if (!oldArgs) - { - obj[index] = args; - - return false; - } - - for (let i = 1, n = oldArgs.length; i < n; i++) - { - if (oldArgs[i] !== args[i]) - { - obj[index] = args; - - return false; - } - } - - return true; -} - -type RenderPassObjectsCommandKey = [device: GPUDevice, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[]]; -const _renderPassObjectsCommandMap = new ChainMap; - setBindGroupCommands: Array; -}>; \ No newline at end of file +// import { ChainMap, RenderObject, RenderPassObject } from "@feng3d/render-api"; + +// import { watcher } from "@feng3d/watcher"; +// import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; +// import { RenderPassFormat } from "./internal/RenderPassFormat"; +// import { WebGPUBase } from "./WebGPUBase"; + +// /** +// * 缓存命令,优化性能。 +// */ +// export class WebGPUCache extends WebGPUBase +// { +// protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) +// { +// const device = this._device; +// const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat, renderObjects]; +// let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); +// if (!caches) +// { +// // 收集命令 +// const renderPassRecord = new GPURenderPassRecord(); +// const commands = renderPassRecord["_commands"] = []; + +// super.runRenderPassObjects(renderPassRecord, renderPassFormat, renderObjects, occlusionQuery); + +// // 排除无效命令 +// paichuWuxiaoCommands(renderPassFormat.attachmentSize, commands); + +// // +// const setBindGroupCommands = commands.filter((v) => v[0] === "setBindGroup"); + +// caches = { commands, setBindGroupCommands }; + +// _renderPassObjectsCommandMap.set(renderPassObjectsCommandKey, caches); + +// // 监听变化 +// const onchanged = () => +// { +// _renderPassObjectsCommandMap.delete(renderPassObjectsCommandKey); +// // +// renderObjects.forEach((v) => { watcher.unwatch(v, "_version" as any, onchanged); }); +// }; +// renderObjects.forEach((v) => { watcher.watch(v, "_version" as any, onchanged); }); +// } + +// // 执行命令 +// runCommands(passEncoder, caches); +// } + +// protected runRenderBundleObjects(bundleEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: RenderObject[]) +// { +// const device = this._device; +// const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat, renderObjects]; +// let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); +// if (!caches) +// { +// // 收集命令 +// // const renderBundleRecord = new GPURenderBundleRecord(); +// const renderBundleRecord = new GPURenderPassRecord(); +// const commands = renderBundleRecord["_commands"] = []; + +// super.runRenderBundleObjects(renderBundleRecord as any, renderPassFormat, renderObjects); + +// // 排除无效命令 +// paichuWuxiaoCommands(renderPassFormat.attachmentSize, commands); +// // +// const setBindGroupCommands = commands.filter((v) => v[0] === "setBindGroup"); + +// caches = { commands, setBindGroupCommands }; + +// _renderPassObjectsCommandMap.set(renderPassObjectsCommandKey, caches); + +// // 监听变化 +// const onchanged = () => +// { +// _renderPassObjectsCommandMap.delete(renderPassObjectsCommandKey); +// // +// renderObjects.forEach((v) => { watcher.unwatch(v, "_version", onchanged); }); +// }; +// renderObjects.forEach((v) => { watcher.watch(v, "_version", onchanged); }); +// } + +// // 排除在 GPURenderBundleEncoder 中不支持的命令 +// const commands = caches.commands.filter((v) => (v[0] in bundleEncoder)); + +// // 执行命令 +// runCommands(bundleEncoder, { ...caches, commands }); +// } + +// protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) +// { +// const device = this._device; +// const _commands = passEncoder["_commands"] as any[]; + +// const renderObjectCommandKey: RenderObjectCommandKey = [device, renderPassFormat, renderObject]; +// const commands = renderObjectCommandMap.get(renderObjectCommandKey); +// if (commands) +// { +// commands.forEach((v) => _commands.push(v)); + +// return; +// } + +// const start = _commands.length; + +// super.runRenderObject(passEncoder, renderPassFormat, renderObject); + +// renderObjectCommandMap.set(renderObjectCommandKey, _commands.slice(start)); + +// // +// const onchanged = () => +// { +// renderObjectCommandMap.delete(renderObjectCommandKey); +// // +// renderObject._version = ~~renderObject._version + 1; +// watcher.unwatch(renderObject.pipeline, '_version', onchanged); +// } +// watcher.watch(renderObject.pipeline, '_version', onchanged); +// } +// } +// type RenderObjectCommandKey = [device: GPUDevice, renderPassFormat: RenderPassFormat, renderObject: RenderObject]; +// const renderObjectCommandMap = new ChainMap>(); + +// class GPURenderPassRecord implements GPURenderPassEncoder +// { +// __brand: "GPURenderPassEncoder" = "GPURenderPassEncoder"; +// label: string; +// // +// setViewport(...args: any): undefined { this["_commands"].push(["setViewport", args]); } +// setScissorRect(...args: any): undefined { this["_commands"].push(["setScissorRect", args]); } +// setBlendConstant(...args: any): undefined { this["_commands"].push(["setBlendConstant", args]); } +// setStencilReference(...args: any): undefined { this["_commands"].push(["setStencilReference", args]); } +// // +// setPipeline(...args: any): undefined { this["_commands"].push(["setPipeline", args]); } +// setVertexBuffer(...args: any): undefined { this["_commands"].push(["setVertexBuffer", args]); } +// setIndexBuffer(...args: any): undefined { this["_commands"].push(["setIndexBuffer", args]); } +// setBindGroup(...args: any): undefined { this["_commands"].push(["setBindGroup", args]); } +// draw(...args: any): undefined { this["_commands"].push(["draw", args]); } +// drawIndexed(...args: any): undefined { this["_commands"].push(["drawIndexed", args]); } +// drawIndirect(...args: any): undefined { this["_commands"].push(["drawIndirect", args]); } +// drawIndexedIndirect(...args: any): undefined { this["_commands"].push(["drawIndexedIndirect", args]); } +// // +// beginOcclusionQuery(...args: any): undefined { this["_commands"].push(["beginOcclusionQuery", args]); } +// endOcclusionQuery(...args: any): undefined { this["_commands"].push(["endOcclusionQuery", args]); } +// // +// executeBundles(...args: any): undefined { this["_commands"].push(["executeBundles", args]); } +// // +// end(...args: any): undefined { this["_commands"].push(["end", args]); } +// // +// pushDebugGroup(...args: any): undefined { this["_commands"].push(["pushDebugGroup", args]); } +// popDebugGroup(...args: any): undefined { this["_commands"].push(["popDebugGroup", args]); } +// insertDebugMarker(...args: any): undefined { this["_commands"].push(["insertDebugMarker", args]); } +// } + +// function runCommands(_passEncoder: GPURenderPassEncoder | GPUComputePassEncoder | GPURenderBundleEncoder, caches: { +// commands: Array; +// setBindGroupCommands: Array; +// }) +// { +// const { commands, setBindGroupCommands } = caches; + +// setBindGroupCommands.forEach((v) => +// { +// v[1][1] = v[1][1](); +// }); + +// commands.forEach((v) => +// { +// _passEncoder[v[0]].apply(_passEncoder, v[1]); +// }); +// } + +// /** +// * 排除无效命令 +// * +// * @param attachmentSize +// */ +// function paichuWuxiaoCommands(attachmentSize: { readonly width: number; readonly height: number; }, commands: any[]) +// { +// const _obj = { +// setBindGroup: [], setVertexBuffer: [], +// setViewport: [0, 0, attachmentSize.width, attachmentSize.height, 0, 1], +// setScissorRect: [0, 0, attachmentSize.width, attachmentSize.height], +// }; +// // +// let length = 0; +// commands.concat().forEach((v) => +// { +// // 排除重复的无效命令 +// if (v[0] === "setBindGroup" || v[0] === "setVertexBuffer") +// { +// if (!arrayEq1(_obj, v[0], v[1][0], v[1])) +// { +// commands[length++] = v; +// } +// } +// else if (0 +// || v[0] === "setPipeline" +// || v[0] === "setIndexBuffer" +// || v[0] === "setViewport" +// || v[0] === "setScissorRect" +// || v[0] === "setBlendConstant" +// || v[0] === "setStencilReference" +// ) +// { +// if (!arrayEq0(_obj, v[0], v[1])) +// { +// commands[length++] = v; +// } +// } +// else +// { +// commands[length++] = v; +// } +// }); +// commands.length = length; +// } + +// function arrayEq0(_obj: any, name: string, args: any[]) +// { +// const obj = _obj; +// const oldArgs: any[] = obj[name]; +// if (!oldArgs) +// { +// obj[name] = args; + +// return false; +// } + +// for (let i = 0, n = oldArgs.length; i < n; i++) +// { +// if (oldArgs[i] !== args[i]) +// { +// obj[name] = args; + +// return false; +// } +// } + +// return true; +// } + +// function arrayEq1(_obj: any, name: string, index: number, args: any[]) +// { +// const obj = _obj[name]; +// const oldArgs: any[] = obj[index]; +// if (!oldArgs) +// { +// obj[index] = args; + +// return false; +// } + +// for (let i = 1, n = oldArgs.length; i < n; i++) +// { +// if (oldArgs[i] !== args[i]) +// { +// obj[index] = args; + +// return false; +// } +// } + +// return true; +// } + +// type RenderPassObjectsCommandKey = [device: GPUDevice, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[]]; +// const _renderPassObjectsCommandMap = new ChainMap; +// setBindGroupCommands: Array; +// }>; \ No newline at end of file diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts new file mode 100644 index 0000000..e0192b2 --- /dev/null +++ b/src/internal/RenderObjectCache.ts @@ -0,0 +1,65 @@ +export interface RenderObjectCache +{ + setViewport?: [x: number, y: number, width: number, height: number, minDepth: number, maxDepth: number]; + setScissorRect?: [x: GPUIntegerCoordinate, y: GPUIntegerCoordinate, width: GPUIntegerCoordinate, height: GPUIntegerCoordinate]; + setPipeline: [pipeline: GPURenderPipeline]; + setBlendConstant?: [color: GPUColor]; + setStencilReference?: [reference: GPUStencilValue]; + setBindGroup?: [index: number, bindGroup: GPUBindGroup][]; + setVertexBuffer?: [slot: GPUIndex32, buffer: GPUBuffer, offset?: GPUSize64, size?: GPUSize64][]; + setIndexBuffer?: [buffer: GPUBuffer, indexFormat: GPUIndexFormat, offset?: GPUSize64, size?: GPUSize64]; + draw?: [vertexCount: GPUSize32, instanceCount?: GPUSize32, firstVertex?: GPUSize32, firstInstance?: GPUSize32]; + drawIndexed?: [indexCount: GPUSize32, instanceCount?: GPUSize32, firstIndex?: GPUSize32, baseVertex?: GPUSignedOffset32, firstInstance?: GPUSize32]; +} + +export class RenderObjectCache +{ + static run(renderObjectCache: RenderObjectCache, renderPass: GPURenderPassEncoder | GPURenderBundleEncoder) + { + const { setViewport, setScissorRect, setPipeline, setBlendConstant, setStencilReference, setBindGroup, setVertexBuffer, setIndexBuffer, draw, drawIndexed } = renderObjectCache; + + if (setViewport && "setViewport" in renderPass) + { + renderPass.setViewport(...setViewport); + } + if (setScissorRect && "setScissorRect" in renderPass) + { + renderPass.setScissorRect(...setScissorRect); + } + renderPass.setPipeline(...setPipeline); + if (setBlendConstant && "setBlendConstant" in renderPass) + { + renderPass.setBlendConstant(...setBlendConstant); + } + if (setStencilReference && "setStencilReference" in renderPass) + { + renderPass.setStencilReference(...setStencilReference); + } + if (setBindGroup) + { + for (let i = 0, len = setBindGroup.length; i < len; i++) + { + renderPass.setBindGroup(...setBindGroup[i]); + } + } + if (setVertexBuffer) + { + for (let i = 0, len = setVertexBuffer.length; i < len; i++) + { + renderPass.setVertexBuffer(...setVertexBuffer[i]); + } + } + if (setIndexBuffer) + { + renderPass.setIndexBuffer(...setIndexBuffer); + } + if (draw) + { + renderPass.draw(...draw); + } + if (drawIndexed) + { + renderPass.drawIndexed(...drawIndexed); + } + } +} \ No newline at end of file -- Gitee From d61cc8d190bd4ba5bf3ee4ffae3c09981ec5c593 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 15:26:31 +0800 Subject: [PATCH 166/214] =?UTF-8?q?refactor(WebGPUBase):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=B8=B2=E6=9F=93=E6=B5=81=E7=A8=8B=E5=B9=B6=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了所有 run 函数中不必要的 passEncoder 参数 - 新增 RenderObjectCache.run 方法统一处理渲染流程 - 优化了渲染流程的代码结构,提高了代码可读性和可维护性 --- src/WebGPUBase.ts | 58 ++++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 183cbd4..5360059 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -421,24 +421,25 @@ export class WebGPUBase const renderObjectCache: RenderObjectCache = {} as any; result = computed(() => { - this.runviewport(passEncoder, renderObject, renderPassFormat, renderObjectCache); - this.runScissorRect(passEncoder, renderObject, renderPassFormat, renderObjectCache); - this.runRenderPipeline(passEncoder, renderPassFormat, renderObject, renderObjectCache); - this.runBindingResources(passEncoder, renderObject, renderObjectCache); - this.runVertexAttributes(passEncoder, renderObject, renderObjectCache); - this.runIndices(passEncoder, renderObject, renderObjectCache); - this.runDraw(passEncoder, renderObject, renderObjectCache); + this.runviewport(renderObject, renderPassFormat, renderObjectCache); + this.runScissorRect(renderObject, renderPassFormat, renderObjectCache); + this.runRenderPipeline(renderPassFormat, renderObject, renderObjectCache); + this.runBindingResources(renderObject, renderObjectCache); + this.runVertexAttributes(renderObject, renderObjectCache); + this.runIndices(renderObject, renderObjectCache); + this.runDraw(renderObject, renderObjectCache); return renderObjectCache; }); renderObjectCacheMap.set(renderObjectCacheKey, result); + RenderObjectCache.run(result.value, passEncoder); + return result.value; } - protected runviewport(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderPassFormat: RenderPassFormat, renderObjectCache: RenderObjectCache) + protected runviewport(renderObject: RenderObject, renderPassFormat: RenderPassFormat, renderObjectCache: RenderObjectCache) { - if (!("setViewport" in passEncoder)) return; const attachmentSize = renderPassFormat.attachmentSize; const viewport = renderObject.viewport; if (viewport) @@ -455,21 +456,18 @@ export class WebGPUBase { y = attachmentSize.height - y - height; } - passEncoder.setViewport(x, y, width, height, minDepth, maxDepth); // renderObjectCache.setViewport = [x, y, width, height, minDepth, maxDepth]; } else { - passEncoder.setViewport(0, 0, attachmentSize.width, attachmentSize.height, 0, 1); // renderObjectCache.setViewport = [0, 0, attachmentSize.width, attachmentSize.height, 0, 1]; } } - protected runScissorRect(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderPassFormat: RenderPassFormat, renderObjectCache: RenderObjectCache) + protected runScissorRect(renderObject: RenderObject, renderPassFormat: RenderPassFormat, renderObjectCache: RenderObjectCache) { - if (!("setScissorRect" in passEncoder)) return; const attachmentSize = renderPassFormat.attachmentSize; const scissorRect = renderObject.scissorRect; if (scissorRect) @@ -485,17 +483,15 @@ export class WebGPUBase y = attachmentSize.height - y - height; } - passEncoder.setScissorRect(x, y, width, height); renderObjectCache.setScissorRect = [x, y, width, height]; } else { - passEncoder.setScissorRect(0, 0, attachmentSize.width, attachmentSize.height); renderObjectCache.setScissorRect = [0, 0, attachmentSize.width, attachmentSize.height]; } } - protected runRenderPipeline(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject, renderObjectCache: RenderObjectCache) + protected runRenderPipeline(renderPassFormat: RenderPassFormat, renderObject: RenderObject, renderObjectCache: RenderObjectCache) { const device = this._device; const { pipeline, vertices, indices } = renderObject; @@ -504,56 +500,51 @@ export class WebGPUBase const gpuRenderPipeline = getGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indexFormat); // - passEncoder.setPipeline(gpuRenderPipeline); renderObjectCache.setPipeline = [gpuRenderPipeline]; // - this.runStencilReference(passEncoder, pipeline, renderObjectCache); - this.runBlendConstant(passEncoder, pipeline, renderObjectCache); + this.runStencilReference(pipeline, renderObjectCache); + this.runBlendConstant(pipeline, renderObjectCache); } - protected runStencilReference(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, renderObjectCache: RenderObjectCache) + protected runStencilReference(pipeline: RenderPipeline, renderObjectCache: RenderObjectCache) { - if (!("setStencilReference" in passEncoder)) return; // const stencilReference = getStencilReference(pipeline.depthStencil); if (stencilReference === undefined) return; - passEncoder.setStencilReference(stencilReference); renderObjectCache.setStencilReference = [stencilReference]; } - protected runBlendConstant(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, pipeline: RenderPipeline, renderObjectCache: RenderObjectCache) + protected runBlendConstant(pipeline: RenderPipeline, renderObjectCache: RenderObjectCache) { - if (!("setBlendConstant" in passEncoder)) return; // const blendConstantColor = BlendState.getBlendConstantColor(pipeline.fragment?.targets?.[0]?.blend); if (blendConstantColor === undefined) return; - passEncoder.setBlendConstant(blendConstantColor); renderObjectCache.setBlendConstant = [blendConstantColor]; } - protected runBindingResources(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderObjectCache: RenderObjectCache) + protected runBindingResources(renderObject: RenderObject, renderObjectCache: RenderObjectCache) { const device = this._device; const { pipeline, bindingResources } = renderObject; // 计算 bindGroups + renderObjectCache.setBindGroup = [] const layout = getGPUPipelineLayout(device, { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources); - passEncoder.setBindGroup(group, gpuBindGroup); - renderObjectCache.setBindGroup ??= [] renderObjectCache.setBindGroup[group] = [group, gpuBindGroup]; }); } - protected runVertexAttributes(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderObject: RenderObject, renderObjectCache: RenderObjectCache) + protected runVertexAttributes(renderObject: RenderObject, renderObjectCache: RenderObjectCache) { const device = this._device; const { vertices, pipeline } = renderObject; // + renderObjectCache.setVertexBuffer = []; const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) vertexBuffers?.forEach((vertexBuffer, index) => { @@ -562,13 +553,11 @@ export class WebGPUBase const gBuffer = getGPUBuffer(device, buffer); - passEncoder.setVertexBuffer(index, gBuffer, vertexBuffer.offset, vertexBuffer.size); - renderObjectCache.setVertexBuffer ??= []; renderObjectCache.setVertexBuffer[index] = [index, gBuffer, vertexBuffer.offset, vertexBuffer.size]; }); } - protected runIndices(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject, renderObjectCache: RenderObjectCache) + protected runIndices(geometry: RenderObject, renderObjectCache: RenderObjectCache) { const { indices } = geometry; if (!indices) return; @@ -581,22 +570,19 @@ export class WebGPUBase const gBuffer = getGPUBuffer(device, buffer); // - passEncoder.setIndexBuffer(gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength); renderObjectCache.setIndexBuffer = [gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength]; } - protected runDraw(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, geometry: RenderObject, renderObjectCache: RenderObjectCache) + protected runDraw(geometry: RenderObject, renderObjectCache: RenderObjectCache) { const { draw } = geometry; if (draw.__type__ === 'DrawVertex') { - passEncoder.draw(draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance); renderObjectCache.draw = [draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance]; } else { - passEncoder.drawIndexed(draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance); renderObjectCache.drawIndexed = [draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance]; } } -- Gitee From ba3206037c5126800c6b967aabaee80297595861 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 16:23:50 +0800 Subject: [PATCH 167/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E6=B5=81=E7=A8=8B=E5=92=8C=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 reactive 和 computed 函数优化渲染对象属性的响应式更新 - 改进绑定资源、顶点属性和渲染管线的动态更新机制 - 在多个示例中应用这些优化,提高渲染效率和灵活性 --- .../src/webgpu/RenderObjectChanges/index.ts | 10 +- examples/src/webgpu/blending/index.ts | 4 +- examples/src/webgpu/points/index.ts | 2 +- src/WebGPUBase.ts | 110 ++++++++++++------ src/caches/getGPUPipelineLayout.ts | 14 --- src/caches/getNGPUVertexBuffers.ts | 24 +++- 6 files changed, 103 insertions(+), 61 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index acbc9a8..7d2c5b0 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -65,11 +65,11 @@ const init = async (canvas: HTMLCanvasElement) => window.onclick = () => { - reactive(renderObject.vertices.position).stepMode = "instance"; - reactive(renderObject.vertices.position).stepMode = "vertex"; - reactive(renderObject.vertices.position).data = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -1]); - reactive(renderObject.vertices.position).format = "float32x3"; - reactive(renderObject.vertices.position).data = new Float32Array([1.0, 0.5, 1.0, -0.5, -0.5, 1.0, 0.5, -1, 1.0]); + // reactive(renderObject.vertices.position).stepMode = "instance"; + // reactive(renderObject.vertices.position).stepMode = "vertex"; + // reactive(renderObject.vertices.position).data = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -1]); + // reactive(renderObject.vertices.position).format = "float32x3"; + // reactive(renderObject.vertices.position).data = new Float32Array([1.0, 0.5, 1.0, -0.5, -0.5, 1.0, 0.5, -1, 1.0]); // 修改顶点着色器代码 reactive(renderObject.pipeline.vertex).code = ` @vertex diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 44ad0f3..38c34ad 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -514,8 +514,8 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const { srcTexture, dstTexture, srcBindGroup, dstBindGroup } = textureSets[settings.textureSet === "premultiplied alpha" ? 0 : 1]; - ro.bindingResources = dstBindGroup; - ro1.bindingResources = srcBindGroup; + reactive(ro).bindingResources = dstBindGroup; + reactive(ro1).bindingResources = srcBindGroup; reactive(context.configuration).alphaMode = settings.alphaMode; diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index d19a93d..855a3a1 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -186,7 +186,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const { size, fixedSize, textured } = settings; - ro.pipeline = pipelines[fixedSize ? 1 : 0][textured ? 1 : 0]; + reactive(ro).pipeline = pipelines[fixedSize ? 1 : 0][textured ? 1 : 0]; // Set the size in the uniform values reactive(bindingResources.uni).size = size; diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 5360059..6ac8ad0 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -494,67 +494,107 @@ export class WebGPUBase protected runRenderPipeline(renderPassFormat: RenderPassFormat, renderObject: RenderObject, renderObjectCache: RenderObjectCache) { const device = this._device; - const { pipeline, vertices, indices } = renderObject; - // - const indexFormat: GPUIndexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; - const gpuRenderPipeline = getGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indexFormat); + const r_renderObject = reactive(renderObject); + computed(() => + { + // 监听 + r_renderObject.pipeline; + r_renderObject.vertices; + r_renderObject.indices; - // - renderObjectCache.setPipeline = [gpuRenderPipeline]; + // + const { pipeline, vertices, indices } = renderObject; + // + const indexFormat: GPUIndexFormat = indices ? (indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16") : undefined; + const gpuRenderPipeline = getGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indexFormat); - // - this.runStencilReference(pipeline, renderObjectCache); - this.runBlendConstant(pipeline, renderObjectCache); + // + renderObjectCache.setPipeline = [gpuRenderPipeline]; + + // + this.runStencilReference(pipeline, renderObjectCache); + this.runBlendConstant(pipeline, renderObjectCache); + }).value; } protected runStencilReference(pipeline: RenderPipeline, renderObjectCache: RenderObjectCache) { - // - const stencilReference = getStencilReference(pipeline.depthStencil); - if (stencilReference === undefined) return; + const r_pipeline = reactive(pipeline); + computed(() => + { + const stencilReference = getStencilReference(r_pipeline.depthStencil); + if (stencilReference === undefined) + { + renderObjectCache.setStencilReference = undefined; + return; + } - renderObjectCache.setStencilReference = [stencilReference]; + renderObjectCache.setStencilReference = [stencilReference]; + }).value; } protected runBlendConstant(pipeline: RenderPipeline, renderObjectCache: RenderObjectCache) { - // - const blendConstantColor = BlendState.getBlendConstantColor(pipeline.fragment?.targets?.[0]?.blend); - if (blendConstantColor === undefined) return; + const r_pipeline = reactive(pipeline); + computed(() => + { + // + const blendConstantColor = BlendState.getBlendConstantColor(r_pipeline.fragment?.targets?.[0]?.blend); + if (blendConstantColor === undefined) + { + renderObjectCache.setBlendConstant = undefined; + return; + } - renderObjectCache.setBlendConstant = [blendConstantColor]; + renderObjectCache.setBlendConstant = [blendConstantColor]; + }).value; } protected runBindingResources(renderObject: RenderObject, renderObjectCache: RenderObjectCache) { const device = this._device; - const { pipeline, bindingResources } = renderObject; - // 计算 bindGroups - renderObjectCache.setBindGroup = [] - const layout = getGPUPipelineLayout(device, { vertex: pipeline.vertex.code, fragment: pipeline.fragment?.code }); - layout.bindGroupLayouts.forEach((bindGroupLayout, group) => + const r_renderObject = reactive(renderObject); + computed(() => { - const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources); - renderObjectCache.setBindGroup[group] = [group, gpuBindGroup]; - }); + // 监听 + r_renderObject.bindingResources; + + // 执行 + renderObjectCache.setBindGroup = [] + const { bindingResources } = renderObject; + const layout = getGPUPipelineLayout(device, { vertex: r_renderObject.pipeline.vertex.code, fragment: r_renderObject.pipeline.fragment?.code }); + layout.bindGroupLayouts.forEach((bindGroupLayout, group) => + { + const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources); + renderObjectCache.setBindGroup[group] = [group, gpuBindGroup]; + }); + }).value; } protected runVertexAttributes(renderObject: RenderObject, renderObjectCache: RenderObjectCache) { const device = this._device; - const { vertices, pipeline } = renderObject; - // - renderObjectCache.setVertexBuffer = []; - const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) - vertexBuffers?.forEach((vertexBuffer, index) => + const r_renderObject = reactive(renderObject); + computed(() => { - const buffer = getGBuffer(vertexBuffer.data); - (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); + // 监听 + r_renderObject.vertices; + r_renderObject.pipeline.vertex; - const gBuffer = getGPUBuffer(device, buffer); + const { vertices, pipeline } = renderObject; + // + renderObjectCache.setVertexBuffer = []; + const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) + vertexBuffers?.forEach((vertexBuffer, index) => + { + const buffer = getGBuffer(vertexBuffer.data); + (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); - renderObjectCache.setVertexBuffer[index] = [index, gBuffer, vertexBuffer.offset, vertexBuffer.size]; - }); + const gBuffer = getGPUBuffer(device, buffer); + + renderObjectCache.setVertexBuffer[index] = [index, gBuffer, vertexBuffer.offset, vertexBuffer.size]; + }); + }).value; } protected runIndices(geometry: RenderObject, renderObjectCache: RenderObjectCache) diff --git a/src/caches/getGPUPipelineLayout.ts b/src/caches/getGPUPipelineLayout.ts index 0caaea1..ce86cc3 100644 --- a/src/caches/getGPUPipelineLayout.ts +++ b/src/caches/getGPUPipelineLayout.ts @@ -114,13 +114,6 @@ export function getGPUPipelineLayout(device: GPUDevice, shader: { vertex: string const entries = (descriptor.entries as GPUBindGroupLayoutEntry[]).filter((v) => !!v); const key = entries.map((v) => v.key).join(","); // 相同的布局只保留一个。 - if (__DEV__) - { - if (bindGroupLayoutMap[key]) - { - console.log(`命中相同的布局 ${key},公用绑定组布局对象。`); - } - } let bindGroupLayout = bindGroupLayoutMap[key]; if (!bindGroupLayout) { @@ -133,13 +126,6 @@ export function getGPUPipelineLayout(device: GPUDevice, shader: { vertex: string // 管线布局描述标识符。 const pipelineLayoutKey = bindGroupLayouts.map((v, i) => `[${i}: ${v.key}]`).join(","); - if (__DEV__) - { - if (pipelineLayoutDescriptorMap[pipelineLayoutKey]) - { - console.log(`命中相同的布局 ${pipelineLayoutKey},公用管线布局对象。`); - } - } gpuPipelineLayout = pipelineLayoutDescriptorMap[pipelineLayoutKey]; if (!gpuPipelineLayout) { diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts index 4339391..4f0ccc2 100644 --- a/src/caches/getNGPUVertexBuffers.ts +++ b/src/caches/getNGPUVertexBuffers.ts @@ -4,14 +4,30 @@ import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; export function getGPUVertexBufferLayouts(vertexState: VertexState, vertices: VertexAttributes) { - const { vertexBufferLayouts } = getVertexBuffersBuffers(vertexState, vertices); - return vertexBufferLayouts; + const result = computed(() => + { + const { vertexBufferLayouts } = getVertexBuffersBuffers(vertexState, vertices); + return vertexBufferLayouts; + }); + return result.value; } export function getNVertexBuffers(vertexState: VertexState, vertices: VertexAttributes) { - const { vertexBuffers } = getVertexBuffersBuffers(vertexState, vertices); - return vertexBuffers; + let _vertexBuffers: NVertexBuffer[]; + const result = computed(() => + { + const { vertexBuffers } = getVertexBuffersBuffers(vertexState, vertices); + + if (_vertexBuffers && _vertexBuffers.length === vertexBuffers.length && _vertexBuffers.every((v, i) => v === vertexBuffers[i])) + { + return _vertexBuffers; + } + _vertexBuffers = vertexBuffers; + + return vertexBuffers; + }); + return result.value; } declare global -- Gitee From 1957492a4cc49bba8e87e96ea797fb65e5eccf8f Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 17:14:35 +0800 Subject: [PATCH 168/214] =?UTF-8?q?refactor(WebGPUBase):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E8=A7=86=E5=8F=A3=E5=92=8C=E5=89=AA=E8=A3=81=E7=9F=A9?= =?UTF-8?q?=E5=BD=A2=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 reactive 和 computed 函数优化了视口和剪裁矩形的计算过程 - 重构了渲染对象和渲染格式的处理方式,提高了代码的可维护性 --- src/WebGPUBase.ts | 125 +++++++++++------- src/caches/getNGPUVertexBuffers.ts | 23 ++-- .../{NGPUVertexBuffer.ts => VertexBuffer.ts} | 2 +- 3 files changed, 89 insertions(+), 61 deletions(-) rename src/internal/{NGPUVertexBuffer.ts => VertexBuffer.ts} (96%) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 6ac8ad0..4094f4a 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -440,55 +440,65 @@ export class WebGPUBase protected runviewport(renderObject: RenderObject, renderPassFormat: RenderPassFormat, renderObjectCache: RenderObjectCache) { - const attachmentSize = renderPassFormat.attachmentSize; - const viewport = renderObject.viewport; - if (viewport) + const r_renderObject = reactive(renderObject); + const r_renderPassFormat = reactive(renderPassFormat); + computed(() => { - const isYup = viewport.isYup ?? true; - const x = viewport.x ?? 0; - let y = viewport.y ?? 0; - const width = viewport.width ?? attachmentSize.width; - const height = viewport.height ?? attachmentSize.height; - const minDepth = viewport.minDepth ?? 0; - const maxDepth = viewport.maxDepth ?? 1; - - if (isYup) + const attachmentSize = r_renderPassFormat.attachmentSize; + const viewport = r_renderObject.viewport; + if (viewport) { - y = attachmentSize.height - y - height; + const isYup = viewport.isYup ?? true; + const x = viewport.x ?? 0; + let y = viewport.y ?? 0; + const width = viewport.width ?? attachmentSize.width; + const height = viewport.height ?? attachmentSize.height; + const minDepth = viewport.minDepth ?? 0; + const maxDepth = viewport.maxDepth ?? 1; + + if (isYup) + { + y = attachmentSize.height - y - height; + } + // + renderObjectCache.setViewport = [x, y, width, height, minDepth, maxDepth]; } - // - renderObjectCache.setViewport = [x, y, width, height, minDepth, maxDepth]; - } - else - { - // - renderObjectCache.setViewport = [0, 0, attachmentSize.width, attachmentSize.height, 0, 1]; - } + else + { + // + renderObjectCache.setViewport = [0, 0, attachmentSize.width, attachmentSize.height, 0, 1]; + } + }).value; } protected runScissorRect(renderObject: RenderObject, renderPassFormat: RenderPassFormat, renderObjectCache: RenderObjectCache) { - const attachmentSize = renderPassFormat.attachmentSize; - const scissorRect = renderObject.scissorRect; - if (scissorRect) + const r_renderObject = reactive(renderObject); + const r_renderPassFormat = reactive(renderPassFormat); + computed(() => { - const isYup = scissorRect.isYup ?? true; - const x = scissorRect.x ?? 0; - let y = scissorRect.y ?? 0; - const width = scissorRect.width ?? attachmentSize.width; - const height = scissorRect.height ?? attachmentSize.height; - - if (isYup) + const attachmentSize = r_renderPassFormat.attachmentSize; + const scissorRect = r_renderObject.scissorRect; + if (scissorRect) { - y = attachmentSize.height - y - height; + const isYup = scissorRect.isYup ?? true; + const x = scissorRect.x ?? 0; + let y = scissorRect.y ?? 0; + const width = scissorRect.width ?? attachmentSize.width; + const height = scissorRect.height ?? attachmentSize.height; + + if (isYup) + { + y = attachmentSize.height - y - height; + } + + renderObjectCache.setScissorRect = [x, y, width, height]; } - - renderObjectCache.setScissorRect = [x, y, width, height]; - } - else - { - renderObjectCache.setScissorRect = [0, 0, attachmentSize.width, attachmentSize.height]; - } + else + { + renderObjectCache.setScissorRect = [0, 0, attachmentSize.width, attachmentSize.height]; + } + }).value; } protected runRenderPipeline(renderPassFormat: RenderPassFormat, renderObject: RenderObject, renderObjectCache: RenderObjectCache) @@ -587,30 +597,45 @@ export class WebGPUBase const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) vertexBuffers?.forEach((vertexBuffer, index) => { - const buffer = getGBuffer(vertexBuffer.data); + const { data, offset, size } = reactive(vertexBuffer); + + const buffer = getGBuffer(data); (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); const gBuffer = getGPUBuffer(device, buffer); - renderObjectCache.setVertexBuffer[index] = [index, gBuffer, vertexBuffer.offset, vertexBuffer.size]; + renderObjectCache.setVertexBuffer[index] = [index, gBuffer, offset, size]; }); }).value; } - protected runIndices(geometry: RenderObject, renderObjectCache: RenderObjectCache) + protected runIndices(renderObject: RenderObject, renderObjectCache: RenderObjectCache) { - const { indices } = geometry; - if (!indices) return; + const r_renderObject = reactive(renderObject); - const device = this._device; + computed(() => + { + // 监听 + r_renderObject.indices; - const buffer = getGBuffer(indices); - (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); + const { indices } = renderObject; + if (!indices) + { + renderObjectCache.setIndexBuffer = undefined; + return; + } - const gBuffer = getGPUBuffer(device, buffer); + const device = this._device; - // - renderObjectCache.setIndexBuffer = [gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength]; + const buffer = getGBuffer(indices); + (buffer as UnReadonly).label = buffer.label || (`顶点索引 ${autoIndex++}`); + + const gBuffer = getGPUBuffer(device, buffer); + + // + renderObjectCache.setIndexBuffer = [gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength]; + + }).value; } protected runDraw(geometry: RenderObject, renderObjectCache: RenderObjectCache) diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts index 4f0ccc2..450fc0a 100644 --- a/src/caches/getNGPUVertexBuffers.ts +++ b/src/caches/getNGPUVertexBuffers.ts @@ -1,5 +1,5 @@ import { ChainMap, computed, ComputedRef, reactive, VertexAttribute, VertexAttributes, VertexDataTypes, vertexFormatMap, VertexState } from "@feng3d/render-api"; -import { NVertexBuffer } from "../internal/NGPUVertexBuffer"; +import { VertexBuffer } from "../internal/VertexBuffer"; import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; export function getGPUVertexBufferLayouts(vertexState: VertexState, vertices: VertexAttributes) @@ -14,7 +14,7 @@ export function getGPUVertexBufferLayouts(vertexState: VertexState, vertices: Ve export function getNVertexBuffers(vertexState: VertexState, vertices: VertexAttributes) { - let _vertexBuffers: NVertexBuffer[]; + let _vertexBuffers: VertexBuffer[]; const result = computed(() => { const { vertexBuffers } = getVertexBuffersBuffers(vertexState, vertices); @@ -75,7 +75,7 @@ function getVertexBuffersBuffers(vertexState: VertexState, vertices: VertexAttri // 计算 const vertexBufferLayouts: GPUVertexBufferLayout[] = []; - const vertexBuffers: NVertexBuffer[] = []; + const vertexBuffers: VertexBuffer[] = []; const bufferIndexMap = new Map(); vertexEntryFunctionInfo.inputs.forEach((inputInfo) => @@ -153,22 +153,25 @@ function getVertexBuffers(vertexAttribute: VertexAttribute) { let result = getVertexBuffersMap.get(vertexAttribute); if (result) return result.value; - const NVertexBuffer: NVertexBuffer = {} as any; + const vertexBuffer: VertexBuffer = {} as any; + const r_vertexBuffer = reactive(vertexBuffer); result = computed(() => { // 监听 reactive(vertexAttribute).data; + // const data = vertexAttribute.data; - NVertexBuffer.data = data; - NVertexBuffer.offset = data.byteOffset; - NVertexBuffer.size = data.byteLength; - return NVertexBuffer; + // 修改数据并通知更新 + r_vertexBuffer.data = data; + r_vertexBuffer.offset = data.byteOffset; + r_vertexBuffer.size = data.byteLength; + return vertexBuffer; }); getVertexBuffersMap.set(vertexAttribute, result); return result.value; } -const getVertexBuffersMap = new WeakMap>(); +const getVertexBuffersMap = new WeakMap>(); type GetVertexBuffersBuffersKey = [vertexState: VertexState, vertices: VertexAttributes]; -const getVertexBuffersBuffersMap = new ChainMap>(); \ No newline at end of file +const getVertexBuffersBuffersMap = new ChainMap>(); \ No newline at end of file diff --git a/src/internal/NGPUVertexBuffer.ts b/src/internal/VertexBuffer.ts similarity index 96% rename from src/internal/NGPUVertexBuffer.ts rename to src/internal/VertexBuffer.ts index 77fed53..bd3deba 100644 --- a/src/internal/NGPUVertexBuffer.ts +++ b/src/internal/VertexBuffer.ts @@ -7,7 +7,7 @@ import { VertexDataTypes } from "@feng3d/render-api"; * * {@link GPURenderCommandsMixin.setVertexBuffer} */ -export interface NVertexBuffer +export interface VertexBuffer { /** * Buffer containing vertex data to use for subsequent drawing commands. -- Gitee From b19745d417034938793d7b6fdc95bc81e939568d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 17:25:27 +0800 Subject: [PATCH 169/214] =?UTF-8?q?refactor(WebGPUBase):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20runDraw=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将方法中的 geometry 参数改为 renderObject,提高了代码的通用性和可读性 - 使用 computed 和 reactive 函数包裹相关代码,提升了性能和响应性 - 保留了原有的功能逻辑,没有引入新的变化 --- src/WebGPUBase.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 4094f4a..377fa4c 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -638,18 +638,21 @@ export class WebGPUBase }).value; } - protected runDraw(geometry: RenderObject, renderObjectCache: RenderObjectCache) + protected runDraw(renderObject: RenderObject, renderObjectCache: RenderObjectCache) { - const { draw } = geometry; - - if (draw.__type__ === 'DrawVertex') - { - renderObjectCache.draw = [draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance]; - } - else + computed(() => { - renderObjectCache.drawIndexed = [draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance]; - } + const { draw } = reactive(renderObject); + + if (draw.__type__ === 'DrawVertex') + { + renderObjectCache.draw = [draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance]; + } + else + { + renderObjectCache.drawIndexed = [draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance]; + } + }).value; } } -- Gitee From b2de8f412c514bd4188a5a20ea8f4ee1f4458f56 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 19:08:42 +0800 Subject: [PATCH 170/214] =?UTF-8?q?perf(WebGPU):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=91=BD=E4=BB=A4=E7=BC=96=E7=A0=81=E8=BF=87?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构了 renderBundleEncoder 的执行逻辑 - 新增 RenderObjectCache.runs 静态方法,用于批量处理渲染对象缓存 - 实现了 RenderObjectCache.diff 方法,用于计算缓存差异 - 移除了 WebGPUBase 类中的 runRenderBundleObjects 方法 --- src/WebGPUBase.ts | 16 +++--- src/internal/RenderObjectCache.ts | 89 +++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 10 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 377fa4c..f909619 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -353,7 +353,12 @@ export class WebGPUBase // const renderBundleEncoder = device.createRenderBundleEncoder(descriptor); - this.runRenderBundleObjects(renderBundleEncoder, renderPassFormat, renderBundleObject.renderObjects); + // + const renderObjectCaches = renderBundleObject.renderObjects.map((element) => + { + return this.runRenderObject(renderBundleEncoder, renderPassFormat, element as RenderObject); + }); + RenderObjectCache.runs(renderObjectCaches, renderBundleEncoder); const gpuRenderBundle = renderBundleEncoder.finish(); return gpuRenderBundle; @@ -363,15 +368,6 @@ export class WebGPUBase return result.value; } - protected runRenderBundleObjects(passEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: readonly RenderObject[]) - { - // - renderObjects.forEach((element) => - { - this.runRenderObject(passEncoder, renderPassFormat, element as RenderObject); - }); - } - /** * 执行计算对象。 * diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index e0192b2..35e07c7 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -62,4 +62,93 @@ export class RenderObjectCache renderPass.drawIndexed(...drawIndexed); } } + + static runs(renderObjectCaches: RenderObjectCache[], renderPass: GPURenderPassEncoder | GPURenderBundleEncoder) + { + if (renderObjectCaches.length === 0) return; + + renderObjectCaches.forEach((renderObjectCache, i) => + { + const diff = RenderObjectCache.diff(renderObjectCaches[i - 1], renderObjectCache); + RenderObjectCache.run(diff, renderPass); + }); + } + + static diff(a: RenderObjectCache, b: RenderObjectCache) + { + if (!a) return b; + + const result: RenderObjectCache = {} as any; + + if (b.setViewport && (!a.setViewport || b.setViewport.some((v, i) => v !== a.setViewport[i]))) + { + result.setViewport = b.setViewport; + } + if (b.setScissorRect && (!a.setScissorRect || b.setScissorRect.some((v, i) => v !== a.setScissorRect[i]))) + { + result.setScissorRect = b.setScissorRect; + } + if (b.setPipeline && (!a.setPipeline || b.setPipeline.some((v, i) => v !== a.setPipeline[i]))) + { + result.setPipeline = b.setPipeline; + } + if (b.setBlendConstant && (!a.setBlendConstant || b.setBlendConstant.some((v, i) => v !== a.setBlendConstant[i]))) + { + result.setBlendConstant = b.setBlendConstant; + } + if (b.setStencilReference && (!a.setStencilReference || b.setStencilReference.some((v, i) => v !== a.setStencilReference[i]))) + { + result.setStencilReference = b.setStencilReference; + } + result.setBindGroup = []; + if (b.setBindGroup) + { + if (!a.setBindGroup) + { + result.setBindGroup = b.setBindGroup; + } + else + { + for (let i = 0, len = b.setBindGroup.length; i < len; i++) + { + if (!a.setBindGroup[i] || b.setBindGroup[i].some((v, i) => v !== a.setBindGroup[i][i])) + { + result.setBindGroup.push(b.setBindGroup[i]); + } + } + } + } + result.setVertexBuffer = []; + if (b.setVertexBuffer) + { + if (!a.setVertexBuffer) + { + result.setVertexBuffer = b.setVertexBuffer; + } + else + { + for (let i = 0, len = b.setVertexBuffer.length; i < len; i++) + { + if (!a.setVertexBuffer[i] || b.setVertexBuffer[i].some((v, j) => v !== a.setVertexBuffer[i][j])) + { + result.setVertexBuffer.push(b.setVertexBuffer[i]); + } + } + } + } + if (b.setIndexBuffer && (!a.setIndexBuffer || b.setIndexBuffer.some((v, i) => v !== a.setIndexBuffer[i]))) + { + result.setIndexBuffer = b.setIndexBuffer; + } + if (b.draw && (!a.draw || b.draw.some((v, i) => v !== a.draw[i]))) + { + result.draw = b.draw; + } + if (b.drawIndexed && (!a.drawIndexed || b.drawIndexed.some((v, i) => v !== a.drawIndexed[i]))) + { + result.drawIndexed = b.drawIndexed; + } + + return result; + } } \ No newline at end of file -- Gitee From 72000c9f4ffc9882ee1d8c1ed03e5878b7a10e7d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 19:18:27 +0800 Subject: [PATCH 171/214] =?UTF-8?q?refactor(WebGPUBase):=20=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E8=A7=86=E5=8F=A3=E5=92=8C=E5=89=AA=E8=A3=81=E7=9F=A9?= =?UTF-8?q?=E5=BD=A2=E7=9A=84=E9=BB=98=E8=AE=A4=E5=A4=A7=E5=B0=8F=E8=AE=A1?= =?UTF-8?q?=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除了在设置视口和剪裁矩形时对 width 和 height 属性的默认值计算。现在直接使用用户提供的值,不再自动使用 attachmentSize 的大小作为默认值。 --- src/WebGPUBase.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index f909619..d387889 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -447,8 +447,8 @@ export class WebGPUBase const isYup = viewport.isYup ?? true; const x = viewport.x ?? 0; let y = viewport.y ?? 0; - const width = viewport.width ?? attachmentSize.width; - const height = viewport.height ?? attachmentSize.height; + const width = viewport.width; + const height = viewport.height; const minDepth = viewport.minDepth ?? 0; const maxDepth = viewport.maxDepth ?? 1; @@ -480,8 +480,8 @@ export class WebGPUBase const isYup = scissorRect.isYup ?? true; const x = scissorRect.x ?? 0; let y = scissorRect.y ?? 0; - const width = scissorRect.width ?? attachmentSize.width; - const height = scissorRect.height ?? attachmentSize.height; + const width = scissorRect.width; + const height = scissorRect.height; if (isYup) { -- Gitee From 8d728bc50ba96d7a93879baa4e895d1468045ce7 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 21:31:12 +0800 Subject: [PATCH 172/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20RenderObjectCache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 RenderObjectCache 改为类,并添加 push 和 delete 方法 - 优化 run 方法,使用命令模式执行缓存操作 - 移除未使用的 diff 方法 - 调整 WebGPUBase 中使用新的 RenderObjectCache 类 --- src/WebGPUBase.ts | 22 +-- src/internal/RenderObjectCache.ts | 280 ++++++++++++++++-------------- 2 files changed, 162 insertions(+), 140 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index d387889..e67e426 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -358,7 +358,7 @@ export class WebGPUBase { return this.runRenderObject(renderBundleEncoder, renderPassFormat, element as RenderObject); }); - RenderObjectCache.runs(renderObjectCaches, renderBundleEncoder); + // RenderObjectCache.runs(renderObjectCaches, renderBundleEncoder); const gpuRenderBundle = renderBundleEncoder.finish(); return gpuRenderBundle; @@ -409,12 +409,12 @@ export class WebGPUBase let result = renderObjectCacheMap.get(renderObjectCacheKey); if (result) { - RenderObjectCache.run(result.value, passEncoder); + result.value.run(passEncoder); return result.value; } - const renderObjectCache: RenderObjectCache = {} as any; + const renderObjectCache = new RenderObjectCache(); result = computed(() => { this.runviewport(renderObject, renderPassFormat, renderObjectCache); @@ -429,7 +429,7 @@ export class WebGPUBase }); renderObjectCacheMap.set(renderObjectCacheKey, result); - RenderObjectCache.run(result.value, passEncoder); + result.value.run(passEncoder); return result.value; } @@ -457,12 +457,12 @@ export class WebGPUBase y = attachmentSize.height - y - height; } // - renderObjectCache.setViewport = [x, y, width, height, minDepth, maxDepth]; + renderObjectCache.push(["setViewport", x, y, width, height, minDepth, maxDepth]) } else { // - renderObjectCache.setViewport = [0, 0, attachmentSize.width, attachmentSize.height, 0, 1]; + renderObjectCache.push(["setViewport", 0, 0, attachmentSize.width, attachmentSize.height, 0, 1]); } }).value; } @@ -488,11 +488,11 @@ export class WebGPUBase y = attachmentSize.height - y - height; } - renderObjectCache.setScissorRect = [x, y, width, height]; + renderObjectCache.push(["setScissorRect", x, y, width, height]); } else { - renderObjectCache.setScissorRect = [0, 0, attachmentSize.width, attachmentSize.height]; + renderObjectCache.push(["setScissorRect", 0, 0, attachmentSize.width, attachmentSize.height]); } }).value; } @@ -515,7 +515,7 @@ export class WebGPUBase const gpuRenderPipeline = getGPURenderPipeline(device, pipeline, renderPassFormat, vertices, indexFormat); // - renderObjectCache.setPipeline = [gpuRenderPipeline]; + renderObjectCache.push(["setPipeline", gpuRenderPipeline]); // this.runStencilReference(pipeline, renderObjectCache); @@ -548,11 +548,11 @@ export class WebGPUBase const blendConstantColor = BlendState.getBlendConstantColor(r_pipeline.fragment?.targets?.[0]?.blend); if (blendConstantColor === undefined) { - renderObjectCache.setBlendConstant = undefined; + renderObjectCache.delete("setBlendConstant"); return; } - renderObjectCache.setBlendConstant = [blendConstantColor]; + renderObjectCache.push(["setBlendConstant", blendConstantColor]); }).value; } diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 35e07c7..067cf8a 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -1,154 +1,176 @@ -export interface RenderObjectCache +import { ChainMap } from "@feng3d/render-api"; + +export const cache = new ChainMap(); + +export function setVaule>(cache: ChainMap, keys: T): T +{ + const v = cache.get(keys); + if (v) return v; + cache.set(keys, keys); + return keys; +} + +type CommandType = + | [func: "setViewport", x: number, y: number, width: number, height: number, minDepth: number, maxDepth: number] + | [func: "setScissorRect", x: GPUIntegerCoordinate, y: GPUIntegerCoordinate, width: GPUIntegerCoordinate, height: GPUIntegerCoordinate] + | [func: "setPipeline", pipeline: GPURenderPipeline] + | [func: "setBindGroup", index: number, bindGroup: GPUBindGroup] + | [func: "setVertexBuffer", slot: GPUIndex32, buffer: GPUBuffer, offset?: GPUSize64, size?: GPUSize64] + | [func: "setIndexBuffer", buffer: GPUBuffer, indexFormat: GPUIndexFormat, offset?: GPUSize64, size?: GPUSize64] + | [func: "draw", vertexCount: GPUSize32, instanceCount?: GPUSize32, firstVertex?: GPUSize32, firstInstance?: GPUSize32] + | [func: "drawIndexed", indexCount: GPUSize32, instanceCount?: GPUSize32, firstIndex?: GPUSize32, baseVertex?: GPUSignedOffset32, firstInstance?: GPUSize32] + | [func: "setBlendConstant", color: GPUColor] + | [func: "setStencilReference", reference: GPUStencilValue] + ; + +export class RenderObjectCache { - setViewport?: [x: number, y: number, width: number, height: number, minDepth: number, maxDepth: number]; - setScissorRect?: [x: GPUIntegerCoordinate, y: GPUIntegerCoordinate, width: GPUIntegerCoordinate, height: GPUIntegerCoordinate]; - setPipeline: [pipeline: GPURenderPipeline]; - setBlendConstant?: [color: GPUColor]; + private commands: CommandType[] = []; + push(command: CommandType) + { + this.commands.push(setVaule(cache, command)); + } + + delete(func: CommandType[0]) + { + this.commands = this.commands.filter((c) => c[0] !== func); + } + setStencilReference?: [reference: GPUStencilValue]; setBindGroup?: [index: number, bindGroup: GPUBindGroup][]; setVertexBuffer?: [slot: GPUIndex32, buffer: GPUBuffer, offset?: GPUSize64, size?: GPUSize64][]; setIndexBuffer?: [buffer: GPUBuffer, indexFormat: GPUIndexFormat, offset?: GPUSize64, size?: GPUSize64]; draw?: [vertexCount: GPUSize32, instanceCount?: GPUSize32, firstVertex?: GPUSize32, firstInstance?: GPUSize32]; drawIndexed?: [indexCount: GPUSize32, instanceCount?: GPUSize32, firstIndex?: GPUSize32, baseVertex?: GPUSignedOffset32, firstInstance?: GPUSize32]; -} -export class RenderObjectCache -{ - static run(renderObjectCache: RenderObjectCache, renderPass: GPURenderPassEncoder | GPURenderBundleEncoder) + run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder) { - const { setViewport, setScissorRect, setPipeline, setBlendConstant, setStencilReference, setBindGroup, setVertexBuffer, setIndexBuffer, draw, drawIndexed } = renderObjectCache; - - if (setViewport && "setViewport" in renderPass) - { - renderPass.setViewport(...setViewport); - } - if (setScissorRect && "setScissorRect" in renderPass) - { - renderPass.setScissorRect(...setScissorRect); - } - renderPass.setPipeline(...setPipeline); - if (setBlendConstant && "setBlendConstant" in renderPass) - { - renderPass.setBlendConstant(...setBlendConstant); - } - if (setStencilReference && "setStencilReference" in renderPass) + this.commands.forEach((command) => { - renderPass.setStencilReference(...setStencilReference); - } - if (setBindGroup) - { - for (let i = 0, len = setBindGroup.length; i < len; i++) + const func = command[0]; + if (func === "setPipeline") { - renderPass.setBindGroup(...setBindGroup[i]); + renderPass.setPipeline(command[1]); } - } - if (setVertexBuffer) - { - for (let i = 0, len = setVertexBuffer.length; i < len; i++) + else if (func === "setBindGroup") { - renderPass.setVertexBuffer(...setVertexBuffer[i]); + renderPass.setBindGroup(command[1], command[2]); } - } - if (setIndexBuffer) - { - renderPass.setIndexBuffer(...setIndexBuffer); - } - if (draw) - { - renderPass.draw(...draw); - } - if (drawIndexed) - { - renderPass.drawIndexed(...drawIndexed); - } - } - - static runs(renderObjectCaches: RenderObjectCache[], renderPass: GPURenderPassEncoder | GPURenderBundleEncoder) - { - if (renderObjectCaches.length === 0) return; - - renderObjectCaches.forEach((renderObjectCache, i) => - { - const diff = RenderObjectCache.diff(renderObjectCaches[i - 1], renderObjectCache); - RenderObjectCache.run(diff, renderPass); - }); - } - - static diff(a: RenderObjectCache, b: RenderObjectCache) - { - if (!a) return b; - - const result: RenderObjectCache = {} as any; - - if (b.setViewport && (!a.setViewport || b.setViewport.some((v, i) => v !== a.setViewport[i]))) - { - result.setViewport = b.setViewport; - } - if (b.setScissorRect && (!a.setScissorRect || b.setScissorRect.some((v, i) => v !== a.setScissorRect[i]))) - { - result.setScissorRect = b.setScissorRect; - } - if (b.setPipeline && (!a.setPipeline || b.setPipeline.some((v, i) => v !== a.setPipeline[i]))) - { - result.setPipeline = b.setPipeline; - } - if (b.setBlendConstant && (!a.setBlendConstant || b.setBlendConstant.some((v, i) => v !== a.setBlendConstant[i]))) - { - result.setBlendConstant = b.setBlendConstant; - } - if (b.setStencilReference && (!a.setStencilReference || b.setStencilReference.some((v, i) => v !== a.setStencilReference[i]))) - { - result.setStencilReference = b.setStencilReference; - } - result.setBindGroup = []; - if (b.setBindGroup) - { - if (!a.setBindGroup) + else if (func === "setVertexBuffer") { - result.setBindGroup = b.setBindGroup; + renderPass.setVertexBuffer(command[1], command[2], command[3], command[4]); } - else + else if (func === "setIndexBuffer") { - for (let i = 0, len = b.setBindGroup.length; i < len; i++) - { - if (!a.setBindGroup[i] || b.setBindGroup[i].some((v, i) => v !== a.setBindGroup[i][i])) - { - result.setBindGroup.push(b.setBindGroup[i]); - } - } + renderPass.setIndexBuffer(command[1], command[2], command[3], command[4]); } - } - result.setVertexBuffer = []; - if (b.setVertexBuffer) - { - if (!a.setVertexBuffer) + else if (func === "draw") + { + renderPass.draw(command[1], command[2], command[3], command[4]); + } + else if (func === "drawIndexed") + { + renderPass.drawIndexed(command[1], command[2], command[3], command[4], command[5]); + } + else if (func === "setViewport") { - result.setVertexBuffer = b.setVertexBuffer; + if ("setViewport" in renderPass) renderPass.setViewport(command[1], command[2], command[3], command[4], command[5], command[6]); + } + else if (func === "setScissorRect") + { + if ("setScissorRect" in renderPass) renderPass.setScissorRect(command[1], command[2], command[3], command[4]); + } + else if (func === "setBlendConstant") + { + if ("setBlendConstant" in renderPass) + renderPass.setBlendConstant(command[1]); + } + else if (func === "setStencilReference") + { + if ("setStencilReference" in renderPass) renderPass.setStencilReference(command[1]); } else { - for (let i = 0, len = b.setVertexBuffer.length; i < len; i++) - { - if (!a.setVertexBuffer[i] || b.setVertexBuffer[i].some((v, j) => v !== a.setVertexBuffer[i][j])) - { - result.setVertexBuffer.push(b.setVertexBuffer[i]); - } - } + func; } - } - if (b.setIndexBuffer && (!a.setIndexBuffer || b.setIndexBuffer.some((v, i) => v !== a.setIndexBuffer[i]))) - { - result.setIndexBuffer = b.setIndexBuffer; - } - if (b.draw && (!a.draw || b.draw.some((v, i) => v !== a.draw[i]))) - { - result.draw = b.draw; - } - if (b.drawIndexed && (!a.drawIndexed || b.drawIndexed.some((v, i) => v !== a.drawIndexed[i]))) - { - result.drawIndexed = b.drawIndexed; - } - - return result; + }); } + + // static diff(a: RenderObjectCache, b: RenderObjectCache) + // { + // if (!a) return b; + + // const result: RenderObjectCache = {} as any; + + // if (a.setViewport !== b.setViewport && b.setViewport && (a.setViewport[0] !== b.setViewport[0] || a.setViewport[1] !== b.setViewport[1] || a.setViewport[2] !== b.setViewport[2] || a.setViewport[3] !== b.setViewport[3] || a.setViewport[4] !== b.setViewport[4] || a.setViewport[5] !== b.setViewport[5])) + // { + // result.setViewport = b.setViewport; + // } + // if (b.setScissorRect && (!a.setScissorRect || b.setScissorRect.some((v, i) => v !== a.setScissorRect[i]))) + // { + // result.setScissorRect = b.setScissorRect; + // } + // if (b.setPipeline && (!a.setPipeline || b.setPipeline.some((v, i) => v !== a.setPipeline[i]))) + // { + // result.setPipeline = b.setPipeline; + // } + // if (b.setBlendConstant && (!a.setBlendConstant || b.setBlendConstant.some((v, i) => v !== a.setBlendConstant[i]))) + // { + // result.setBlendConstant = b.setBlendConstant; + // } + // if (b.setStencilReference && (!a.setStencilReference || b.setStencilReference.some((v, i) => v !== a.setStencilReference[i]))) + // { + // result.setStencilReference = b.setStencilReference; + // } + // result.setBindGroup = []; + // if (b.setBindGroup) + // { + // if (!a.setBindGroup) + // { + // result.setBindGroup = b.setBindGroup; + // } + // else + // { + // for (let i = 0, len = b.setBindGroup.length; i < len; i++) + // { + // if (!a.setBindGroup[i] || b.setBindGroup[i].some((v, i) => v !== a.setBindGroup[i][i])) + // { + // result.setBindGroup.push(b.setBindGroup[i]); + // } + // } + // } + // } + // result.setVertexBuffer = []; + // if (b.setVertexBuffer) + // { + // if (!a.setVertexBuffer) + // { + // result.setVertexBuffer = b.setVertexBuffer; + // } + // else + // { + // for (let i = 0, len = b.setVertexBuffer.length; i < len; i++) + // { + // if (!a.setVertexBuffer[i] || b.setVertexBuffer[i].some((v, j) => v !== a.setVertexBuffer[i][j])) + // { + // result.setVertexBuffer.push(b.setVertexBuffer[i]); + // } + // } + // } + // } + // if (b.setIndexBuffer && (!a.setIndexBuffer || b.setIndexBuffer.some((v, i) => v !== a.setIndexBuffer[i]))) + // { + // result.setIndexBuffer = b.setIndexBuffer; + // } + // if (b.draw && (!a.draw || b.draw.some((v, i) => v !== a.draw[i]))) + // { + // result.draw = b.draw; + // } + // if (b.drawIndexed && (!a.drawIndexed || b.drawIndexed.some((v, i) => v !== a.drawIndexed[i]))) + // { + // result.drawIndexed = b.drawIndexed; + // } + + // return result; + // } } \ No newline at end of file -- Gitee From 507241e8803ffb00583789241d49de7de0c7cc38 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 22:12:19 +0800 Subject: [PATCH 173/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20RenderObjectCache=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 commands 数组替换为单独的属性,以提高可读性和性能 - 优化了 push 和 delete 方法的实现 - 重构了 run 方法,直接使用新结构化的数据执行命令 - 移除了未使用的 diff 方法和 setVaule 函数 --- src/WebGPUBase.ts | 22 ++-- src/internal/RenderObjectCache.ts | 185 +++++++++++++++++++++--------- 2 files changed, 143 insertions(+), 64 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index e67e426..a1b4b61 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -531,11 +531,11 @@ export class WebGPUBase const stencilReference = getStencilReference(r_pipeline.depthStencil); if (stencilReference === undefined) { - renderObjectCache.setStencilReference = undefined; + renderObjectCache.delete("setStencilReference"); return; } - renderObjectCache.setStencilReference = [stencilReference]; + renderObjectCache.push(["setStencilReference", stencilReference]); }).value; } @@ -566,13 +566,13 @@ export class WebGPUBase r_renderObject.bindingResources; // 执行 - renderObjectCache.setBindGroup = [] + renderObjectCache.delete("setBindGroup"); const { bindingResources } = renderObject; const layout = getGPUPipelineLayout(device, { vertex: r_renderObject.pipeline.vertex.code, fragment: r_renderObject.pipeline.fragment?.code }); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources); - renderObjectCache.setBindGroup[group] = [group, gpuBindGroup]; + renderObjectCache.push(["setBindGroup", group, gpuBindGroup]); }); }).value; } @@ -589,7 +589,7 @@ export class WebGPUBase const { vertices, pipeline } = renderObject; // - renderObjectCache.setVertexBuffer = []; + renderObjectCache.delete("setVertexBuffer"); const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) vertexBuffers?.forEach((vertexBuffer, index) => { @@ -600,7 +600,7 @@ export class WebGPUBase const gBuffer = getGPUBuffer(device, buffer); - renderObjectCache.setVertexBuffer[index] = [index, gBuffer, offset, size]; + renderObjectCache.push(["setVertexBuffer", index, gBuffer, offset, size]); }); }).value; } @@ -617,7 +617,7 @@ export class WebGPUBase const { indices } = renderObject; if (!indices) { - renderObjectCache.setIndexBuffer = undefined; + renderObjectCache.delete("setIndexBuffer"); return; } @@ -629,7 +629,7 @@ export class WebGPUBase const gBuffer = getGPUBuffer(device, buffer); // - renderObjectCache.setIndexBuffer = [gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength]; + renderObjectCache.push(["setIndexBuffer", gBuffer, indices.BYTES_PER_ELEMENT === 4 ? "uint32" : "uint16", indices.byteOffset, indices.byteLength]); }).value; } @@ -640,13 +640,15 @@ export class WebGPUBase { const { draw } = reactive(renderObject); + renderObjectCache.delete("draw"); + renderObjectCache.delete("drawIndexed"); if (draw.__type__ === 'DrawVertex') { - renderObjectCache.draw = [draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance]; + renderObjectCache.push(["draw", draw.vertexCount, draw.instanceCount, draw.firstVertex, draw.firstInstance]); } else { - renderObjectCache.drawIndexed = [draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance]; + renderObjectCache.push(["drawIndexed", draw.indexCount, draw.instanceCount, draw.firstIndex, draw.baseVertex, draw.firstInstance]); } }).value; } diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 067cf8a..3bc2c4b 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -25,75 +25,152 @@ type CommandType = export class RenderObjectCache { - private commands: CommandType[] = []; + protected setViewport?: [func: "setViewport", x: number, y: number, width: number, height: number, minDepth: number, maxDepth: number]; + protected setScissorRect?: [func: "setScissorRect", x: GPUIntegerCoordinate, y: GPUIntegerCoordinate, width: GPUIntegerCoordinate, height: GPUIntegerCoordinate]; + protected setPipeline: [func: "setPipeline", pipeline: GPURenderPipeline]; + protected setBlendConstant?: [func: "setBlendConstant", color: GPUColor]; + protected setStencilReference?: [func: "setStencilReference", reference: GPUStencilValue]; + protected setBindGroup?: [func: "setBindGroup", index: number, bindGroup: GPUBindGroup][]; + protected setVertexBuffer?: [func: "setVertexBuffer", slot: GPUIndex32, buffer: GPUBuffer, offset?: GPUSize64, size?: GPUSize64][]; + protected setIndexBuffer?: [func: "setIndexBuffer", buffer: GPUBuffer, indexFormat: GPUIndexFormat, offset?: GPUSize64, size?: GPUSize64]; + protected draw?: [func: "draw", vertexCount: GPUSize32, instanceCount?: GPUSize32, firstVertex?: GPUSize32, firstInstance?: GPUSize32]; + protected drawIndexed?: [func: "drawIndexed", indexCount: GPUSize32, instanceCount?: GPUSize32, firstIndex?: GPUSize32, baseVertex?: GPUSignedOffset32, firstInstance?: GPUSize32]; + + // private commands: CommandType[] = []; push(command: CommandType) { - this.commands.push(setVaule(cache, command)); + const func = command[0]; + if (func === "setBindGroup") + { + if (!this.setBindGroup) this.setBindGroup = []; + this.setBindGroup.push(command); + return; + } + else if (func === "setVertexBuffer") + { + if (!this.setVertexBuffer) this.setVertexBuffer = []; + this.setVertexBuffer.push(command); + return; + } + command = setVaule(cache, command); + this[command[0]] = command as any; } delete(func: CommandType[0]) { - this.commands = this.commands.filter((c) => c[0] !== func); + if (func === "setBindGroup") + { + this.setBindGroup = []; + return; + } + else if (func === "setVertexBuffer") + { + this.setVertexBuffer = []; + return; + } + this[func as any] = undefined; } - setStencilReference?: [reference: GPUStencilValue]; - setBindGroup?: [index: number, bindGroup: GPUBindGroup][]; - setVertexBuffer?: [slot: GPUIndex32, buffer: GPUBuffer, offset?: GPUSize64, size?: GPUSize64][]; - setIndexBuffer?: [buffer: GPUBuffer, indexFormat: GPUIndexFormat, offset?: GPUSize64, size?: GPUSize64]; - draw?: [vertexCount: GPUSize32, instanceCount?: GPUSize32, firstVertex?: GPUSize32, firstInstance?: GPUSize32]; - drawIndexed?: [indexCount: GPUSize32, instanceCount?: GPUSize32, firstIndex?: GPUSize32, baseVertex?: GPUSignedOffset32, firstInstance?: GPUSize32]; - run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder) { - this.commands.forEach((command) => + // this.commands.forEach((command) => + // { + // const func = command[0]; + // if (func === "setPipeline") + // { + // renderPass.setPipeline(command[1]); + // } + // else if (func === "setBindGroup") + // { + // renderPass.setBindGroup(command[1], command[2]); + // } + // else if (func === "setVertexBuffer") + // { + // renderPass.setVertexBuffer(command[1], command[2], command[3], command[4]); + // } + // else if (func === "setIndexBuffer") + // { + // renderPass.setIndexBuffer(command[1], command[2], command[3], command[4]); + // } + // else if (func === "draw") + // { + // renderPass.draw(command[1], command[2], command[3], command[4]); + // } + // else if (func === "drawIndexed") + // { + // renderPass.drawIndexed(command[1], command[2], command[3], command[4], command[5]); + // } + // else if (func === "setViewport") + // { + // if ("setViewport" in renderPass) renderPass.setViewport(command[1], command[2], command[3], command[4], command[5], command[6]); + // } + // else if (func === "setScissorRect") + // { + // if ("setScissorRect" in renderPass) renderPass.setScissorRect(command[1], command[2], command[3], command[4]); + // } + // else if (func === "setBlendConstant") + // { + // if ("setBlendConstant" in renderPass) + // renderPass.setBlendConstant(command[1]); + // } + // else if (func === "setStencilReference") + // { + // if ("setStencilReference" in renderPass) renderPass.setStencilReference(command[1]); + // } + // else + // { + // func; + // } + // }); + + const { setViewport, setScissorRect, setPipeline, setBlendConstant, setStencilReference, setBindGroup, setVertexBuffer, setIndexBuffer, draw, drawIndexed } = this; + + if (setViewport && "setViewport" in renderPass) { - const func = command[0]; - if (func === "setPipeline") - { - renderPass.setPipeline(command[1]); - } - else if (func === "setBindGroup") - { - renderPass.setBindGroup(command[1], command[2]); - } - else if (func === "setVertexBuffer") - { - renderPass.setVertexBuffer(command[1], command[2], command[3], command[4]); - } - else if (func === "setIndexBuffer") - { - renderPass.setIndexBuffer(command[1], command[2], command[3], command[4]); - } - else if (func === "draw") - { - renderPass.draw(command[1], command[2], command[3], command[4]); - } - else if (func === "drawIndexed") - { - renderPass.drawIndexed(command[1], command[2], command[3], command[4], command[5]); - } - else if (func === "setViewport") - { - if ("setViewport" in renderPass) renderPass.setViewport(command[1], command[2], command[3], command[4], command[5], command[6]); - } - else if (func === "setScissorRect") - { - if ("setScissorRect" in renderPass) renderPass.setScissorRect(command[1], command[2], command[3], command[4]); - } - else if (func === "setBlendConstant") - { - if ("setBlendConstant" in renderPass) - renderPass.setBlendConstant(command[1]); - } - else if (func === "setStencilReference") + renderPass.setViewport(setViewport[1], setViewport[2], setViewport[3], setViewport[4], setViewport[5], setViewport[6]); + } + if (setScissorRect && "setScissorRect" in renderPass) + { + renderPass.setScissorRect(setScissorRect[1], setScissorRect[2], setScissorRect[3], setScissorRect[4]); + } + renderPass.setPipeline(setPipeline[1]); + if (setBlendConstant && "setBlendConstant" in renderPass) + { + renderPass.setBlendConstant(setBlendConstant[1]); + } + if (setStencilReference && "setStencilReference" in renderPass) + { + renderPass.setStencilReference(setStencilReference[1]); + } + if (setBindGroup) + { + for (let i = 0, len = setBindGroup.length; i < len; i++) { - if ("setStencilReference" in renderPass) renderPass.setStencilReference(command[1]); + const [, index, bindGroup] = setBindGroup[i]; + renderPass.setBindGroup(index, bindGroup); } - else + } + if (setVertexBuffer) + { + for (let i = 0, len = setVertexBuffer.length; i < len; i++) { - func; + const [, slot, buffer, offset, size] = setVertexBuffer[i]; + renderPass.setVertexBuffer(slot, buffer, offset, size); } - }); + } + if (setIndexBuffer) + { + const [, buffer, indexFormat, offset, size] = setIndexBuffer; + renderPass.setIndexBuffer(buffer, indexFormat, offset, size); + } + if (draw) + { + renderPass.draw(draw[1], draw[2], draw[3], draw[4]); + } + if (drawIndexed) + { + renderPass.drawIndexed(drawIndexed[1], drawIndexed[2], drawIndexed[3], drawIndexed[4], drawIndexed[5]); + } } // static diff(a: RenderObjectCache, b: RenderObjectCache) -- Gitee From 31298e8104321bf1f9cfa8a2bed05f9042ad4434 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 22:13:05 +0800 Subject: [PATCH 174/214] =?UTF-8?q?refactor(internal):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20RenderObjectCache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 cache 变量从导出改为私有 - 将 setVaule 函数从导出改为私有 - 优化了代码结构,提高了模块的封装性 --- src/internal/RenderObjectCache.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 3bc2c4b..a155a0c 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -1,8 +1,8 @@ import { ChainMap } from "@feng3d/render-api"; -export const cache = new ChainMap(); +const cache = new ChainMap(); -export function setVaule>(cache: ChainMap, keys: T): T +function setVaule>(cache: ChainMap, keys: T): T { const v = cache.get(keys); if (v) return v; -- Gitee From f028f2bbf84ade08339571275fa1cdfc90443510 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 22:45:02 +0800 Subject: [PATCH 175/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=BC=93=E5=AD=98=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 OcclusionQueryCache 类,用于缓存和执行 occlusion query 相关操作 - 优化 RenderObjectCache 类,添加状态管理和 diff 方法 - 调整 WebGPUBase 类中的渲染流程,使用新的缓存机制 - 移除不必要的注释代码,提高代码可读性 --- src/WebGPUBase.ts | 20 +-- src/internal/RenderObjectCache.ts | 195 +++++++++++++++++------------- 2 files changed, 120 insertions(+), 95 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index a1b4b61..7c7b6f0 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -19,7 +19,7 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit, webgpuEvents } from "./eventnames"; -import { RenderObjectCache } from "./internal/RenderObjectCache"; +import { OcclusionQueryCache, RenderObjectCache } from "./internal/RenderObjectCache"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; @@ -212,11 +212,11 @@ export class WebGPUBase { if (!element.__type__) { - this.runRenderObject(passEncoder, renderPassFormat, element as RenderObject); + const renderObjectCache = this.runRenderObject(passEncoder, renderPassFormat, element as RenderObject); } else if (element.__type__ === "RenderObject") { - this.runRenderObject(passEncoder, renderPassFormat, element); + const renderObjectCache = this.runRenderObject(passEncoder, renderPassFormat, element); } else if (element.__type__ === "RenderBundle") { @@ -314,14 +314,17 @@ export class WebGPUBase protected runRenderOcclusionQueryObject(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderOcclusionQueryObject: OcclusionQuery, occlusionQuery: GPURenderOcclusionQuery) { - passEncoder.beginOcclusionQuery(occlusionQuery.getQueryIndex(renderOcclusionQueryObject)); + const occlusionQueryCache = new OcclusionQueryCache(); + occlusionQueryCache.queryIndex = occlusionQuery.getQueryIndex(renderOcclusionQueryObject); - renderOcclusionQueryObject.renderObjects.forEach((renderObject) => + occlusionQueryCache.renderObjectCaches = renderOcclusionQueryObject.renderObjects.map((renderObject) => { - this.runRenderObject(passEncoder, renderPassFormat, renderObject); + return this.runRenderObject(passEncoder, renderPassFormat, renderObject); }); - passEncoder.endOcclusionQuery(); + occlusionQueryCache.run(passEncoder); + + return occlusionQueryCache; } protected runRenderBundle(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) @@ -358,7 +361,6 @@ export class WebGPUBase { return this.runRenderObject(renderBundleEncoder, renderPassFormat, element as RenderObject); }); - // RenderObjectCache.runs(renderObjectCaches, renderBundleEncoder); const gpuRenderBundle = renderBundleEncoder.finish(); return gpuRenderBundle; @@ -409,7 +411,7 @@ export class WebGPUBase let result = renderObjectCacheMap.get(renderObjectCacheKey); if (result) { - result.value.run(passEncoder); + // result.value.run(passEncoder); return result.value; } diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index a155a0c..13ee66d 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -71,7 +71,7 @@ export class RenderObjectCache this[func as any] = undefined; } - run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder) + run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder, state?: RenderObjectCache) { // this.commands.forEach((command) => // { @@ -127,41 +127,48 @@ export class RenderObjectCache if (setViewport && "setViewport" in renderPass) { - renderPass.setViewport(setViewport[1], setViewport[2], setViewport[3], setViewport[4], setViewport[5], setViewport[6]); + if (!state || state.setViewport !== setViewport) renderPass.setViewport(setViewport[1], setViewport[2], setViewport[3], setViewport[4], setViewport[5], setViewport[6]); + if (state) state.setViewport = setViewport; } if (setScissorRect && "setScissorRect" in renderPass) { - renderPass.setScissorRect(setScissorRect[1], setScissorRect[2], setScissorRect[3], setScissorRect[4]); + if (!state || state.setScissorRect !== setScissorRect) renderPass.setScissorRect(setScissorRect[1], setScissorRect[2], setScissorRect[3], setScissorRect[4]); + if (state) state.setScissorRect = setScissorRect; } - renderPass.setPipeline(setPipeline[1]); + if (!state || state.setPipeline !== setPipeline) renderPass.setPipeline(setPipeline[1]); + if (state) state.setPipeline = setPipeline; if (setBlendConstant && "setBlendConstant" in renderPass) { - renderPass.setBlendConstant(setBlendConstant[1]); + if (!state || state.setBlendConstant !== setBlendConstant) renderPass.setBlendConstant(setBlendConstant[1]); + if (state) state.setBlendConstant = setBlendConstant; } if (setStencilReference && "setStencilReference" in renderPass) { - renderPass.setStencilReference(setStencilReference[1]); + if (!state || state.setStencilReference !== setStencilReference) renderPass.setStencilReference(setStencilReference[1]); + if (state) state.setStencilReference = setStencilReference; } if (setBindGroup) { + if (state) state.setBindGroup ??= []; for (let i = 0, len = setBindGroup.length; i < len; i++) { - const [, index, bindGroup] = setBindGroup[i]; - renderPass.setBindGroup(index, bindGroup); + if (!state || !state.setBindGroup[i] || state.setBindGroup[i] !== setBindGroup[i]) renderPass.setBindGroup(setBindGroup[i][1], setBindGroup[i][2]); + if (state) state.setBindGroup[i] = setBindGroup[i]; } } if (setVertexBuffer) { + if (state) state.setVertexBuffer ??= []; for (let i = 0, len = setVertexBuffer.length; i < len; i++) { - const [, slot, buffer, offset, size] = setVertexBuffer[i]; - renderPass.setVertexBuffer(slot, buffer, offset, size); + if (!state || !state.setVertexBuffer[i] || state.setVertexBuffer[i] !== setVertexBuffer[i]) renderPass.setVertexBuffer(setVertexBuffer[i][1], setVertexBuffer[i][2], setVertexBuffer[i][3], setVertexBuffer[i][4]); + if (state) state.setVertexBuffer[i] = setVertexBuffer[i]; } } if (setIndexBuffer) { - const [, buffer, indexFormat, offset, size] = setIndexBuffer; - renderPass.setIndexBuffer(buffer, indexFormat, offset, size); + if (!state || state.setIndexBuffer !== setIndexBuffer) renderPass.setIndexBuffer(setIndexBuffer[1], setIndexBuffer[2], setIndexBuffer[3]); + if (state) state.setIndexBuffer = setIndexBuffer; } if (draw) { @@ -173,81 +180,97 @@ export class RenderObjectCache } } - // static diff(a: RenderObjectCache, b: RenderObjectCache) - // { - // if (!a) return b; + static diff(a: RenderObjectCache, b: RenderObjectCache) + { + if (!a) return b; + + const result: RenderObjectCache = {} as any; + + if (a.setViewport !== b.setViewport && b.setViewport && (a.setViewport[0] !== b.setViewport[0] || a.setViewport[1] !== b.setViewport[1] || a.setViewport[2] !== b.setViewport[2] || a.setViewport[3] !== b.setViewport[3] || a.setViewport[4] !== b.setViewport[4] || a.setViewport[5] !== b.setViewport[5])) + { + result.setViewport = b.setViewport; + } + if (b.setScissorRect && (!a.setScissorRect || b.setScissorRect.some((v, i) => v !== a.setScissorRect[i]))) + { + result.setScissorRect = b.setScissorRect; + } + if (b.setPipeline && (!a.setPipeline || b.setPipeline.some((v, i) => v !== a.setPipeline[i]))) + { + result.setPipeline = b.setPipeline; + } + if (b.setBlendConstant && (!a.setBlendConstant || b.setBlendConstant.some((v, i) => v !== a.setBlendConstant[i]))) + { + result.setBlendConstant = b.setBlendConstant; + } + if (b.setStencilReference && (!a.setStencilReference || b.setStencilReference.some((v, i) => v !== a.setStencilReference[i]))) + { + result.setStencilReference = b.setStencilReference; + } + result.setBindGroup = []; + if (b.setBindGroup) + { + if (!a.setBindGroup) + { + result.setBindGroup = b.setBindGroup; + } + else + { + for (let i = 0, len = b.setBindGroup.length; i < len; i++) + { + if (!a.setBindGroup[i] || b.setBindGroup[i].some((v, i) => v !== a.setBindGroup[i][i])) + { + result.setBindGroup.push(b.setBindGroup[i]); + } + } + } + } + result.setVertexBuffer = []; + if (b.setVertexBuffer) + { + if (!a.setVertexBuffer) + { + result.setVertexBuffer = b.setVertexBuffer; + } + else + { + for (let i = 0, len = b.setVertexBuffer.length; i < len; i++) + { + if (!a.setVertexBuffer[i] || b.setVertexBuffer[i].some((v, j) => v !== a.setVertexBuffer[i][j])) + { + result.setVertexBuffer.push(b.setVertexBuffer[i]); + } + } + } + } + if (b.setIndexBuffer && (!a.setIndexBuffer || b.setIndexBuffer.some((v, i) => v !== a.setIndexBuffer[i]))) + { + result.setIndexBuffer = b.setIndexBuffer; + } + if (b.draw && (!a.draw || b.draw.some((v, i) => v !== a.draw[i]))) + { + result.draw = b.draw; + } + if (b.drawIndexed && (!a.drawIndexed || b.drawIndexed.some((v, i) => v !== a.drawIndexed[i]))) + { + result.drawIndexed = b.drawIndexed; + } - // const result: RenderObjectCache = {} as any; + return result; + } +} - // if (a.setViewport !== b.setViewport && b.setViewport && (a.setViewport[0] !== b.setViewport[0] || a.setViewport[1] !== b.setViewport[1] || a.setViewport[2] !== b.setViewport[2] || a.setViewport[3] !== b.setViewport[3] || a.setViewport[4] !== b.setViewport[4] || a.setViewport[5] !== b.setViewport[5])) - // { - // result.setViewport = b.setViewport; - // } - // if (b.setScissorRect && (!a.setScissorRect || b.setScissorRect.some((v, i) => v !== a.setScissorRect[i]))) - // { - // result.setScissorRect = b.setScissorRect; - // } - // if (b.setPipeline && (!a.setPipeline || b.setPipeline.some((v, i) => v !== a.setPipeline[i]))) - // { - // result.setPipeline = b.setPipeline; - // } - // if (b.setBlendConstant && (!a.setBlendConstant || b.setBlendConstant.some((v, i) => v !== a.setBlendConstant[i]))) - // { - // result.setBlendConstant = b.setBlendConstant; - // } - // if (b.setStencilReference && (!a.setStencilReference || b.setStencilReference.some((v, i) => v !== a.setStencilReference[i]))) - // { - // result.setStencilReference = b.setStencilReference; - // } - // result.setBindGroup = []; - // if (b.setBindGroup) - // { - // if (!a.setBindGroup) - // { - // result.setBindGroup = b.setBindGroup; - // } - // else - // { - // for (let i = 0, len = b.setBindGroup.length; i < len; i++) - // { - // if (!a.setBindGroup[i] || b.setBindGroup[i].some((v, i) => v !== a.setBindGroup[i][i])) - // { - // result.setBindGroup.push(b.setBindGroup[i]); - // } - // } - // } - // } - // result.setVertexBuffer = []; - // if (b.setVertexBuffer) - // { - // if (!a.setVertexBuffer) - // { - // result.setVertexBuffer = b.setVertexBuffer; - // } - // else - // { - // for (let i = 0, len = b.setVertexBuffer.length; i < len; i++) - // { - // if (!a.setVertexBuffer[i] || b.setVertexBuffer[i].some((v, j) => v !== a.setVertexBuffer[i][j])) - // { - // result.setVertexBuffer.push(b.setVertexBuffer[i]); - // } - // } - // } - // } - // if (b.setIndexBuffer && (!a.setIndexBuffer || b.setIndexBuffer.some((v, i) => v !== a.setIndexBuffer[i]))) - // { - // result.setIndexBuffer = b.setIndexBuffer; - // } - // if (b.draw && (!a.draw || b.draw.some((v, i) => v !== a.draw[i]))) - // { - // result.draw = b.draw; - // } - // if (b.drawIndexed && (!a.drawIndexed || b.drawIndexed.some((v, i) => v !== a.drawIndexed[i]))) - // { - // result.drawIndexed = b.drawIndexed; - // } +export class OcclusionQueryCache +{ + queryIndex: number; + renderObjectCaches: RenderObjectCache[]; - // return result; - // } + run(passEncoder: GPURenderPassEncoder) + { + passEncoder.beginOcclusionQuery(this.queryIndex); + for (let i = 0, len = this.renderObjectCaches.length; i < len; i++) + { + this.renderObjectCaches[i].run(passEncoder); + } + passEncoder.endOcclusionQuery(); + } } \ No newline at end of file -- Gitee From a88a27f8d7e4977d064d9627380bab1d6b525593 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 23:18:38 +0800 Subject: [PATCH 176/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=91=BD=E4=BB=A4=E6=89=A7=E8=A1=8C=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 RenderPassObjectCommand 接口,统一渲染命令执行逻辑 - 创建 RenderBundleCommand 和 RenderPassCommand 类封装渲染命令 - 优化渲染命令的缓存和执行机制 - 调整 WebGPUBase 类中的渲染方法,使用新的命令执行流程 --- src/WebGPUBase.ts | 90 ++++++++++++++++++------------- src/internal/RenderObjectCache.ts | 39 +++++++++++++- 2 files changed, 89 insertions(+), 40 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 7c7b6f0..4f7c5c1 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -19,13 +19,24 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit, webgpuEvents } from "./eventnames"; -import { OcclusionQueryCache, RenderObjectCache } from "./internal/RenderObjectCache"; +import { RenderPassObjectCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand } from "./internal/RenderObjectCache"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; +declare global +{ + interface GPURenderPassEncoder + { + /** + * 创建时由引擎设置。 + */ + device: GPUDevice; + } +} + /** * WebGPU 基础类 */ @@ -180,6 +191,8 @@ export class WebGPUBase const device = this._device; const { descriptor, renderObjects } = renderPass; + const renderPassCommand = new RenderPassCommand(); + const renderPassDescriptor = getGPURenderPassDescriptor(device, descriptor); const renderPassFormat = getGPURenderPassFormat(descriptor); @@ -191,9 +204,12 @@ export class WebGPUBase const occlusionQuery = getGPURenderOcclusionQuery(renderObjects); occlusionQuery.init(device, renderPassDescriptor); + renderPassCommand.renderPassDescriptor = renderPassDescriptor; + const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); + passEncoder.device = device; - this.runRenderPassObjects(passEncoder, renderPassFormat, renderObjects, occlusionQuery); + renderPassCommand.renderPassObjects = this.runRenderPassObjects(passEncoder, renderPassFormat, renderObjects, occlusionQuery); passEncoder.end(); @@ -202,35 +218,44 @@ export class WebGPUBase // 处理时间戳查询 timestampQuery.resolve(device, commandEncoder, renderPass); + + return renderPassCommand; } protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderPassObjects: readonly RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) { if (!renderPassObjects) return; // - renderPassObjects.forEach((element) => + const commands: RenderPassObjectCommand[] = renderPassObjects.map((element) => { if (!element.__type__) { - const renderObjectCache = this.runRenderObject(passEncoder, renderPassFormat, element as RenderObject); + return this.runRenderObject(renderPassFormat, element as RenderObject); } - else if (element.__type__ === "RenderObject") + if (element.__type__ === "RenderObject") { - const renderObjectCache = this.runRenderObject(passEncoder, renderPassFormat, element); + return this.runRenderObject(renderPassFormat, element); } - else if (element.__type__ === "RenderBundle") + if (element.__type__ === "RenderBundle") { - this.runRenderBundle(passEncoder, renderPassFormat, element); + return this.runRenderBundle(renderPassFormat, element); } - else if (element.__type__ === "OcclusionQuery") + if (element.__type__ === "OcclusionQuery") { - this.runRenderOcclusionQueryObject(passEncoder, renderPassFormat, element, occlusionQuery); + return this.runRenderOcclusionQueryObject(renderPassFormat, element, occlusionQuery); } else { throw `未处理 ${(element as RenderPassObject).__type__} 类型的渲染通道对象!`; } }); + + commands.forEach((command) => + { + command.run(passEncoder); + }); + + return commands; } /** @@ -312,36 +337,34 @@ export class WebGPUBase ); } - protected runRenderOcclusionQueryObject(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderOcclusionQueryObject: OcclusionQuery, occlusionQuery: GPURenderOcclusionQuery) + protected runRenderOcclusionQueryObject(renderPassFormat: RenderPassFormat, renderOcclusionQueryObject: OcclusionQuery, occlusionQuery: GPURenderOcclusionQuery) { const occlusionQueryCache = new OcclusionQueryCache(); occlusionQueryCache.queryIndex = occlusionQuery.getQueryIndex(renderOcclusionQueryObject); occlusionQueryCache.renderObjectCaches = renderOcclusionQueryObject.renderObjects.map((renderObject) => { - return this.runRenderObject(passEncoder, renderPassFormat, renderObject); + return this.runRenderObject(renderPassFormat, renderObject); }); - occlusionQueryCache.run(passEncoder); - return occlusionQueryCache; } - protected runRenderBundle(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) + protected runRenderBundle(renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) { - const device = this._device; + const renderBundleCommand = this.getGPURenderBundle(renderBundleObject, renderPassFormat); - const gpuRenderBundle = this.getGPURenderBundle(device, renderBundleObject, renderPassFormat); - - passEncoder.executeBundles([gpuRenderBundle]); + return renderBundleCommand; } - private getGPURenderBundle(device: GPUDevice, renderBundleObject: RenderBundle, renderPassFormat: RenderPassFormat) + private getGPURenderBundle(renderBundleObject: RenderBundle, renderPassFormat: RenderPassFormat) { - const gpuRenderBundleKey: GPURenderBundleKey = [device, renderBundleObject, renderPassFormat]; + const gpuRenderBundleKey: GPURenderBundleKey = [renderBundleObject, renderPassFormat]; let result = gpuRenderBundleMap.get(gpuRenderBundleKey); if (result) return result.value; + const renderBundleCommand = new RenderBundleCommand(); + result = computed(() => { // 监听 @@ -353,17 +376,15 @@ export class WebGPUBase // 执行 const descriptor: GPURenderBundleEncoderDescriptor = { ...renderBundleObject.descriptor, ...renderPassFormat }; - // - const renderBundleEncoder = device.createRenderBundleEncoder(descriptor); + renderBundleCommand.descriptor = descriptor; // - const renderObjectCaches = renderBundleObject.renderObjects.map((element) => + renderBundleCommand.renderObjectCaches = renderBundleObject.renderObjects.map((element) => { - return this.runRenderObject(renderBundleEncoder, renderPassFormat, element as RenderObject); + return this.runRenderObject(renderPassFormat, element as RenderObject); }); - const gpuRenderBundle = renderBundleEncoder.finish(); - return gpuRenderBundle; + return renderBundleCommand; }); gpuRenderBundleMap.set(gpuRenderBundleKey, result); @@ -404,17 +425,12 @@ export class WebGPUBase * @param renderObject 渲染对象。 * @param renderPass 渲染通道。 */ - protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) + protected runRenderObject(renderPassFormat: RenderPassFormat, renderObject: RenderObject) { const device = this._device; const renderObjectCacheKey: RenderObjectCacheKey = [device, renderObject, renderPassFormat]; let result = renderObjectCacheMap.get(renderObjectCacheKey); - if (result) - { - // result.value.run(passEncoder); - - return result.value; - } + if (result) { return result.value; } const renderObjectCache = new RenderObjectCache(); result = computed(() => @@ -431,8 +447,6 @@ export class WebGPUBase }); renderObjectCacheMap.set(renderObjectCacheKey, result); - result.value.run(passEncoder); - return result.value; } @@ -693,8 +707,8 @@ function getStencilReference(depthStencil?: DepthStencilState) return stencilReference; } -type GPURenderBundleKey = [device: GPUDevice, renderBundle: RenderBundle, renderPassFormat: RenderPassFormat]; -const gpuRenderBundleMap = new ChainMap>(); +type GPURenderBundleKey = [renderBundle: RenderBundle, renderPassFormat: RenderPassFormat]; +const gpuRenderBundleMap = new ChainMap>(); type RenderObjectCacheKey = [device: GPUDevice, renderObject: RenderObject, renderPassFormat: RenderPassFormat]; const renderObjectCacheMap = new ChainMap>(); \ No newline at end of file diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 13ee66d..1cae493 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -23,7 +23,7 @@ type CommandType = | [func: "setStencilReference", reference: GPUStencilValue] ; -export class RenderObjectCache +export class RenderObjectCache implements RenderPassObjectCommand { protected setViewport?: [func: "setViewport", x: number, y: number, width: number, height: number, minDepth: number, maxDepth: number]; protected setScissorRect?: [func: "setScissorRect", x: GPUIntegerCoordinate, y: GPUIntegerCoordinate, width: GPUIntegerCoordinate, height: GPUIntegerCoordinate]; @@ -259,7 +259,7 @@ export class RenderObjectCache } } -export class OcclusionQueryCache +export class OcclusionQueryCache implements RenderPassObjectCommand { queryIndex: number; renderObjectCaches: RenderObjectCache[]; @@ -273,4 +273,39 @@ export class OcclusionQueryCache } passEncoder.endOcclusionQuery(); } +} + +export interface RenderPassObjectCommand +{ + run(passEncoder: GPURenderPassEncoder): void; +} + +export class RenderBundleCommand implements RenderPassObjectCommand +{ + gpuRenderBundle: GPURenderBundle; + descriptor: GPURenderBundleEncoderDescriptor; + renderObjectCaches: RenderObjectCache[]; + run(passEncoder: GPURenderPassEncoder): void + { + if (!this.gpuRenderBundle) + { + // + const renderBundleEncoder = passEncoder.device.createRenderBundleEncoder(this.descriptor); + // + this.renderObjectCaches.forEach((renderObjectCache) => + { + renderObjectCache.run(renderBundleEncoder); + }); + + this.gpuRenderBundle = renderBundleEncoder.finish(); + } + + passEncoder.executeBundles([this.gpuRenderBundle]); + } +} + +export class RenderPassCommand +{ + renderPassDescriptor: GPURenderPassDescriptor; + renderPassObjects: RenderPassObjectCommand[]; } \ No newline at end of file -- Gitee From 9987c42879bb69c3404c813a61bdadf860e4eb5a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 23:38:48 +0800 Subject: [PATCH 177/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=88=B3=E6=9F=A5=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将时间戳查询的初始化和解析逻辑移至 GPURenderPassDescriptor 和 GPUComputePassDescriptor 中 - 新增 timestampWrites 属性用于存储时间戳查询集和解析方法 - 修改 getGPURenderTimestampQuery 函数以适应新的逻辑 - 优化时间戳查询的创建和解析流程 --- src/WebGPUBase.ts | 13 +++--- src/caches/getGPURenderTimestampQuery.ts | 58 ++++++++++++++---------- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 4f7c5c1..f003a39 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -197,8 +197,8 @@ export class WebGPUBase const renderPassFormat = getGPURenderPassFormat(descriptor); // 处理时间戳查询 - const timestampQuery = getGPURenderTimestampQuery(device, renderPass.timestampQuery); - timestampQuery.init(device, renderPassDescriptor); + renderPassDescriptor.commandEncoder = commandEncoder; + const timestampQuery = getGPURenderTimestampQuery(device, renderPassDescriptor, renderPass.timestampQuery); // 处理不被遮挡查询。 const occlusionQuery = getGPURenderOcclusionQuery(renderObjects); @@ -216,8 +216,7 @@ export class WebGPUBase // 处理不被遮挡查询。 occlusionQuery.resolve(device, commandEncoder, renderPass); - // 处理时间戳查询 - timestampQuery.resolve(device, commandEncoder, renderPass); + renderPassDescriptor.timestampWrites?.resolve(); return renderPassCommand; } @@ -271,8 +270,8 @@ export class WebGPUBase const descriptor: GPUComputePassDescriptor = {}; // 处理时间戳查询 - const timestampQuery = getGPURenderTimestampQuery(device, computePass?.timestampQuery); - timestampQuery.init(device, descriptor); + descriptor.commandEncoder = commandEncoder; + const timestampQuery = getGPURenderTimestampQuery(device, descriptor, computePass?.timestampQuery); const passEncoder = commandEncoder.beginComputePass(descriptor); @@ -281,7 +280,7 @@ export class WebGPUBase passEncoder.end(); // 处理时间戳查询 - timestampQuery.resolve(device, commandEncoder, computePass); + descriptor.timestampWrites?.resolve(); } protected runComputeObjects(passEncoder: GPUComputePassEncoder, computeObjects: ComputeObject[]) diff --git a/src/caches/getGPURenderTimestampQuery.ts b/src/caches/getGPURenderTimestampQuery.ts index c1f2b92..8ff166b 100644 --- a/src/caches/getGPURenderTimestampQuery.ts +++ b/src/caches/getGPURenderTimestampQuery.ts @@ -4,12 +4,36 @@ import { ComputePass } from "../data/ComputePass"; import { TimestampQuery } from "../data/TimestampQuery"; import { GPUQueue_submit } from "../eventnames"; -export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: TimestampQuery): GPURenderTimestampQuery +declare global +{ + interface GPURenderPassDescriptor + { + commandEncoder?: GPUCommandEncoder; + } + + interface GPUComputePassDescriptor + { + commandEncoder?: GPUCommandEncoder; + } + + interface GPURenderPassTimestampWrites + { + resolve?: () => void; + } + interface GPUComputePassTimestampWrites + { + resolve?: () => void; + } +} + +export function getGPURenderTimestampQuery(device: GPUDevice, passDescriptor: GPURenderPassDescriptor | GPUComputePassDescriptor, timestampQuery?: TimestampQuery): GPURenderTimestampQuery { if (!timestampQuery) return defautGPURenderTimestampQuery; let renderTimestampQuery: GPURenderTimestampQuery = timestampQuery["_GPURenderTimestampQuery"]; if (renderTimestampQuery) return renderTimestampQuery; - + + const commandEncoder = passDescriptor.commandEncoder; + // 判断是否支持 `timestamp-query` if (timestampQuery["isSupports"] === undefined) { @@ -23,7 +47,7 @@ export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: T return defautGPURenderTimestampQuery; } - let querySet: GPUQuerySet; + const querySet = device.createQuerySet({ type: "timestamp", count: 2 }); // Create a buffer where to store the result of GPU queries const timestampByteSize = 8; // timestamps are uint64 @@ -32,26 +56,13 @@ export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: T // Create a buffer to map the result back to the CPU let resultBuf: GPUBuffer; - /** - * 初始化。 - * - * 在渲染通道描述上设置 occlusionQuerySet 。 - * - * @param device - * @param passDescriptor - */ - const init = (device: GPUDevice, passDescriptor: GPURenderPassDescriptor | GPUComputePassDescriptor) => - { - querySet = querySet || device.createQuerySet({ type: "timestamp", count: 2 }); - - passDescriptor.timestampWrites = { - querySet, - beginningOfPassWriteIndex: 0, - endOfPassWriteIndex: 1, - }; + passDescriptor.timestampWrites = { + querySet, + beginningOfPassWriteIndex: 0, + endOfPassWriteIndex: 1, }; - const resolve = (device: GPUDevice, commandEncoder: GPUCommandEncoder) => + passDescriptor.timestampWrites.resolve = () => { resolveBuf = resolveBuf || device.createBuffer({ size: 2 * timestampByteSize, @@ -117,15 +128,14 @@ export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: T anyEmitter.on(device.queue, GPUQueue_submit, getQueryResult); }; - timestampQuery["_GPURenderTimestampQuery"] = renderTimestampQuery = { init, resolve }; + timestampQuery["_GPURenderTimestampQuery"] = renderTimestampQuery; return renderTimestampQuery; } interface GPURenderTimestampQuery { - init: (device: GPUDevice, passDescriptor: GPURenderPassDescriptor | GPUComputePassDescriptor) => void - resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass | ComputePass) => void + resolve: (commandEncoder: GPUCommandEncoder) => void } const defautGPURenderTimestampQuery = { init: () => { }, resolve: () => { } }; \ No newline at end of file -- Gitee From 8be94e36c915f7a413f5bc4190ba31f26c3ad01b Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 21 Mar 2025 23:41:04 +0800 Subject: [PATCH 178/214] =?UTF-8?q?refactor(webgpu):=20=E5=B0=86=20Compute?= =?UTF-8?q?Object=20=E6=8E=A5=E5=8F=A3=E4=B8=AD=E7=9A=84=20uniforms=20?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20bindin?= =?UTF-8?q?gResources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改了以下文件中的 uniforms 属性为 bindingResources: - atmosphericScatteringSky/index.ts - bitonicSort/index.ts - computeBoids/index.ts - cornell/radiosity.ts - cornell/raytracer.ts - cornell/tonemapper.ts - deferredRendering/index.ts - gameOfLife/index.ts - imageBlur/index.ts - particles/index.ts - WebGPUBase.ts - ComputeObject.ts 这个改动使代码更加清晰,因为它强调了这些资源是绑定到计算管道的,而不仅仅是统一变量。它也使代码更易于维护和扩展,因为绑定资源可以包括不仅仅是统一变量,还可以包括纹理、缓冲区等其他类型的资源。 --- examples/src/webgpu/atmosphericScatteringSky/index.ts | 2 +- examples/src/webgpu/bitonicSort/index.ts | 4 ++-- examples/src/webgpu/computeBoids/index.ts | 10 +++++----- examples/src/webgpu/cornell/radiosity.ts | 4 ++-- examples/src/webgpu/cornell/raytracer.ts | 2 +- examples/src/webgpu/cornell/tonemapper.ts | 2 +- examples/src/webgpu/deferredRendering/index.ts | 2 +- examples/src/webgpu/gameOfLife/index.ts | 2 +- examples/src/webgpu/imageBlur/index.ts | 8 ++++---- examples/src/webgpu/particles/index.ts | 6 +++--- src/WebGPUBase.ts | 2 +- src/data/ComputeObject.ts | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/examples/src/webgpu/atmosphericScatteringSky/index.ts b/examples/src/webgpu/atmosphericScatteringSky/index.ts index 42932df..a8ee3da 100644 --- a/examples/src/webgpu/atmosphericScatteringSky/index.ts +++ b/examples/src/webgpu/atmosphericScatteringSky/index.ts @@ -48,7 +48,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: { compute: { code: atmosphericScatteringSkyWGSL } }, - uniforms: { + bindingResources: { uniformBuffer, outTexture: { texture: framebuffer } }, diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index bff3ebf..3ead52f 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -380,7 +380,7 @@ async function init( __type__: "ComputePass", computeObjects: [{ pipeline: atomicToZeroComputePipeline, - uniforms: computeBGCluster, + bindingResources: computeBGCluster, workgroups: { workgroupCountX: 1 }, }] }] @@ -739,7 +739,7 @@ async function init( timestampQuery: querySet, computeObjects: [{ pipeline: computePipeline, - uniforms: computeBGCluster, + bindingResources: computeBGCluster, workgroups: { workgroupCountX: settings["Workgroups Per Step"] }, }] }; diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index 56a3ec0..035fa88 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -54,7 +54,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => pipeline: { compute: { code: updateSpritesWGSL } }, - uniforms: { + bindingResources: { params: simParams, particlesA: { bufferView: particleBuffers[0], @@ -68,14 +68,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const computeObject1: ComputeObject = { ...computeObject0, - uniforms: { - ...computeObject0.uniforms, + bindingResources: { + ...computeObject0.bindingResources, particlesA: { - ...computeObject0.uniforms.particlesA as {}, + ...computeObject0.bindingResources.particlesA as {}, bufferView: particleBuffers[1], }, particlesB: { - ...computeObject0.uniforms.particlesA as {}, + ...computeObject0.bindingResources.particlesA as {}, bufferView: particleBuffers[0], }, }, diff --git a/examples/src/webgpu/cornell/radiosity.ts b/examples/src/webgpu/cornell/radiosity.ts index a8a19bf..bed912c 100644 --- a/examples/src/webgpu/cornell/radiosity.ts +++ b/examples/src/webgpu/cornell/radiosity.ts @@ -114,7 +114,7 @@ export default class Radiosity // Dispatch the radiosity workgroups { pipeline: this.radiosityPipeline, - uniforms: { + bindingResources: { ...this.common.uniforms.bindGroup, ...this.bindGroup, }, @@ -123,7 +123,7 @@ export default class Radiosity // Then copy the 'accumulation' data to 'lightmap' { pipeline: this.accumulationToLightmapPipeline, - uniforms: { + bindingResources: { ...this.common.uniforms.bindGroup, ...this.bindGroup, }, diff --git a/examples/src/webgpu/cornell/raytracer.ts b/examples/src/webgpu/cornell/raytracer.ts index 98f80e7..1b73e93 100644 --- a/examples/src/webgpu/cornell/raytracer.ts +++ b/examples/src/webgpu/cornell/raytracer.ts @@ -56,7 +56,7 @@ export default class Raytracer __type__: "ComputePass", computeObjects: [{ pipeline: this.material, - uniforms: { + bindingResources: { ...this.common.uniforms.bindGroup, ...this.bindGroup, }, diff --git a/examples/src/webgpu/cornell/tonemapper.ts b/examples/src/webgpu/cornell/tonemapper.ts index 89be3cc..5b8e7ba 100644 --- a/examples/src/webgpu/cornell/tonemapper.ts +++ b/examples/src/webgpu/cornell/tonemapper.ts @@ -48,7 +48,7 @@ export default class Tonemapper __type__: "ComputePass", computeObjects: [{ pipeline: this.material, - uniforms: { + bindingResources: { ...this.bindGroup, }, workgroups: { diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index 3702117..babb496 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -342,7 +342,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => computeObjects: [ { pipeline: lightUpdateComputePipeline, - uniforms: { + bindingResources: { ...lightsBufferComputeBindGroup, }, workgroups: { workgroupCountX: Math.ceil(kMaxNumLights / 64) }, diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 5d40d20..6a40fe8 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -125,7 +125,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => __type__: "ComputePass", computeObjects: [{ pipeline: computePipeline, - uniforms: i ? bindGroup1 : bindGroup0, + bindingResources: i ? bindGroup1 : bindGroup0, workgroups: { workgroupCountX: GameOptions.width / GameOptions.workgroupSize, workgroupCountY: GameOptions.height / GameOptions.workgroupSize diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 6c96d3e..002b71c 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -181,12 +181,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gpuComputePassEncoder.computeObjects = [ { pipeline: blurPipeline, - uniforms: bindingResources0, + bindingResources: bindingResources0, workgroups: { workgroupCountX: Math.ceil(srcWidth / blockDim), workgroupCountY: Math.ceil(srcHeight / batch[1]) } }, { pipeline: blurPipeline, - uniforms: bindingResources1, + bindingResources: bindingResources1, workgroups: { workgroupCountX: Math.ceil(srcHeight / blockDim), workgroupCountY: Math.ceil(srcWidth / batch[1]) } }, ]; @@ -196,7 +196,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gpuComputePassEncoder.computeObjects.push( { pipeline: blurPipeline, - uniforms: bindingResources2, + bindingResources: bindingResources2, workgroups: { workgroupCountX: Math.ceil(srcWidth / blockDim), workgroupCountY: Math.ceil(srcHeight / batch[1]) } } ); @@ -204,7 +204,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gpuComputePassEncoder.computeObjects.push( { pipeline: blurPipeline, - uniforms: bindingResources1, + bindingResources: bindingResources1, workgroups: { workgroupCountX: Math.ceil(srcHeight / blockDim), workgroupCountY: Math.ceil(srcWidth / batch[1]) } } ); diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index d496924..433379e 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -204,7 +204,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => __type__: "ComputePass", computeObjects: [{ pipeline: probabilityMapImportLevelPipeline, - uniforms: { ...probabilityMapBindGroup }, + bindingResources: { ...probabilityMapBindGroup }, workgroups: { workgroupCountX: Math.ceil(levelWidth / 64), workgroupCountY: levelHeight }, }], }); @@ -215,7 +215,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => __type__: "ComputePass", computeObjects: [{ pipeline: probabilityMapExportLevelPipeline, - uniforms: { ...probabilityMapBindGroup }, + bindingResources: { ...probabilityMapBindGroup }, workgroups: { workgroupCountX: Math.ceil(levelWidth / 64), workgroupCountY: levelHeight }, }], }); @@ -282,7 +282,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => __type__: "ComputePass", computeObjects: [{ pipeline: computePipeline, - uniforms: { ...computeBindGroup }, + bindingResources: { ...computeBindGroup }, workgroups: { workgroupCountX: Math.ceil(numParticles / 64) }, }] }, diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index f003a39..aaacb20 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -400,7 +400,7 @@ export class WebGPUBase protected runComputeObject(passEncoder: GPUComputePassEncoder, computeObject: ComputeObject) { const device = this._device; - const { pipeline, uniforms: bindingResources, workgroups } = computeObject; + const { pipeline, bindingResources: bindingResources, workgroups } = computeObject; const computePipeline = getGPUComputePipeline(device, pipeline); passEncoder.setPipeline(computePipeline); diff --git a/src/data/ComputeObject.ts b/src/data/ComputeObject.ts index 2056664..a7fcec5 100644 --- a/src/data/ComputeObject.ts +++ b/src/data/ComputeObject.ts @@ -21,7 +21,7 @@ export interface ComputeObject /** * 绑定资源。包含数值、纹理、采样、外部纹理。 */ - readonly uniforms?: BindingResources; + readonly bindingResources?: BindingResources; /** * {@link GPUComputePassEncoder.dispatchWorkgroups} -- Gitee From 9e2a7f1b7ec0b2b0d3e611cb1e6a1ffff521fef6 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 00:05:47 +0800 Subject: [PATCH 179/214] 1 --- src/WebGPUBase.ts | 44 +++++++++++++---------- src/caches/getGPUComputePassDescriptor.ts | 15 ++++++++ src/caches/getGPURenderTimestampQuery.ts | 17 +++------ src/data/ComputePass.ts | 7 ++++ src/internal/RenderObjectCache.ts | 17 +++++++++ 5 files changed, 70 insertions(+), 30 deletions(-) create mode 100644 src/caches/getGPUComputePassDescriptor.ts diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index aaacb20..cecfd45 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -3,6 +3,7 @@ import { BlendState, Buffer, ChainMap, CommandEncoder, computed, ComputedRef, Co import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; +import { getGPUComputePassDescriptor } from "./caches/getGPUComputePassDescriptor"; import { getGPUComputePipeline } from "./caches/getGPUComputePipeline"; import { getGPUPipelineLayout } from "./caches/getGPUPipelineLayout"; import { getGPURenderOcclusionQuery, GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; @@ -19,7 +20,7 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit, webgpuEvents } from "./eventnames"; -import { RenderPassObjectCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand } from "./internal/RenderObjectCache"; +import { ComputeObjectCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand, RenderPassObjectCommand } from "./internal/RenderObjectCache"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; @@ -28,6 +29,14 @@ import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultipl declare global { + interface GPUCommandEncoder + { + /** + * 创建时由引擎设置。 + */ + device: GPUDevice; + } + interface GPURenderPassEncoder { /** @@ -154,6 +163,7 @@ export class WebGPUBase { const device = this._device; const gpuCommandEncoder = device.createCommandEncoder(); + gpuCommandEncoder.device = device; commandEncoder.passEncoders.forEach((passEncoder) => { @@ -198,7 +208,7 @@ export class WebGPUBase // 处理时间戳查询 renderPassDescriptor.commandEncoder = commandEncoder; - const timestampQuery = getGPURenderTimestampQuery(device, renderPassDescriptor, renderPass.timestampQuery); + getGPURenderTimestampQuery(device, renderPassDescriptor, renderPass.timestampQuery); // 处理不被遮挡查询。 const occlusionQuery = getGPURenderOcclusionQuery(renderObjects); @@ -266,16 +276,12 @@ export class WebGPUBase */ protected runComputePass(commandEncoder: GPUCommandEncoder, computePass: ComputePass) { - const device = this._device; - - const descriptor: GPUComputePassDescriptor = {}; + const descriptor = getGPUComputePassDescriptor(commandEncoder, computePass); // 处理时间戳查询 - descriptor.commandEncoder = commandEncoder; - const timestampQuery = getGPURenderTimestampQuery(device, descriptor, computePass?.timestampQuery); - const passEncoder = commandEncoder.beginComputePass(descriptor); - this.runComputeObjects(passEncoder, computePass.computeObjects); + const computeObjectCommands = this.runComputeObjects(computePass.computeObjects); + computeObjectCommands.forEach((command) => command.run(passEncoder)); passEncoder.end(); @@ -283,12 +289,9 @@ export class WebGPUBase descriptor.timestampWrites?.resolve(); } - protected runComputeObjects(passEncoder: GPUComputePassEncoder, computeObjects: ComputeObject[]) + protected runComputeObjects(computeObjects: ComputeObject[]) { - computeObjects.forEach((computeObject) => - { - this.runComputeObject(passEncoder, computeObject); - }); + return computeObjects.map((computeObject) => this.runComputeObject(computeObject)); } protected runCopyTextureToTexture(commandEncoder: GPUCommandEncoder, copyTextureToTexture: CopyTextureToTexture) @@ -397,23 +400,28 @@ export class WebGPUBase * @param passEncoder 计算通道编码器。 * @param computeObject 计算对象。 */ - protected runComputeObject(passEncoder: GPUComputePassEncoder, computeObject: ComputeObject) + protected runComputeObject(computeObject: ComputeObject) { const device = this._device; const { pipeline, bindingResources: bindingResources, workgroups } = computeObject; const computePipeline = getGPUComputePipeline(device, pipeline); - passEncoder.setPipeline(computePipeline); + + const computeObjectCommand = new ComputeObjectCommand(); + computeObjectCommand.computePipeline = computePipeline; // 计算 bindGroups + computeObjectCommand.setBindGroup = []; const layout = getGPUPipelineLayout(device, { compute: pipeline.compute.code }); layout.bindGroupLayouts.forEach((bindGroupLayout, group) => { const gpuBindGroup: GPUBindGroup = getGPUBindGroup(device, bindGroupLayout, bindingResources); - passEncoder.setBindGroup(group, gpuBindGroup); + computeObjectCommand.setBindGroup.push([group, gpuBindGroup]); }); - passEncoder.dispatchWorkgroups(workgroups.workgroupCountX, workgroups.workgroupCountY, workgroups.workgroupCountZ); + computeObjectCommand.dispatchWorkgroups = [workgroups.workgroupCountX, workgroups.workgroupCountY, workgroups.workgroupCountZ]; + + return computeObjectCommand; } /** diff --git a/src/caches/getGPUComputePassDescriptor.ts b/src/caches/getGPUComputePassDescriptor.ts new file mode 100644 index 0000000..2d51ecb --- /dev/null +++ b/src/caches/getGPUComputePassDescriptor.ts @@ -0,0 +1,15 @@ +import { ComputePass } from "../data/ComputePass"; +import { getGPURenderTimestampQuery } from "./getGPURenderTimestampQuery"; + +export function getGPUComputePassDescriptor(commandEncoder: GPUCommandEncoder, computePass: ComputePass) +{ + const descriptor: GPUComputePassDescriptor = {}; + descriptor.commandEncoder = commandEncoder; + + const device = commandEncoder.device; + + if (computePass.timestampQuery) + getGPURenderTimestampQuery(device, descriptor, computePass?.timestampQuery); + + return descriptor; +} \ No newline at end of file diff --git a/src/caches/getGPURenderTimestampQuery.ts b/src/caches/getGPURenderTimestampQuery.ts index 8ff166b..a06b7ca 100644 --- a/src/caches/getGPURenderTimestampQuery.ts +++ b/src/caches/getGPURenderTimestampQuery.ts @@ -26,10 +26,10 @@ declare global } } -export function getGPURenderTimestampQuery(device: GPUDevice, passDescriptor: GPURenderPassDescriptor | GPUComputePassDescriptor, timestampQuery?: TimestampQuery): GPURenderTimestampQuery +export function getGPURenderTimestampQuery(device: GPUDevice, passDescriptor: GPURenderPassDescriptor | GPUComputePassDescriptor, timestampQuery?: TimestampQuery) { - if (!timestampQuery) return defautGPURenderTimestampQuery; - let renderTimestampQuery: GPURenderTimestampQuery = timestampQuery["_GPURenderTimestampQuery"]; + if (!timestampQuery) return; + let renderTimestampQuery: GPURenderPassTimestampWrites | GPUComputePassTimestampWrites = timestampQuery["_GPURenderTimestampQuery"]; if (renderTimestampQuery) return renderTimestampQuery; const commandEncoder = passDescriptor.commandEncoder; @@ -44,7 +44,7 @@ export function getGPURenderTimestampQuery(device: GPUDevice, passDescriptor: GP { console.warn(`WebGPU未开启或者不支持 timestamp-query 特性,请确认 WebGPU.init 初始化参数是否正确!`); - return defautGPURenderTimestampQuery; + return; } const querySet = device.createQuerySet({ type: "timestamp", count: 2 }); @@ -56,7 +56,7 @@ export function getGPURenderTimestampQuery(device: GPUDevice, passDescriptor: GP // Create a buffer to map the result back to the CPU let resultBuf: GPUBuffer; - passDescriptor.timestampWrites = { + renderTimestampQuery = passDescriptor.timestampWrites = { querySet, beginningOfPassWriteIndex: 0, endOfPassWriteIndex: 1, @@ -132,10 +132,3 @@ export function getGPURenderTimestampQuery(device: GPUDevice, passDescriptor: GP return renderTimestampQuery; } - -interface GPURenderTimestampQuery -{ - resolve: (commandEncoder: GPUCommandEncoder) => void -} - -const defautGPURenderTimestampQuery = { init: () => { }, resolve: () => { } }; \ No newline at end of file diff --git a/src/data/ComputePass.ts b/src/data/ComputePass.ts index c992269..a29c69c 100644 --- a/src/data/ComputePass.ts +++ b/src/data/ComputePass.ts @@ -14,6 +14,8 @@ export interface ComputePass */ readonly __type__: "ComputePass"; + descriptor?: ComputePassDescriptor; + /** * 计算对象列表。 */ @@ -25,4 +27,9 @@ export interface ComputePass * 如果需要查询通道运行消耗时长,需要为该属性赋值,如 `pass.timestampQuery = {};`。WebGPU渲染完成后引擎自动填充结果到属性`elapsedNs`。 */ timestampQuery?: TimestampQuery; +} + +export interface ComputePassDescriptor +{ + } \ No newline at end of file diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 1cae493..680d965 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -308,4 +308,21 @@ export class RenderPassCommand { renderPassDescriptor: GPURenderPassDescriptor; renderPassObjects: RenderPassObjectCommand[]; +} + +export class ComputeObjectCommand +{ + run(passEncoder: GPUComputePassEncoder) + { + passEncoder.setPipeline(this.computePipeline); + this.setBindGroup.forEach(([index, bindGroup]) => + { + passEncoder.setBindGroup(index, bindGroup); + }); + const [workgroupCountX, workgroupCountY, workgroupCountZ] = this.dispatchWorkgroups; + passEncoder.dispatchWorkgroups(workgroupCountX, workgroupCountY, workgroupCountZ); + } + computePipeline: GPUComputePipeline; + setBindGroup: [index: GPUIndex32, bindGroup: GPUBindGroup][]; + dispatchWorkgroups: [workgroupCountX: GPUSize32, workgroupCountY?: GPUSize32, workgroupCountZ?: GPUSize32]; } \ No newline at end of file -- Gitee From 5973a47fcfbce939f730e328335005948d327987 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 00:16:36 +0800 Subject: [PATCH 180/214] =?UTF-8?q?refactor(webgpu):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=88=B3=E6=9F=A5=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 ComputePass 和 RenderPass 中的 commandEncoder 属性 - 修改 timestampQuery 的处理逻辑,使其通过 descriptor 传递 - 调整 timestampWrites 的 resolve 方法,增加 commandEncoder 参数 - 优化相关缓存和数据结构,以适应新的时间戳查询流程 --- examples/src/webgpu/bitonicSort/index.ts | 4 ++- examples/src/webgpu/timestampQuery/index.ts | 4 +-- src/WebGPUBase.ts | 7 +++-- src/caches/getGPUComputePassDescriptor.ts | 7 ++--- src/caches/getGPURenderTimestampQuery.ts | 30 +++++++-------------- src/data/ComputePass.ts | 8 +++--- src/data/polyfills/RenderPass.ts | 9 +------ 7 files changed, 25 insertions(+), 44 deletions(-) diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index 3ead52f..cc18df9 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -736,7 +736,9 @@ async function init( { const computePassEncoder: ComputePass = { __type__: "ComputePass", - timestampQuery: querySet, + // descriptor: { + // timestampQuery: querySet, + // }, computeObjects: [{ pipeline: computePipeline, bindingResources: computeBGCluster, diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index 2670812..bd5d0a5 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -101,6 +101,8 @@ const init = async (canvas: HTMLCanvasElement) => depthLoadOp: "clear", depthStoreOp: "store", }, + // 开启时间戳查询 + timestampQuery, }; const renderObject: RenderObject = { @@ -118,8 +120,6 @@ const init = async (canvas: HTMLCanvasElement) => passEncoders: [ { descriptor: renderPassDescriptor, renderObjects: [renderObject], - // 开启时间戳查询 - timestampQuery, }, ] } diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index cecfd45..88f69cb 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -207,8 +207,7 @@ export class WebGPUBase const renderPassFormat = getGPURenderPassFormat(descriptor); // 处理时间戳查询 - renderPassDescriptor.commandEncoder = commandEncoder; - getGPURenderTimestampQuery(device, renderPassDescriptor, renderPass.timestampQuery); + getGPURenderTimestampQuery(device, descriptor.timestampQuery); // 处理不被遮挡查询。 const occlusionQuery = getGPURenderOcclusionQuery(renderObjects); @@ -226,7 +225,7 @@ export class WebGPUBase // 处理不被遮挡查询。 occlusionQuery.resolve(device, commandEncoder, renderPass); - renderPassDescriptor.timestampWrites?.resolve(); + renderPassDescriptor.timestampWrites?.resolve(commandEncoder); return renderPassCommand; } @@ -286,7 +285,7 @@ export class WebGPUBase passEncoder.end(); // 处理时间戳查询 - descriptor.timestampWrites?.resolve(); + descriptor.timestampWrites?.resolve(commandEncoder); } protected runComputeObjects(computeObjects: ComputeObject[]) diff --git a/src/caches/getGPUComputePassDescriptor.ts b/src/caches/getGPUComputePassDescriptor.ts index 2d51ecb..5d95fb3 100644 --- a/src/caches/getGPUComputePassDescriptor.ts +++ b/src/caches/getGPUComputePassDescriptor.ts @@ -4,12 +4,13 @@ import { getGPURenderTimestampQuery } from "./getGPURenderTimestampQuery"; export function getGPUComputePassDescriptor(commandEncoder: GPUCommandEncoder, computePass: ComputePass) { const descriptor: GPUComputePassDescriptor = {}; - descriptor.commandEncoder = commandEncoder; const device = commandEncoder.device; - if (computePass.timestampQuery) - getGPURenderTimestampQuery(device, descriptor, computePass?.timestampQuery); + if (computePass.descriptor?.timestampQuery) + { + descriptor.timestampWrites = getGPURenderTimestampQuery(device, computePass.descriptor.timestampQuery); + } return descriptor; } \ No newline at end of file diff --git a/src/caches/getGPURenderTimestampQuery.ts b/src/caches/getGPURenderTimestampQuery.ts index a06b7ca..074e4cd 100644 --- a/src/caches/getGPURenderTimestampQuery.ts +++ b/src/caches/getGPURenderTimestampQuery.ts @@ -6,33 +6,21 @@ import { GPUQueue_submit } from "../eventnames"; declare global { - interface GPURenderPassDescriptor - { - commandEncoder?: GPUCommandEncoder; - } - - interface GPUComputePassDescriptor - { - commandEncoder?: GPUCommandEncoder; - } - interface GPURenderPassTimestampWrites { - resolve?: () => void; + resolve?: (commandEncoder: GPUCommandEncoder) => void; } interface GPUComputePassTimestampWrites { - resolve?: () => void; + resolve?: (commandEncoder: GPUCommandEncoder) => void; } } -export function getGPURenderTimestampQuery(device: GPUDevice, passDescriptor: GPURenderPassDescriptor | GPUComputePassDescriptor, timestampQuery?: TimestampQuery) +export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: TimestampQuery) { if (!timestampQuery) return; - let renderTimestampQuery: GPURenderPassTimestampWrites | GPUComputePassTimestampWrites = timestampQuery["_GPURenderTimestampQuery"]; - if (renderTimestampQuery) return renderTimestampQuery; - - const commandEncoder = passDescriptor.commandEncoder; + let timestampWrites: GPURenderPassTimestampWrites | GPUComputePassTimestampWrites = timestampQuery["_GPURenderTimestampQuery"]; + if (timestampWrites) return timestampWrites; // 判断是否支持 `timestamp-query` if (timestampQuery["isSupports"] === undefined) @@ -56,13 +44,13 @@ export function getGPURenderTimestampQuery(device: GPUDevice, passDescriptor: GP // Create a buffer to map the result back to the CPU let resultBuf: GPUBuffer; - renderTimestampQuery = passDescriptor.timestampWrites = { + timestampWrites = { querySet, beginningOfPassWriteIndex: 0, endOfPassWriteIndex: 1, }; - passDescriptor.timestampWrites.resolve = () => + timestampWrites.resolve = (commandEncoder: GPUCommandEncoder) => { resolveBuf = resolveBuf || device.createBuffer({ size: 2 * timestampByteSize, @@ -128,7 +116,7 @@ export function getGPURenderTimestampQuery(device: GPUDevice, passDescriptor: GP anyEmitter.on(device.queue, GPUQueue_submit, getQueryResult); }; - timestampQuery["_GPURenderTimestampQuery"] = renderTimestampQuery; + timestampQuery["_GPURenderTimestampQuery"] = timestampWrites; - return renderTimestampQuery; + return timestampWrites; } diff --git a/src/data/ComputePass.ts b/src/data/ComputePass.ts index a29c69c..a317891 100644 --- a/src/data/ComputePass.ts +++ b/src/data/ComputePass.ts @@ -20,16 +20,14 @@ export interface ComputePass * 计算对象列表。 */ computeObjects: ComputeObject[]; +} +export interface ComputePassDescriptor +{ /** * 查询通道运行消耗时长(单位为纳秒)。 * * 如果需要查询通道运行消耗时长,需要为该属性赋值,如 `pass.timestampQuery = {};`。WebGPU渲染完成后引擎自动填充结果到属性`elapsedNs`。 */ timestampQuery?: TimestampQuery; -} - -export interface ComputePassDescriptor -{ - } \ No newline at end of file diff --git a/src/data/polyfills/RenderPass.ts b/src/data/polyfills/RenderPass.ts index 1e659e8..736d9e7 100644 --- a/src/data/polyfills/RenderPass.ts +++ b/src/data/polyfills/RenderPass.ts @@ -4,14 +4,7 @@ import { TimestampQuery } from "../TimestampQuery"; declare module "@feng3d/render-api" { - /** - * GPU渲染通道编码器。 - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/GPURenderPassEncoder - * - * {@link GPURenderPassEncoder} - */ - export interface RenderPass + export interface RenderPassDescriptor { /** * 查询通道运行消耗时长(单位为纳秒)。 -- Gitee From cf97ca227ab5b96392810da164b369eda6e10780 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 10:18:43 +0800 Subject: [PATCH 181/214] =?UTF-8?q?refactor(WebGPU):=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=88=B3=E6=9F=A5=E8=AF=A2=E5=A4=84=E7=90=86?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 WebGPUBase 类中关于时间戳查询的处理代码 - 将时间戳查询处理逻辑移至 getGPURenderPassDescriptor 函数中 - 优化代码结构,使时间戳查询处理更加集中和清晰 --- src/WebGPUBase.ts | 4 ---- src/caches/getGPURenderPassDescriptor.ts | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 88f69cb..1e7cf93 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -10,7 +10,6 @@ import { getGPURenderOcclusionQuery, GPURenderOcclusionQuery } from "./caches/ge import { getGPURenderPassDescriptor } from "./caches/getGPURenderPassDescriptor"; import { getGPURenderPassFormat } from "./caches/getGPURenderPassFormat"; import { getGPURenderPipeline } from "./caches/getGPURenderPipeline"; -import { getGPURenderTimestampQuery } from "./caches/getGPURenderTimestampQuery"; import { getGPUTexture } from "./caches/getGPUTexture"; import { getGBuffer } from "./caches/getIGPUBuffer"; import { getNVertexBuffers } from "./caches/getNGPUVertexBuffers"; @@ -206,9 +205,6 @@ export class WebGPUBase const renderPassDescriptor = getGPURenderPassDescriptor(device, descriptor); const renderPassFormat = getGPURenderPassFormat(descriptor); - // 处理时间戳查询 - getGPURenderTimestampQuery(device, descriptor.timestampQuery); - // 处理不被遮挡查询。 const occlusionQuery = getGPURenderOcclusionQuery(renderObjects); occlusionQuery.init(device, renderPassDescriptor); diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 1a720ac..644db90 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,5 +1,6 @@ import { CanvasTexture, ChainMap, computed, ComputedRef, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; import { MultisampleTexture } from "../internal/MultisampleTexture"; +import { getGPURenderTimestampQuery } from "./getGPURenderTimestampQuery"; import { getGPUTextureFormat } from "./getGPUTextureFormat"; import { getGPUTextureView } from "./getGPUTextureView"; import { getTextureSize } from "./getTextureSize"; @@ -35,6 +36,9 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render renderPassDescriptor.colorAttachments = getGPURenderPassColorAttachments(device, descriptor); renderPassDescriptor.depthStencilAttachment = getGPURenderPassDepthStencilAttachment(device, descriptor); + // 处理时间戳查询 + renderPassDescriptor.timestampWrites = getGPURenderTimestampQuery(device, descriptor.timestampQuery); + return renderPassDescriptor; }); getGPURenderPassDescriptorMap.set(getGPURenderPassDescriptorKey, result); -- Gitee From 673f285c8747caa31d26e45e074a27a6ce899bc7 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 10:27:27 +0800 Subject: [PATCH 182/214] =?UTF-8?q?refactor(webgpu):=20=E5=B0=86=20renderO?= =?UTF-8?q?bjects=20=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20renderPassObjec?= =?UTF-8?q?ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在多个示例文件中将 renderObjects 属性重命名为 renderPassObjects - 在 WebGPUBase 类中进行相应的属性名称变更和逻辑调整 - 此次重构提高了 --- examples/src/webgpu/RenderObjectChanges/index.ts | 2 +- examples/src/webgpu/a-buffer/index.ts | 6 +++--- examples/src/webgpu/bitonicSort/utils.ts | 2 +- examples/src/webgpu/blending/index.ts | 2 +- examples/src/webgpu/cameras/index.ts | 2 +- examples/src/webgpu/computeBoids/index.ts | 2 +- examples/src/webgpu/cornell/rasterizer.ts | 2 +- examples/src/webgpu/cubemap/index.ts | 2 +- examples/src/webgpu/deferredRendering/index.ts | 6 +++--- examples/src/webgpu/fractalCube/index.ts | 2 +- examples/src/webgpu/gameOfLife/index.ts | 2 +- examples/src/webgpu/helloTriangle/index.ts | 2 +- examples/src/webgpu/helloTriangleMSAA/index.ts | 2 +- examples/src/webgpu/imageBlur/index.ts | 2 +- examples/src/webgpu/instancedCube/index.ts | 2 +- examples/src/webgpu/multipleCanvases/index.ts | 2 +- examples/src/webgpu/normalMap/index.ts | 2 +- examples/src/webgpu/occlusionQuery/index.ts | 2 +- examples/src/webgpu/particles/index.ts | 2 +- examples/src/webgpu/points/index.ts | 2 +- examples/src/webgpu/renderBundles/index.ts | 6 +++--- examples/src/webgpu/resizeCanvas/index.ts | 2 +- examples/src/webgpu/resizeObserverHDDPI/index.ts | 2 +- examples/src/webgpu/reversedZ/index.ts | 10 +++++----- examples/src/webgpu/rotatingCube/index.ts | 2 +- examples/src/webgpu/samplerParameters/index.ts | 2 +- examples/src/webgpu/shadowMapping/index.ts | 4 ++-- examples/src/webgpu/skinnedMesh/index.ts | 4 ++-- examples/src/webgpu/textRenderingMsdf/index.ts | 2 +- examples/src/webgpu/texturedCube/index.ts | 2 +- examples/src/webgpu/timestampQuery/index.ts | 2 +- examples/src/webgpu/transparentCanvas/index.ts | 2 +- examples/src/webgpu/twoCubes/index.ts | 2 +- examples/src/webgpu/videoUploading/index.ts | 2 +- .../src/webgpu/volumeRenderingTexture3D/index.ts | 2 +- examples/src/webgpu/wireframe/index.ts | 2 +- examples/src/webgpu/worker/worker.ts | 2 +- src/WebGPUBase.ts | 16 ++++++++++------ 38 files changed, 59 insertions(+), 55 deletions(-) diff --git a/examples/src/webgpu/RenderObjectChanges/index.ts b/examples/src/webgpu/RenderObjectChanges/index.ts index 7d2c5b0..15a7198 100644 --- a/examples/src/webgpu/RenderObjectChanges/index.ts +++ b/examples/src/webgpu/RenderObjectChanges/index.ts @@ -48,7 +48,7 @@ const init = async (canvas: HTMLCanvasElement) => clearValue: [0.0, 0.0, 0.0, 1.0], // 渲染前填充颜色 }], }, - renderObjects: [renderObject] + renderPassObjects: [renderObject] }, ] } diff --git a/examples/src/webgpu/a-buffer/index.ts b/examples/src/webgpu/a-buffer/index.ts index 183e411..7ebdb5a 100644 --- a/examples/src/webgpu/a-buffer/index.ts +++ b/examples/src/webgpu/a-buffer/index.ts @@ -285,7 +285,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // Draw the opaque objects const opaquePassEncoder: RenderPass = { descriptor: opaquePassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline: opaquePipeline, bindingResources: bindingResources, vertices, @@ -315,7 +315,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const translucentPassEncoder: RenderPass = { descriptor: translucentPassDescriptor, - renderObjects: [ + renderPassObjects: [ // Set the scissor to only process a horizontal slice of the frame { scissorRect: { x: scissorX, y: scissorY, width: scissorWidth, height: scissorHeight }, @@ -336,7 +336,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const compositePassEncoder: RenderPass = { descriptor: compositePassDescriptor, - renderObjects: [ + renderPassObjects: [ // Set the scissor to only process a horizontal slice of the frame { scissorRect: { x: scissorX, y: scissorY, width: scissorWidth, height: scissorHeight }, diff --git a/examples/src/webgpu/bitonicSort/utils.ts b/examples/src/webgpu/bitonicSort/utils.ts index 1730169..baedffd 100644 --- a/examples/src/webgpu/bitonicSort/utils.ts +++ b/examples/src/webgpu/bitonicSort/utils.ts @@ -56,7 +56,7 @@ export abstract class Base2DRendererClass { const passEncoder: RenderPass = { descriptor: renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline: pipeline, bindingResources: bindingResources, draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1 }, diff --git a/examples/src/webgpu/blending/index.ts b/examples/src/webgpu/blending/index.ts index 38c34ad..0140d04 100644 --- a/examples/src/webgpu/blending/index.ts +++ b/examples/src/webgpu/blending/index.ts @@ -502,7 +502,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, - renderObjects: renderObjects + renderPassObjects: renderObjects }] }], }; diff --git a/examples/src/webgpu/cameras/index.ts b/examples/src/webgpu/cameras/index.ts index e2a398c..fe53162 100644 --- a/examples/src/webgpu/cameras/index.ts +++ b/examples/src/webgpu/cameras/index.ts @@ -126,7 +126,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPassDescriptor, renderObjects: [renderObject] }, + { descriptor: renderPassDescriptor, renderPassObjects: [renderObject] }, ] } ], diff --git a/examples/src/webgpu/computeBoids/index.ts b/examples/src/webgpu/computeBoids/index.ts index 035fa88..726e870 100644 --- a/examples/src/webgpu/computeBoids/index.ts +++ b/examples/src/webgpu/computeBoids/index.ts @@ -129,7 +129,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => { passEncoders: [ { __type__: "ComputePass", computeObjects: [[computeObject0, computeObject1][t % 2]] }, - { descriptor: renderPass, renderObjects: [[renderObject, renderObject1][(t + 1) % 2]] }, + { descriptor: renderPass, renderPassObjects: [[renderObject, renderObject1][(t + 1) % 2]] }, ] } ], diff --git a/examples/src/webgpu/cornell/rasterizer.ts b/examples/src/webgpu/cornell/rasterizer.ts index 15464d3..0cf82e6 100644 --- a/examples/src/webgpu/cornell/rasterizer.ts +++ b/examples/src/webgpu/cornell/rasterizer.ts @@ -77,7 +77,7 @@ export default class Rasterizer // this.renderPassEncoder = { descriptor: this.renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline: this.pipeline, bindingResources: { ...this.common.uniforms.bindGroup, diff --git a/examples/src/webgpu/cubemap/index.ts b/examples/src/webgpu/cubemap/index.ts index f6478d3..c0c318f 100644 --- a/examples/src/webgpu/cubemap/index.ts +++ b/examples/src/webgpu/cubemap/index.ts @@ -150,7 +150,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPass, renderObjects: [renderObject] }, + { descriptor: renderPass, renderPassObjects: [renderObject] }, ] } ], diff --git a/examples/src/webgpu/deferredRendering/index.ts b/examples/src/webgpu/deferredRendering/index.ts index babb496..75f8eeb 100644 --- a/examples/src/webgpu/deferredRendering/index.ts +++ b/examples/src/webgpu/deferredRendering/index.ts @@ -325,7 +325,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const passEncoders: (ComputePass | RenderPass)[] = []; passEncoders.push({ descriptor: writeGBufferPassDescriptor, - renderObjects: [ + renderPassObjects: [ { pipeline: writeGBuffersPipeline, bindingResources: { @@ -354,7 +354,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => gBuffersPassEncoders.push({ descriptor: textureQuadPassDescriptor, - renderObjects: [ + renderPassObjects: [ { pipeline: gBuffersDebugViewPipeline, bindingResources: { @@ -367,7 +367,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders.push({ descriptor: textureQuadPassDescriptor, - renderObjects: [ + renderPassObjects: [ { pipeline: deferredRenderPipeline, bindingResources: { diff --git a/examples/src/webgpu/fractalCube/index.ts b/examples/src/webgpu/fractalCube/index.ts index ea4ea78..8e36187 100644 --- a/examples/src/webgpu/fractalCube/index.ts +++ b/examples/src/webgpu/fractalCube/index.ts @@ -114,7 +114,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPass, renderObjects: [renderObject] }, + { descriptor: renderPass, renderPassObjects: [renderObject] }, copyTextureToTexture, ] } diff --git a/examples/src/webgpu/gameOfLife/index.ts b/examples/src/webgpu/gameOfLife/index.ts index 6a40fe8..fb1989d 100644 --- a/examples/src/webgpu/gameOfLife/index.ts +++ b/examples/src/webgpu/gameOfLife/index.ts @@ -134,7 +134,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, { descriptor: renderPass, - renderObjects: [ + renderPassObjects: [ { pipeline: renderPipeline, bindingResources: uniformBindGroup, diff --git a/examples/src/webgpu/helloTriangle/index.ts b/examples/src/webgpu/helloTriangle/index.ts index 7111c79..153c9ab 100644 --- a/examples/src/webgpu/helloTriangle/index.ts +++ b/examples/src/webgpu/helloTriangle/index.ts @@ -20,7 +20,7 @@ const init = async (canvas: HTMLCanvasElement) => clearValue: [0.0, 0.0, 0.0, 1.0], // 渲染前填充颜色 }], }, - renderObjects: [{ // 渲染对象 + renderPassObjects: [{ // 渲染对象 pipeline: { // 渲染管线 vertex: { // 顶点着色器 code: ` diff --git a/examples/src/webgpu/helloTriangleMSAA/index.ts b/examples/src/webgpu/helloTriangleMSAA/index.ts index ca6e5b9..0cfd854 100644 --- a/examples/src/webgpu/helloTriangleMSAA/index.ts +++ b/examples/src/webgpu/helloTriangleMSAA/index.ts @@ -33,7 +33,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPassDescriptor, renderObjects: [renderObject] }, + { descriptor: renderPassDescriptor, renderPassObjects: [renderObject] }, ] } ], diff --git a/examples/src/webgpu/imageBlur/index.ts b/examples/src/webgpu/imageBlur/index.ts index 002b71c..ddcd021 100644 --- a/examples/src/webgpu/imageBlur/index.ts +++ b/examples/src/webgpu/imageBlur/index.ts @@ -142,7 +142,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const gpuRenderPassEncoder: RenderPass = { descriptor: renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline: fullscreenQuadPipeline1, bindingResources: showResultBindGroup1, draw: { __type__: "DrawVertex", vertexCount: 6, instanceCount: 1, firstVertex: 0, firstInstance: 0 }, diff --git a/examples/src/webgpu/instancedCube/index.ts b/examples/src/webgpu/instancedCube/index.ts index 9b20d02..e0d97d4 100644 --- a/examples/src/webgpu/instancedCube/index.ts +++ b/examples/src/webgpu/instancedCube/index.ts @@ -125,7 +125,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPass, renderObjects: [renderObject] }, + { descriptor: renderPass, renderPassObjects: [renderObject] }, ] } ], diff --git a/examples/src/webgpu/multipleCanvases/index.ts b/examples/src/webgpu/multipleCanvases/index.ts index 744e47c..06872c3 100644 --- a/examples/src/webgpu/multipleCanvases/index.ts +++ b/examples/src/webgpu/multipleCanvases/index.ts @@ -317,7 +317,7 @@ const init = async () => // make a render pass encoder to encode render specific commands passEncoders.push({ descriptor: renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline: pipeline, bindingResources: bindGroup, vertices: vertexAttributes, diff --git a/examples/src/webgpu/normalMap/index.ts b/examples/src/webgpu/normalMap/index.ts index fcd5e17..dac020d 100644 --- a/examples/src/webgpu/normalMap/index.ts +++ b/examples/src/webgpu/normalMap/index.ts @@ -316,7 +316,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline: texturedCubePipeline, bindingResources: bindingResourcesList[currentSurfaceBindGroup], // * position : float32x3 diff --git a/examples/src/webgpu/occlusionQuery/index.ts b/examples/src/webgpu/occlusionQuery/index.ts index 87dbe34..bf2c3ff 100644 --- a/examples/src/webgpu/occlusionQuery/index.ts +++ b/examples/src/webgpu/occlusionQuery/index.ts @@ -158,7 +158,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => const renderPass: RenderPass = { descriptor: renderPassDescriptor, - renderObjects: occlusionQueryObjects, + renderPassObjects: occlusionQueryObjects, onOcclusionQuery(_occlusionQuerys, results) { const visible = objectInfos diff --git a/examples/src/webgpu/particles/index.ts b/examples/src/webgpu/particles/index.ts index 433379e..c80fcfc 100644 --- a/examples/src/webgpu/particles/index.ts +++ b/examples/src/webgpu/particles/index.ts @@ -288,7 +288,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }, { descriptor: renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline: renderPipeline, bindingResources: { ...uniformBindGroup }, vertices: { ...particlesVertices, ...quadVertices }, diff --git a/examples/src/webgpu/points/index.ts b/examples/src/webgpu/points/index.ts index 855a3a1..a667df9 100644 --- a/examples/src/webgpu/points/index.ts +++ b/examples/src/webgpu/points/index.ts @@ -173,7 +173,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders: [ { descriptor: renderPassDescriptor, - renderObjects: [ro] + renderPassObjects: [ro] } ] }] diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 079b3da..875f140 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -302,7 +302,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => const renderPass: RenderPass = { descriptor: renderPassDescriptor, - renderObjects: [], + renderPassObjects: [], }; const submit: Submit = { @@ -325,14 +325,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => { // Executing a bundle is equivalent to calling all of the commands encoded // in the render bundle as part of the current render pass. - reactive(renderPass).renderObjects = [renderBundle]; + reactive(renderPass).renderPassObjects = [renderBundle]; } else { // Alternatively, the same render commands can be encoded manually, which // can take longer since each command needs to be interpreted by the // JavaScript virtual machine and re-validated each time. - reactive(renderPass).renderObjects = renderBundle.renderObjects; + reactive(renderPass).renderPassObjects = renderBundle.renderObjects; } webgpu.submit(submit); diff --git a/examples/src/webgpu/resizeCanvas/index.ts b/examples/src/webgpu/resizeCanvas/index.ts index ef17f10..868398f 100644 --- a/examples/src/webgpu/resizeCanvas/index.ts +++ b/examples/src/webgpu/resizeCanvas/index.ts @@ -38,7 +38,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPassDescriptor, renderObjects: [renderObject] }, + { descriptor: renderPassDescriptor, renderPassObjects: [renderObject] }, ] } ], diff --git a/examples/src/webgpu/resizeObserverHDDPI/index.ts b/examples/src/webgpu/resizeObserverHDDPI/index.ts index 0dcced4..02ec7e3 100644 --- a/examples/src/webgpu/resizeObserverHDDPI/index.ts +++ b/examples/src/webgpu/resizeObserverHDDPI/index.ts @@ -97,7 +97,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline: pipeline, bindingResources: bindGroup, draw: { __type__: "DrawVertex", vertexCount: 3 }, diff --git a/examples/src/webgpu/reversedZ/index.ts b/examples/src/webgpu/reversedZ/index.ts index b86cda8..82e3085 100644 --- a/examples/src/webgpu/reversedZ/index.ts +++ b/examples/src/webgpu/reversedZ/index.ts @@ -372,7 +372,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => depthClearValue: depthClearValues[m], } }, - renderObjects: [ + renderPassObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: colorPassPipelines[m], @@ -394,7 +394,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => depthClearValue: depthClearValues[m], } }, - renderObjects: [ + renderPassObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], @@ -411,7 +411,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => depthClearValue: depthClearValues[m], } }, - renderObjects: [ + renderPassObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: precisionPassPipelines[m], @@ -433,7 +433,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => depthClearValue: depthClearValues[m], } }, - renderObjects: [ + renderPassObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: depthPrePassPipelines[m], @@ -444,7 +444,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => }); depthBufferPassEncoders.push({ descriptor: textureQuadPassDescriptors1[m], - renderObjects: [ + renderPassObjects: [ { viewport: { isYup: false, x: (canvas.width * m) / 2, y: 0, width: canvas.width / 2, height: canvas.height, minDepth: 0, maxDepth: 1 }, pipeline: textureQuadPassPipline, diff --git a/examples/src/webgpu/rotatingCube/index.ts b/examples/src/webgpu/rotatingCube/index.ts index 4a3ecaf..806c0bb 100644 --- a/examples/src/webgpu/rotatingCube/index.ts +++ b/examples/src/webgpu/rotatingCube/index.ts @@ -87,7 +87,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPass, renderObjects: [renderObject] }, + { descriptor: renderPass, renderPassObjects: [renderObject] }, ] } ], diff --git a/examples/src/webgpu/samplerParameters/index.ts b/examples/src/webgpu/samplerParameters/index.ts index 81bd8c7..65d4fec 100644 --- a/examples/src/webgpu/samplerParameters/index.ts +++ b/examples/src/webgpu/samplerParameters/index.ts @@ -340,7 +340,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => passEncoders: [ { descriptor: renderPass, - renderObjects, + renderPassObjects: renderObjects, } ] } diff --git a/examples/src/webgpu/shadowMapping/index.ts b/examples/src/webgpu/shadowMapping/index.ts index 74def59..9d2d93c 100644 --- a/examples/src/webgpu/shadowMapping/index.ts +++ b/examples/src/webgpu/shadowMapping/index.ts @@ -218,7 +218,7 @@ const init = async (canvas: HTMLCanvasElement) => passEncoders: [ { descriptor: shadowPassDescriptor, - renderObjects: [ + renderPassObjects: [ { pipeline: shadowPipeline, bindingResources: { @@ -233,7 +233,7 @@ const init = async (canvas: HTMLCanvasElement) => }, { descriptor: renderPassDescriptor, - renderObjects: [ + renderPassObjects: [ { pipeline: pipeline, bindingResources: { diff --git a/examples/src/webgpu/skinnedMesh/index.ts b/examples/src/webgpu/skinnedMesh/index.ts index f4aabc3..26b82be 100644 --- a/examples/src/webgpu/skinnedMesh/index.ts +++ b/examples/src/webgpu/skinnedMesh/index.ts @@ -440,7 +440,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => } const passEncoder: RenderPass = { descriptor: gltfRenderPassDescriptor, - renderObjects + renderPassObjects: renderObjects }; return passEncoder; })(); @@ -464,7 +464,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => // const passEncoder: RenderPass = { descriptor: gltfRenderPassDescriptor, - renderObjects: [renderObject], + renderPassObjects: [renderObject], }; return passEncoder; })(); diff --git a/examples/src/webgpu/textRenderingMsdf/index.ts b/examples/src/webgpu/textRenderingMsdf/index.ts index 6f1399e..3b4c3d2 100644 --- a/examples/src/webgpu/textRenderingMsdf/index.ts +++ b/examples/src/webgpu/textRenderingMsdf/index.ts @@ -270,7 +270,7 @@ setBlendConstant().`, commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, - renderObjects, + renderPassObjects: renderObjects, }] }] }; diff --git a/examples/src/webgpu/texturedCube/index.ts b/examples/src/webgpu/texturedCube/index.ts index 6741dcc..4f94202 100644 --- a/examples/src/webgpu/texturedCube/index.ts +++ b/examples/src/webgpu/texturedCube/index.ts @@ -108,7 +108,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPass, renderObjects: [renderObject] }, + { descriptor: renderPass, renderPassObjects: [renderObject] }, ] } ], diff --git a/examples/src/webgpu/timestampQuery/index.ts b/examples/src/webgpu/timestampQuery/index.ts index bd5d0a5..0d7da38 100644 --- a/examples/src/webgpu/timestampQuery/index.ts +++ b/examples/src/webgpu/timestampQuery/index.ts @@ -119,7 +119,7 @@ const init = async (canvas: HTMLCanvasElement) => { passEncoders: [ { - descriptor: renderPassDescriptor, renderObjects: [renderObject], + descriptor: renderPassDescriptor, renderPassObjects: [renderObject], }, ] } diff --git a/examples/src/webgpu/transparentCanvas/index.ts b/examples/src/webgpu/transparentCanvas/index.ts index 2740dac..ec18ec0 100644 --- a/examples/src/webgpu/transparentCanvas/index.ts +++ b/examples/src/webgpu/transparentCanvas/index.ts @@ -100,7 +100,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline: pipeline, bindingResources: uniformBindGroup, vertices: verticesBuffer, diff --git a/examples/src/webgpu/twoCubes/index.ts b/examples/src/webgpu/twoCubes/index.ts index 4d523c1..77ce7a6 100644 --- a/examples/src/webgpu/twoCubes/index.ts +++ b/examples/src/webgpu/twoCubes/index.ts @@ -123,7 +123,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPassDescriptor, renderObjects: [renderObject, renderObject1] }, + { descriptor: renderPassDescriptor, renderPassObjects: [renderObject, renderObject1] }, ] } ], diff --git a/examples/src/webgpu/videoUploading/index.ts b/examples/src/webgpu/videoUploading/index.ts index 743ad39..d8ca883 100644 --- a/examples/src/webgpu/videoUploading/index.ts +++ b/examples/src/webgpu/videoUploading/index.ts @@ -56,7 +56,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [ { passEncoders: [ - { descriptor: renderPass, renderObjects: [renderObject] }, + { descriptor: renderPass, renderPassObjects: [renderObject] }, ] } ], diff --git a/examples/src/webgpu/volumeRenderingTexture3D/index.ts b/examples/src/webgpu/volumeRenderingTexture3D/index.ts index ddbe76c..3b01da1 100644 --- a/examples/src/webgpu/volumeRenderingTexture3D/index.ts +++ b/examples/src/webgpu/volumeRenderingTexture3D/index.ts @@ -149,7 +149,7 @@ const init = async (canvas: HTMLCanvasElement) => commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline, bindingResources: uniformBindGroup, draw: { __type__: "DrawVertex", vertexCount: 3 }, diff --git a/examples/src/webgpu/wireframe/index.ts b/examples/src/webgpu/wireframe/index.ts index 93e100b..adf60a1 100644 --- a/examples/src/webgpu/wireframe/index.ts +++ b/examples/src/webgpu/wireframe/index.ts @@ -360,7 +360,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, - renderObjects, + renderPassObjects: renderObjects, }] }] }; diff --git a/examples/src/webgpu/worker/worker.ts b/examples/src/webgpu/worker/worker.ts index c0f17f7..e7209bb 100644 --- a/examples/src/webgpu/worker/worker.ts +++ b/examples/src/webgpu/worker/worker.ts @@ -153,7 +153,7 @@ async function init(canvas: OffscreenCanvas) commandEncoders: [{ passEncoders: [{ descriptor: renderPassDescriptor, - renderObjects: [{ + renderPassObjects: [{ pipeline, bindingResources: uniformBindGroup, vertices: verticesBuffer, diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 1e7cf93..07f038d 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -198,7 +198,7 @@ export class WebGPUBase protected runRenderPass(commandEncoder: GPUCommandEncoder, renderPass: RenderPass) { const device = this._device; - const { descriptor, renderObjects } = renderPass; + const { descriptor, renderPassObjects: renderObjects } = renderPass; const renderPassCommand = new RenderPassCommand(); @@ -214,7 +214,7 @@ export class WebGPUBase const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); passEncoder.device = device; - renderPassCommand.renderPassObjects = this.runRenderPassObjects(passEncoder, renderPassFormat, renderObjects, occlusionQuery); + renderPassCommand.renderPassObjects = this.runRenderPassObjects(passEncoder, renderPassFormat, renderObjects); passEncoder.end(); @@ -226,9 +226,10 @@ export class WebGPUBase return renderPassCommand; } - protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderPassObjects: readonly RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) + protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderPassObjects: readonly RenderPassObject[]) { if (!renderPassObjects) return; + let queryIndex = 0; // const commands: RenderPassObjectCommand[] = renderPassObjects.map((element) => { @@ -246,7 +247,9 @@ export class WebGPUBase } if (element.__type__ === "OcclusionQuery") { - return this.runRenderOcclusionQueryObject(renderPassFormat, element, occlusionQuery); + const occlusionQueryCache = this.runRenderOcclusionQueryObject(renderPassFormat, element); + occlusionQueryCache.queryIndex = queryIndex++; + return occlusionQueryCache; } else { @@ -259,6 +262,8 @@ export class WebGPUBase command.run(passEncoder); }); + + return commands; } @@ -334,10 +339,9 @@ export class WebGPUBase ); } - protected runRenderOcclusionQueryObject(renderPassFormat: RenderPassFormat, renderOcclusionQueryObject: OcclusionQuery, occlusionQuery: GPURenderOcclusionQuery) + protected runRenderOcclusionQueryObject(renderPassFormat: RenderPassFormat, renderOcclusionQueryObject: OcclusionQuery) { const occlusionQueryCache = new OcclusionQueryCache(); - occlusionQueryCache.queryIndex = occlusionQuery.getQueryIndex(renderOcclusionQueryObject); occlusionQueryCache.renderObjectCaches = renderOcclusionQueryObject.renderObjects.map((renderObject) => { -- Gitee From fc1de062355b6d86a90d8dad830bcc58cec72bd4 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 11:16:13 +0800 Subject: [PATCH 183/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E9=80=9A=E9=81=93=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 getGPURenderOcclusionQuery 中的冗余逻辑 - 将 GPURenderOcclusionQuery 设计为可复用的类 - 优化 renderPassObjects 的处理流程 - 调整 occlusionQuery 的初始化和解析逻辑 --- src/WebGPUBase.ts | 46 +++---------- src/caches/getGPURenderOcclusionQuery.ts | 86 +++++++++--------------- src/internal/RenderObjectCache.ts | 27 +++++++- 3 files changed, 67 insertions(+), 92 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 07f038d..44ad0c3 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -6,7 +6,6 @@ import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUComputePassDescriptor } from "./caches/getGPUComputePassDescriptor"; import { getGPUComputePipeline } from "./caches/getGPUComputePipeline"; import { getGPUPipelineLayout } from "./caches/getGPUPipelineLayout"; -import { getGPURenderOcclusionQuery, GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; import { getGPURenderPassDescriptor } from "./caches/getGPURenderPassDescriptor"; import { getGPURenderPassFormat } from "./caches/getGPURenderPassFormat"; import { getGPURenderPipeline } from "./caches/getGPURenderPipeline"; @@ -19,7 +18,7 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit, webgpuEvents } from "./eventnames"; -import { ComputeObjectCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand, RenderPassObjectCommand } from "./internal/RenderObjectCache"; +import { ComputeObjectCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand } from "./internal/RenderObjectCache"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; @@ -198,40 +197,17 @@ export class WebGPUBase protected runRenderPass(commandEncoder: GPUCommandEncoder, renderPass: RenderPass) { const device = this._device; - const { descriptor, renderPassObjects: renderObjects } = renderPass; + const { descriptor, renderPassObjects } = renderPass; const renderPassCommand = new RenderPassCommand(); const renderPassDescriptor = getGPURenderPassDescriptor(device, descriptor); const renderPassFormat = getGPURenderPassFormat(descriptor); - // 处理不被遮挡查询。 - const occlusionQuery = getGPURenderOcclusionQuery(renderObjects); - occlusionQuery.init(device, renderPassDescriptor); - + renderPassCommand.renderPass = renderPass; renderPassCommand.renderPassDescriptor = renderPassDescriptor; - - const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); - passEncoder.device = device; - - renderPassCommand.renderPassObjects = this.runRenderPassObjects(passEncoder, renderPassFormat, renderObjects); - - passEncoder.end(); - - // 处理不被遮挡查询。 - occlusionQuery.resolve(device, commandEncoder, renderPass); - - renderPassDescriptor.timestampWrites?.resolve(commandEncoder); - - return renderPassCommand; - } - - protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderPassObjects: readonly RenderPassObject[]) - { - if (!renderPassObjects) return; - let queryIndex = 0; - // - const commands: RenderPassObjectCommand[] = renderPassObjects.map((element) => + renderPassCommand.occlusionQuerys = []; + renderPassCommand.renderPassObjects = renderPassObjects?.map((element) => { if (!element.__type__) { @@ -248,7 +224,8 @@ export class WebGPUBase if (element.__type__ === "OcclusionQuery") { const occlusionQueryCache = this.runRenderOcclusionQueryObject(renderPassFormat, element); - occlusionQueryCache.queryIndex = queryIndex++; + occlusionQueryCache.queryIndex = renderPassCommand.occlusionQuerys.length; + renderPassCommand.occlusionQuerys.push(element); return occlusionQueryCache; } else @@ -257,14 +234,9 @@ export class WebGPUBase } }); - commands.forEach((command) => - { - command.run(passEncoder); - }); - + renderPassCommand.run(commandEncoder); - - return commands; + return renderPassCommand; } /** diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index efb8f05..a9c0ac6 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -1,43 +1,45 @@ import { anyEmitter } from "@feng3d/event"; -import { RenderPassObject, OcclusionQuery, RenderPass } from "@feng3d/render-api"; +import { OcclusionQuery } from "@feng3d/render-api"; import { GPUQueue_submit } from "../eventnames"; -export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassObject[]): GPURenderOcclusionQuery +export class GPURenderOcclusionQuery { - if (!renderObjects) return defautRenderOcclusionQuery; - let renderOcclusionQuery: GPURenderOcclusionQuery = renderObjects["_GPURenderOcclusionQuery"]; - if (renderOcclusionQuery) return renderOcclusionQuery; + occlusionQuerySet: GPUQuerySet; + occlusionQuerys: OcclusionQuery[]; + device: GPUDevice; - const occlusionQuerys: OcclusionQuery[] = renderObjects.filter((cv) => cv.__type__ === "OcclusionQuery") as any; - if (occlusionQuerys.length === 0) + get resolveBuf() { - renderObjects["_GPURenderOcclusionQuery"] = defautRenderOcclusionQuery; - - return defautRenderOcclusionQuery; + const { device, occlusionQuerys } = this; + this._resolveBuf ??= device.createBuffer({ + label: "resolveBuffer", + // Query results are 64bit unsigned integers. + size: occlusionQuerys.length * BigUint64Array.BYTES_PER_ELEMENT, + usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC, + }); + return this._resolveBuf; } + private _resolveBuf: GPUBuffer; - let occlusionQuerySet: GPUQuerySet; - let resolveBuf: GPUBuffer; - let resultBuf: GPUBuffer; - - /** - * 初始化。 - * - * 在渲染通道描述上设置 occlusionQuerySet 。 - * - * @param device - * @param renderPassDescriptor - */ - const init = (device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor) => + get resultBuf() { - occlusionQuerySet = renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: occlusionQuerys.length }); - }; + const { device, resolveBuf } = this; + this._resultBuf ??= device.createBuffer({ + label: "resultBuffer", + size: resolveBuf.size, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, + }); + return this._resultBuf; + } + private _resultBuf: GPUBuffer; - const getQueryIndex = (occlusionQuery: OcclusionQuery) => + init(device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor, _occlusionQuerys: OcclusionQuery[]) { - return occlusionQuerys.indexOf(occlusionQuery); - }; + this.device = device; + this.occlusionQuerys = _occlusionQuerys; + this.occlusionQuerySet = renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: this.occlusionQuerys.length }); + } /** * 查询结果。 @@ -46,23 +48,12 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb * @param commandEncoder * @param renderPass */ - const resolve = (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass) => + resolve(commandEncoder: GPUCommandEncoder, renderPass) { - resolveBuf = resolveBuf || device.createBuffer({ - label: "resolveBuffer", - // Query results are 64bit unsigned integers. - size: occlusionQuerys.length * BigUint64Array.BYTES_PER_ELEMENT, - usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC, - }); + const { device, occlusionQuerys, occlusionQuerySet, resolveBuf, resultBuf } = this; commandEncoder.resolveQuerySet(occlusionQuerySet, 0, occlusionQuerys.length, resolveBuf, 0); - resultBuf = resultBuf || device.createBuffer({ - label: "resultBuffer", - size: resolveBuf.size, - usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, - }); - if (resultBuf.mapState === "unmapped") { commandEncoder.copyBufferToBuffer(resolveBuf, 0, resultBuf, 0, resultBuf.size); @@ -99,17 +90,4 @@ export function getGPURenderOcclusionQuery(renderObjects?: readonly RenderPassOb // 监听提交WebGPU事件 anyEmitter.on(device.queue, GPUQueue_submit, getOcclusionQueryResult); }; - - renderObjects["_GPURenderOcclusionQuery"] = renderOcclusionQuery = { init, resolve, getQueryIndex }; - - return renderOcclusionQuery; } - -export interface GPURenderOcclusionQuery -{ - init: (device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor) => void - getQueryIndex: (occlusionQuery: OcclusionQuery) => number; - resolve: (device: GPUDevice, commandEncoder: GPUCommandEncoder, renderPass: RenderPass) => void -} - -const defautRenderOcclusionQuery = { init: () => { }, getQueryIndex: () => 0, resolve: () => { } }; \ No newline at end of file diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 680d965..55fd3c0 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -1,4 +1,5 @@ -import { ChainMap } from "@feng3d/render-api"; +import { ChainMap, OcclusionQuery, RenderPass } from "@feng3d/render-api"; +import { GPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; const cache = new ChainMap(); @@ -306,8 +307,32 @@ export class RenderBundleCommand implements RenderPassObjectCommand export class RenderPassCommand { + run(commandEncoder: GPUCommandEncoder) + { + const { renderPassDescriptor, renderPassObjects, occlusionQuerys, renderPass } = this; + const { device } = commandEncoder; + + // 处理不被遮挡查询。 + const occlusionQuery = new GPURenderOcclusionQuery(); + occlusionQuery.init(device, renderPassDescriptor, occlusionQuerys); + + const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); + passEncoder.device = device; + renderPassObjects.forEach((command) => + { + command.run(passEncoder); + }); + passEncoder.end(); + + // 处理不被遮挡查询。 + occlusionQuery.resolve(commandEncoder, renderPass); + + renderPassDescriptor.timestampWrites?.resolve(commandEncoder); + } + renderPass: RenderPass; renderPassDescriptor: GPURenderPassDescriptor; renderPassObjects: RenderPassObjectCommand[]; + occlusionQuerys: OcclusionQuery[]; } export class ComputeObjectCommand -- Gitee From c34d4d8289b78bf68bc24adc34fa6e957b950b26 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 12:13:29 +0800 Subject: [PATCH 184/214] =?UTF-8?q?feat(WebGPU):=20=E6=B7=BB=E5=8A=A0=20oc?= =?UTF-8?q?clusionQuery=20=E5=B1=9E=E6=80=A7=E5=88=B0=20RenderPassCommand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 RenderPassCommand 类中添加了 occlusionQuery 属性,用于处理遮挡查询 - 在 WebGPUBase 类中为 renderPassCommand 添加了 occlusionQuery 属性初始化 - 这些更改将支持在渲染过程中使用遮挡查询功能 --- src/WebGPUBase.ts | 2 ++ src/internal/RenderObjectCache.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 44ad0c3..155132b 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -24,6 +24,7 @@ import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; +import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; declare global { @@ -204,6 +205,7 @@ export class WebGPUBase const renderPassDescriptor = getGPURenderPassDescriptor(device, descriptor); const renderPassFormat = getGPURenderPassFormat(descriptor); + renderPassCommand.occlusionQuery = new GPURenderOcclusionQuery(); renderPassCommand.renderPass = renderPass; renderPassCommand.renderPassDescriptor = renderPassDescriptor; renderPassCommand.occlusionQuerys = []; diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 55fd3c0..110e81f 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -333,6 +333,7 @@ export class RenderPassCommand renderPassDescriptor: GPURenderPassDescriptor; renderPassObjects: RenderPassObjectCommand[]; occlusionQuerys: OcclusionQuery[]; + occlusionQuery: GPURenderOcclusionQuery; } export class ComputeObjectCommand -- Gitee From c85f0cfe98732352789593b51ec27883a836e275 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 15:06:04 +0800 Subject: [PATCH 185/214] =?UTF-8?q?refactor(WebGPUBase):=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20GPURenderOcclusionQuery=20=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 GPURenderOcclusionQuery 的导入从文件末尾移动到相关导入部分 - 优化了代码结构,使同类的导入更加集中 --- src/WebGPUBase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 155132b..1b0a628 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -6,6 +6,7 @@ import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUComputePassDescriptor } from "./caches/getGPUComputePassDescriptor"; import { getGPUComputePipeline } from "./caches/getGPUComputePipeline"; import { getGPUPipelineLayout } from "./caches/getGPUPipelineLayout"; +import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; import { getGPURenderPassDescriptor } from "./caches/getGPURenderPassDescriptor"; import { getGPURenderPassFormat } from "./caches/getGPURenderPassFormat"; import { getGPURenderPipeline } from "./caches/getGPURenderPipeline"; @@ -24,7 +25,6 @@ import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; import { readPixels } from "./utils/readPixels"; import { textureInvertYPremultiplyAlpha } from "./utils/textureInvertYPremultiplyAlpha"; -import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; declare global { -- Gitee From f78ee6eec4eebc2087079ea6f8d547622b720a57 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 15:16:09 +0800 Subject: [PATCH 186/214] =?UTF-8?q?perf(occlusionQuery):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20occlusion=20query=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 GPURenderOcclusionQuery 类中添加空数组判断,避免不必要的操作 - 更新 bitonicSort 示例中的 computePassEncoder 配置 --- examples/src/webgpu/bitonicSort/index.ts | 6 +++--- src/caches/getGPURenderOcclusionQuery.ts | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/src/webgpu/bitonicSort/index.ts b/examples/src/webgpu/bitonicSort/index.ts index cc18df9..8acafea 100644 --- a/examples/src/webgpu/bitonicSort/index.ts +++ b/examples/src/webgpu/bitonicSort/index.ts @@ -736,9 +736,9 @@ async function init( { const computePassEncoder: ComputePass = { __type__: "ComputePass", - // descriptor: { - // timestampQuery: querySet, - // }, + descriptor: { + timestampQuery: querySet, + }, computeObjects: [{ pipeline: computePipeline, bindingResources: computeBGCluster, diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index a9c0ac6..08c3124 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { OcclusionQuery } from "@feng3d/render-api"; +import { OcclusionQuery, RenderPass } from "@feng3d/render-api"; import { GPUQueue_submit } from "../eventnames"; @@ -36,8 +36,9 @@ export class GPURenderOcclusionQuery init(device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor, _occlusionQuerys: OcclusionQuery[]) { - this.device = device; this.occlusionQuerys = _occlusionQuerys; + if (this.occlusionQuerys.length === 0) return; + this.device = device; this.occlusionQuerySet = renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: this.occlusionQuerys.length }); } @@ -48,8 +49,10 @@ export class GPURenderOcclusionQuery * @param commandEncoder * @param renderPass */ - resolve(commandEncoder: GPUCommandEncoder, renderPass) + resolve(commandEncoder: GPUCommandEncoder, renderPass: RenderPass) { + if (this.occlusionQuerys.length === 0) return; + const { device, occlusionQuerys, occlusionQuerySet, resolveBuf, resultBuf } = this; commandEncoder.resolveQuerySet(occlusionQuerySet, 0, occlusionQuerys.length, resolveBuf, 0); -- Gitee From 46c6c1017e9b37939cd7c42dff84cb58880ab920 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 15:55:04 +0800 Subject: [PATCH 187/214] =?UTF-8?q?refactor(caches):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=88=B3=E6=9F=A5=E8=AF=A2=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 getGPURenderTimestampQuery 重命名为 getGPUPassTimestampWrites - 优化了 GPURenderOcclusionQuery 类的实现 - 更新了相关文件中的导入和调用 --- src/caches/getGPUComputePassDescriptor.ts | 4 +- ...pQuery.ts => getGPUPassTimestampWrites.ts} | 14 +++-- src/caches/getGPURenderOcclusionQuery.ts | 56 +++++++++++-------- src/caches/getGPURenderPassDescriptor.ts | 4 +- 4 files changed, 47 insertions(+), 31 deletions(-) rename src/caches/{getGPURenderTimestampQuery.ts => getGPUPassTimestampWrites.ts} (85%) diff --git a/src/caches/getGPUComputePassDescriptor.ts b/src/caches/getGPUComputePassDescriptor.ts index 5d95fb3..82cffb1 100644 --- a/src/caches/getGPUComputePassDescriptor.ts +++ b/src/caches/getGPUComputePassDescriptor.ts @@ -1,5 +1,5 @@ import { ComputePass } from "../data/ComputePass"; -import { getGPURenderTimestampQuery } from "./getGPURenderTimestampQuery"; +import { getGPUPassTimestampWrites } from "./getGPUPassTimestampWrites"; export function getGPUComputePassDescriptor(commandEncoder: GPUCommandEncoder, computePass: ComputePass) { @@ -9,7 +9,7 @@ export function getGPUComputePassDescriptor(commandEncoder: GPUCommandEncoder, c if (computePass.descriptor?.timestampQuery) { - descriptor.timestampWrites = getGPURenderTimestampQuery(device, computePass.descriptor.timestampQuery); + descriptor.timestampWrites = getGPUPassTimestampWrites(device, computePass.descriptor.timestampQuery); } return descriptor; diff --git a/src/caches/getGPURenderTimestampQuery.ts b/src/caches/getGPUPassTimestampWrites.ts similarity index 85% rename from src/caches/getGPURenderTimestampQuery.ts rename to src/caches/getGPUPassTimestampWrites.ts index 074e4cd..1cac786 100644 --- a/src/caches/getGPURenderTimestampQuery.ts +++ b/src/caches/getGPUPassTimestampWrites.ts @@ -1,6 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { RenderPass } from "@feng3d/render-api"; -import { ComputePass } from "../data/ComputePass"; +import { ChainMap } from "@feng3d/render-api"; import { TimestampQuery } from "../data/TimestampQuery"; import { GPUQueue_submit } from "../eventnames"; @@ -16,10 +15,12 @@ declare global } } -export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: TimestampQuery) +export function getGPUPassTimestampWrites(device: GPUDevice, timestampQuery?: TimestampQuery) { if (!timestampQuery) return; - let timestampWrites: GPURenderPassTimestampWrites | GPUComputePassTimestampWrites = timestampQuery["_GPURenderTimestampQuery"]; + + const getGPUPassTimestampWritesKey: GetGPUPassTimestampWritesKey = [device, timestampQuery]; + let timestampWrites = getGPUPassTimestampWritesMap.get(getGPUPassTimestampWritesKey); if (timestampWrites) return timestampWrites; // 判断是否支持 `timestamp-query` @@ -116,7 +117,10 @@ export function getGPURenderTimestampQuery(device: GPUDevice, timestampQuery?: T anyEmitter.on(device.queue, GPUQueue_submit, getQueryResult); }; - timestampQuery["_GPURenderTimestampQuery"] = timestampWrites; + getGPUPassTimestampWritesMap.set(getGPUPassTimestampWritesKey, timestampWrites); return timestampWrites; } + +type GetGPUPassTimestampWritesKey = [GPUDevice, TimestampQuery]; +const getGPUPassTimestampWritesMap = new ChainMap(); \ No newline at end of file diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts index 08c3124..cd49289 100644 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ b/src/caches/getGPURenderOcclusionQuery.ts @@ -9,37 +9,49 @@ export class GPURenderOcclusionQuery occlusionQuerys: OcclusionQuery[]; device: GPUDevice; - get resolveBuf() + resolveBuf: GPUBuffer; + + resultBuf: GPUBuffer; + + querylength: number; + + init(device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor, _occlusionQuerys: OcclusionQuery[]) { - const { device, occlusionQuerys } = this; - this._resolveBuf ??= device.createBuffer({ + this.occlusionQuerys = _occlusionQuerys; + if (this.occlusionQuerys.length === 0) + { + renderPassDescriptor.occlusionQuerySet = undefined; + return; + } + this.device = device; + // + const querylength = this.occlusionQuerys.length; + if (this.querylength !== querylength) + { + // + this.occlusionQuerySet?.destroy(); + this.resolveBuf?.destroy(); + this.resultBuf?.destroy(); + this.occlusionQuerySet = null; + this.resolveBuf = null; + this.resultBuf = null; + // + this.querylength = querylength; + } + + this.occlusionQuerySet = renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: querylength }); + this.resolveBuf = device.createBuffer({ label: "resolveBuffer", // Query results are 64bit unsigned integers. - size: occlusionQuerys.length * BigUint64Array.BYTES_PER_ELEMENT, + size: querylength * BigUint64Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC, }); - return this._resolveBuf; - } - private _resolveBuf: GPUBuffer; - - get resultBuf() - { - const { device, resolveBuf } = this; - this._resultBuf ??= device.createBuffer({ + this.resultBuf = device.createBuffer({ label: "resultBuffer", - size: resolveBuf.size, + size: this.resolveBuf.size, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, }); - return this._resultBuf; - } - private _resultBuf: GPUBuffer; - init(device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor, _occlusionQuerys: OcclusionQuery[]) - { - this.occlusionQuerys = _occlusionQuerys; - if (this.occlusionQuerys.length === 0) return; - this.device = device; - this.occlusionQuerySet = renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: this.occlusionQuerys.length }); } /** diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 644db90..af21d2f 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,6 +1,6 @@ import { CanvasTexture, ChainMap, computed, ComputedRef, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; import { MultisampleTexture } from "../internal/MultisampleTexture"; -import { getGPURenderTimestampQuery } from "./getGPURenderTimestampQuery"; +import { getGPUPassTimestampWrites } from "./getGPUPassTimestampWrites"; import { getGPUTextureFormat } from "./getGPUTextureFormat"; import { getGPUTextureView } from "./getGPUTextureView"; import { getTextureSize } from "./getTextureSize"; @@ -37,7 +37,7 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render renderPassDescriptor.depthStencilAttachment = getGPURenderPassDepthStencilAttachment(device, descriptor); // 处理时间戳查询 - renderPassDescriptor.timestampWrites = getGPURenderTimestampQuery(device, descriptor.timestampQuery); + renderPassDescriptor.timestampWrites = getGPUPassTimestampWrites(device, descriptor.timestampQuery); return renderPassDescriptor; }); -- Gitee From bddbb15fc152e8b02edb3395e7eec4f2b4b48192 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 16:32:21 +0800 Subject: [PATCH 188/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20occlusion=20query=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 GPURenderOcclusionQuery --- src/WebGPUBase.ts | 10 +- src/caches/getGPUComputePassDescriptor.ts | 2 +- src/caches/getGPURenderOcclusionQuery.ts | 108 ---------------------- src/caches/getGPURenderPassDescriptor.ts | 77 ++++++++++++++- src/internal/RenderObjectCache.ts | 16 +--- 5 files changed, 82 insertions(+), 131 deletions(-) delete mode 100644 src/caches/getGPURenderOcclusionQuery.ts diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 1b0a628..87d32ab 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -6,7 +6,6 @@ import { getGPUBuffer } from "./caches/getGPUBuffer"; import { getGPUComputePassDescriptor } from "./caches/getGPUComputePassDescriptor"; import { getGPUComputePipeline } from "./caches/getGPUComputePipeline"; import { getGPUPipelineLayout } from "./caches/getGPUPipelineLayout"; -import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; import { getGPURenderPassDescriptor } from "./caches/getGPURenderPassDescriptor"; import { getGPURenderPassFormat } from "./caches/getGPURenderPassFormat"; import { getGPURenderPipeline } from "./caches/getGPURenderPipeline"; @@ -202,13 +201,11 @@ export class WebGPUBase const renderPassCommand = new RenderPassCommand(); - const renderPassDescriptor = getGPURenderPassDescriptor(device, descriptor); + const renderPassDescriptor = getGPURenderPassDescriptor(device, renderPass); const renderPassFormat = getGPURenderPassFormat(descriptor); - renderPassCommand.occlusionQuery = new GPURenderOcclusionQuery(); - renderPassCommand.renderPass = renderPass; renderPassCommand.renderPassDescriptor = renderPassDescriptor; - renderPassCommand.occlusionQuerys = []; + let queryIndex = 0; renderPassCommand.renderPassObjects = renderPassObjects?.map((element) => { if (!element.__type__) @@ -226,8 +223,7 @@ export class WebGPUBase if (element.__type__ === "OcclusionQuery") { const occlusionQueryCache = this.runRenderOcclusionQueryObject(renderPassFormat, element); - occlusionQueryCache.queryIndex = renderPassCommand.occlusionQuerys.length; - renderPassCommand.occlusionQuerys.push(element); + occlusionQueryCache.queryIndex = queryIndex++; return occlusionQueryCache; } else diff --git a/src/caches/getGPUComputePassDescriptor.ts b/src/caches/getGPUComputePassDescriptor.ts index 82cffb1..d880511 100644 --- a/src/caches/getGPUComputePassDescriptor.ts +++ b/src/caches/getGPUComputePassDescriptor.ts @@ -13,4 +13,4 @@ export function getGPUComputePassDescriptor(commandEncoder: GPUCommandEncoder, c } return descriptor; -} \ No newline at end of file +} diff --git a/src/caches/getGPURenderOcclusionQuery.ts b/src/caches/getGPURenderOcclusionQuery.ts deleted file mode 100644 index cd49289..0000000 --- a/src/caches/getGPURenderOcclusionQuery.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { anyEmitter } from "@feng3d/event"; -import { OcclusionQuery, RenderPass } from "@feng3d/render-api"; - -import { GPUQueue_submit } from "../eventnames"; - -export class GPURenderOcclusionQuery -{ - occlusionQuerySet: GPUQuerySet; - occlusionQuerys: OcclusionQuery[]; - device: GPUDevice; - - resolveBuf: GPUBuffer; - - resultBuf: GPUBuffer; - - querylength: number; - - init(device: GPUDevice, renderPassDescriptor: GPURenderPassDescriptor, _occlusionQuerys: OcclusionQuery[]) - { - this.occlusionQuerys = _occlusionQuerys; - if (this.occlusionQuerys.length === 0) - { - renderPassDescriptor.occlusionQuerySet = undefined; - return; - } - this.device = device; - // - const querylength = this.occlusionQuerys.length; - if (this.querylength !== querylength) - { - // - this.occlusionQuerySet?.destroy(); - this.resolveBuf?.destroy(); - this.resultBuf?.destroy(); - this.occlusionQuerySet = null; - this.resolveBuf = null; - this.resultBuf = null; - // - this.querylength = querylength; - } - - this.occlusionQuerySet = renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: querylength }); - this.resolveBuf = device.createBuffer({ - label: "resolveBuffer", - // Query results are 64bit unsigned integers. - size: querylength * BigUint64Array.BYTES_PER_ELEMENT, - usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC, - }); - this.resultBuf = device.createBuffer({ - label: "resultBuffer", - size: this.resolveBuf.size, - usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, - }); - - } - - /** - * 查询结果。 - * - * @param device - * @param commandEncoder - * @param renderPass - */ - resolve(commandEncoder: GPUCommandEncoder, renderPass: RenderPass) - { - if (this.occlusionQuerys.length === 0) return; - - const { device, occlusionQuerys, occlusionQuerySet, resolveBuf, resultBuf } = this; - - commandEncoder.resolveQuerySet(occlusionQuerySet, 0, occlusionQuerys.length, resolveBuf, 0); - - if (resultBuf.mapState === "unmapped") - { - commandEncoder.copyBufferToBuffer(resolveBuf, 0, resultBuf, 0, resultBuf.size); - } - - const getOcclusionQueryResult = () => - { - if (resultBuf.mapState === "unmapped") - { - resultBuf.mapAsync(GPUMapMode.READ).then(() => - { - const bigUint64Array = new BigUint64Array(resultBuf.getMappedRange()); - - const results = bigUint64Array.reduce((pv: number[], cv) => - { - pv.push(Number(cv)); - return pv; - }, []); - resultBuf.unmap(); - - occlusionQuerys.forEach((v, i) => - { - v.onQuery?.(results[i]); - }); - - renderPass.onOcclusionQuery?.(occlusionQuerys, results); - - // - anyEmitter.off(device.queue, GPUQueue_submit, getOcclusionQueryResult); - }); - } - }; - - // 监听提交WebGPU事件 - anyEmitter.on(device.queue, GPUQueue_submit, getOcclusionQueryResult); - }; -} diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index af21d2f..bd1e27c 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,10 +1,20 @@ -import { CanvasTexture, ChainMap, computed, ComputedRef, reactive, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; +import { anyEmitter } from "@feng3d/event"; +import { CanvasTexture, ChainMap, computed, ComputedRef, OcclusionQuery, reactive, RenderPass, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; +import { GPUQueue_submit } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { getGPUPassTimestampWrites } from "./getGPUPassTimestampWrites"; import { getGPUTextureFormat } from "./getGPUTextureFormat"; import { getGPUTextureView } from "./getGPUTextureView"; import { getTextureSize } from "./getTextureSize"; +declare global +{ + interface GPUQuerySet + { + resolve(commandEncoder: GPUCommandEncoder): void; + } +} + /** * 获取GPU渲染通道描述。 * @@ -12,8 +22,9 @@ import { getTextureSize } from "./getTextureSize"; * @param descriptor 渲染通道描述。 * @returns GPU渲染通道描述。 */ -export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: RenderPassDescriptor): GPURenderPassDescriptor +export function getGPURenderPassDescriptor(device: GPUDevice, renderPass: RenderPass): GPURenderPassDescriptor { + const descriptor: RenderPassDescriptor = renderPass.descriptor; // 缓存 const getGPURenderPassDescriptorKey: GetGPURenderPassDescriptorKey = [device, descriptor]; let result = getGPURenderPassDescriptorMap.get(getGPURenderPassDescriptorKey); @@ -39,6 +50,8 @@ export function getGPURenderPassDescriptor(device: GPUDevice, descriptor: Render // 处理时间戳查询 renderPassDescriptor.timestampWrites = getGPUPassTimestampWrites(device, descriptor.timestampQuery); + setOcclusionQuerySet(device, renderPass, renderPassDescriptor); + return renderPassDescriptor; }); getGPURenderPassDescriptorMap.set(getGPURenderPassDescriptorKey, result); @@ -315,3 +328,63 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac type GetGPURenderPassColorAttachmentKey = [device: GPUDevice, renderPassColorAttachment: RenderPassColorAttachment, descriptor: RenderPassDescriptor]; const getGPURenderPassColorAttachmentMap = new ChainMap>; +function setOcclusionQuerySet(device: GPUDevice, renderPass: RenderPass, renderPassDescriptor: GPURenderPassDescriptor) +{ + const occlusionQuerys = renderPass.renderPassObjects.filter((v) => v.__type__ === "OcclusionQuery") as OcclusionQuery[]; + renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: occlusionQuerys.length }); + const resolveBuf = device.createBuffer({ + label: "resolveBuffer", + // Query results are 64bit unsigned integers. + size: occlusionQuerys.length * BigUint64Array.BYTES_PER_ELEMENT, + usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC, + }); + const resultBuf = device.createBuffer({ + label: "resultBuffer", + size: resolveBuf.size, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, + }); + + // + renderPassDescriptor.occlusionQuerySet.resolve = (commandEncoder: GPUCommandEncoder) => + { + if (occlusionQuerys.length === 0) return; + + commandEncoder.resolveQuerySet(renderPassDescriptor.occlusionQuerySet, 0, occlusionQuerys.length, resolveBuf, 0); + + if (resultBuf.mapState === "unmapped") + { + commandEncoder.copyBufferToBuffer(resolveBuf, 0, resultBuf, 0, resultBuf.size); + } + + const getOcclusionQueryResult = () => + { + if (resultBuf.mapState === "unmapped") + { + resultBuf.mapAsync(GPUMapMode.READ).then(() => + { + const bigUint64Array = new BigUint64Array(resultBuf.getMappedRange()); + + const results = bigUint64Array.reduce((pv: number[], cv) => + { + pv.push(Number(cv)); + return pv; + }, []); + resultBuf.unmap(); + + occlusionQuerys.forEach((v, i) => + { + v.onQuery?.(results[i]); + }); + + renderPass.onOcclusionQuery?.(occlusionQuerys, results); + + // + anyEmitter.off(device.queue, GPUQueue_submit, getOcclusionQueryResult); + }); + } + }; + + // 监听提交WebGPU事件 + anyEmitter.on(device.queue, GPUQueue_submit, getOcclusionQueryResult); + }; +} diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 110e81f..9a51018 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -1,5 +1,4 @@ -import { ChainMap, OcclusionQuery, RenderPass } from "@feng3d/render-api"; -import { GPURenderOcclusionQuery } from "../caches/getGPURenderOcclusionQuery"; +import { ChainMap } from "@feng3d/render-api"; const cache = new ChainMap(); @@ -309,13 +308,9 @@ export class RenderPassCommand { run(commandEncoder: GPUCommandEncoder) { - const { renderPassDescriptor, renderPassObjects, occlusionQuerys, renderPass } = this; + const { renderPassDescriptor, renderPassObjects } = this; const { device } = commandEncoder; - // 处理不被遮挡查询。 - const occlusionQuery = new GPURenderOcclusionQuery(); - occlusionQuery.init(device, renderPassDescriptor, occlusionQuerys); - const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); passEncoder.device = device; renderPassObjects.forEach((command) => @@ -324,16 +319,11 @@ export class RenderPassCommand }); passEncoder.end(); - // 处理不被遮挡查询。 - occlusionQuery.resolve(commandEncoder, renderPass); - renderPassDescriptor.timestampWrites?.resolve(commandEncoder); + renderPassDescriptor.occlusionQuerySet?.resolve(commandEncoder); } - renderPass: RenderPass; renderPassDescriptor: GPURenderPassDescriptor; renderPassObjects: RenderPassObjectCommand[]; - occlusionQuerys: OcclusionQuery[]; - occlusionQuery: GPURenderOcclusionQuery; } export class ComputeObjectCommand -- Gitee From 240d63a4c582b5a633c0bbe5f8fb75620b61dc1c Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 16:33:41 +0800 Subject: [PATCH 189/214] =?UTF-8?q?refactor(WebGPUBase):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20renderPass=20=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整变量声明顺序,提高代码可读性 - 移除冗余的 renderPassDescriptor 变量赋值 - 提取 getGPURenderPassFormat 调用位置,减少代码重复 --- src/WebGPUBase.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 87d32ab..f8f0067 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -200,12 +200,10 @@ export class WebGPUBase const { descriptor, renderPassObjects } = renderPass; const renderPassCommand = new RenderPassCommand(); + renderPassCommand.renderPassDescriptor = getGPURenderPassDescriptor(device, renderPass); - const renderPassDescriptor = getGPURenderPassDescriptor(device, renderPass); - const renderPassFormat = getGPURenderPassFormat(descriptor); - - renderPassCommand.renderPassDescriptor = renderPassDescriptor; let queryIndex = 0; + const renderPassFormat = getGPURenderPassFormat(descriptor); renderPassCommand.renderPassObjects = renderPassObjects?.map((element) => { if (!element.__type__) -- Gitee From dec0d41655a25d0c8694ecab25c8a1a9674141fd Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 16:36:25 +0800 Subject: [PATCH 190/214] =?UTF-8?q?refactor(WebGPUBase):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=B8=B2=E6=9F=93=E5=91=BD=E4=BB=A4=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 runRenderPass 方法签名,移除不必要的 commandEncoder 参数 - 将 renderPassCommand 的执行移至 runRenderPass 方法外部 - 统一处理不同类型 passEncoder 的逻辑 --- src/WebGPUBase.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index f8f0067..bd4399a 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -167,11 +167,13 @@ export class WebGPUBase { if (!passEncoder.__type__) { - this.runRenderPass(gpuCommandEncoder, passEncoder as RenderPass); + const renderPassCommand = this.runRenderPass(passEncoder as RenderPass); + renderPassCommand.run(gpuCommandEncoder); } else if (passEncoder.__type__ === "RenderPass") { - this.runRenderPass(gpuCommandEncoder, passEncoder); + const renderPassCommand = this.runRenderPass(passEncoder); + renderPassCommand.run(gpuCommandEncoder); } else if (passEncoder.__type__ === "ComputePass") { @@ -194,7 +196,7 @@ export class WebGPUBase return gpuCommandEncoder.finish(); } - protected runRenderPass(commandEncoder: GPUCommandEncoder, renderPass: RenderPass) + protected runRenderPass(renderPass: RenderPass) { const device = this._device; const { descriptor, renderPassObjects } = renderPass; @@ -230,8 +232,6 @@ export class WebGPUBase } }); - renderPassCommand.run(commandEncoder); - return renderPassCommand; } -- Gitee From bf59601d757aba58bb252549b3118a3592fc98af Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 22 Mar 2025 17:00:25 +0800 Subject: [PATCH 191/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E7=BC=96=E7=A0=81=E5=99=A8=E7=9A=84=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将各种命令编码器操作抽象为 PassEncoderCommand 接口 - 新增 ComputePassCommand、CopyTextureToTextureCommand 和 CopyBufferToBufferCommand 类 - 修改 WebGPUBase 类,使用新的命令编码器结构 - 优化了命令编码器的执行流程,提高了代码的可读性和可维护性 --- src/WebGPUBase.ts | 73 ++++++++++------------- src/caches/getGPUComputePassDescriptor.ts | 4 +- src/internal/RenderObjectCache.ts | 55 +++++++++++++++++ 3 files changed, 87 insertions(+), 45 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index bd4399a..abcef59 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -18,7 +18,7 @@ import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; import { GPUQueue_submit, webgpuEvents } from "./eventnames"; -import { ComputeObjectCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand } from "./internal/RenderObjectCache"; +import { ComputeObjectCommand, ComputePassCommand, CopyBufferToBufferCommand, CopyTextureToTextureCommand, OcclusionQueryCache, PassEncoderCommand, RenderBundleCommand, RenderObjectCache, RenderPassCommand } from "./internal/RenderObjectCache"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; @@ -163,29 +163,27 @@ export class WebGPUBase const gpuCommandEncoder = device.createCommandEncoder(); gpuCommandEncoder.device = device; - commandEncoder.passEncoders.forEach((passEncoder) => + const passEncoders: PassEncoderCommand[] = commandEncoder.passEncoders.map((passEncoder) => { if (!passEncoder.__type__) { - const renderPassCommand = this.runRenderPass(passEncoder as RenderPass); - renderPassCommand.run(gpuCommandEncoder); + return this.runRenderPass(passEncoder as RenderPass); } else if (passEncoder.__type__ === "RenderPass") { - const renderPassCommand = this.runRenderPass(passEncoder); - renderPassCommand.run(gpuCommandEncoder); + return this.runRenderPass(passEncoder); } else if (passEncoder.__type__ === "ComputePass") { - this.runComputePass(gpuCommandEncoder, passEncoder); + return this.runComputePass(passEncoder); } else if (passEncoder.__type__ === "CopyTextureToTexture") { - this.runCopyTextureToTexture(gpuCommandEncoder, passEncoder); + return this.runCopyTextureToTexture(passEncoder); } else if (passEncoder.__type__ === "CopyBufferToBuffer") { - this.runCopyBufferToBuffer(gpuCommandEncoder, passEncoder); + return this.runCopyBufferToBuffer(passEncoder); } else { @@ -193,6 +191,8 @@ export class WebGPUBase } }); + passEncoders.forEach((passEncoder) => passEncoder.run(gpuCommandEncoder)); + return gpuCommandEncoder.finish(); } @@ -242,19 +242,14 @@ export class WebGPUBase * @param commandEncoder 命令编码器。 * @param computePass 计算通道。 */ - protected runComputePass(commandEncoder: GPUCommandEncoder, computePass: ComputePass) + protected runComputePass(computePass: ComputePass) { - const descriptor = getGPUComputePassDescriptor(commandEncoder, computePass); - // 处理时间戳查询 - const passEncoder = commandEncoder.beginComputePass(descriptor); - - const computeObjectCommands = this.runComputeObjects(computePass.computeObjects); - computeObjectCommands.forEach((command) => command.run(passEncoder)); + const computePassCommand = new ComputePassCommand(); - passEncoder.end(); + computePassCommand.descriptor = getGPUComputePassDescriptor(this._device, computePass); + computePassCommand.computeObjectCommands = this.runComputeObjects(computePass.computeObjects); - // 处理时间戳查询 - descriptor.timestampWrites?.resolve(commandEncoder); + return computePassCommand; } protected runComputeObjects(computeObjects: ComputeObject[]) @@ -262,49 +257,43 @@ export class WebGPUBase return computeObjects.map((computeObject) => this.runComputeObject(computeObject)); } - protected runCopyTextureToTexture(commandEncoder: GPUCommandEncoder, copyTextureToTexture: CopyTextureToTexture) + protected runCopyTextureToTexture(copyTextureToTexture: CopyTextureToTexture) { const device = this._device; + const copyTextureToTextureCommand = new CopyTextureToTextureCommand(); + const sourceTexture = getGPUTexture(device, copyTextureToTexture.source.texture); const destinationTexture = getGPUTexture(device, copyTextureToTexture.destination.texture); - const source: GPUImageCopyTexture = { + copyTextureToTextureCommand.source = { ...copyTextureToTexture.source, texture: sourceTexture, }; - const destination: GPUImageCopyTexture = { + copyTextureToTextureCommand.destination = { ...copyTextureToTexture.destination, texture: destinationTexture, }; - commandEncoder.copyTextureToTexture( - source, - destination, - copyTextureToTexture.copySize, - ); + copyTextureToTextureCommand.copySize = copyTextureToTexture.copySize; + + return copyTextureToTextureCommand; } - protected runCopyBufferToBuffer(commandEncoder: GPUCommandEncoder, v: CopyBufferToBuffer) + protected runCopyBufferToBuffer(copyBufferToBuffer: CopyBufferToBuffer) { const device = this._device; - v.sourceOffset ||= 0; - v.destinationOffset ||= 0; - v.size ||= v.source.size; + const copyBufferToBufferCommand = new CopyBufferToBufferCommand(); - // - const sourceBuffer = getGPUBuffer(device, v.source); - const destinationBuffer = getGPUBuffer(device, v.destination); - - commandEncoder.copyBufferToBuffer( - sourceBuffer, - v.sourceOffset, - destinationBuffer, - v.destinationOffset, - v.size, - ); + copyBufferToBufferCommand.source = getGPUBuffer(device, copyBufferToBuffer.source); + copyBufferToBufferCommand.sourceOffset = copyBufferToBuffer.sourceOffset ?? 0; + copyBufferToBufferCommand.destination = getGPUBuffer(device, copyBufferToBuffer.destination); + copyBufferToBufferCommand.destinationOffset = copyBufferToBuffer.destinationOffset ?? 0; + copyBufferToBufferCommand.size = copyBufferToBuffer.size ?? copyBufferToBuffer.source.size; + + return copyBufferToBufferCommand; } protected runRenderOcclusionQueryObject(renderPassFormat: RenderPassFormat, renderOcclusionQueryObject: OcclusionQuery) diff --git a/src/caches/getGPUComputePassDescriptor.ts b/src/caches/getGPUComputePassDescriptor.ts index d880511..73de523 100644 --- a/src/caches/getGPUComputePassDescriptor.ts +++ b/src/caches/getGPUComputePassDescriptor.ts @@ -1,12 +1,10 @@ import { ComputePass } from "../data/ComputePass"; import { getGPUPassTimestampWrites } from "./getGPUPassTimestampWrites"; -export function getGPUComputePassDescriptor(commandEncoder: GPUCommandEncoder, computePass: ComputePass) +export function getGPUComputePassDescriptor(device: GPUDevice, computePass: ComputePass) { const descriptor: GPUComputePassDescriptor = {}; - const device = commandEncoder.device; - if (computePass.descriptor?.timestampQuery) { descriptor.timestampWrites = getGPUPassTimestampWrites(device, computePass.descriptor.timestampQuery); diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 9a51018..175d8fc 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -304,6 +304,11 @@ export class RenderBundleCommand implements RenderPassObjectCommand } } +export interface PassEncoderCommand +{ + run(commandEncoder: GPUCommandEncoder): void; +} + export class RenderPassCommand { run(commandEncoder: GPUCommandEncoder) @@ -341,4 +346,54 @@ export class ComputeObjectCommand computePipeline: GPUComputePipeline; setBindGroup: [index: GPUIndex32, bindGroup: GPUBindGroup][]; dispatchWorkgroups: [workgroupCountX: GPUSize32, workgroupCountY?: GPUSize32, workgroupCountZ?: GPUSize32]; +} + +export class ComputePassCommand +{ + run(commandEncoder: GPUCommandEncoder) + { + const { descriptor, computeObjectCommands } = this; + // + const passEncoder = commandEncoder.beginComputePass(descriptor); + computeObjectCommands.forEach((command) => command.run(passEncoder)); + passEncoder.end(); + // 处理时间戳查询 + descriptor.timestampWrites?.resolve(commandEncoder); + } + descriptor: GPUComputePassDescriptor; + computeObjectCommands: ComputeObjectCommand[]; +} + +export class CopyTextureToTextureCommand +{ + run(commandEncoder: GPUCommandEncoder) + { + const { source, destination, copySize } = this; + + commandEncoder.copyTextureToTexture( + source, + destination, + copySize, + ); + } + source: GPUImageCopyTexture; + destination: GPUImageCopyTexture; + copySize: GPUExtent3DStrict; +} + +export class CopyBufferToBufferCommand +{ + run(commandEncoder: GPUCommandEncoder) + { + const { source, sourceOffset, destination, destinationOffset, size } = this; + + commandEncoder.copyBufferToBuffer( + source, sourceOffset, destination, destinationOffset, size + ); + } + source: GPUBuffer; + sourceOffset: number; + destination: GPUBuffer; + destinationOffset: number; + size: number; } \ No newline at end of file -- Gitee From 2cac79c1fde4b0ecc471cb880ce3d899a416a1bf Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 23 Mar 2025 10:20:36 +0800 Subject: [PATCH 192/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=92=8C=E5=91=BD=E4=BB=A4=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E5=99=A8=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 WebGPUBase 中的直接命令编码器和提交逻辑 - 新增 CommandEncoderCommand 和 SubmitCommand 类 - 将命令编码器和提交逻辑移至新类中 - 更新 WebGPUBase 中的 runCommandEncoder 和 submit 方法 - 优化事件触发逻辑 --- src/WebGPUBase.ts | 24 +++++++--------------- src/internal/RenderObjectCache.ts | 34 ++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index abcef59..9758523 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,4 +1,3 @@ -import { anyEmitter } from "@feng3d/event"; import { BlendState, Buffer, ChainMap, CommandEncoder, computed, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; @@ -17,8 +16,7 @@ import { ComputePass } from "./data/ComputePass"; import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; -import { GPUQueue_submit, webgpuEvents } from "./eventnames"; -import { ComputeObjectCommand, ComputePassCommand, CopyBufferToBufferCommand, CopyTextureToTextureCommand, OcclusionQueryCache, PassEncoderCommand, RenderBundleCommand, RenderObjectCache, RenderPassCommand } from "./internal/RenderObjectCache"; +import { CommandEncoderCommand, ComputeObjectCommand, ComputePassCommand, CopyBufferToBufferCommand, CopyTextureToTextureCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand, SubmitCommand } from "./internal/RenderObjectCache"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; @@ -90,21 +88,17 @@ export class WebGPUBase { const device = this._device; - // 提交前数值加一,用于处理提交前需要执行的操作。 - reactive(webgpuEvents).preSubmit = ~~reactive(webgpuEvents).preSubmit + 1; + const submitCommand = new SubmitCommand(); // - const commandBuffers = submit.commandEncoders.map((v) => + submitCommand.commandBuffers = submit.commandEncoders.map((v) => { const commandBuffer = this.runCommandEncoder(v); return commandBuffer; }); - device.queue.submit(commandBuffers); - - // 派发提交WebGPU事件 - anyEmitter.emit(device.queue, GPUQueue_submit); + submitCommand.run(device); } destoryTexture(texture: TextureLike) @@ -159,11 +153,9 @@ export class WebGPUBase protected runCommandEncoder(commandEncoder: CommandEncoder) { - const device = this._device; - const gpuCommandEncoder = device.createCommandEncoder(); - gpuCommandEncoder.device = device; + const commandEncoderCommand = new CommandEncoderCommand(); - const passEncoders: PassEncoderCommand[] = commandEncoder.passEncoders.map((passEncoder) => + commandEncoderCommand.passEncoders = commandEncoder.passEncoders.map((passEncoder) => { if (!passEncoder.__type__) { @@ -191,9 +183,7 @@ export class WebGPUBase } }); - passEncoders.forEach((passEncoder) => passEncoder.run(gpuCommandEncoder)); - - return gpuCommandEncoder.finish(); + return commandEncoderCommand; } protected runRenderPass(renderPass: RenderPass) diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 175d8fc..58b12f2 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -1,4 +1,6 @@ -import { ChainMap } from "@feng3d/render-api"; +import { anyEmitter } from "@feng3d/event"; +import { ChainMap, reactive } from "@feng3d/render-api"; +import { GPUQueue_submit, webgpuEvents } from "../eventnames"; const cache = new ChainMap(); @@ -396,4 +398,34 @@ export class CopyBufferToBufferCommand destination: GPUBuffer; destinationOffset: number; size: number; +} + +export class CommandEncoderCommand +{ + run(device: GPUDevice) + { + const gpuCommandEncoder = device.createCommandEncoder(); + gpuCommandEncoder.device = device; + this.passEncoders.forEach((passEncoder) => passEncoder.run(gpuCommandEncoder)); + return gpuCommandEncoder.finish(); + } + passEncoders: (RenderPassCommand | ComputePassCommand | CopyTextureToTextureCommand | CopyBufferToBufferCommand)[]; + +} + +export class SubmitCommand +{ + run(device: GPUDevice) + { + const { commandBuffers } = this; + + // 提交前数值加一,用于处理提交前需要执行的操作。 + reactive(webgpuEvents).preSubmit = ~~reactive(webgpuEvents).preSubmit + 1; + + device.queue.submit(commandBuffers.map((v) => v.run(device))); + + // 派发提交WebGPU事件 + anyEmitter.emit(device.queue, GPUQueue_submit); + } + commandBuffers: CommandEncoderCommand[]; } \ No newline at end of file -- Gitee From 834548335738b6d6a3fb9b5eb853789d5c61ee8e Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sun, 23 Mar 2025 10:46:34 +0800 Subject: [PATCH 193/214] =?UTF-8?q?refactor(internal):=20=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E6=9C=AA=E4=BD=BF=E7=94=A8=E7=9A=84=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=92=8C=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了未使用的 PipelineLayoutDescriptor 接口 - 移除了 RenderObjectCache 中的无用代码 - 更新了 RenderPassFormat 接口,使其继承自 GPURenderPassLayout --- src/internal/PipelineLayoutDescriptor.ts | 28 ------------------------ src/internal/RenderObjectCache.ts | 1 - src/internal/RenderPassFormat.ts | 4 ++-- 3 files changed, 2 insertions(+), 31 deletions(-) delete mode 100644 src/internal/PipelineLayoutDescriptor.ts diff --git a/src/internal/PipelineLayoutDescriptor.ts b/src/internal/PipelineLayoutDescriptor.ts deleted file mode 100644 index a5e0978..0000000 --- a/src/internal/PipelineLayoutDescriptor.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { VariableInfo } from "wgsl_reflect"; - -// /** -// * GPU管线布局描述。 -// * -// * {@link GPUPipelineLayoutDescriptor} -// * -// * {@link GPUDevice.createPipelineLayout} -// * -// * {@link GPUPipelineLayout} -// */ -// export interface PipelineLayoutDescriptor -// { -// label?: string; -// /** -// * A list of {@link GPUBindGroupLayout}s the pipeline will use. Each element corresponds to a -// * @group attribute in the {@link GPUShaderModule}, with the `N`th element corresponding with -// * `@group(N)`. -// */ -// bindGroupLayouts: GPUBindGroupLayoutDescriptor[]; - -// key: string; -// } - -declare global -{ - -} \ No newline at end of file diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 58b12f2..a71f4f8 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -410,7 +410,6 @@ export class CommandEncoderCommand return gpuCommandEncoder.finish(); } passEncoders: (RenderPassCommand | ComputePassCommand | CopyTextureToTextureCommand | CopyBufferToBufferCommand)[]; - } export class SubmitCommand diff --git a/src/internal/RenderPassFormat.ts b/src/internal/RenderPassFormat.ts index 1257fbb..00beb78 100644 --- a/src/internal/RenderPassFormat.ts +++ b/src/internal/RenderPassFormat.ts @@ -3,10 +3,10 @@ * * @private */ -export interface RenderPassFormat +export interface RenderPassFormat extends GPURenderPassLayout { readonly attachmentSize: { readonly width: number, readonly height: number } readonly colorFormats: readonly GPUTextureFormat[], readonly depthStencilFormat: GPUTextureFormat, readonly sampleCount?: 4 -} \ No newline at end of file +} -- Gitee From 090781deafa6ea339b22206e3af6635fde7688d2 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 24 Mar 2025 15:35:19 +0800 Subject: [PATCH 194/214] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A4=BA=E4=BE=8B=20?= =?UTF-8?q?animometer=20=E8=BF=90=E8=A1=8C=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/src/webgpu/animometer/index.ts | 8 ++++---- src/caches/getGPURenderPassDescriptor.ts | 3 ++- src/internal/RenderObjectCache.ts | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/src/webgpu/animometer/index.ts b/examples/src/webgpu/animometer/index.ts index bf0d755..879202e 100644 --- a/examples/src/webgpu/animometer/index.ts +++ b/examples/src/webgpu/animometer/index.ts @@ -134,14 +134,14 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI) => ] }; - const renderBundlesPass = { + const renderBundlesPass: RenderPass = { descriptor: renderPassDescriptor, - renderObjects: [renderBundleObject], + renderPassObjects: [renderBundleObject], }; - const renderPass = { + const renderPass: RenderPass = { descriptor: renderPassDescriptor, - renderObjects, + renderPassObjects: renderObjects, }; return function doDraw(timestamp: number) diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index bd1e27c..dba8bb4 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -330,7 +330,8 @@ const getGPURenderPassColorAttachmentMap = new ChainMap v.__type__ === "OcclusionQuery") as OcclusionQuery[]; + const occlusionQuerys = renderPass.renderPassObjects?.filter((v) => v.__type__ === "OcclusionQuery") as OcclusionQuery[]; + if (!occlusionQuerys || occlusionQuerys.length === 0) return; renderPassDescriptor.occlusionQuerySet = device.createQuerySet({ type: "occlusion", count: occlusionQuerys.length }); const resolveBuf = device.createBuffer({ label: "resolveBuffer", diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index a71f4f8..1413efc 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -320,7 +320,7 @@ export class RenderPassCommand const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); passEncoder.device = device; - renderPassObjects.forEach((command) => + renderPassObjects?.forEach((command) => { command.run(passEncoder); }); -- Gitee From 01f3857eceb4137ec2cda3c458e1e5bf8cd68e28 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Mon, 24 Mar 2025 15:54:01 +0800 Subject: [PATCH 195/214] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=20WebGPU?= =?UTF-8?q?Cache=20=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 WebGPUCache.ts 文件 - 移除了 package.json 中的 @feng3d/watcher 依赖 --- package.json | 1 - src/WebGPUCache.ts | 271 --------------------------------------------- 2 files changed, 272 deletions(-) delete mode 100644 src/WebGPUCache.ts diff --git a/package.json b/package.json index 150099a..703e27f 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "dependencies": { "@feng3d/event": "^0.8.4", "@feng3d/render-api": "0.0.2", - "@feng3d/watcher": "^0.8.11", "@webgpu/types": "0.1.49", "wgsl_reflect": "^1.0.16" } diff --git a/src/WebGPUCache.ts b/src/WebGPUCache.ts deleted file mode 100644 index 242d567..0000000 --- a/src/WebGPUCache.ts +++ /dev/null @@ -1,271 +0,0 @@ -// import { ChainMap, RenderObject, RenderPassObject } from "@feng3d/render-api"; - -// import { watcher } from "@feng3d/watcher"; -// import { GPURenderOcclusionQuery } from "./caches/getGPURenderOcclusionQuery"; -// import { RenderPassFormat } from "./internal/RenderPassFormat"; -// import { WebGPUBase } from "./WebGPUBase"; - -// /** -// * 缓存命令,优化性能。 -// */ -// export class WebGPUCache extends WebGPUBase -// { -// protected runRenderPassObjects(passEncoder: GPURenderPassEncoder, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[], occlusionQuery: GPURenderOcclusionQuery) -// { -// const device = this._device; -// const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat, renderObjects]; -// let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); -// if (!caches) -// { -// // 收集命令 -// const renderPassRecord = new GPURenderPassRecord(); -// const commands = renderPassRecord["_commands"] = []; - -// super.runRenderPassObjects(renderPassRecord, renderPassFormat, renderObjects, occlusionQuery); - -// // 排除无效命令 -// paichuWuxiaoCommands(renderPassFormat.attachmentSize, commands); - -// // -// const setBindGroupCommands = commands.filter((v) => v[0] === "setBindGroup"); - -// caches = { commands, setBindGroupCommands }; - -// _renderPassObjectsCommandMap.set(renderPassObjectsCommandKey, caches); - -// // 监听变化 -// const onchanged = () => -// { -// _renderPassObjectsCommandMap.delete(renderPassObjectsCommandKey); -// // -// renderObjects.forEach((v) => { watcher.unwatch(v, "_version" as any, onchanged); }); -// }; -// renderObjects.forEach((v) => { watcher.watch(v, "_version" as any, onchanged); }); -// } - -// // 执行命令 -// runCommands(passEncoder, caches); -// } - -// protected runRenderBundleObjects(bundleEncoder: GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObjects?: RenderObject[]) -// { -// const device = this._device; -// const renderPassObjectsCommandKey: RenderPassObjectsCommandKey = [device, renderPassFormat, renderObjects]; -// let caches = _renderPassObjectsCommandMap.get(renderPassObjectsCommandKey); -// if (!caches) -// { -// // 收集命令 -// // const renderBundleRecord = new GPURenderBundleRecord(); -// const renderBundleRecord = new GPURenderPassRecord(); -// const commands = renderBundleRecord["_commands"] = []; - -// super.runRenderBundleObjects(renderBundleRecord as any, renderPassFormat, renderObjects); - -// // 排除无效命令 -// paichuWuxiaoCommands(renderPassFormat.attachmentSize, commands); -// // -// const setBindGroupCommands = commands.filter((v) => v[0] === "setBindGroup"); - -// caches = { commands, setBindGroupCommands }; - -// _renderPassObjectsCommandMap.set(renderPassObjectsCommandKey, caches); - -// // 监听变化 -// const onchanged = () => -// { -// _renderPassObjectsCommandMap.delete(renderPassObjectsCommandKey); -// // -// renderObjects.forEach((v) => { watcher.unwatch(v, "_version", onchanged); }); -// }; -// renderObjects.forEach((v) => { watcher.watch(v, "_version", onchanged); }); -// } - -// // 排除在 GPURenderBundleEncoder 中不支持的命令 -// const commands = caches.commands.filter((v) => (v[0] in bundleEncoder)); - -// // 执行命令 -// runCommands(bundleEncoder, { ...caches, commands }); -// } - -// protected runRenderObject(passEncoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderPassFormat: RenderPassFormat, renderObject: RenderObject) -// { -// const device = this._device; -// const _commands = passEncoder["_commands"] as any[]; - -// const renderObjectCommandKey: RenderObjectCommandKey = [device, renderPassFormat, renderObject]; -// const commands = renderObjectCommandMap.get(renderObjectCommandKey); -// if (commands) -// { -// commands.forEach((v) => _commands.push(v)); - -// return; -// } - -// const start = _commands.length; - -// super.runRenderObject(passEncoder, renderPassFormat, renderObject); - -// renderObjectCommandMap.set(renderObjectCommandKey, _commands.slice(start)); - -// // -// const onchanged = () => -// { -// renderObjectCommandMap.delete(renderObjectCommandKey); -// // -// renderObject._version = ~~renderObject._version + 1; -// watcher.unwatch(renderObject.pipeline, '_version', onchanged); -// } -// watcher.watch(renderObject.pipeline, '_version', onchanged); -// } -// } -// type RenderObjectCommandKey = [device: GPUDevice, renderPassFormat: RenderPassFormat, renderObject: RenderObject]; -// const renderObjectCommandMap = new ChainMap>(); - -// class GPURenderPassRecord implements GPURenderPassEncoder -// { -// __brand: "GPURenderPassEncoder" = "GPURenderPassEncoder"; -// label: string; -// // -// setViewport(...args: any): undefined { this["_commands"].push(["setViewport", args]); } -// setScissorRect(...args: any): undefined { this["_commands"].push(["setScissorRect", args]); } -// setBlendConstant(...args: any): undefined { this["_commands"].push(["setBlendConstant", args]); } -// setStencilReference(...args: any): undefined { this["_commands"].push(["setStencilReference", args]); } -// // -// setPipeline(...args: any): undefined { this["_commands"].push(["setPipeline", args]); } -// setVertexBuffer(...args: any): undefined { this["_commands"].push(["setVertexBuffer", args]); } -// setIndexBuffer(...args: any): undefined { this["_commands"].push(["setIndexBuffer", args]); } -// setBindGroup(...args: any): undefined { this["_commands"].push(["setBindGroup", args]); } -// draw(...args: any): undefined { this["_commands"].push(["draw", args]); } -// drawIndexed(...args: any): undefined { this["_commands"].push(["drawIndexed", args]); } -// drawIndirect(...args: any): undefined { this["_commands"].push(["drawIndirect", args]); } -// drawIndexedIndirect(...args: any): undefined { this["_commands"].push(["drawIndexedIndirect", args]); } -// // -// beginOcclusionQuery(...args: any): undefined { this["_commands"].push(["beginOcclusionQuery", args]); } -// endOcclusionQuery(...args: any): undefined { this["_commands"].push(["endOcclusionQuery", args]); } -// // -// executeBundles(...args: any): undefined { this["_commands"].push(["executeBundles", args]); } -// // -// end(...args: any): undefined { this["_commands"].push(["end", args]); } -// // -// pushDebugGroup(...args: any): undefined { this["_commands"].push(["pushDebugGroup", args]); } -// popDebugGroup(...args: any): undefined { this["_commands"].push(["popDebugGroup", args]); } -// insertDebugMarker(...args: any): undefined { this["_commands"].push(["insertDebugMarker", args]); } -// } - -// function runCommands(_passEncoder: GPURenderPassEncoder | GPUComputePassEncoder | GPURenderBundleEncoder, caches: { -// commands: Array; -// setBindGroupCommands: Array; -// }) -// { -// const { commands, setBindGroupCommands } = caches; - -// setBindGroupCommands.forEach((v) => -// { -// v[1][1] = v[1][1](); -// }); - -// commands.forEach((v) => -// { -// _passEncoder[v[0]].apply(_passEncoder, v[1]); -// }); -// } - -// /** -// * 排除无效命令 -// * -// * @param attachmentSize -// */ -// function paichuWuxiaoCommands(attachmentSize: { readonly width: number; readonly height: number; }, commands: any[]) -// { -// const _obj = { -// setBindGroup: [], setVertexBuffer: [], -// setViewport: [0, 0, attachmentSize.width, attachmentSize.height, 0, 1], -// setScissorRect: [0, 0, attachmentSize.width, attachmentSize.height], -// }; -// // -// let length = 0; -// commands.concat().forEach((v) => -// { -// // 排除重复的无效命令 -// if (v[0] === "setBindGroup" || v[0] === "setVertexBuffer") -// { -// if (!arrayEq1(_obj, v[0], v[1][0], v[1])) -// { -// commands[length++] = v; -// } -// } -// else if (0 -// || v[0] === "setPipeline" -// || v[0] === "setIndexBuffer" -// || v[0] === "setViewport" -// || v[0] === "setScissorRect" -// || v[0] === "setBlendConstant" -// || v[0] === "setStencilReference" -// ) -// { -// if (!arrayEq0(_obj, v[0], v[1])) -// { -// commands[length++] = v; -// } -// } -// else -// { -// commands[length++] = v; -// } -// }); -// commands.length = length; -// } - -// function arrayEq0(_obj: any, name: string, args: any[]) -// { -// const obj = _obj; -// const oldArgs: any[] = obj[name]; -// if (!oldArgs) -// { -// obj[name] = args; - -// return false; -// } - -// for (let i = 0, n = oldArgs.length; i < n; i++) -// { -// if (oldArgs[i] !== args[i]) -// { -// obj[name] = args; - -// return false; -// } -// } - -// return true; -// } - -// function arrayEq1(_obj: any, name: string, index: number, args: any[]) -// { -// const obj = _obj[name]; -// const oldArgs: any[] = obj[index]; -// if (!oldArgs) -// { -// obj[index] = args; - -// return false; -// } - -// for (let i = 1, n = oldArgs.length; i < n; i++) -// { -// if (oldArgs[i] !== args[i]) -// { -// obj[index] = args; - -// return false; -// } -// } - -// return true; -// } - -// type RenderPassObjectsCommandKey = [device: GPUDevice, renderPassFormat: RenderPassFormat, renderObjects: RenderPassObject[]]; -// const _renderPassObjectsCommandMap = new ChainMap; -// setBindGroupCommands: Array; -// }>; \ No newline at end of file -- Gitee From cea09a3ecda5cc154ae40718030c6013768e1fcc Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Fri, 28 Mar 2025 21:55:56 +0800 Subject: [PATCH 196/214] =?UTF-8?q?refactor:=20=E6=9B=BF=E6=8D=A2=20Comput?= =?UTF-8?q?edRef=20=E4=B8=BA=20Computed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在多个文件中将 ComputedRef 类型替换为 Computed - 这一变更可以简化代码结构,并可能提高性能 --- src/WebGPUBase.ts | 6 ++--- src/caches/getGPUBindGroup.ts | 10 ++++---- src/caches/getGPUBuffer.ts | 4 +-- src/caches/getGPUCanvasContext.ts | 4 +-- src/caches/getGPURenderPassDescriptor.ts | 12 ++++----- src/caches/getGPURenderPassFormat.ts | 4 +-- src/caches/getGPURenderPipeline.ts | 32 ++++++++++++------------ src/caches/getGPUSampler.ts | 4 +-- src/caches/getGPUTexture.ts | 4 +-- src/caches/getGPUTextureFormat.ts | 4 +-- src/caches/getGPUTextureView.ts | 4 +-- src/caches/getNGPUVertexBuffers.ts | 6 ++--- src/caches/getTextureSize.ts | 4 +-- src/caches/getVertexEntryFunctionInfo.ts | 6 ++--- 14 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 9758523..6dd2062 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,4 +1,4 @@ -import { BlendState, Buffer, ChainMap, CommandEncoder, computed, ComputedRef, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; +import { BlendState, Buffer, ChainMap, CommandEncoder, computed, Computed, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -661,7 +661,7 @@ function getStencilReference(depthStencil?: DepthStencilState) } type GPURenderBundleKey = [renderBundle: RenderBundle, renderPassFormat: RenderPassFormat]; -const gpuRenderBundleMap = new ChainMap>(); +const gpuRenderBundleMap = new ChainMap>(); type RenderObjectCacheKey = [device: GPUDevice, renderObject: RenderObject, renderPassFormat: RenderPassFormat]; -const renderObjectCacheMap = new ChainMap>(); \ No newline at end of file +const renderObjectCacheMap = new ChainMap>(); \ No newline at end of file diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 74b7cc4..02de841 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,4 +1,4 @@ -import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, ComputedRef, reactive, Sampler, TextureView, UnReadonly } from "@feng3d/render-api"; +import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, Computed, reactive, Sampler, TextureView, UnReadonly } from "@feng3d/render-api"; import { ArrayInfo, ResourceType, StructInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; import { VideoTexture } from "../data/VideoTexture"; import { webgpuEvents } from "../eventnames"; @@ -81,7 +81,7 @@ type GPUBindGroupKey = [bindGroupLayout: GPUBindGroupLayout, ...resources: GPUBi const gpuBindGroupMap = new ChainMap(); type GetGPUBindGroupKey = [bindGroupLayout: GPUBindGroupLayout, bindingResources: BindingResources]; -const getGPUBindGroupMap = new ChainMap>(); +const getGPUBindGroupMap = new ChainMap>(); function getGPUBufferBinding(device: GPUDevice, bufferBinding: BufferBinding, type: TypeInfo) { @@ -128,7 +128,7 @@ type GPUBufferBindingKey = [buffer: GPUBuffer, offset: number, size: number]; const gpuBufferBindingMap = new ChainMap(); type GetGPUBindingResourceKey = [device: GPUDevice, bufferBinding: BufferBinding, type: TypeInfo]; -const getGPUBindingResourceMap = new ChainMap>(); +const getGPUBindingResourceMap = new ChainMap>(); function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) { @@ -151,7 +151,7 @@ function getGPUExternalTexture(device: GPUDevice, videoTexture: VideoTexture) return result.value; } type GetGPUExternalTextureKey = [device: GPUDevice, videoTexture: VideoTexture]; -const getGPUExternalTextureMap = new ChainMap>(); +const getGPUExternalTextureMap = new ChainMap>(); /** * 初始化缓冲区绑定。 @@ -229,7 +229,7 @@ export function updateBufferBinding(uniformData: BufferBinding, type: TypeInfo) return result.value; } type UpdateBufferBindingKey = [uniformData: BufferBinding, type: TypeInfo]; -const updateBufferBindingMap = new ChainMap>(); +const updateBufferBindingMap = new ChainMap>(); /** * 获取缓冲区绑定信息。 diff --git a/src/caches/getGPUBuffer.ts b/src/caches/getGPUBuffer.ts index ac4e2ed..1117189 100644 --- a/src/caches/getGPUBuffer.ts +++ b/src/caches/getGPUBuffer.ts @@ -1,4 +1,4 @@ -import { ChainMap, computed, ComputedRef, Buffer, reactive } from "@feng3d/render-api"; +import { ChainMap, computed, Computed, Buffer, reactive } from "@feng3d/render-api"; /** * 除了GPU与CPU数据交换的`MAP_READ`与`MAP_WRITE`除外。 @@ -77,7 +77,7 @@ export function getGPUBuffer(device: GPUDevice, buffer: Buffer) return result.value; } type GetGPUBufferKey = [device: GPUDevice, buffer: Buffer]; -const getGPUBufferMap = new ChainMap>; +const getGPUBufferMap = new ChainMap>; function dataChange(buffer: Buffer) { diff --git a/src/caches/getGPUCanvasContext.ts b/src/caches/getGPUCanvasContext.ts index 28844e4..2c2a2d9 100644 --- a/src/caches/getGPUCanvasContext.ts +++ b/src/caches/getGPUCanvasContext.ts @@ -1,5 +1,5 @@ import { CanvasContext, ChainMap } from "@feng3d/render-api"; -import { computed, ComputedRef, reactive } from "@vue/reactivity"; +import { computed, Computed, reactive } from "@feng3d/reactivity"; import "../data/polyfills/CanvasContext"; export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) @@ -59,4 +59,4 @@ export function getGPUCanvasContext(device: GPUDevice, context: CanvasContext) return result.value; } type GetGPUCanvasContextKey = [device: GPUDevice, context: CanvasContext]; -const getGPUCanvasContextMap = new ChainMap>; \ No newline at end of file +const getGPUCanvasContextMap = new ChainMap>; \ No newline at end of file diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index dba8bb4..5aba88a 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CanvasTexture, ChainMap, computed, ComputedRef, OcclusionQuery, reactive, RenderPass, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; +import { CanvasTexture, ChainMap, computed, Computed, OcclusionQuery, reactive, RenderPass, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; import { GPUQueue_submit } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { getGPUPassTimestampWrites } from "./getGPUPassTimestampWrites"; @@ -60,7 +60,7 @@ export function getGPURenderPassDescriptor(device: GPUDevice, renderPass: Render } type GetGPURenderPassDescriptorKey = [device: GPUDevice, descriptor: RenderPassDescriptor]; -const getGPURenderPassDescriptorMap = new ChainMap>; +const getGPURenderPassDescriptorMap = new ChainMap>; /** * 设置纹理尺寸。 @@ -117,7 +117,7 @@ function getMultisampleTextureView(texture: TextureLike, sampleCount: 4) getMultisampleTextureViewMap.set(texture, result); return result.value; } -const getMultisampleTextureViewMap = new WeakMap>; +const getMultisampleTextureViewMap = new WeakMap>; /** * 获取深度模板附件完整描述。 @@ -212,7 +212,7 @@ function getGPURenderPassDepthStencilAttachment(device: GPUDevice, descriptor: R return result.value; } type GetGPURenderPassDepthStencilAttachmentKey = [device: GPUDevice, depthStencilAttachment: RenderPassDepthStencilAttachment]; -const getGPURenderPassDepthStencilAttachmentMap = new ChainMap>; +const getGPURenderPassDepthStencilAttachmentMap = new ChainMap>; /** * 获取颜色附件完整描述列表。 @@ -253,7 +253,7 @@ function getGPURenderPassColorAttachments(device: GPUDevice, descriptor: RenderP return result.value; } type GetGPURenderPassColorAttachmentsKey = [device: GPUDevice, descriptor: RenderPassDescriptor]; -const getIGPURenderPassColorAttachmentsMap = new ChainMap>; +const getIGPURenderPassColorAttachmentsMap = new ChainMap>; /** * 获取颜色附件完整描述。 @@ -326,7 +326,7 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac return result.value; } type GetGPURenderPassColorAttachmentKey = [device: GPUDevice, renderPassColorAttachment: RenderPassColorAttachment, descriptor: RenderPassDescriptor]; -const getGPURenderPassColorAttachmentMap = new ChainMap>; +const getGPURenderPassColorAttachmentMap = new ChainMap>; function setOcclusionQuerySet(device: GPUDevice, renderPass: RenderPass, renderPassDescriptor: GPURenderPassDescriptor) { diff --git a/src/caches/getGPURenderPassFormat.ts b/src/caches/getGPURenderPassFormat.ts index fa2e476..6540a9a 100644 --- a/src/caches/getGPURenderPassFormat.ts +++ b/src/caches/getGPURenderPassFormat.ts @@ -1,4 +1,4 @@ -import { computed, ComputedRef, reactive, RenderPassDescriptor } from "@feng3d/render-api"; +import { computed, Computed, reactive, RenderPassDescriptor } from "@feng3d/render-api"; import { getGPUTextureFormat } from "../caches/getGPUTextureFormat"; import { RenderPassFormat } from "../internal/RenderPassFormat"; @@ -55,4 +55,4 @@ export function getGPURenderPassFormat(descriptor: RenderPassDescriptor): Render return result.value; } const renderPassFormatMap: Record = {}; -const getGPURenderPassFormatMap = new WeakMap>(); +const getGPURenderPassFormatMap = new WeakMap>(); diff --git a/src/caches/getGPURenderPipeline.ts b/src/caches/getGPURenderPipeline.ts index ec313cd..dfea2a8 100644 --- a/src/caches/getGPURenderPipeline.ts +++ b/src/caches/getGPURenderPipeline.ts @@ -1,4 +1,4 @@ -import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, ComputedRef, DepthStencilState, FragmentState, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, VertexState, WGSLVertexType, WriteMask } from "@feng3d/render-api"; +import { BlendComponent, BlendState, ChainMap, ColorTargetState, computed, Computed, DepthStencilState, FragmentState, PrimitiveState, reactive, RenderPipeline, StencilFaceState, VertexAttributes, VertexState, WGSLVertexType, WriteMask } from "@feng3d/render-api"; import { TemplateInfo, TypeInfo } from "wgsl_reflect"; import { MultisampleState } from "../data/MultisampleState"; @@ -62,7 +62,7 @@ export function getGPURenderPipeline(device: GPUDevice, renderPipeline: RenderPi return result.value; } type GetGPURenderPipelineKey = [device: GPUDevice, renderPipeline: RenderPipeline, renderPassFormat: RenderPassFormat, vertices: VertexAttributes, indexFormat: GPUIndexFormat]; -const getGPURenderPipelineMap = new ChainMap>; +const getGPURenderPipelineMap = new ChainMap>; /** * 获取完整的顶点阶段描述与顶点缓冲区列表。 @@ -108,7 +108,7 @@ function getGPUVertexState(device: GPUDevice, vertexState: VertexState, vertices } type GetGPUVertexStateKey = [device: GPUDevice, vertexState: VertexState, vertices: VertexAttributes]; -const getGPUVertexStateMap = new ChainMap>(); +const getGPUVertexStateMap = new ChainMap>(); type GPUVertexStateKey = [module: GPUShaderModule, entryPoint: string, buffers: Iterable, constants: Record]; const gpuVertexStateMap = new ChainMap(); @@ -116,7 +116,7 @@ function getConstants(constants: Record) { if (!constants) return undefined; - let result: ComputedRef> = getConstantsMap.get(constants); + let result: Computed> = getConstantsMap.get(constants); if (result) return result.value; result = computed(() => @@ -142,13 +142,13 @@ function getConstants(constants: Record) return result.value; } const constantsMap: { [constantsKey: string]: Record } = {}; -const getConstantsMap = new WeakMap, ComputedRef>>(); +const getConstantsMap = new WeakMap, Computed>>(); function getGPUPrimitiveState(primitive?: PrimitiveState, indexFormat?: GPUIndexFormat): GPUPrimitiveState { if (!primitive) return defaultGPUPrimitiveState; - const result: ComputedRef = primitive["_cache_GPUPrimitiveState_" + indexFormat] ??= computed(() => + const result: Computed = primitive["_cache_GPUPrimitiveState_" + indexFormat] ??= computed(() => { // 监听 const r_primitive = reactive(primitive); @@ -179,7 +179,7 @@ function getGPUMultisampleState(multisampleState?: MultisampleState, sampleCount if (!sampleCount) return undefined; if (!multisampleState) return defaultGPUMultisampleState; - const result: ComputedRef = multisampleState["_cache_GPUMultisampleState_" + sampleCount] ??= computed(() => + const result: Computed = multisampleState["_cache_GPUMultisampleState_" + sampleCount] ??= computed(() => { // 监听 const r_multisampleState = reactive(multisampleState); @@ -281,7 +281,7 @@ function getGPUDepthStencilState(depthStencil: DepthStencilState, depthStencilFo return result.value; } type GetGPUDepthStencilStateKey = [depthStencil: DepthStencilState, depthStencilFormat: GPUTextureFormat]; -const getGPUDepthStencilStateMap = new ChainMap>(); +const getGPUDepthStencilStateMap = new ChainMap>(); type GPUDepthStencilStateKey = [format: GPUTextureFormat, depthWriteEnabled: boolean, depthCompare: GPUCompareFunction, stencilFront: GPUStencilFaceState, stencilBack: GPUStencilFaceState, stencilReadMask: number, stencilWriteMask: number, depthBias: number, depthBiasSlopeScale: number, depthBiasClamp: number] const gpuDepthStencilStateMap = new ChainMap(); @@ -356,7 +356,7 @@ function getGPUStencilFaceState(stencilFaceState?: StencilFaceState) return result.value; } const defaultGPUStencilFaceState: GPUStencilFaceState = {}; -const getGPUStencilFaceStateMap = new WeakMap>(); +const getGPUStencilFaceStateMap = new WeakMap>(); type GPUStencilFaceStateKey = [compare: GPUCompareFunction, failOp: GPUStencilOperation, depthFailOp: GPUStencilOperation, passOp: GPUStencilOperation]; const GPUStencilFaceStateMap = new ChainMap(); @@ -364,7 +364,7 @@ function getGPUColorTargetState(colorTargetState: ColorTargetState, format: GPUT { if (!colorTargetState) return getDefaultGPUColorTargetState(format); - const result: ComputedRef = colorTargetState["_GPUColorTargetState_" + format] ??= computed(() => + const result: Computed = colorTargetState["_GPUColorTargetState_" + format] ??= computed(() => { // 监听 const r_colorTargetState = reactive(colorTargetState); @@ -441,7 +441,7 @@ function getGPUFragmentState(device: GPUDevice, fragmentState: FragmentState, co type GPUFragmentStateKey = [module: GPUShaderModule, entryPoint: string, targets: Iterable, constants: Record] const gpuFragmentStateMap = new ChainMap(); type GetGPUFragmentStateKey = [device: GPUDevice, fragmentState: FragmentState, colorAttachmentsKey: string]; -const getGPUFragmentStateMap = new ChainMap>; +const getGPUFragmentStateMap = new ChainMap>; function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]): GPUColorTargetState[] { @@ -471,7 +471,7 @@ function getGPUColorTargetStates(targets: readonly ColorTargetState[], colorAtta return result.value; } type GetGPUColorTargetStatesKey = [targets: readonly ColorTargetState[], colorAttachments: readonly GPUTextureFormat[]]; -const getGPUColorTargetStatesMap = new ChainMap>(); +const getGPUColorTargetStatesMap = new ChainMap>(); const getDefaultGPUColorTargetStates = (colorAttachments: readonly GPUTextureFormat[]) => { @@ -484,7 +484,7 @@ const defaultGPUColorTargetStates: { [key: string]: GPUColorTargetState[] } = {} function getEntryPoint(fragmentState: FragmentState) { - const result: ComputedRef = fragmentState["_entryPoint"] ??= computed(() => + const result: Computed = fragmentState["_entryPoint"] ??= computed(() => { // 监听 const r_fragmentState = reactive(fragmentState); @@ -509,7 +509,7 @@ function getGPUBlendState(blend?: BlendState): GPUBlendState { if (!blend) return undefined; - let result: ComputedRef = blend["_GPUBlendState"]; + let result: Computed = blend["_GPUBlendState"]; if (result) return result.value; result = blend["_GPUBlendState"] = computed(() => @@ -534,7 +534,7 @@ function getGPUBlendComponent(blendComponent?: BlendComponent): GPUBlendComponen { if (!blendComponent) return { operation: "add", srcFactor: "one", dstFactor: "zero" }; - const result: ComputedRef = blendComponent["_GPUBlendComponent"] ??= computed(() => + const result: Computed = blendComponent["_GPUBlendComponent"] ??= computed(() => { // 监听 const r_blendComponent = reactive(blendComponent); @@ -560,7 +560,7 @@ function getGPUColorWriteFlags(writeMask?: WriteMask) { if (!writeMask) return 15; - const result: ComputedRef = writeMask["_GPUColorWriteFlags"] ??= computed(() => + const result: Computed = writeMask["_GPUColorWriteFlags"] ??= computed(() => { // 监听 const r_writeMask = reactive(writeMask); diff --git a/src/caches/getGPUSampler.ts b/src/caches/getGPUSampler.ts index 52ff4dc..1a33281 100644 --- a/src/caches/getGPUSampler.ts +++ b/src/caches/getGPUSampler.ts @@ -1,4 +1,4 @@ -import { ChainMap, computed, ComputedRef, reactive, Sampler } from "@feng3d/render-api"; +import { ChainMap, computed, Computed, reactive, Sampler } from "@feng3d/render-api"; export function getGPUSampler(device: GPUDevice, sampler: Sampler) { @@ -45,7 +45,7 @@ export function getGPUSampler(device: GPUDevice, sampler: Sampler) return result.value; } type GetGPUSamplerKey = [device: GPUDevice, sampler: Sampler]; -const getGPUSamplerMap = new ChainMap>; +const getGPUSamplerMap = new ChainMap>; /** * GPU采样器默认值。 diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index f033698..1eb4685 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -1,4 +1,4 @@ -import { ChainMap, computed, ComputedRef, reactive, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSource } from "@feng3d/render-api"; +import { ChainMap, computed, Computed, reactive, Texture, TextureDataSource, TextureDimension, TextureImageSource, TextureLike, TextureSource } from "@feng3d/render-api"; import { webgpuEvents } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { generateMipmap } from "../utils/generate-mipmap"; @@ -106,7 +106,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC } let autoIndex = 0; type GetGPUTextureMap = [device: GPUDevice, texture: TextureLike]; -const getGPUTextureMap = new ChainMap>; +const getGPUTextureMap = new ChainMap>; const textureMap = new ChainMap<[device: GPUDevice, texture: Texture], GPUTexture>(); diff --git a/src/caches/getGPUTextureFormat.ts b/src/caches/getGPUTextureFormat.ts index f397d16..3135a4b 100644 --- a/src/caches/getGPUTextureFormat.ts +++ b/src/caches/getGPUTextureFormat.ts @@ -1,4 +1,4 @@ -import { computed, ComputedRef, reactive, TextureLike } from "@feng3d/render-api"; +import { computed, Computed, reactive, TextureLike } from "@feng3d/render-api"; /** * 获取纹理格式。 @@ -33,4 +33,4 @@ export function getGPUTextureFormat(texture: TextureLike): GPUTextureFormat return result.value; } -const getGPUTextureFormatMap = new WeakMap>(); \ No newline at end of file +const getGPUTextureFormatMap = new WeakMap>(); \ No newline at end of file diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index d4da178..c0a2197 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -1,4 +1,4 @@ -import { ChainMap, computed, ComputedRef, reactive, Texture, TextureView } from "@feng3d/render-api"; +import { ChainMap, computed, Computed, reactive, Texture, TextureView } from "@feng3d/render-api"; import { getGPUTexture } from "./getGPUTexture"; export function getGPUTextureView(device: GPUDevice, view: TextureView) @@ -31,4 +31,4 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) } type GetGPUTextureViewKey = [device: GPUDevice, view: TextureView]; -const getGPUTextureViewMap = new ChainMap>; +const getGPUTextureViewMap = new ChainMap>; diff --git a/src/caches/getNGPUVertexBuffers.ts b/src/caches/getNGPUVertexBuffers.ts index 450fc0a..c9ab4f9 100644 --- a/src/caches/getNGPUVertexBuffers.ts +++ b/src/caches/getNGPUVertexBuffers.ts @@ -1,4 +1,4 @@ -import { ChainMap, computed, ComputedRef, reactive, VertexAttribute, VertexAttributes, VertexDataTypes, vertexFormatMap, VertexState } from "@feng3d/render-api"; +import { ChainMap, computed, Computed, reactive, VertexAttribute, VertexAttributes, VertexDataTypes, vertexFormatMap, VertexState } from "@feng3d/render-api"; import { VertexBuffer } from "../internal/VertexBuffer"; import { getVertexEntryFunctionInfo } from "./getVertexEntryFunctionInfo"; @@ -171,7 +171,7 @@ function getVertexBuffers(vertexAttribute: VertexAttribute) getVertexBuffersMap.set(vertexAttribute, result); return result.value; } -const getVertexBuffersMap = new WeakMap>(); +const getVertexBuffersMap = new WeakMap>(); type GetVertexBuffersBuffersKey = [vertexState: VertexState, vertices: VertexAttributes]; -const getVertexBuffersBuffersMap = new ChainMap>(); \ No newline at end of file +const getVertexBuffersBuffersMap = new ChainMap>(); \ No newline at end of file diff --git a/src/caches/getTextureSize.ts b/src/caches/getTextureSize.ts index 9bc5f03..b0269cf 100644 --- a/src/caches/getTextureSize.ts +++ b/src/caches/getTextureSize.ts @@ -1,4 +1,4 @@ -import { CanvasTexture, computed, ComputedRef, reactive, TextureLike, TextureSize } from "@feng3d/render-api"; +import { CanvasTexture, computed, Computed, reactive, TextureLike, TextureSize } from "@feng3d/render-api"; /** * 获取纹理尺寸。 @@ -37,4 +37,4 @@ export function getTextureSize(texture: TextureLike) return result.value; } -const getTextureSizeMap = new WeakMap>(); \ No newline at end of file +const getTextureSizeMap = new WeakMap>(); \ No newline at end of file diff --git a/src/caches/getVertexEntryFunctionInfo.ts b/src/caches/getVertexEntryFunctionInfo.ts index 10de884..9ca40ea 100644 --- a/src/caches/getVertexEntryFunctionInfo.ts +++ b/src/caches/getVertexEntryFunctionInfo.ts @@ -1,4 +1,4 @@ -import { computed, ComputedRef, reactive, VertexState } from "@feng3d/render-api"; +import { computed, reactive, VertexState, Computed } from "@feng3d/render-api"; import { FunctionInfo } from "wgsl_reflect"; import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; @@ -10,7 +10,7 @@ import { getWGSLReflectInfo } from "./getWGSLReflectInfo"; */ export function getVertexEntryFunctionInfo(vertexState: VertexState) { - let result: ComputedRef = _getVertexEntryFunctionInfoMap.get(vertexState); + let result: Computed = _getVertexEntryFunctionInfoMap.get(vertexState); if (result) return result.value; result = computed(() => @@ -43,4 +43,4 @@ export function getVertexEntryFunctionInfo(vertexState: VertexState) return result.value; } -const _getVertexEntryFunctionInfoMap = new WeakMap>(); \ No newline at end of file +const _getVertexEntryFunctionInfoMap = new WeakMap>(); \ No newline at end of file -- Gitee From 0ed6362bf517be633fe3d8c9820a832df68d8ad9 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 29 Mar 2025 15:14:23 +0800 Subject: [PATCH 197/214] =?UTF-8?q?refactor(caches):=20=E4=B8=BA=20GPU=20?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E5=92=8C=E8=A7=86=E5=9B=BE=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=B0=83=E8=AF=95=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 getGPUTexture 函数中为 GPU 画布纹理添加标签 - 在 getGPUTextureView 函数中为 GPU 纹理视图添加标签 --- src/caches/getGPUTexture.ts | 1 + src/caches/getGPUTextureView.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index 1eb4685..beb5759 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -31,6 +31,7 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC const context = getGPUCanvasContext(device, canvasTexture.context); const gpuTexture = context.getCurrentTexture(); + gpuTexture.label = "GPU画布纹理"; return gpuTexture; } diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index c0a2197..37665d0 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -19,6 +19,7 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) const { texture } = view; const gpuTexture = getGPUTexture(device, texture); const textureView = gpuTexture.createView({ + label: "GPU纹理视图", ...r_view, dimension: r_view.dimension ?? (texture as Texture).dimension, }); -- Gitee From 8c4d58ea52c038e6f7bcee27ddfdbeb0fb5cc3d5 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 29 Mar 2025 15:34:10 +0800 Subject: [PATCH 198/214] =?UTF-8?q?refactor(textures):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E7=94=BB=E5=B8=83=E5=B0=BA=E5=AF=B8=E5=8F=98=E5=8C=96?= =?UTF-8?q?=E5=90=8E=E6=88=96=E8=80=85=E6=9C=80=E6=96=B0=E7=BA=B9=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在设置画布大小时增加版本号更新,以支持缓存失效 - 在获取 GPU 纹理前检查画布大小版本号,确保使用最新的纹理 --- src/caches/getGPURenderPassDescriptor.ts | 1 + src/caches/getGPUTexture.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 5aba88a..2f11bc3 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -76,6 +76,7 @@ function setTextureSize(texture: TextureLike, attachmentSize: { width: number, h const element = typeof texture.context.canvasId === "string" ? document.getElementById(texture.context.canvasId) as HTMLCanvasElement : texture.context.canvasId; if (element.width !== attachmentSize.width) element.width = attachmentSize.width; if (element.height !== attachmentSize.height) element.height = attachmentSize.height; + reactive(texture)._canvasSizeVersion = ~~texture._canvasSizeVersion + 1; } else { diff --git a/src/caches/getGPUTexture.ts b/src/caches/getGPUTexture.ts index beb5759..1b931c6 100644 --- a/src/caches/getGPUTexture.ts +++ b/src/caches/getGPUTexture.ts @@ -24,10 +24,12 @@ export function getGPUTexture(device: GPUDevice, textureLike: TextureLike, autoC { if ("context" in textureLike) { + const canvasTexture = textureLike; + // 确保在提交之前使用正确的画布纹理。 reactive(webgpuEvents).preSubmit; + reactive(canvasTexture)._canvasSizeVersion; - const canvasTexture = textureLike; const context = getGPUCanvasContext(device, canvasTexture.context); const gpuTexture = context.getCurrentTexture(); -- Gitee From 85e638b40613f01e24ddcd1c01e95e21587073bf Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Sat, 29 Mar 2025 16:18:03 +0800 Subject: [PATCH 199/214] =?UTF-8?q?refactor(src):=20=E9=87=8D=E6=9E=84=20G?= =?UTF-8?q?PU=20=E7=BA=B9=E7=90=86=E8=A7=86=E5=9B=BE=E7=9A=84=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将纹理视图的属性逐个解构并响应式处理 - 优化纹理视图的创建参数,明确指定各属性 - 调整视图标签的生成逻辑,使用纹理的 label 属性 --- src/caches/getGPUTextureView.ts | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/caches/getGPUTextureView.ts b/src/caches/getGPUTextureView.ts index 37665d0..b7f482f 100644 --- a/src/caches/getGPUTextureView.ts +++ b/src/caches/getGPUTextureView.ts @@ -14,14 +14,30 @@ export function getGPUTextureView(device: GPUDevice, view: TextureView) // 监听 const r_view = reactive(view); r_view.texture; + r_view.label; + r_view.format; + r_view.dimension; + r_view.usage; + r_view.aspect; + r_view.baseMipLevel; + r_view.baseArrayLayer; + r_view.mipLevelCount; + r_view.arrayLayerCount; // 执行 - const { texture } = view; + const { texture, label, format, dimension, usage, aspect, baseMipLevel, baseArrayLayer, mipLevelCount, arrayLayerCount } = view; const gpuTexture = getGPUTexture(device, texture); const textureView = gpuTexture.createView({ - label: "GPU纹理视图", - ...r_view, - dimension: r_view.dimension ?? (texture as Texture).dimension, + label: label ?? `${gpuTexture.label}视图`, + format, + dimension: dimension ?? (texture as Texture).dimension, + usage, + aspect, + baseMipLevel, + mipLevelCount, + baseArrayLayer, + arrayLayerCount, + }); return textureView; -- Gitee From f61c8d19b626f17c0b08306a7fe54e9aeb3834be Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 10:41:38 +0800 Subject: [PATCH 200/214] =?UTF-8?q?fix(WebGPUBase):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=A1=B6=E7=82=B9=E5=B1=9E=E6=80=A7=E7=BC=93=E5=86=B2=E5=8C=BA?= =?UTF-8?q?=E7=9A=84=E5=93=8D=E5=BA=94=E5=BC=8F=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在处理顶点缓冲区时,先使用 reactive() 进行监听 - 然后解构获取需要的属性,确保响应式更新 - 此修改解决了顶点属性缓冲区无法正确更新的问题 --- src/WebGPUBase.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 6dd2062..82a1b60 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -562,8 +562,14 @@ export class WebGPUBase const vertexBuffers = getNVertexBuffers(pipeline.vertex, vertices) vertexBuffers?.forEach((vertexBuffer, index) => { - const { data, offset, size } = reactive(vertexBuffer); - + // 监听 + const r_vertexBuffer = reactive(vertexBuffer); + r_vertexBuffer.data; + r_vertexBuffer.offset; + r_vertexBuffer.size; + + // 执行 + const { data, offset, size } = vertexBuffer; const buffer = getGBuffer(data); (buffer as any).label = buffer.label || (`顶点属性 ${autoVertexIndex++}`); -- Gitee From 9f63bfa7fd157e1cae99b97b8236dbd27eb138ce Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 10:48:25 +0800 Subject: [PATCH 201/214] =?UTF-8?q?refactor(caches):=20=E5=B0=86=20writeBu?= =?UTF-8?q?ffer=20=E4=B8=AD=20computed=20=E6=9B=BF=E6=8D=A2=E4=B8=BA=20eff?= =?UTF-8?q?ect=20=E5=8F=8A=E6=97=B6=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/caches/getGPUBuffer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/caches/getGPUBuffer.ts b/src/caches/getGPUBuffer.ts index 1117189..d8d1ab2 100644 --- a/src/caches/getGPUBuffer.ts +++ b/src/caches/getGPUBuffer.ts @@ -1,4 +1,4 @@ -import { ChainMap, computed, Computed, Buffer, reactive } from "@feng3d/render-api"; +import { ChainMap, computed, Computed, Buffer, reactive, effect } from "@feng3d/render-api"; /** * 除了GPU与CPU数据交换的`MAP_READ`与`MAP_WRITE`除外。 @@ -103,7 +103,7 @@ function dataChange(buffer: Buffer) function writeBuffer(device: GPUDevice, buffer: Buffer, gBuffer: GPUBuffer) { - computed(() => + return effect(() => { // 监听 const rb = reactive(buffer); @@ -153,5 +153,5 @@ function writeBuffer(device: GPUDevice, buffer: Buffer, gBuffer: GPUBuffer) // 清空写入数据 rb.writeBuffers = null; - }).value; + }); }; \ No newline at end of file -- Gitee From 4ba5240c2c2ffbfb47390477270600c3c187ebeb Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 11:00:32 +0800 Subject: [PATCH 202/214] =?UTF-8?q?refactor(WebGPUBase):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20render=20pass=20=E5=92=8C=20render=20bundle=20?= =?UTF-8?q?=E7=9A=84=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了对 render pass command 的缓存机制,提高性能 - 重构了 render bundle 的处理流程,简化了代码结构 - 移除了未使用的注释代码,提高了代码可读性 --- src/WebGPUBase.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 82a1b60..d016ba9 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -189,6 +189,9 @@ export class WebGPUBase protected runRenderPass(renderPass: RenderPass) { const device = this._device; + // const result = this._renderPassCommandMap.get(renderPass); + // if (result) return result; + const { descriptor, renderPassObjects } = renderPass; const renderPassCommand = new RenderPassCommand(); @@ -222,6 +225,8 @@ export class WebGPUBase } }); + // this._renderPassCommandMap.set(renderPass, renderPassCommand); + return renderPassCommand; } @@ -298,14 +303,7 @@ export class WebGPUBase return occlusionQueryCache; } - protected runRenderBundle(renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) - { - const renderBundleCommand = this.getGPURenderBundle(renderBundleObject, renderPassFormat); - - return renderBundleCommand; - } - - private getGPURenderBundle(renderBundleObject: RenderBundle, renderPassFormat: RenderPassFormat) + private runRenderBundle(renderPassFormat: RenderPassFormat, renderBundleObject: RenderBundle) { const gpuRenderBundleKey: GPURenderBundleKey = [renderBundleObject, renderPassFormat]; let result = gpuRenderBundleMap.get(gpuRenderBundleKey); @@ -627,6 +625,8 @@ export class WebGPUBase } }).value; } + + private _renderPassCommandMap = new WeakMap(); } let autoIndex = 0; -- Gitee From 2f8c44df780e72d9d63559a46100ddcc9539aec9 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 11:21:04 +0800 Subject: [PATCH 203/214] =?UTF-8?q?refactor(WebGPUBase):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=B8=B2=E6=9F=93=E5=91=BD=E4=BB=A4=E7=94=9F=E6=88=90?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 runRenderPassObjects、runRenderObjects 等方法,优化渲染命令生成流程 - 引入 Map 结构缓存渲染命令,提高性能 - 重构原有方法,提高代码可读性和可维护性 --- src/WebGPUBase.ts | 107 +++++++++++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 34 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index d016ba9..0cd2a64 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -16,7 +16,7 @@ import { ComputePass } from "./data/ComputePass"; import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; -import { CommandEncoderCommand, ComputeObjectCommand, ComputePassCommand, CopyBufferToBufferCommand, CopyTextureToTextureCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand, SubmitCommand } from "./internal/RenderObjectCache"; +import { CommandEncoderCommand, ComputeObjectCommand, ComputePassCommand, CopyBufferToBufferCommand, CopyTextureToTextureCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand, RenderPassObjectCommand, SubmitCommand } from "./internal/RenderObjectCache"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; @@ -197,37 +197,55 @@ export class WebGPUBase const renderPassCommand = new RenderPassCommand(); renderPassCommand.renderPassDescriptor = getGPURenderPassDescriptor(device, renderPass); - let queryIndex = 0; const renderPassFormat = getGPURenderPassFormat(descriptor); - renderPassCommand.renderPassObjects = renderPassObjects?.map((element) => + + renderPassCommand.renderPassObjects = this.runRenderPassObjects(renderPassFormat, renderPassObjects); + + return renderPassCommand; + } + + private runRenderPassObjects(renderPassFormat: RenderPassFormat, renderPassObjects: readonly RenderPassObject[]) + { + const renderPassObjectCommandsKey: RenderPassObjectCommandsKey = [renderPassObjects, renderPassFormat]; + let result = this._renderPassObjectCommandsMap.get(renderPassObjectCommandsKey); + if (result) return result.value; + + result = computed(() => { - if (!element.__type__) - { - return this.runRenderObject(renderPassFormat, element as RenderObject); - } - if (element.__type__ === "RenderObject") - { - return this.runRenderObject(renderPassFormat, element); - } - if (element.__type__ === "RenderBundle") + let queryIndex = 0; + const renderPassObjectCommands: RenderPassObjectCommand[] = renderPassObjects?.map((element) => { - return this.runRenderBundle(renderPassFormat, element); - } - if (element.__type__ === "OcclusionQuery") - { - const occlusionQueryCache = this.runRenderOcclusionQueryObject(renderPassFormat, element); - occlusionQueryCache.queryIndex = queryIndex++; - return occlusionQueryCache; - } - else - { - throw `未处理 ${(element as RenderPassObject).__type__} 类型的渲染通道对象!`; - } + if (!element.__type__) + { + return this.runRenderObject(renderPassFormat, element as RenderObject); + } + if (element.__type__ === "RenderObject") + { + return this.runRenderObject(renderPassFormat, element); + } + if (element.__type__ === "RenderBundle") + { + return this.runRenderBundle(renderPassFormat, element); + } + if (element.__type__ === "OcclusionQuery") + { + const occlusionQueryCache = this.runRenderOcclusionQueryObject(renderPassFormat, element); + occlusionQueryCache.queryIndex = queryIndex++; + return occlusionQueryCache; + } + else + { + throw `未处理 ${(element as RenderPassObject).__type__} 类型的渲染通道对象!`; + } + }); + + return renderPassObjectCommands; + }); - // this._renderPassCommandMap.set(renderPass, renderPassCommand); + this._renderPassObjectCommandsMap.set(renderPassObjectCommandsKey, result); - return renderPassCommand; + return result.value; } /** @@ -295,10 +313,7 @@ export class WebGPUBase { const occlusionQueryCache = new OcclusionQueryCache(); - occlusionQueryCache.renderObjectCaches = renderOcclusionQueryObject.renderObjects.map((renderObject) => - { - return this.runRenderObject(renderPassFormat, renderObject); - }); + occlusionQueryCache.renderObjectCaches = this.runRenderObjects(renderPassFormat, renderOcclusionQueryObject.renderObjects); return occlusionQueryCache; } @@ -324,15 +339,33 @@ export class WebGPUBase renderBundleCommand.descriptor = descriptor; + renderBundleCommand.renderObjectCaches = this.runRenderObjects(renderPassFormat, renderBundleObject.renderObjects); + + return renderBundleCommand; + }); + gpuRenderBundleMap.set(gpuRenderBundleKey, result); + + return result.value; + } + + private runRenderObjects(renderPassFormat: RenderPassFormat, renderObjects: readonly RenderObject[]) + { + const renderObjectCachesKey: RenderObjectCachesKey = [renderObjects, renderPassFormat]; + let result = this._renderObjectCachesMap.get(renderObjectCachesKey); + if (result) return result.value; + + result = computed(() => + { // - renderBundleCommand.renderObjectCaches = renderBundleObject.renderObjects.map((element) => + const renderObjectCaches = renderObjects.map((element) => { return this.runRenderObject(renderPassFormat, element as RenderObject); }); - return renderBundleCommand; + return renderObjectCaches; + }); - gpuRenderBundleMap.set(gpuRenderBundleKey, result); + this._renderObjectCachesMap.set(renderObjectCachesKey, result); return result.value; } @@ -627,6 +660,9 @@ export class WebGPUBase } private _renderPassCommandMap = new WeakMap(); + + private _renderObjectCachesMap = new ChainMap>(); + private _renderPassObjectCommandsMap = new ChainMap>(); } let autoIndex = 0; @@ -670,4 +706,7 @@ type GPURenderBundleKey = [renderBundle: RenderBundle, renderPassFormat: RenderP const gpuRenderBundleMap = new ChainMap>(); type RenderObjectCacheKey = [device: GPUDevice, renderObject: RenderObject, renderPassFormat: RenderPassFormat]; -const renderObjectCacheMap = new ChainMap>(); \ No newline at end of file +const renderObjectCacheMap = new ChainMap>(); + +type RenderObjectCachesKey = [renderObjects: readonly RenderObject[], renderPassFormat: RenderPassFormat]; +type RenderPassObjectCommandsKey = [renderPassObjects: readonly RenderPassObject[], renderPassFormat: RenderPassFormat]; \ No newline at end of file -- Gitee From 5b46c047c8987f1c55683c44deed3179f223d46a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 11:39:50 +0800 Subject: [PATCH 204/214] =?UTF-8?q?refactor(getGPUBindGroup):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20uniform=20=E7=BC=93=E5=86=B2=E5=8C=BA=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9B=B4=E6=96=B0=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 updateBufferBinding 函数中的 computed 和 ChainMap - 使用 effect 替代 computed 进行响应式更新 - 简化了缓冲区数据的更新流程 - 优化了代码结构,提高了可读性和性能 --- src/caches/getGPUBindGroup.ts | 98 +++++++++++++++-------------------- 1 file changed, 43 insertions(+), 55 deletions(-) diff --git a/src/caches/getGPUBindGroup.ts b/src/caches/getGPUBindGroup.ts index 02de841..fb6235a 100644 --- a/src/caches/getGPUBindGroup.ts +++ b/src/caches/getGPUBindGroup.ts @@ -1,4 +1,4 @@ -import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, Computed, reactive, Sampler, TextureView, UnReadonly } from "@feng3d/render-api"; +import { BindingResources, BufferBinding, BufferBindingInfo, ChainMap, computed, Computed, effect, reactive, Sampler, TextureView, UnReadonly } from "@feng3d/render-api"; import { ArrayInfo, ResourceType, StructInfo, TemplateInfo, TypeInfo } from "wgsl_reflect"; import { VideoTexture } from "../data/VideoTexture"; import { webgpuEvents } from "../eventnames"; @@ -162,74 +162,62 @@ const getGPUExternalTextureMap = new ChainMap + const size = bufferBindingInfo.size; + // 是否存在默认值。 + const hasDefautValue = !!uniformData.bufferView; + if (!hasDefautValue) { - const bufferBindingInfo = getBufferBindingInfo(type); - - const size = bufferBindingInfo.size; - // 是否存在默认值。 - const hasDefautValue = !!uniformData.bufferView; - if (!hasDefautValue) - { - (uniformData as UnReadonly).bufferView = new Uint8Array(size); - } + (uniformData as UnReadonly).bufferView = new Uint8Array(size); + } - const buffer = getGBuffer(uniformData.bufferView); - const offset = uniformData.bufferView.byteOffset; + const buffer = getGBuffer(uniformData.bufferView); + const offset = uniformData.bufferView.byteOffset; - for (let i = 0; i < bufferBindingInfo.items.length; i++) + for (let i = 0; i < bufferBindingInfo.items.length; i++) + { + const { paths, offset: itemInfoOffset, size: itemInfoSize, Cls } = bufferBindingInfo.items[i]; + // 更新数据 + effect(() => { - const { paths, offset: itemInfoOffset, size: itemInfoSize, Cls } = bufferBindingInfo.items[i]; - // 更新数据 - computed(() => + // 监听 + let value: any = reactive(uniformData); + for (let i = 0; i < paths.length; i++) { - // 监听 - let value: any = reactive(uniformData); - for (let i = 0; i < paths.length; i++) + value = value[paths[i]]; + if (value === undefined) { - value = value[paths[i]]; - if (value === undefined) + if (!hasDefautValue) { - if (!hasDefautValue) - { - console.warn(`没有找到 统一块变量属性 ${paths.join(".")} 的值!`); - } - - return; + console.warn(`没有找到 统一块变量属性 ${paths.join(".")} 的值!`); } - } - // 更新数据 - let data: Float32Array | Int32Array | Uint32Array | Int16Array; - if (typeof value === "number") - { - data = new Cls([value]); - } - else if (value.constructor.name !== Cls.name) - { - data = new Cls(value as ArrayLike); - } - else - { - data = value as any; + return; } + } - const writeBuffers = buffer.writeBuffers ?? []; - writeBuffers.push({ bufferOffset: offset + itemInfoOffset, data: data.buffer, dataOffset: data.byteOffset, size: Math.min(itemInfoSize, data.byteLength) }); - reactive(buffer).writeBuffers = writeBuffers; - }).value; - } - }); - updateBufferBindingMap.set(updateBufferBindingKey, result); + // 更新数据 + let data: Float32Array | Int32Array | Uint32Array | Int16Array; + if (typeof value === "number") + { + data = new Cls([value]); + } + else if (value.constructor.name !== Cls.name) + { + data = new Cls(value as ArrayLike); + } + else + { + data = value as any; + } - return result.value; + const writeBuffers = buffer.writeBuffers ?? []; + writeBuffers.push({ bufferOffset: offset + itemInfoOffset, data: data.buffer, dataOffset: data.byteOffset, size: Math.min(itemInfoSize, data.byteLength) }); + reactive(buffer).writeBuffers = writeBuffers; + }); + } } -type UpdateBufferBindingKey = [uniformData: BufferBinding, type: TypeInfo]; -const updateBufferBindingMap = new ChainMap>(); /** * 获取缓冲区绑定信息。 -- Gitee From c58f61c4b37ee0baf3f078c44e3b29eafdefe694 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 11:56:41 +0800 Subject: [PATCH 205/214] =?UTF-8?q?refactor(internal):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20RenderObjectCache=20=E7=B1=BB=E7=9A=84=20run=20?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 run 方法的逻辑提取到新的 runCommands 函数中 - 为 run 方法添加 commands 参数,用于传递命令数组 - 在 RenderBundleCommand 中实现命令数组的收集和执行 - 删除 RenderObjectCache 中的冗余代码和注释 --- src/internal/RenderObjectCache.ts | 101 +++++++++++++++--------------- 1 file changed, 49 insertions(+), 52 deletions(-) diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 1413efc..974dd74 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -73,58 +73,8 @@ export class RenderObjectCache implements RenderPassObjectCommand this[func as any] = undefined; } - run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder, state?: RenderObjectCache) + run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder, commands?: CommandType[], state?: RenderObjectCache) { - // this.commands.forEach((command) => - // { - // const func = command[0]; - // if (func === "setPipeline") - // { - // renderPass.setPipeline(command[1]); - // } - // else if (func === "setBindGroup") - // { - // renderPass.setBindGroup(command[1], command[2]); - // } - // else if (func === "setVertexBuffer") - // { - // renderPass.setVertexBuffer(command[1], command[2], command[3], command[4]); - // } - // else if (func === "setIndexBuffer") - // { - // renderPass.setIndexBuffer(command[1], command[2], command[3], command[4]); - // } - // else if (func === "draw") - // { - // renderPass.draw(command[1], command[2], command[3], command[4]); - // } - // else if (func === "drawIndexed") - // { - // renderPass.drawIndexed(command[1], command[2], command[3], command[4], command[5]); - // } - // else if (func === "setViewport") - // { - // if ("setViewport" in renderPass) renderPass.setViewport(command[1], command[2], command[3], command[4], command[5], command[6]); - // } - // else if (func === "setScissorRect") - // { - // if ("setScissorRect" in renderPass) renderPass.setScissorRect(command[1], command[2], command[3], command[4]); - // } - // else if (func === "setBlendConstant") - // { - // if ("setBlendConstant" in renderPass) - // renderPass.setBlendConstant(command[1]); - // } - // else if (func === "setStencilReference") - // { - // if ("setStencilReference" in renderPass) renderPass.setStencilReference(command[1]); - // } - // else - // { - // func; - // } - // }); - const { setViewport, setScissorRect, setPipeline, setBlendConstant, setStencilReference, setBindGroup, setVertexBuffer, setIndexBuffer, draw, drawIndexed } = this; if (setViewport && "setViewport" in renderPass) @@ -294,11 +244,15 @@ export class RenderBundleCommand implements RenderPassObjectCommand // const renderBundleEncoder = passEncoder.device.createRenderBundleEncoder(this.descriptor); // + const state: RenderObjectCache = {} as any; + const commands: CommandType[] = []; this.renderObjectCaches.forEach((renderObjectCache) => { - renderObjectCache.run(renderBundleEncoder); + renderObjectCache.run(renderBundleEncoder, commands, state); }); + runCommands(renderBundleEncoder, commands); + this.gpuRenderBundle = renderBundleEncoder.finish(); } @@ -427,4 +381,47 @@ export class SubmitCommand anyEmitter.emit(device.queue, GPUQueue_submit); } commandBuffers: CommandEncoderCommand[]; +} + +function runCommands(renderBundleEncoder: GPURenderBundleEncoder, commands: CommandType[]) +{ + commands.forEach((command) => + { + switch (command[0]) + { + case "setBindGroup": + renderBundleEncoder.setBindGroup(command[1], command[2], command[3]); + break; + case "setPipeline": + renderBundleEncoder.setPipeline(command[1]); + break; + case "setVertexBuffer": + renderBundleEncoder.setVertexBuffer(command[1], command[2], command[3], command[4]); + break; + case "setIndexBuffer": + renderBundleEncoder.setIndexBuffer(command[1], command[2], command[3]); + break; + case "draw": + renderBundleEncoder.draw(command[1], command[2], command[3], command[4]); + break; + case "drawIndexed": + renderBundleEncoder.drawIndexed(command[1], command[2], command[3], command[4], command[5]); + break; + case "setViewport": + renderBundleEncoder.setViewport(command[1], command[2], command[3], command[4], command[5], command[6]); + break; + case "setScissorRect": + renderBundleEncoder.setScissorRect(command[1], command[2], command[3], command[4]); + break + case "setBlendConstant": + renderBundleEncoder.setBlendConstant(command[1]); + break; + case "setStencilReference": + renderBundleEncoder.setStencilReference(command[1]); + break; + default: + console.error("RenderBundleCommand: unknown command:", command[0]); + break; + } + }); } \ No newline at end of file -- Gitee From 8ff4838dc07030d96ec9d26600645eb93cf0da36 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 13:11:33 +0800 Subject: [PATCH 206/214] =?UTF-8?q?refactor(internal):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=B8=B2=E6=9F=93=E5=91=BD=E4=BB=A4=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 RenderObjectCache 的 run 方法,增加 commands 和 state 参数 - 更新 OcclusionQueryCache 和 RenderPassCommand 以使用新的 run 方法 - 优化 runCommands 函数,支持 GPURenderPassEncoder 和 GPURenderBundleEncoder - 调整 setBindGroup 命令的参数 --- src/internal/RenderObjectCache.ts | 46 +++++++++++++++++-------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 974dd74..03af262 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -73,30 +73,30 @@ export class RenderObjectCache implements RenderPassObjectCommand this[func as any] = undefined; } - run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder, commands?: CommandType[], state?: RenderObjectCache) + run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder, commands: CommandType[], state: RenderObjectCache) { const { setViewport, setScissorRect, setPipeline, setBlendConstant, setStencilReference, setBindGroup, setVertexBuffer, setIndexBuffer, draw, drawIndexed } = this; if (setViewport && "setViewport" in renderPass) { - if (!state || state.setViewport !== setViewport) renderPass.setViewport(setViewport[1], setViewport[2], setViewport[3], setViewport[4], setViewport[5], setViewport[6]); + if (!state || state.setViewport !== setViewport) commands.push(setViewport); if (state) state.setViewport = setViewport; } if (setScissorRect && "setScissorRect" in renderPass) { - if (!state || state.setScissorRect !== setScissorRect) renderPass.setScissorRect(setScissorRect[1], setScissorRect[2], setScissorRect[3], setScissorRect[4]); + if (!state || state.setScissorRect !== setScissorRect) commands.push(setScissorRect); if (state) state.setScissorRect = setScissorRect; } - if (!state || state.setPipeline !== setPipeline) renderPass.setPipeline(setPipeline[1]); + if (!state || state.setPipeline !== setPipeline) commands.push(setPipeline); if (state) state.setPipeline = setPipeline; if (setBlendConstant && "setBlendConstant" in renderPass) { - if (!state || state.setBlendConstant !== setBlendConstant) renderPass.setBlendConstant(setBlendConstant[1]); + if (!state || state.setBlendConstant !== setBlendConstant) commands.push(setBlendConstant); if (state) state.setBlendConstant = setBlendConstant; } if (setStencilReference && "setStencilReference" in renderPass) { - if (!state || state.setStencilReference !== setStencilReference) renderPass.setStencilReference(setStencilReference[1]); + if (!state || state.setStencilReference !== setStencilReference) commands.push(setStencilReference); if (state) state.setStencilReference = setStencilReference; } if (setBindGroup) @@ -104,7 +104,7 @@ export class RenderObjectCache implements RenderPassObjectCommand if (state) state.setBindGroup ??= []; for (let i = 0, len = setBindGroup.length; i < len; i++) { - if (!state || !state.setBindGroup[i] || state.setBindGroup[i] !== setBindGroup[i]) renderPass.setBindGroup(setBindGroup[i][1], setBindGroup[i][2]); + if (!state || !state.setBindGroup[i] || state.setBindGroup[i] !== setBindGroup[i]) commands.push(setBindGroup[i]); if (state) state.setBindGroup[i] = setBindGroup[i]; } } @@ -113,22 +113,22 @@ export class RenderObjectCache implements RenderPassObjectCommand if (state) state.setVertexBuffer ??= []; for (let i = 0, len = setVertexBuffer.length; i < len; i++) { - if (!state || !state.setVertexBuffer[i] || state.setVertexBuffer[i] !== setVertexBuffer[i]) renderPass.setVertexBuffer(setVertexBuffer[i][1], setVertexBuffer[i][2], setVertexBuffer[i][3], setVertexBuffer[i][4]); + if (!state || !state.setVertexBuffer[i] || state.setVertexBuffer[i] !== setVertexBuffer[i]) commands.push(setVertexBuffer[i]); if (state) state.setVertexBuffer[i] = setVertexBuffer[i]; } } if (setIndexBuffer) { - if (!state || state.setIndexBuffer !== setIndexBuffer) renderPass.setIndexBuffer(setIndexBuffer[1], setIndexBuffer[2], setIndexBuffer[3]); + if (!state || state.setIndexBuffer !== setIndexBuffer) commands.push(setIndexBuffer); if (state) state.setIndexBuffer = setIndexBuffer; } if (draw) { - renderPass.draw(draw[1], draw[2], draw[3], draw[4]); + commands.push(draw); } if (drawIndexed) { - renderPass.drawIndexed(drawIndexed[1], drawIndexed[2], drawIndexed[3], drawIndexed[4], drawIndexed[5]); + commands.push(drawIndexed); } } @@ -219,9 +219,11 @@ export class OcclusionQueryCache implements RenderPassObjectCommand run(passEncoder: GPURenderPassEncoder) { passEncoder.beginOcclusionQuery(this.queryIndex); + const commands: CommandType[] = []; + const state: RenderObjectCache = {} as any; for (let i = 0, len = this.renderObjectCaches.length; i < len; i++) { - this.renderObjectCaches[i].run(passEncoder); + this.renderObjectCaches[i].run(passEncoder, commands, state); } passEncoder.endOcclusionQuery(); } @@ -229,7 +231,7 @@ export class OcclusionQueryCache implements RenderPassObjectCommand export interface RenderPassObjectCommand { - run(passEncoder: GPURenderPassEncoder): void; + run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder, commands: CommandType[], state: RenderObjectCache): void; } export class RenderBundleCommand implements RenderPassObjectCommand @@ -274,10 +276,14 @@ export class RenderPassCommand const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); passEncoder.device = device; + + const commands: CommandType[] = []; + const state: RenderObjectCache = {} as any; renderPassObjects?.forEach((command) => { - command.run(passEncoder); + command.run(passEncoder, commands, state); }); + runCommands(passEncoder, commands); passEncoder.end(); renderPassDescriptor.timestampWrites?.resolve(commandEncoder); @@ -383,14 +389,14 @@ export class SubmitCommand commandBuffers: CommandEncoderCommand[]; } -function runCommands(renderBundleEncoder: GPURenderBundleEncoder, commands: CommandType[]) +function runCommands(renderBundleEncoder: GPURenderBundleEncoder | GPURenderPassEncoder, commands: CommandType[]) { commands.forEach((command) => { switch (command[0]) { case "setBindGroup": - renderBundleEncoder.setBindGroup(command[1], command[2], command[3]); + renderBundleEncoder.setBindGroup(command[1], command[2]); break; case "setPipeline": renderBundleEncoder.setPipeline(command[1]); @@ -408,16 +414,16 @@ function runCommands(renderBundleEncoder: GPURenderBundleEncoder, commands: Comm renderBundleEncoder.drawIndexed(command[1], command[2], command[3], command[4], command[5]); break; case "setViewport": - renderBundleEncoder.setViewport(command[1], command[2], command[3], command[4], command[5], command[6]); + (renderBundleEncoder as GPURenderPassEncoder).setViewport(command[1], command[2], command[3], command[4], command[5], command[6]); break; case "setScissorRect": - renderBundleEncoder.setScissorRect(command[1], command[2], command[3], command[4]); + (renderBundleEncoder as GPURenderPassEncoder).setScissorRect(command[1], command[2], command[3], command[4]); break case "setBlendConstant": - renderBundleEncoder.setBlendConstant(command[1]); + (renderBundleEncoder as GPURenderPassEncoder).setBlendConstant(command[1]); break; case "setStencilReference": - renderBundleEncoder.setStencilReference(command[1]); + (renderBundleEncoder as GPURenderPassEncoder).setStencilReference(command[1]); break; default: console.error("RenderBundleCommand: unknown command:", command[0]); -- Gitee From 55726c0ca11b6407028f2f37739af4b5074c845d Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 13:49:54 +0800 Subject: [PATCH 207/214] =?UTF-8?q?refactor(internal):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20RenderObjectCache=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化了 RenderObjectCache 类的结构和逻辑 - 移除了不必要的 diff 方法 - 简化了命令的存储和执行过程 - 提高了代码的可读性和性能 --- src/internal/RenderObjectCache.ts | 188 +++++++++++------------------- 1 file changed, 65 insertions(+), 123 deletions(-) diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 03af262..8c08144 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -32,26 +32,23 @@ export class RenderObjectCache implements RenderPassObjectCommand protected setPipeline: [func: "setPipeline", pipeline: GPURenderPipeline]; protected setBlendConstant?: [func: "setBlendConstant", color: GPUColor]; protected setStencilReference?: [func: "setStencilReference", reference: GPUStencilValue]; - protected setBindGroup?: [func: "setBindGroup", index: number, bindGroup: GPUBindGroup][]; - protected setVertexBuffer?: [func: "setVertexBuffer", slot: GPUIndex32, buffer: GPUBuffer, offset?: GPUSize64, size?: GPUSize64][]; + protected setBindGroup?: [func: "setBindGroup", index: number, bindGroup: GPUBindGroup][] = []; + protected setVertexBuffer?: [func: "setVertexBuffer", slot: GPUIndex32, buffer: GPUBuffer, offset?: GPUSize64, size?: GPUSize64][] = []; protected setIndexBuffer?: [func: "setIndexBuffer", buffer: GPUBuffer, indexFormat: GPUIndexFormat, offset?: GPUSize64, size?: GPUSize64]; protected draw?: [func: "draw", vertexCount: GPUSize32, instanceCount?: GPUSize32, firstVertex?: GPUSize32, firstInstance?: GPUSize32]; protected drawIndexed?: [func: "drawIndexed", indexCount: GPUSize32, instanceCount?: GPUSize32, firstIndex?: GPUSize32, baseVertex?: GPUSignedOffset32, firstInstance?: GPUSize32]; - // private commands: CommandType[] = []; push(command: CommandType) { const func = command[0]; if (func === "setBindGroup") { - if (!this.setBindGroup) this.setBindGroup = []; - this.setBindGroup.push(command); + this.setBindGroup[command[1]] = command; return; } else if (func === "setVertexBuffer") { - if (!this.setVertexBuffer) this.setVertexBuffer = []; - this.setVertexBuffer.push(command); + this.setVertexBuffer[command[1]] = command; return; } command = setVaule(cache, command); @@ -77,137 +74,82 @@ export class RenderObjectCache implements RenderPassObjectCommand { const { setViewport, setScissorRect, setPipeline, setBlendConstant, setStencilReference, setBindGroup, setVertexBuffer, setIndexBuffer, draw, drawIndexed } = this; - if (setViewport && "setViewport" in renderPass) + if (state) { - if (!state || state.setViewport !== setViewport) commands.push(setViewport); - if (state) state.setViewport = setViewport; - } - if (setScissorRect && "setScissorRect" in renderPass) - { - if (!state || state.setScissorRect !== setScissorRect) commands.push(setScissorRect); - if (state) state.setScissorRect = setScissorRect; - } - if (!state || state.setPipeline !== setPipeline) commands.push(setPipeline); - if (state) state.setPipeline = setPipeline; - if (setBlendConstant && "setBlendConstant" in renderPass) - { - if (!state || state.setBlendConstant !== setBlendConstant) commands.push(setBlendConstant); - if (state) state.setBlendConstant = setBlendConstant; - } - if (setStencilReference && "setStencilReference" in renderPass) - { - if (!state || state.setStencilReference !== setStencilReference) commands.push(setStencilReference); - if (state) state.setStencilReference = setStencilReference; - } - if (setBindGroup) - { - if (state) state.setBindGroup ??= []; - for (let i = 0, len = setBindGroup.length; i < len; i++) + if (setViewport && "setViewport" in renderPass) { - if (!state || !state.setBindGroup[i] || state.setBindGroup[i] !== setBindGroup[i]) commands.push(setBindGroup[i]); - if (state) state.setBindGroup[i] = setBindGroup[i]; + if (state.setViewport !== setViewport && setViewport) + { + commands.push(setViewport); + state.setViewport = setViewport; + } + if (state.setScissorRect !== setScissorRect && setScissorRect) + { + commands.push(setScissorRect); + state.setScissorRect = setScissorRect; + } + if (state.setBlendConstant !== setBlendConstant && setBlendConstant) + { + commands.push(setBlendConstant); + state.setBlendConstant = setBlendConstant; + } + if (state.setStencilReference !== setStencilReference && setStencilReference) + { + commands.push(setStencilReference); + } } - } - if (setVertexBuffer) - { - if (state) state.setVertexBuffer ??= []; - for (let i = 0, len = setVertexBuffer.length; i < len; i++) + if (state.setPipeline !== setPipeline) { - if (!state || !state.setVertexBuffer[i] || state.setVertexBuffer[i] !== setVertexBuffer[i]) commands.push(setVertexBuffer[i]); - if (state) state.setVertexBuffer[i] = setVertexBuffer[i]; + commands.push(setPipeline); + state.setPipeline = setPipeline; } - } - if (setIndexBuffer) - { - if (!state || state.setIndexBuffer !== setIndexBuffer) commands.push(setIndexBuffer); - if (state) state.setIndexBuffer = setIndexBuffer; - } - if (draw) - { - commands.push(draw); - } - if (drawIndexed) - { - commands.push(drawIndexed); - } - } - - static diff(a: RenderObjectCache, b: RenderObjectCache) - { - if (!a) return b; - - const result: RenderObjectCache = {} as any; - - if (a.setViewport !== b.setViewport && b.setViewport && (a.setViewport[0] !== b.setViewport[0] || a.setViewport[1] !== b.setViewport[1] || a.setViewport[2] !== b.setViewport[2] || a.setViewport[3] !== b.setViewport[3] || a.setViewport[4] !== b.setViewport[4] || a.setViewport[5] !== b.setViewport[5])) - { - result.setViewport = b.setViewport; - } - if (b.setScissorRect && (!a.setScissorRect || b.setScissorRect.some((v, i) => v !== a.setScissorRect[i]))) - { - result.setScissorRect = b.setScissorRect; - } - if (b.setPipeline && (!a.setPipeline || b.setPipeline.some((v, i) => v !== a.setPipeline[i]))) - { - result.setPipeline = b.setPipeline; - } - if (b.setBlendConstant && (!a.setBlendConstant || b.setBlendConstant.some((v, i) => v !== a.setBlendConstant[i]))) - { - result.setBlendConstant = b.setBlendConstant; - } - if (b.setStencilReference && (!a.setStencilReference || b.setStencilReference.some((v, i) => v !== a.setStencilReference[i]))) - { - result.setStencilReference = b.setStencilReference; - } - result.setBindGroup = []; - if (b.setBindGroup) - { - if (!a.setBindGroup) + for (let i = 0, len = setBindGroup.length; i < len; i++) { - result.setBindGroup = b.setBindGroup; + if (state.setBindGroup[i] !== setBindGroup[i] && setBindGroup[i]) + { + commands.push(setBindGroup[i]); + state.setBindGroup[i] = setBindGroup[i]; + } } - else + for (let i = 0, len = setVertexBuffer.length; i < len; i++) { - for (let i = 0, len = b.setBindGroup.length; i < len; i++) + if (state.setVertexBuffer[i] !== setVertexBuffer[i]) { - if (!a.setBindGroup[i] || b.setBindGroup[i].some((v, i) => v !== a.setBindGroup[i][i])) - { - result.setBindGroup.push(b.setBindGroup[i]); - } + commands.push(setVertexBuffer[i]); + state.setVertexBuffer[i] = setVertexBuffer[i]; } } + if (state.setIndexBuffer !== setIndexBuffer && setIndexBuffer) + { + commands.push(setIndexBuffer); + state.setIndexBuffer = setIndexBuffer; + } + draw && commands.push(draw); + drawIndexed && commands.push(drawIndexed); } - result.setVertexBuffer = []; - if (b.setVertexBuffer) + else { - if (!a.setVertexBuffer) + if (setViewport && "setViewport" in renderPass) { - result.setVertexBuffer = b.setVertexBuffer; + setViewport && commands.push(setViewport); + setScissorRect && commands.push(setScissorRect); + setBlendConstant && commands.push(setBlendConstant); + setStencilReference && commands.push(setStencilReference); } - else + commands.push(setPipeline); + for (let i = 0, len = setBindGroup.length; i < len; i++) { - for (let i = 0, len = b.setVertexBuffer.length; i < len; i++) - { - if (!a.setVertexBuffer[i] || b.setVertexBuffer[i].some((v, j) => v !== a.setVertexBuffer[i][j])) - { - result.setVertexBuffer.push(b.setVertexBuffer[i]); - } - } + commands.push(setBindGroup[i]); } + if (state) state.setVertexBuffer ??= []; + for (let i = 0, len = setVertexBuffer.length; i < len; i++) + { + commands.push(setVertexBuffer[i]); + } + setIndexBuffer && commands.push(setIndexBuffer); + draw && commands.push(draw); + drawIndexed && commands.push(drawIndexed); } - if (b.setIndexBuffer && (!a.setIndexBuffer || b.setIndexBuffer.some((v, i) => v !== a.setIndexBuffer[i]))) - { - result.setIndexBuffer = b.setIndexBuffer; - } - if (b.draw && (!a.draw || b.draw.some((v, i) => v !== a.draw[i]))) - { - result.draw = b.draw; - } - if (b.drawIndexed && (!a.drawIndexed || b.drawIndexed.some((v, i) => v !== a.drawIndexed[i]))) - { - result.drawIndexed = b.drawIndexed; - } - - return result; } } @@ -220,7 +162,7 @@ export class OcclusionQueryCache implements RenderPassObjectCommand { passEncoder.beginOcclusionQuery(this.queryIndex); const commands: CommandType[] = []; - const state: RenderObjectCache = {} as any; + const state = new RenderObjectCache(); for (let i = 0, len = this.renderObjectCaches.length; i < len; i++) { this.renderObjectCaches[i].run(passEncoder, commands, state); @@ -246,8 +188,8 @@ export class RenderBundleCommand implements RenderPassObjectCommand // const renderBundleEncoder = passEncoder.device.createRenderBundleEncoder(this.descriptor); // - const state: RenderObjectCache = {} as any; const commands: CommandType[] = []; + const state = new RenderObjectCache(); this.renderObjectCaches.forEach((renderObjectCache) => { renderObjectCache.run(renderBundleEncoder, commands, state); @@ -278,7 +220,7 @@ export class RenderPassCommand passEncoder.device = device; const commands: CommandType[] = []; - const state: RenderObjectCache = {} as any; + const state = new RenderObjectCache(); renderPassObjects?.forEach((command) => { command.run(passEncoder, commands, state); -- Gitee From 1e7d9f49a0eb73e70cba6cf9c6792220bcbc42b5 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 13:56:06 +0800 Subject: [PATCH 208/214] =?UTF-8?q?perf(internal):=20=E4=BC=98=E5=8C=96=20?= =?UTF-8?q?RenderObjectCache=20=E4=B8=AD=E7=9A=84=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 commandMap 以缓存和重用命令,减少内存分配 - 优化 push 方法,使用缓存的命令对象 - 添加 ChainMap 类以支持命令缓存 --- src/internal/RenderObjectCache.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 8c08144..afc5d34 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -40,6 +40,17 @@ export class RenderObjectCache implements RenderPassObjectCommand push(command: CommandType) { + let command1 = commandMap.get(command); + if (!command1) + { + command1 = command; + commandMap.set(command, command1); + } + else + { + command = command1; + } + const func = command[0]; if (func === "setBindGroup") { @@ -372,4 +383,6 @@ function runCommands(renderBundleEncoder: GPURenderBundleEncoder | GPURenderPass break; } }); -} \ No newline at end of file +} + +const commandMap = new ChainMap(); \ No newline at end of file -- Gitee From d110338e60a6c97ea6fdbd584e947017e05cc085 Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 14:19:00 +0800 Subject: [PATCH 209/214] =?UTF-8?q?refactor(internal):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20RenderObjectCache=20=E4=B8=AD=E7=9A=84=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E6=89=A7=E8=A1=8C=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将命令执行逻辑从 switch 语句改为 if-else 结构 - 优化了命令的执行流程,减少了冗余的类型转换和方法调用 - 提高了代码的可读性和可维护性 --- src/internal/RenderObjectCache.ts | 45 +++++++------------------------ 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index afc5d34..1fbaaab 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -344,45 +344,18 @@ export class SubmitCommand function runCommands(renderBundleEncoder: GPURenderBundleEncoder | GPURenderPassEncoder, commands: CommandType[]) { - commands.forEach((command) => + for (let i = 0, n = commands.length; i < n; i++) { - switch (command[0]) + const command = commands[i]; + if (command[0] === "setBindGroup") { - case "setBindGroup": - renderBundleEncoder.setBindGroup(command[1], command[2]); - break; - case "setPipeline": - renderBundleEncoder.setPipeline(command[1]); - break; - case "setVertexBuffer": - renderBundleEncoder.setVertexBuffer(command[1], command[2], command[3], command[4]); - break; - case "setIndexBuffer": - renderBundleEncoder.setIndexBuffer(command[1], command[2], command[3]); - break; - case "draw": - renderBundleEncoder.draw(command[1], command[2], command[3], command[4]); - break; - case "drawIndexed": - renderBundleEncoder.drawIndexed(command[1], command[2], command[3], command[4], command[5]); - break; - case "setViewport": - (renderBundleEncoder as GPURenderPassEncoder).setViewport(command[1], command[2], command[3], command[4], command[5], command[6]); - break; - case "setScissorRect": - (renderBundleEncoder as GPURenderPassEncoder).setScissorRect(command[1], command[2], command[3], command[4]); - break - case "setBlendConstant": - (renderBundleEncoder as GPURenderPassEncoder).setBlendConstant(command[1]); - break; - case "setStencilReference": - (renderBundleEncoder as GPURenderPassEncoder).setStencilReference(command[1]); - break; - default: - console.error("RenderBundleCommand: unknown command:", command[0]); - break; + renderBundleEncoder.setBindGroup(command[1], command[2]); } - }); + else + { + renderBundleEncoder[command[0]](command[1], command[2], command[3], command[4], command[5], command[6]); + } + } } const commandMap = new ChainMap(); \ No newline at end of file -- Gitee From 9b65f4026a6b223c641feb9aa40e71f7b584808a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 14:48:31 +0800 Subject: [PATCH 210/214] =?UTF-8?q?refactor(internal):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20RenderObjectCache=20=E5=92=8C=20RenderBundleCommand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化了 RenderObjectCache 中的命令生成逻辑,提高了代码的可读性和效率 - 改进了 RenderBundleCommand 的执行流程,支持过滤掉不适用于 render bundle 的命令 - 增加了对 executeBundles 命令的支持 --- src/internal/RenderObjectCache.ts | 115 ++++++++++++------------------ 1 file changed, 47 insertions(+), 68 deletions(-) diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 1fbaaab..e088ff1 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -23,6 +23,7 @@ type CommandType = | [func: "drawIndexed", indexCount: GPUSize32, instanceCount?: GPUSize32, firstIndex?: GPUSize32, baseVertex?: GPUSignedOffset32, firstInstance?: GPUSize32] | [func: "setBlendConstant", color: GPUColor] | [func: "setStencilReference", reference: GPUStencilValue] + | [func: "executeBundles", bundles: GPURenderBundle[]] ; export class RenderObjectCache implements RenderPassObjectCommand @@ -85,82 +86,53 @@ export class RenderObjectCache implements RenderPassObjectCommand { const { setViewport, setScissorRect, setPipeline, setBlendConstant, setStencilReference, setBindGroup, setVertexBuffer, setIndexBuffer, draw, drawIndexed } = this; - if (state) + if (state.setViewport !== setViewport && setViewport) { - if (setViewport && "setViewport" in renderPass) - { - if (state.setViewport !== setViewport && setViewport) - { - commands.push(setViewport); - state.setViewport = setViewport; - } - if (state.setScissorRect !== setScissorRect && setScissorRect) - { - commands.push(setScissorRect); - state.setScissorRect = setScissorRect; - } - if (state.setBlendConstant !== setBlendConstant && setBlendConstant) - { - commands.push(setBlendConstant); - state.setBlendConstant = setBlendConstant; - } - if (state.setStencilReference !== setStencilReference && setStencilReference) - { - commands.push(setStencilReference); - } - } - if (state.setPipeline !== setPipeline) - { - commands.push(setPipeline); - state.setPipeline = setPipeline; - } - for (let i = 0, len = setBindGroup.length; i < len; i++) - { - if (state.setBindGroup[i] !== setBindGroup[i] && setBindGroup[i]) - { - commands.push(setBindGroup[i]); - state.setBindGroup[i] = setBindGroup[i]; - } - } - for (let i = 0, len = setVertexBuffer.length; i < len; i++) - { - if (state.setVertexBuffer[i] !== setVertexBuffer[i]) - { - commands.push(setVertexBuffer[i]); - state.setVertexBuffer[i] = setVertexBuffer[i]; - } - } - if (state.setIndexBuffer !== setIndexBuffer && setIndexBuffer) - { - commands.push(setIndexBuffer); - state.setIndexBuffer = setIndexBuffer; - } - draw && commands.push(draw); - drawIndexed && commands.push(drawIndexed); + commands.push(setViewport); + state.setViewport = setViewport; } - else + if (state.setScissorRect !== setScissorRect && setScissorRect) + { + commands.push(setScissorRect); + state.setScissorRect = setScissorRect; + } + if (state.setBlendConstant !== setBlendConstant && setBlendConstant) + { + commands.push(setBlendConstant); + state.setBlendConstant = setBlendConstant; + } + if (state.setStencilReference !== setStencilReference && setStencilReference) + { + commands.push(setStencilReference); + } + if (state.setPipeline !== setPipeline) { - if (setViewport && "setViewport" in renderPass) - { - setViewport && commands.push(setViewport); - setScissorRect && commands.push(setScissorRect); - setBlendConstant && commands.push(setBlendConstant); - setStencilReference && commands.push(setStencilReference); - } commands.push(setPipeline); - for (let i = 0, len = setBindGroup.length; i < len; i++) + state.setPipeline = setPipeline; + } + for (let i = 0, len = setBindGroup.length; i < len; i++) + { + if (state.setBindGroup[i] !== setBindGroup[i] && setBindGroup[i]) { commands.push(setBindGroup[i]); + state.setBindGroup[i] = setBindGroup[i]; } - if (state) state.setVertexBuffer ??= []; - for (let i = 0, len = setVertexBuffer.length; i < len; i++) + } + for (let i = 0, len = setVertexBuffer.length; i < len; i++) + { + if (state.setVertexBuffer[i] !== setVertexBuffer[i]) { commands.push(setVertexBuffer[i]); + state.setVertexBuffer[i] = setVertexBuffer[i]; } - setIndexBuffer && commands.push(setIndexBuffer); - draw && commands.push(draw); - drawIndexed && commands.push(drawIndexed); } + if (state.setIndexBuffer !== setIndexBuffer && setIndexBuffer) + { + commands.push(setIndexBuffer); + state.setIndexBuffer = setIndexBuffer; + } + draw && commands.push(draw); + drawIndexed && commands.push(drawIndexed); } } @@ -192,7 +164,7 @@ export class RenderBundleCommand implements RenderPassObjectCommand gpuRenderBundle: GPURenderBundle; descriptor: GPURenderBundleEncoderDescriptor; renderObjectCaches: RenderObjectCache[]; - run(passEncoder: GPURenderPassEncoder): void + run(passEncoder: GPURenderPassEncoder, commands: CommandType[], state: RenderObjectCache): void { if (!this.gpuRenderBundle) { @@ -206,12 +178,19 @@ export class RenderBundleCommand implements RenderPassObjectCommand renderObjectCache.run(renderBundleEncoder, commands, state); }); - runCommands(renderBundleEncoder, commands); + const bundleCommands = commands.filter((command) => ( + command[0] !== "setViewport" + && command[0] !== "setScissorRect" + && command[0] !== "setBlendConstant" + && command[0] !== "setStencilReference" + )); + + runCommands(renderBundleEncoder, bundleCommands); this.gpuRenderBundle = renderBundleEncoder.finish(); } - passEncoder.executeBundles([this.gpuRenderBundle]); + commands.push(["executeBundles", [this.gpuRenderBundle]]); } } -- Gitee From 6d653f475d67fd565c227c3aa54790d9979cdddf Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 14:58:29 +0800 Subject: [PATCH 211/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=20RenderBundleCommand=20=E5=88=9D=E5=A7=8B=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 renderObjectCaches 的处理逻辑移至 WebGPUBase 类中 - 在 WebGPUBase 中生成并过滤 bundleCommands - 优化 RenderBundleCommand 类结构,存储预处理的 bundleCommands - 调整 RenderObjectCache 类,导出 CommandType 供外部使用 --- src/WebGPUBase.ts | 19 +++++++++++++++++-- src/internal/RenderObjectCache.ts | 20 +++----------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 0cd2a64..63a2484 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -16,7 +16,7 @@ import { ComputePass } from "./data/ComputePass"; import "./data/polyfills/RenderObject"; import "./data/polyfills/RenderPass"; import { RenderBundle } from "./data/RenderBundle"; -import { CommandEncoderCommand, ComputeObjectCommand, ComputePassCommand, CopyBufferToBufferCommand, CopyTextureToTextureCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand, RenderPassObjectCommand, SubmitCommand } from "./internal/RenderObjectCache"; +import { CommandEncoderCommand, CommandType, ComputeObjectCommand, ComputePassCommand, CopyBufferToBufferCommand, CopyTextureToTextureCommand, OcclusionQueryCache, RenderBundleCommand, RenderObjectCache, RenderPassCommand, RenderPassObjectCommand, SubmitCommand } from "./internal/RenderObjectCache"; import { RenderPassFormat } from "./internal/RenderPassFormat"; import { copyDepthTexture } from "./utils/copyDepthTexture"; import { getGPUDevice } from "./utils/getGPUDevice"; @@ -339,7 +339,22 @@ export class WebGPUBase renderBundleCommand.descriptor = descriptor; - renderBundleCommand.renderObjectCaches = this.runRenderObjects(renderPassFormat, renderBundleObject.renderObjects); + const renderObjectCaches = this.runRenderObjects(renderPassFormat, renderBundleObject.renderObjects); + + // + const commands: CommandType[] = []; + const state = new RenderObjectCache(); + renderObjectCaches.forEach((renderObjectCache) => + { + renderObjectCache.run(undefined, commands, state); + }); + + renderBundleCommand.bundleCommands = commands.filter((command) => ( + command[0] !== "setViewport" + && command[0] !== "setScissorRect" + && command[0] !== "setBlendConstant" + && command[0] !== "setStencilReference" + )); return renderBundleCommand; }); diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index e088ff1..36f3604 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -12,7 +12,7 @@ function setVaule>(cache: ChainMap, keys: T): T return keys; } -type CommandType = +export type CommandType = | [func: "setViewport", x: number, y: number, width: number, height: number, minDepth: number, maxDepth: number] | [func: "setScissorRect", x: GPUIntegerCoordinate, y: GPUIntegerCoordinate, width: GPUIntegerCoordinate, height: GPUIntegerCoordinate] | [func: "setPipeline", pipeline: GPURenderPipeline] @@ -163,29 +163,15 @@ export class RenderBundleCommand implements RenderPassObjectCommand { gpuRenderBundle: GPURenderBundle; descriptor: GPURenderBundleEncoderDescriptor; - renderObjectCaches: RenderObjectCache[]; + bundleCommands: CommandType[]; run(passEncoder: GPURenderPassEncoder, commands: CommandType[], state: RenderObjectCache): void { if (!this.gpuRenderBundle) { // const renderBundleEncoder = passEncoder.device.createRenderBundleEncoder(this.descriptor); - // - const commands: CommandType[] = []; - const state = new RenderObjectCache(); - this.renderObjectCaches.forEach((renderObjectCache) => - { - renderObjectCache.run(renderBundleEncoder, commands, state); - }); - - const bundleCommands = commands.filter((command) => ( - command[0] !== "setViewport" - && command[0] !== "setScissorRect" - && command[0] !== "setBlendConstant" - && command[0] !== "setStencilReference" - )); - runCommands(renderBundleEncoder, bundleCommands); + runCommands(renderBundleEncoder, this.bundleCommands); this.gpuRenderBundle = renderBundleEncoder.finish(); } -- Gitee From d61468d6580f1aee7b126cf04804ff635ab8e4dd Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 15:07:51 +0800 Subject: [PATCH 212/214] =?UTF-8?q?refactor(internal):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20OcclusionQueryCache=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 beginOcclusionQuery 和 endOcclusionQuery 方法调用移至 RenderObjectCache - 优化 OcclusionQueryCache.run 方法,减少重复代码 - 调整命令数组结构,提高可读性 --- src/internal/RenderObjectCache.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 36f3604..848a154 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -24,6 +24,8 @@ export type CommandType = | [func: "setBlendConstant", color: GPUColor] | [func: "setStencilReference", reference: GPUStencilValue] | [func: "executeBundles", bundles: GPURenderBundle[]] + | [func: "beginOcclusionQuery", queryIndex: GPUSize32] + | [func: "endOcclusionQuery"] ; export class RenderObjectCache implements RenderPassObjectCommand @@ -141,16 +143,14 @@ export class OcclusionQueryCache implements RenderPassObjectCommand queryIndex: number; renderObjectCaches: RenderObjectCache[]; - run(passEncoder: GPURenderPassEncoder) + run(passEncoder: GPURenderPassEncoder, commands: CommandType[], state: RenderObjectCache) { - passEncoder.beginOcclusionQuery(this.queryIndex); - const commands: CommandType[] = []; - const state = new RenderObjectCache(); + commands.push(["beginOcclusionQuery", this.queryIndex]); for (let i = 0, len = this.renderObjectCaches.length; i < len; i++) { - this.renderObjectCaches[i].run(passEncoder, commands, state); + this.renderObjectCaches[i].run(undefined, commands, state); } - passEncoder.endOcclusionQuery(); + commands.push(["endOcclusionQuery"]); } } -- Gitee From 8bba4206012df6a7d3350bea35fc82546c6af47b Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 15:16:15 +0800 Subject: [PATCH 213/214] =?UTF-8?q?refactor(WebGPU):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=91=BD=E4=BB=A4=E7=9A=84=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 renderPassObjects 的处理逻辑移出 renderPassCommand - 新增 renderPassObjectCommands 数组来存储处理结果 - 在 RenderObjectCache 和相关类中修改 run 方法签名 - 更新 RenderPassCommand 结构,使用 commands 数组替代 renderPassObjects --- src/WebGPUBase.ts | 10 ++++++++-- src/internal/RenderObjectCache.ts | 20 +++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 63a2484..405d855 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -199,7 +199,14 @@ export class WebGPUBase const renderPassFormat = getGPURenderPassFormat(descriptor); - renderPassCommand.renderPassObjects = this.runRenderPassObjects(renderPassFormat, renderPassObjects); + const renderPassObjectCommands = this.runRenderPassObjects(renderPassFormat, renderPassObjects); + const commands: CommandType[] = []; + const state = new RenderObjectCache(); + renderPassObjectCommands?.forEach((command) => + { + command.run(device, commands, state); + }); + renderPassCommand.commands = commands; return renderPassCommand; } @@ -240,7 +247,6 @@ export class WebGPUBase }); return renderPassObjectCommands; - }); this._renderPassObjectCommandsMap.set(renderPassObjectCommandsKey, result); diff --git a/src/internal/RenderObjectCache.ts b/src/internal/RenderObjectCache.ts index 848a154..8f9e746 100644 --- a/src/internal/RenderObjectCache.ts +++ b/src/internal/RenderObjectCache.ts @@ -84,7 +84,7 @@ export class RenderObjectCache implements RenderPassObjectCommand this[func as any] = undefined; } - run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder, commands: CommandType[], state: RenderObjectCache) + run(device: GPUDevice, commands: CommandType[], state: RenderObjectCache) { const { setViewport, setScissorRect, setPipeline, setBlendConstant, setStencilReference, setBindGroup, setVertexBuffer, setIndexBuffer, draw, drawIndexed } = this; @@ -143,7 +143,7 @@ export class OcclusionQueryCache implements RenderPassObjectCommand queryIndex: number; renderObjectCaches: RenderObjectCache[]; - run(passEncoder: GPURenderPassEncoder, commands: CommandType[], state: RenderObjectCache) + run(device: GPUDevice, commands: CommandType[], state: RenderObjectCache) { commands.push(["beginOcclusionQuery", this.queryIndex]); for (let i = 0, len = this.renderObjectCaches.length; i < len; i++) @@ -156,7 +156,7 @@ export class OcclusionQueryCache implements RenderPassObjectCommand export interface RenderPassObjectCommand { - run(renderPass: GPURenderPassEncoder | GPURenderBundleEncoder, commands: CommandType[], state: RenderObjectCache): void; + run(device: GPUDevice, commands: CommandType[], state: RenderObjectCache): void; } export class RenderBundleCommand implements RenderPassObjectCommand @@ -164,12 +164,12 @@ export class RenderBundleCommand implements RenderPassObjectCommand gpuRenderBundle: GPURenderBundle; descriptor: GPURenderBundleEncoderDescriptor; bundleCommands: CommandType[]; - run(passEncoder: GPURenderPassEncoder, commands: CommandType[], state: RenderObjectCache): void + run(device: GPUDevice, commands: CommandType[], state: RenderObjectCache): void { if (!this.gpuRenderBundle) { // - const renderBundleEncoder = passEncoder.device.createRenderBundleEncoder(this.descriptor); + const renderBundleEncoder = device.createRenderBundleEncoder(this.descriptor); runCommands(renderBundleEncoder, this.bundleCommands); @@ -189,18 +189,12 @@ export class RenderPassCommand { run(commandEncoder: GPUCommandEncoder) { - const { renderPassDescriptor, renderPassObjects } = this; + const { renderPassDescriptor, commands } = this; const { device } = commandEncoder; const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); passEncoder.device = device; - const commands: CommandType[] = []; - const state = new RenderObjectCache(); - renderPassObjects?.forEach((command) => - { - command.run(passEncoder, commands, state); - }); runCommands(passEncoder, commands); passEncoder.end(); @@ -208,7 +202,7 @@ export class RenderPassCommand renderPassDescriptor.occlusionQuerySet?.resolve(commandEncoder); } renderPassDescriptor: GPURenderPassDescriptor; - renderPassObjects: RenderPassObjectCommand[]; + commands: CommandType[] } export class ComputeObjectCommand -- Gitee From c7b6c6f6e3cfa043d64e37f89cc7021df8547d4a Mon Sep 17 00:00:00 2001 From: feng <908087098@qq.com> Date: Wed, 2 Apr 2025 16:22:12 +0800 Subject: [PATCH 214/214] =?UTF-8?q?refactor(webgpu):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E6=B5=81=E7=A8=8B=E5=92=8C=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整了 renderBundles 示例中的渲染逻辑 - 重构了 WebGPUBase 类中的 renderPass 命令生成过程 - 优化了 getGPURenderPassDescriptor 和相关缓存的实现 - 引入了 effect 函数替代 computed,简化了响应式处理 --- examples/src/webgpu/renderBundles/index.ts | 47 ++++++++++-------- src/WebGPUBase.ts | 37 ++++++++------ src/caches/getGPURenderPassDescriptor.ts | 57 ++++++++++------------ 3 files changed, 76 insertions(+), 65 deletions(-) diff --git a/examples/src/webgpu/renderBundles/index.ts b/examples/src/webgpu/renderBundles/index.ts index 875f140..899f4fe 100644 --- a/examples/src/webgpu/renderBundles/index.ts +++ b/examples/src/webgpu/renderBundles/index.ts @@ -24,7 +24,7 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => useRenderBundles: true, asteroidCount: 5000, }; - gui.add(settings, "useRenderBundles"); + gui.add(settings, "useRenderBundles").onChange(onUseRenderBundlesChanged); gui.add(settings, "asteroidCount", 1000, 10000, 1000).onChange(() => { // If the content of the scene changes the render bundle must be recreated. @@ -275,6 +275,19 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => return ros; } + const renderPass: RenderPass = { + descriptor: renderPassDescriptor, + renderPassObjects: [], + }; + + const submit: Submit = { + commandEncoders: [ + { + passEncoders: [renderPass], + } + ] + }; + // The render bundle can be encoded once and re-used as many times as needed. // Because it encodes all of the commands needed to render at the GPU level, // those commands will not need to execute the associated JavaScript code upon @@ -297,30 +310,12 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => renderObjects: renderScene(), }; renderBundle = renderBundleEncoder; + onUseRenderBundlesChanged(); } updateRenderBundle(); - const renderPass: RenderPass = { - descriptor: renderPassDescriptor, - renderPassObjects: [], - }; - - const submit: Submit = { - commandEncoders: [ - { - passEncoders: [renderPass], - } - ] - }; - - function frame() + function onUseRenderBundlesChanged() { - stats.begin(); - - const transformationMatrix = getTransformationMatrix(); - - reactive(getGBuffer(uniformBuffer)).writeBuffers = [{ data: transformationMatrix }]; - if (settings.useRenderBundles) { // Executing a bundle is equivalent to calling all of the commands encoded @@ -334,6 +329,16 @@ const init = async (canvas: HTMLCanvasElement, gui: GUI, stats) => // JavaScript virtual machine and re-validated each time. reactive(renderPass).renderPassObjects = renderBundle.renderObjects; } + } + onUseRenderBundlesChanged(); + + function frame() + { + stats.begin(); + + const transformationMatrix = getTransformationMatrix(); + + reactive(getGBuffer(uniformBuffer)).writeBuffers = [{ data: transformationMatrix }]; webgpu.submit(submit); diff --git a/src/WebGPUBase.ts b/src/WebGPUBase.ts index 405d855..7b22bb6 100644 --- a/src/WebGPUBase.ts +++ b/src/WebGPUBase.ts @@ -1,4 +1,4 @@ -import { BlendState, Buffer, ChainMap, CommandEncoder, computed, Computed, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; +import { BlendState, Buffer, ChainMap, CommandEncoder, computed, Computed, CopyBufferToBuffer, CopyTextureToTexture, DepthStencilState, effect, OcclusionQuery, reactive, ReadPixels, RenderObject, RenderPass, RenderPassObject, RenderPipeline, Submit, TextureLike, UnReadonly } from "@feng3d/render-api"; import { getGPUBindGroup } from "./caches/getGPUBindGroup"; import { getGPUBuffer } from "./caches/getGPUBuffer"; @@ -189,24 +189,33 @@ export class WebGPUBase protected runRenderPass(renderPass: RenderPass) { const device = this._device; - // const result = this._renderPassCommandMap.get(renderPass); - // if (result) return result; + let renderPassCommand = this._renderPassCommandMap.get(renderPass); + if (renderPassCommand) return renderPassCommand; - const { descriptor, renderPassObjects } = renderPass; + renderPassCommand = new RenderPassCommand(); - const renderPassCommand = new RenderPassCommand(); - renderPassCommand.renderPassDescriptor = getGPURenderPassDescriptor(device, renderPass); + effect(() => + { + const r_renderPass = reactive(renderPass); + r_renderPass.renderPassObjects; + r_renderPass.descriptor; - const renderPassFormat = getGPURenderPassFormat(descriptor); + const { descriptor, renderPassObjects } = renderPass; + renderPassCommand.renderPassDescriptor = getGPURenderPassDescriptor(device, renderPass); - const renderPassObjectCommands = this.runRenderPassObjects(renderPassFormat, renderPassObjects); - const commands: CommandType[] = []; - const state = new RenderObjectCache(); - renderPassObjectCommands?.forEach((command) => - { - command.run(device, commands, state); + const renderPassFormat = getGPURenderPassFormat(descriptor); + + const renderPassObjectCommands = this.runRenderPassObjects(renderPassFormat, renderPassObjects); + const commands: CommandType[] = []; + const state = new RenderObjectCache(); + renderPassObjectCommands?.forEach((command) => + { + command.run(device, commands, state); + }); + renderPassCommand.commands = commands; }); - renderPassCommand.commands = commands; + + this._renderPassCommandMap.set(renderPass, renderPassCommand); return renderPassCommand; } diff --git a/src/caches/getGPURenderPassDescriptor.ts b/src/caches/getGPURenderPassDescriptor.ts index 2f11bc3..fdfcb91 100644 --- a/src/caches/getGPURenderPassDescriptor.ts +++ b/src/caches/getGPURenderPassDescriptor.ts @@ -1,5 +1,5 @@ import { anyEmitter } from "@feng3d/event"; -import { CanvasTexture, ChainMap, computed, Computed, OcclusionQuery, reactive, RenderPass, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; +import { CanvasTexture, ChainMap, computed, Computed, effect, OcclusionQuery, reactive, RenderPass, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, Texture, TextureLike, TextureView } from "@feng3d/render-api"; import { GPUQueue_submit } from "../eventnames"; import { MultisampleTexture } from "../internal/MultisampleTexture"; import { getGPUPassTimestampWrites } from "./getGPUPassTimestampWrites"; @@ -27,12 +27,12 @@ export function getGPURenderPassDescriptor(device: GPUDevice, renderPass: Render const descriptor: RenderPassDescriptor = renderPass.descriptor; // 缓存 const getGPURenderPassDescriptorKey: GetGPURenderPassDescriptorKey = [device, descriptor]; - let result = getGPURenderPassDescriptorMap.get(getGPURenderPassDescriptorKey); - if (result) return result.value; + let renderPassDescriptor = getGPURenderPassDescriptorMap.get(getGPURenderPassDescriptorKey); + if (renderPassDescriptor) return renderPassDescriptor; // 避免重复创建,触发反应链。 - const renderPassDescriptor: GPURenderPassDescriptor = {} as any; - result = computed(() => + renderPassDescriptor = {} as any; + effect(() => { // 监听 const r_descriptor = reactive(descriptor); @@ -51,16 +51,15 @@ export function getGPURenderPassDescriptor(device: GPUDevice, renderPass: Render renderPassDescriptor.timestampWrites = getGPUPassTimestampWrites(device, descriptor.timestampQuery); setOcclusionQuerySet(device, renderPass, renderPassDescriptor); - - return renderPassDescriptor; }); - getGPURenderPassDescriptorMap.set(getGPURenderPassDescriptorKey, result); - return result.value; + getGPURenderPassDescriptorMap.set(getGPURenderPassDescriptorKey, renderPassDescriptor); + + return renderPassDescriptor; } type GetGPURenderPassDescriptorKey = [device: GPUDevice, descriptor: RenderPassDescriptor]; -const getGPURenderPassDescriptorMap = new ChainMap>; +const getGPURenderPassDescriptorMap = new ChainMap; /** * 设置纹理尺寸。 @@ -101,24 +100,23 @@ function getMultisampleTextureView(texture: TextureLike, sampleCount: 4) if (sampleCount !== 4) return undefined; if (!texture) return undefined; - let result = getMultisampleTextureViewMap.get(texture); - if (result) return result.value; + let multisampleTextureView = getMultisampleTextureViewMap.get(texture); + if (multisampleTextureView) return multisampleTextureView; // 新增用于解决多重采样的纹理 const multisampleTexture: MultisampleTexture = { label: "自动生成多重采样的纹理", sampleCount } as MultisampleTexture; - const multisampleTextureView: TextureView = { texture: multisampleTexture }; - result = computed(() => + multisampleTextureView = { texture: multisampleTexture }; + effect(() => { // 新建的多重采样纹理尺寸与格式与原始纹理同步。 reactive(multisampleTexture).size = getTextureSize(texture); reactive(multisampleTexture).format = getGPUTextureFormat(texture); - - return multisampleTextureView; }); - getMultisampleTextureViewMap.set(texture, result); - return result.value; + + getMultisampleTextureViewMap.set(texture, multisampleTextureView); + return multisampleTextureView; } -const getMultisampleTextureViewMap = new WeakMap>; +const getMultisampleTextureViewMap = new WeakMap; /** * 获取深度模板附件完整描述。 @@ -262,8 +260,8 @@ const getIGPURenderPassColorAttachmentsMap = new ChainMap + attachment = {} as any; + effect(() => { // 监听 const r_renderPassColorAttachment = reactive(renderPassColorAttachment); @@ -298,7 +296,7 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac } // 更新纹理尺寸 - computed(() => + effect(() => { // 监听 const r_descriptor = reactive(descriptor); @@ -312,22 +310,21 @@ function getGPURenderPassColorAttachment(device: GPUDevice, renderPassColorAttac // 更改纹理尺寸将会销毁重新创建纹理,需要重新获取view。 attachment.view = getGPUTextureView(device, view); attachment.resolveTarget = getGPUTextureView(device, resolveTarget); - }).value; + }); // attachment.depthSlice = depthSlice; attachment.clearValue = clearValue; attachment.loadOp = loadOp ?? "clear"; attachment.storeOp = storeOp ?? "store"; - - return attachment; }); - getGPURenderPassColorAttachmentMap.set(getGPURenderPassColorAttachmentKey, result); - return result.value; + getGPURenderPassColorAttachmentMap.set(getGPURenderPassColorAttachmentKey, attachment); + + return attachment; } type GetGPURenderPassColorAttachmentKey = [device: GPUDevice, renderPassColorAttachment: RenderPassColorAttachment, descriptor: RenderPassDescriptor]; -const getGPURenderPassColorAttachmentMap = new ChainMap>; +const getGPURenderPassColorAttachmentMap = new ChainMap; function setOcclusionQuerySet(device: GPUDevice, renderPass: RenderPass, renderPassDescriptor: GPURenderPassDescriptor) { -- Gitee