Skip to content

Commit 0f0fb87

Browse files
author
Mike Bond
committed
Fix for vertex pulling of interleaved buffers
1 parent 22fc220 commit 0f0fb87

File tree

4 files changed

+108
-5
lines changed

4 files changed

+108
-5
lines changed

packages/dev/core/src/Engines/WebGPU/webgpuDrawContext.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { VertexBuffer } from "../../Buffers/buffer";
1+
import { VertexBuffer } from "../../Buffers/buffer";
22
import type { DataBuffer } from "../../Buffers/dataBuffer";
33
import type { WebGPUDataBuffer } from "../../Meshes/WebGPU/webgpuDataBuffer";
44
import type { Nullable } from "../../types";
@@ -170,6 +170,11 @@ export class WebGPUDrawContext implements IDrawContext {
170170
this._bufferManager.setRawData(this.indirectDrawBuffer, 0, this._indirectDrawData, 0, 20);
171171
}
172172

173+
/**
174+
* Metadata storage for vertex buffer configurations (stride, offset, etc.)
175+
*/
176+
public vertexBufferMetadata: { [name: string]: { strideInFloats: number; offsetInFloats: number; componentCount: number } } = {};
177+
173178
public setVertexPulling(
174179
useVertexPulling: boolean,
175180
webgpuPipelineContext: WebGPUPipelineContext,
@@ -186,6 +191,9 @@ export class WebGPUDrawContext implements IDrawContext {
186191

187192
const bufferNames = webgpuPipelineContext.shaderProcessingContext.bufferNames;
188193

194+
// Clear previous metadata
195+
this.vertexBufferMetadata = {};
196+
189197
if (overrideVertexBuffers) {
190198
for (const attributeName in overrideVertexBuffers) {
191199
const vertexBuffer = overrideVertexBuffers[attributeName];
@@ -196,6 +204,17 @@ export class WebGPUDrawContext implements IDrawContext {
196204
const buffer = vertexBuffer.effectiveBuffer as Nullable<WebGPUDataBuffer>;
197205

198206
this.setBuffer(attributeName, useVertexPulling ? buffer : null);
207+
208+
// Store metadata for vertex pulling
209+
if (useVertexPulling) {
210+
const bytesPerElement =
211+
vertexBuffer.type === VertexBuffer.FLOAT ? 4 : vertexBuffer.type === VertexBuffer.UNSIGNED_INT || vertexBuffer.type === VertexBuffer.INT ? 4 : 2;
212+
this.vertexBufferMetadata[attributeName] = {
213+
strideInFloats: vertexBuffer.effectiveByteStride / bytesPerElement, // Convert bytes to float32 elements
214+
offsetInFloats: vertexBuffer.effectiveByteOffset / bytesPerElement, // Convert bytes to float32 elements
215+
componentCount: vertexBuffer.getSize(),
216+
};
217+
}
199218
}
200219
}
201220

@@ -212,6 +231,17 @@ export class WebGPUDrawContext implements IDrawContext {
212231
const buffer = vertexBuffer.effectiveBuffer as Nullable<WebGPUDataBuffer>;
213232

214233
this.setBuffer(attributeName, useVertexPulling ? buffer : null);
234+
235+
// Store metadata for vertex pulling
236+
if (useVertexPulling) {
237+
const bytesPerElement =
238+
vertexBuffer.type === VertexBuffer.FLOAT ? 4 : vertexBuffer.type === VertexBuffer.UNSIGNED_INT || vertexBuffer.type === VertexBuffer.INT ? 4 : 2;
239+
this.vertexBufferMetadata[attributeName] = {
240+
strideInFloats: vertexBuffer.effectiveByteStride / bytesPerElement, // Convert bytes to float32 elements
241+
offsetInFloats: vertexBuffer.effectiveByteOffset / bytesPerElement, // Convert bytes to float32 elements
242+
componentCount: vertexBuffer.getSize(),
243+
};
244+
}
215245
}
216246

217247
if (bufferNames.indexOf("indices") !== -1) {

packages/dev/core/src/Materials/materialHelper.functions.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,44 @@ export function GetFogState(mesh: AbstractMesh, scene: Scene) {
598598
return scene.fogEnabled && mesh.applyFog && scene.fogMode !== Constants.FOGMODE_NONE;
599599
}
600600

601+
/**
602+
* Helper used to prepare vertex pulling metadata defines (stride, offset, component count)
603+
* This should be called when USE_VERTEX_PULLING is enabled to properly configure buffer access
604+
* @param mesh The mesh being rendered
605+
* @param defines The defines object to update
606+
* @param attributeNames Array of attribute names to configure (e.g., ["position", "normal"])
607+
*/
608+
export function PrepareDefinesForVertexPullingMetadata(mesh: AbstractMesh, defines: any, attributeNames: string[] = ["position"]): void {
609+
if (!defines["USE_VERTEX_PULLING"]) {
610+
return;
611+
}
612+
613+
const geometry = mesh.geometry;
614+
if (!geometry) {
615+
return;
616+
}
617+
618+
for (const attributeName of attributeNames) {
619+
const vertexBuffer = geometry.getVertexBuffer(attributeName);
620+
if (!vertexBuffer) {
621+
continue;
622+
}
623+
624+
const upperName = attributeName.toUpperCase();
625+
626+
// Calculate stride in float32 elements
627+
const strideInFloats = vertexBuffer.effectiveByteStride / 4;
628+
defines[`${upperName}_STRIDE_IN_FLOATS`] = strideInFloats || vertexBuffer.getSize();
629+
630+
// Calculate offset in float32 elements
631+
const offsetInFloats = vertexBuffer.effectiveByteOffset / 4;
632+
defines[`${upperName}_OFFSET_IN_FLOATS`] = offsetInFloats;
633+
634+
// Component count
635+
defines[`${upperName}_COMPONENT_COUNT`] = vertexBuffer.getSize();
636+
}
637+
}
638+
601639
/**
602640
* Helper used to prepare the list of defines associated with misc. values for shader compilation
603641
* @param mesh defines the current mesh

packages/dev/core/src/Materials/shaderMaterial.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,27 @@ export class ShaderMaterial extends PushMaterial {
891891
defines.push("#define VERTEX_PULLING_INDEX_BUFFER_32BITS");
892892
}
893893
}
894+
895+
// Add vertex buffer metadata defines for proper stride/offset handling
896+
const geometry = renderingMesh.geometry;
897+
if (geometry) {
898+
const vertexBuffers = geometry.getVertexBuffers();
899+
if (vertexBuffers) {
900+
for (const attributeName in vertexBuffers) {
901+
const vertexBuffer = vertexBuffers[attributeName];
902+
if (vertexBuffer) {
903+
const upperName = attributeName.toUpperCase();
904+
const strideInFloats = vertexBuffer.effectiveByteStride / 4;
905+
const offsetInFloats = vertexBuffer.effectiveByteOffset / 4;
906+
const componentCount = vertexBuffer.getSize();
907+
908+
defines.push(`#define ${upperName}_STRIDE_IN_FLOATS ${strideInFloats || componentCount}`);
909+
defines.push(`#define ${upperName}_OFFSET_IN_FLOATS ${offsetInFloats}`);
910+
defines.push(`#define ${upperName}_COMPONENT_COUNT ${componentCount}`);
911+
}
912+
}
913+
}
914+
}
894915
}
895916

896917
const drawWrapper = storeEffectOnSubMeshes ? subMesh._getDrawWrapper(undefined, true) : this._drawWrapper;

packages/dev/core/src/ShadersWGSL/iblVoxelGrid.vertex.fx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
// This shader uses vertex pulling to determine the
1010
// provoked vertex and calculate the normal. Then, based on
11-
// the direction of teh normal, it swizzles the position to
11+
// the direction of the normal, it swizzles the position to
1212
// maximize the rasterized area.
1313
#ifdef VERTEX_PULLING_USE_INDEX_BUFFER
1414
var<storage, read> indices : array<u32>;
@@ -21,11 +21,25 @@ uniform invWorldScale: mat4x4f;
2121
varying vNormalizedPosition : vec3f;
2222
flat varying f_swizzle: i32;
2323

24+
// Vertex buffer metadata (set via defines or defaults)
25+
#ifndef POSITION_STRIDE_IN_FLOATS
26+
#define POSITION_STRIDE_IN_FLOATS 3
27+
#endif
28+
29+
#ifndef POSITION_OFFSET_IN_FLOATS
30+
#define POSITION_OFFSET_IN_FLOATS 0
31+
#endif
32+
33+
#ifndef POSITION_COMPONENT_COUNT
34+
#define POSITION_COMPONENT_COUNT 3
35+
#endif
36+
2437
fn readVertexPosition(index : u32)->vec3f {
2538
var pos : vec3f;
26-
pos.x = position[index * 3];
27-
pos.y = position[index * 3 + 1];
28-
pos.z = position[index * 3 + 2];
39+
let baseOffset = POSITION_OFFSET_IN_FLOATS + index * POSITION_STRIDE_IN_FLOATS;
40+
pos.x = position[baseOffset];
41+
pos.y = position[baseOffset + 1u];
42+
pos.z = position[baseOffset + 2u];
2943
return pos;
3044
}
3145

0 commit comments

Comments
 (0)