Skip to content

Reuse webgpu resources#18208

Merged
dumganhar merged 36 commits into
cocos:v3.8.6from
GengineJS:v3.8.6-0114
Feb 26, 2025
Merged

Reuse webgpu resources#18208
dumganhar merged 36 commits into
cocos:v3.8.6from
GengineJS:v3.8.6-0114

Conversation

@GengineJS

@GengineJS GengineJS commented Jan 17, 2025

Copy link
Copy Markdown
Contributor

Resource Reuse Issues Caused by WebGPU Bind Group Refactoring

@GengineJS GengineJS requested a review from star-e January 17, 2025 02:32
@github-actions

github-actions Bot commented Jan 17, 2025

Copy link
Copy Markdown

Code Size Check Report

Wechat (WASM) Before After Diff
2D Empty (legacy pipeline) 1001794 bytes 1001876 bytes ⚠️ +82 bytes
2D All (legacy pipeline) 2408779 bytes 2408861 bytes ⚠️ +82 bytes
2D All (new pipeline) 2498268 bytes 2496090 bytes 👍 -2178 bytes
(2D + 3D) All 5412998 bytes 5412353 bytes 👍 -645 bytes
Web (WASM + ASMJS) Before After Diff
(2D + 3D) All 16636449 bytes 16635733 bytes 👍 -716 bytes

Interface Check Report

! WARNING this pull request has changed these public interfaces:

@@ -9587,8 +9587,9 @@
         export const FormatInfos: readonly FormatInfo[];
         export const DESCRIPTOR_BUFFER_TYPE: number;
         export const DESCRIPTOR_SAMPLER_TYPE: number;
         export const DESCRIPTOR_DYNAMIC_TYPE: number;
+        export const DESCRIPTOR_STORAGE_BUFFER_TYPE: number;
         export const DRAW_INFO_SIZE = 28;
         export type BufferSource = ArrayBuffer | IndirectBuffer;
         export interface FormatAlignment {
             width: number;
@@ -67508,13 +67509,125 @@
             gpuBlocks: _cocos_gfx_webgpu_webgpu_gpu_objects__IWebGPUGPUUniformBlock[];
             gpuSamplers: _cocos_gfx_webgpu_webgpu_gpu_objects__IWebGPUGPUUniformSampler[];
             bindings: Map<number, number[]>;
         }
