|
1 | 1 |
|
2 | 2 | import Node from './Node.js'; |
3 | | -import { getByteBoundaryFromType, getMemoryLengthFromType } from './NodeUtils.js'; |
| 3 | +import { getAlignmentFromType, getMemoryLengthFromType } from './NodeUtils.js'; |
4 | 4 |
|
5 | 5 | /** |
6 | 6 | * Generates a layout for struct members. |
@@ -86,37 +86,31 @@ class StructTypeNode extends Node { |
86 | 86 | */ |
87 | 87 | getLength() { |
88 | 88 |
|
89 | | - const GPU_CHUNK_BYTES = 8; |
90 | 89 | const BYTES_PER_ELEMENT = Float32Array.BYTES_PER_ELEMENT; |
91 | | - |
92 | | - let offset = 0; // global buffer offset in bytes |
| 90 | + let maxAlignment = 1; // maximum alignment value in this struct |
| 91 | + let offset = 0; // global buffer offset in 4 byte elements |
93 | 92 |
|
94 | 93 | for ( const member of this.membersLayout ) { |
95 | 94 |
|
96 | 95 | const type = member.type; |
97 | 96 |
|
98 | | - const itemSize = getMemoryLengthFromType( type ) * BYTES_PER_ELEMENT; |
99 | | - const boundary = getByteBoundaryFromType( type ); |
100 | | - |
101 | | - const chunkOffset = offset % GPU_CHUNK_BYTES; // offset in the current chunk |
102 | | - const chunkPadding = chunkOffset % boundary; // required padding to match boundary |
103 | | - const chunkStart = chunkOffset + chunkPadding; // start position in the current chunk for the data |
104 | | - |
105 | | - offset += chunkPadding; |
| 97 | + const itemSize = getMemoryLengthFromType( type ); |
| 98 | + const alignment = getAlignmentFromType( type ) / BYTES_PER_ELEMENT; |
| 99 | + maxAlignment = Math.max( maxAlignment, alignment ); |
106 | 100 |
|
107 | | - // Check for chunk overflow |
108 | | - if ( chunkStart !== 0 && ( GPU_CHUNK_BYTES - chunkStart ) < itemSize ) { |
| 101 | + const chunkOffset = offset % maxAlignment; // offset in the current chunk of maxAlignment elements |
| 102 | + const overhang = chunkOffset % alignment; // distance from the last aligned offset |
| 103 | + if ( overhang !== 0 ) { |
109 | 104 |
|
110 | | - // Add padding to the end of the chunk |
111 | | - offset += ( GPU_CHUNK_BYTES - chunkStart ); |
| 105 | + offset += alignment - overhang; // move to next aligned offset |
112 | 106 |
|
113 | 107 | } |
114 | 108 |
|
115 | 109 | offset += itemSize; |
116 | 110 |
|
117 | 111 | } |
118 | 112 |
|
119 | | - return ( Math.ceil( offset / GPU_CHUNK_BYTES ) * GPU_CHUNK_BYTES ) / BYTES_PER_ELEMENT; |
| 113 | + return ( Math.ceil( offset / maxAlignment ) * maxAlignment ); // ensure length is a multiple of maxAlignment |
120 | 114 |
|
121 | 115 | } |
122 | 116 |
|
|
0 commit comments