Skip to content

Commit 059cb3c

Browse files
fix uniform-buffer-layout size calculation and add support for arrays (#2398)
1 parent 16fcea2 commit 059cb3c

File tree

4 files changed

+21
-10
lines changed

4 files changed

+21
-10
lines changed

modules/core/src/portable/uniform-buffer-layout.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,19 @@ export class UniformBufferLayout {
2929
readonly byteLength: number;
3030

3131
/** Create a new UniformBufferLayout given a map of attributes. */
32-
constructor(uniformTypes: Record<string, VariableShaderType>) {
32+
constructor(
33+
uniformTypes: Record<string, VariableShaderType>,
34+
uniformSizes: Record<string, number> = {}
35+
) {
3336
/** number of 4 byte slots taken */
3437
let size: number = 0;
3538

3639
// Add layout (type, size and offset) definitions for each uniform in the layout
3740
for (const [key, uniformType] of Object.entries(uniformTypes)) {
3841
const typeAndComponents = getVariableShaderTypeInfo(uniformType);
39-
const {type, components: count} = typeAndComponents;
42+
const {type, components} = typeAndComponents;
43+
// Calculate total count for uniform arrays.
44+
const count = components * (uniformSizes?.[key] ?? 1);
4045
// First, align (bump) current offset to an even multiple of current object (1, 2, 4)
4146
size = alignTo(size, count);
4247
// Use the aligned size as the offset of the current uniform.
@@ -53,19 +58,15 @@ export class UniformBufferLayout {
5358

5459
/** Get the data for the complete buffer */
5560
getData(uniformValues: Record<string, UniformValue>): Uint8Array {
56-
const bufferSize = Math.max(this.byteLength, minBufferSize);
57-
5861
// Allocate three typed arrays pointing at same memory
59-
const arrayBuffer = getScratchArrayBuffer(bufferSize);
62+
const arrayBuffer = getScratchArrayBuffer(this.byteLength);
6063
const typedArrays = {
6164
i32: new Int32Array(arrayBuffer),
6265
u32: new Uint32Array(arrayBuffer),
6366
f32: new Float32Array(arrayBuffer),
6467
// TODO not implemented
6568
f16: new Uint16Array(arrayBuffer)
6669
};
67-
// TODO is this needed?
68-
// typedArrays.i32.fill(0);
6970

7071
for (const [name, value] of Object.entries(uniformValues)) {
7172
const uniformLayout = this.layout[name];
@@ -101,7 +102,7 @@ export class UniformBufferLayout {
101102
}
102103
}
103104

104-
return new Uint8Array(arrayBuffer);
105+
return new Uint8Array(arrayBuffer, 0, this.byteLength);
105106
}
106107

107108
/** Does this layout have a field with specified name */

modules/core/src/portable/uniform-store.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export class UniformStore<
3939
keyof TPropGroups,
4040
{
4141
uniformTypes?: Record<string, VariableShaderType>;
42+
uniformSizes?: Record<string, number>;
4243
defaultProps?: Record<string, unknown>;
4344
defaultUniforms?: Record<string, UniformValue>;
4445
}
@@ -48,7 +49,10 @@ export class UniformStore<
4849
const uniformBufferName = bufferName as keyof TPropGroups;
4950

5051
// Create a layout object to help us generate correctly formatted binary uniform buffers
51-
const uniformBufferLayout = new UniformBufferLayout(block.uniformTypes || {});
52+
const uniformBufferLayout = new UniformBufferLayout(
53+
block.uniformTypes ?? {},
54+
block.uniformSizes ?? {}
55+
);
5256
this.uniformBufferLayouts.set(uniformBufferName, uniformBufferLayout);
5357

5458
// Create a Uniform block to store the uniforms for each buffer.

modules/shadertools/src/lib/shader-module/shader-module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
makePropValidators,
1010
getValidatedProperties
1111
} from '../filters/prop-types';
12-
import type {UniformTypes, UniformValue} from '../utils/uniform-types';
12+
import type {UniformSizes, UniformTypes, UniformValue} from '../utils/uniform-types';
1313
import {ShaderInjection, normalizeInjections} from '../shader-assembly/shader-injections';
1414

1515
// To avoid dependency on core module, do not import `Binding` type.
@@ -58,6 +58,8 @@ export type ShaderModule<
5858

5959
/** Uniform shader types @note: Both order and types MUST match uniform block declarations in shader */
6060
uniformTypes?: Required<UniformTypes<UniformsT>>; // Record<keyof UniformsT, UniformFormat>;
61+
/** Uniform shader array sizes (default 1) */
62+
uniformSizes?: Required<UniformSizes<UniformsT>>;
6163
/** Uniform JS prop types */
6264
propTypes?: Record<keyof UniformsT, UniformInfo>;
6365
/** Default uniform values */

modules/shadertools/src/lib/utils/uniform-types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,7 @@ type UniformProps = {
6464
export type UniformTypes<PropsT extends UniformProps> = {
6565
[name in keyof PropsT]: UniformType<PropsT[name]>;
6666
};
67+
68+
export type UniformSizes<PropsT extends UniformProps> = {
69+
[name in keyof PropsT]: number;
70+
};

0 commit comments

Comments
 (0)