+        export type __types_webGPU__GPUIndex32 = number;
+        export type __types_webGPU__GPUShaderStageFlags = number;
+        export type __types_webGPU__GPUBufferBindingType = "uniform" | "storage" | "read-only-storage";
+        export interface __types_webGPU__GPUBufferBindingLayout {
+            /**
+             * Indicates the type required for buffers bound to this bindings.
+             */
+            type?: __types_webGPU__GPUBufferBindingType;
+            /**
+             * Indicates whether this binding requires a dynamic offset.
+             */
+            hasDynamicOffset?: boolean;
+            /**
+             * Indicates the minimum {@link GPUBufferBinding#size} of a buffer binding used with this bind point.
+             * Bindings are always validated against this size in {@link GPUDevice#createBindGroup}.
+             * If this *is not* `0`, pipeline creation additionally [$validating shader binding|validates$]
+             * that this value &ge; the minimum buffer binding size of the variable.
+             * If this *is* `0`, it is ignored by pipeline creation, and instead draw/dispatch commands
+             * [$Validate encoder bind groups|validate$] that each binding in the {@link GPUBindGroup}
+             * satisfies the minimum buffer binding size of the variable.
+             * Note:
+             * Similar execution-time validation is theoretically possible for other
+             * binding-related fields specified for early validation, like
+             * {@link GPUTextureBindingLayout#sampleType} and {@link GPUStorageTextureBindingLayout#format},
+             * which currently can only be validated in pipeline creation.
+             * However, such execution-time validation could be costly or unnecessarily complex, so it is
+             * available only for {@link GPUBufferBindingLayout#minBindingSize} which is expected to have the
+             * most ergonomic impact.
+             */
+            minBindingSize?: __types_webGPU__GPUSize64;
+        }
+        export type __types_webGPU__GPUSamplerBindingType = "filtering" | "non-filtering" | "comparison";
+        export interface __types_webGPU__GPUSamplerBindingLayout {
+            /**
+             * Indicates the required type of a sampler bound to this bindings.
+             */
+            type?: __types_webGPU__GPUSamplerBindingType;
+        }
+        export type __types_webGPU__GPUTextureSampleType = "float" | "unfilterable-float" | "depth" | "sint" | "uint";
+        export interface __types_webGPU__GPUTextureBindingLayout {
+            /**
+             * Indicates the type required for texture views bound to this binding.
+             */
+            sampleType?: __types_webGPU__GPUTextureSampleType;
+            /**
+             * Indicates the required {@link GPUTextureViewDescriptor#dimension} for texture views bound to
+             * this binding.
+             */
+            viewDimension?: __types_webGPU__GPUTextureViewDimension;
+            /**
+             * Indicates whether or not texture views bound to this binding must be multisampled.
+             */
+            multisampled?: boolean;
+        }
+        export type __types_webGPU__GPUStorageTextureAccess = "write-only" | "read-only" | "read-write";
+        export interface __types_webGPU__GPUStorageTextureBindingLayout {
+            /**
+             * The access mode for this binding, indicating readability and writability.
+             */
+            access?: __types_webGPU__GPUStorageTextureAccess;
+            /**
+             * The required {@link GPUTextureViewDescriptor#format} of texture views bound to this binding.
+             */
+            format: __types_webGPU__GPUTextureFormat;
+            /**
+             * Indicates the required {@link GPUTextureViewDescriptor#dimension} for texture views bound to
+             * this binding.
+             */
+            viewDimension?: __types_webGPU__GPUTextureViewDimension;
+        }
+        export interface __types_webGPU__GPUExternalTextureBindingLayout {
+        }
+        export interface __types_webGPU__GPUBindGroupLayoutEntry {
+            /**
+             * A unique identifier for a resource binding within the {@link GPUBindGroupLayout}, corresponding
+             * to a {@link GPUBindGroupEntry#binding|GPUBindGroupEntry.binding} and a @binding
+             * attribute in the {@link GPUShaderModule}.
+             */
+            binding: __types_webGPU__GPUIndex32;
+            /**
+             * A bitset of the members of {@link GPUShaderStage}.
+             * Each set bit indicates that a {@link GPUBindGroupLayoutEntry}'s resource
+             * will be accessible from the associated shader stage.
+             */
+            visibility: __types_webGPU__GPUShaderStageFlags;
+            /**
+             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
+             * is {@link GPUBufferBinding}.
+             */
+            buffer?: __types_webGPU__GPUBufferBindingLayout;
+            /**
+             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
+             * is {@link GPUSampler}.
+             */
+            sampler?: __types_webGPU__GPUSamplerBindingLayout;
+            /**
+             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
+             * is {@link GPUTextureView}.
+             */
+            texture?: __types_webGPU__GPUTextureBindingLayout;
+            /**
+             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
+             * is {@link GPUTextureView}.
+             */
+            storageTexture?: __types_webGPU__GPUStorageTextureBindingLayout;
+            /**
+             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
+             * is {@link GPUExternalTexture}.
+             */
+            externalTexture?: __types_webGPU__GPUExternalTextureBindingLayout;
+        }
         export interface _cocos_gfx_webgpu_webgpu_gpu_objects__IWebGPUGPUDescriptorSetLayout {
             bindings: gfx.DescriptorSetLayoutBinding[];
             dynamicBindings: number[];
             descriptorIndices: number[];
             descriptorCount: number;
+            entries: __types_webGPU__GPUBindGroupLayoutEntry[];
             bindGroupLayout: GPUBindGroupLayout | null;
         }
         export interface _cocos_gfx_webgpu_webgpu_gpu_objects__IWebGPUGPUPipelineLayout {
             setLayouts: gfx.DescriptorSetLayout[];
@@ -67535,9 +67648,8 @@
             layout: GPUPipelineLayout | __types_webGPU__GPUAutoLayoutMode;
         }
         export type __types_webGPU__GPUVertexStepMode = "vertex" | "instance";
         export type __types_webGPU__GPUVertexFormat = "uint8" | "uint8x2" | "uint8x4" | "sint8" | "sint8x2" | "sint8x4" | "unorm8" | "unorm8x2" | "unorm8x4" | "snorm8" | "snorm8x2" | "snorm8x4" | "uint16" | "uint16x2" | "uint16x4" | "sint16" | "sint16x2" | "sint16x4" | "unorm16" | "unorm16x2" | "unorm16x4" | "snorm16" | "snorm16x2" | "snorm16x4" | "float16" | "float16x2" | "float16x4" | "float32" | "float32x2" | "float32x3" | "float32x4" | "uint32" | "uint32x2" | "uint32x3" | "uint32x4" | "sint32" | "sint32x2" | "sint32x3" | "sint32x4" | "unorm10-10-10-2" | "unorm8x4-bgra";
-        export type __types_webGPU__GPUIndex32 = number;
         export interface __types_webGPU__GPUVertexAttribute {
             /**
              * The {@link GPUVertexFormat} of the attribute.
              */
@@ -67887,12 +67999,15 @@
             buffersDescLayout: Map<number, _cocos_gfx_webgpu_webgpu_buffer__WebGPUBuffer>;
             texturesDescLayout: Map<number, _cocos_gfx_webgpu_webgpu_texture__WebGPUTexture>;
             samplersDescLayout: Map<number, _cocos_gfx_webgpu_webgpu_sampler__WebGPUSampler>;
             buffer: _cocos_gfx_webgpu_webgpu_buffer__WebGPUBuffer;
+            storageBuffers: _cocos_gfx_webgpu_webgpu_buffer__WebGPUBuffer[];
             texture: _cocos_gfx_webgpu_webgpu_texture__WebGPUTexture;
+            cubeTexture: _cocos_gfx_webgpu_webgpu_texture__WebGPUTexture;
             sampler: _cocos_gfx_webgpu_webgpu_sampler__WebGPUSampler;
             setLayout: gfx.DescriptorSetLayout;
             descSet: gfx.DescriptorSet;
+            getStorageBuffer(idx: number): _cocos_gfx_webgpu_webgpu_buffer__WebGPUBuffer;
         }
         export type __types_webGPU__GPUCanvasToneMappingMode = "standard" | "extended";
         export interface __types_webGPU__GPUCanvasToneMapping {
             mode?: __types_webGPU__GPUCanvasToneMappingMode;
@@ -67938,118 +68053,8 @@
              */
             alphaMode?: __types_webGPU__GPUCanvasAlphaMode;
         }
         export type __types_webGPU__GPUSupportedFeatures = ReadonlySet<string>;
-        export type __types_webGPU__GPUShaderStageFlags = number;
-        export type __types_webGPU__GPUBufferBindingType = "uniform" | "storage" | "read-only-storage";
-        export interface __types_webGPU__GPUBufferBindingLayout {
-            /**
-             * Indicates the type required for buffers bound to this bindings.
-             */
-            type?: __types_webGPU__GPUBufferBindingType;
-            /**
-             * Indicates whether this binding requires a dynamic offset.
-             */
-            hasDynamicOffset?: boolean;
-            /**
-             * Indicates the minimum {@link GPUBufferBinding#size} of a buffer binding used with this bind point.
-             * Bindings are always validated against this size in {@link GPUDevice#createBindGroup}.
-             * If this *is not* `0`, pipeline creation additionally [$validating shader binding|validates$]
-             * that this value &ge; the minimum buffer binding size of the variable.
-             * If this *is* `0`, it is ignored by pipeline creation, and instead draw/dispatch commands
-             * [$Validate encoder bind groups|validate$] that each binding in the {@link GPUBindGroup}
-             * satisfies the minimum buffer binding size of the variable.
-             * Note:
-             * Similar execution-time validation is theoretically possible for other
-             * binding-related fields specified for early validation, like
-             * {@link GPUTextureBindingLayout#sampleType} and {@link GPUStorageTextureBindingLayout#format},
-             * which currently can only be validated in pipeline creation.
-             * However, such execution-time validation could be costly or unnecessarily complex, so it is
-             * available only for {@link GPUBufferBindingLayout#minBindingSize} which is expected to have the
-             * most ergonomic impact.
-             */
-            minBindingSize?: __types_webGPU__GPUSize64;
-        }
-        export type __types_webGPU__GPUSamplerBindingType = "filtering" | "non-filtering" | "comparison";
-        export interface __types_webGPU__GPUSamplerBindingLayout {
-            /**
-             * Indicates the required type of a sampler bound to this bindings.
-             */
-            type?: __types_webGPU__GPUSamplerBindingType;
-        }
-        export type __types_webGPU__GPUTextureSampleType = "float" | "unfilterable-float" | "depth" | "sint" | "uint";
-        export interface __types_webGPU__GPUTextureBindingLayout {
-            /**
-             * Indicates the type required for texture views bound to this binding.
-             */
-            sampleType?: __types_webGPU__GPUTextureSampleType;
-            /**
-             * Indicates the required {@link GPUTextureViewDescriptor#dimension} for texture views bound to
-             * this binding.
-             */
-            viewDimension?: __types_webGPU__GPUTextureViewDimension;
-            /**
-             * Indicates whether or not texture views bound to this binding must be multisampled.
-             */
-            multisampled?: boolean;
-        }
-        export type __types_webGPU__GPUStorageTextureAccess = "write-only" | "read-only" | "read-write";
-        export interface __types_webGPU__GPUStorageTextureBindingLayout {
-            /**
-             * The access mode for this binding, indicating readability and writability.
-             */
-            access?: __types_webGPU__GPUStorageTextureAccess;
-            /**
-             * The required {@link GPUTextureViewDescriptor#format} of texture views bound to this binding.
-             */
-            format: __types_webGPU__GPUTextureFormat;
-            /**
-             * Indicates the required {@link GPUTextureViewDescriptor#dimension} for texture views bound to
-             * this binding.
-             */
-            viewDimension?: __types_webGPU__GPUTextureViewDimension;
-        }
-        export interface __types_webGPU__GPUExternalTextureBindingLayout {
-        }
-        export interface __types_webGPU__GPUBindGroupLayoutEntry {
-            /**
-             * A unique identifier for a resource binding within the {@link GPUBindGroupLayout}, corresponding
-             * to a {@link GPUBindGroupEntry#binding|GPUBindGroupEntry.binding} and a @binding
-             * attribute in the {@link GPUShaderModule}.
-             */
-            binding: __types_webGPU__GPUIndex32;
-            /**
-             * A bitset of the members of {@link GPUShaderStage}.
-             * Each set bit indicates that a {@link GPUBindGroupLayoutEntry}'s resource
-             * will be accessible from the associated shader stage.
-             */
-            visibility: __types_webGPU__GPUShaderStageFlags;
-            /**
-             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
-             * is {@link GPUBufferBinding}.
-             */
-            buffer?: __types_webGPU__GPUBufferBindingLayout;
-            /**
-             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
-             * is {@link GPUSampler}.
-             */
-            sampler?: __types_webGPU__GPUSamplerBindingLayout;
-            /**
-             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
-             * is {@link GPUTextureView}.
-             */
-            texture?: __types_webGPU__GPUTextureBindingLayout;
-            /**
-             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
-             * is {@link GPUTextureView}.
-             */
-            storageTexture?: __types_webGPU__GPUStorageTextureBindingLayout;
-            /**
-             * When map/exist|provided, indicates the binding resource type for this {@link GPUBindGroupLayoutEntry}
-             * is {@link GPUExternalTexture}.
-             */
-            externalTexture?: __types_webGPU__GPUExternalTextureBindingLayout;
-        }
         /**
          * @en Test line and line
          * @zh 测试线段与线段是否相交
          */

Comment thread cocos/gfx/webgpu/webgpu-commands.ts Outdated
'read-write',
];

export function CreateBindGroupLayoutEntry (currBind: DescriptorSetLayoutBinding): GPUBindGroupLayoutEntry[] {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep the same coding style, the first letter of functions must use lowercase .

Comment thread cocos/gfx/webgpu/instantiated.ts Outdated
@GengineJS

Copy link
Copy Markdown
Contributor Author

@GengineJS GengineJS requested a review from dumganhar February 25, 2025 08:29
Comment thread cocos/gfx/webgpu/webgpu-commands.ts Outdated

export function WebGPUCmdFuncCreateTexture (device: WebGPUDevice, gpuTexture: IWebGPUTexture): void {
if (gpuTexture.width === 512 && gpuTexture.height === 512 && gpuTexture.format === Format.R32F) {
console.log('WebGPUCmdFuncCreateTexture shadowmap');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The log can be removed.

Comment on lines +52 to +54
// private _currBinds: number[] = [];
// private _needUpdate: boolean = false;
// private _prepareDynOffsets: number[] = [];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused code can be removed. If you think it should be kept, it's also fine.

public initialize (info: Readonly<DescriptorSetInfo>): void {
const layout = this._layout = info.layout as WebGPUDescriptorSetLayout;
layout.addRef(this);
// layout.addRef(this);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused code can be removed. If you think it should be kept, it's also fine.

destBind.gpuBuffer = buffer.gpuBuffer;
}
const layout = this._layout as WebGPUDescriptorSetLayout;
// const layout = this._layout as WebGPUDescriptorSetLayout;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused code can be removed. If you think it should be kept, it's also fine.

Comment thread cocos/gfx/webgpu/webgpu-device.ts Outdated
this._features[Feature.INSTANCED_ARRAYS] = true;
this._features[Feature.MULTIPLE_RENDER_TARGETS] = true;
this._features[Feature.BLEND_MINMAX] = true;
// this._features[Feature.BLEND_MINMAX] = true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused code can be removed. If you think it should be kept, it's also fine.

Comment thread cocos/gfx/webgpu/webgpu-device.ts Outdated
defaultResource.descSet.bindBuffer(0, defaultResource.buffer);
defaultResource.descSet.update();
(defaultResource.descSet as WebGPUDescriptorSet).prepare(DescUpdateFrequency.NORMAL, [0]);
// (defaultResource.descSet as WebGPUDescriptorSet).prepare(DescUpdateFrequency.NORMAL, [0]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused code can be removed. If you think it should be kept, it's also fine.

: (isBound(binds, this._currBinds) && isBound(binds, layout.currBinds)))
&& this._hasIncludeDynamic() && this._isResourceChange(binds);
public prepare (force: boolean = false): void {
const breakUpdate = this._isResourceChange() && !force;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here some comments might be added. What does prepare do, and why _isResourceChange is needed can be explained.

@star-e

star-e commented Feb 26, 2025

Copy link
Copy Markdown
Contributor

@cocos-robot run test cases

@GengineJS GengineJS requested a review from star-e February 26, 2025 02:47
@star-e

star-e commented Feb 26, 2025

Copy link
Copy Markdown
Contributor

@cocos-robot run test cases

@dumganhar dumganhar merged commit 13140df into cocos:v3.8.6 Feb 26, 2025
@github-actions

Copy link
Copy Markdown

@GengineJS, Please check the result of run test cases:

Task Details

Platform build boot runned crashScene FailScene
web-mobile PASS PASS PASS
ios PASS PASS FAIL reflection-probe
mac PASS PASS FAIL reflection-probe

@github-actions

Copy link
Copy Markdown

@GengineJS, Please check the result of run test cases:

Task Details

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants