(shaderSource, structName)
| 2133 | } |
| 2134 | |
| 2135 | _parseStruct(shaderSource, structName) { |
| 2136 | const structMatch = shaderSource.match( |
| 2137 | new RegExp(`struct\\s+${structName}\\s*\\{([^\\}]+)\\}`) |
| 2138 | ); |
| 2139 | if (!structMatch) { |
| 2140 | throw new Error(`Can't find a struct definition for ${structName}`); |
| 2141 | } |
| 2142 | |
| 2143 | const structBody = structMatch[1]; |
| 2144 | const elements = {}; |
| 2145 | let match; |
| 2146 | let index = 0; |
| 2147 | let offset = 0; |
| 2148 | |
| 2149 | const elementRegex = |
| 2150 | /(?:@location\((\d+)\)\s+)?(\w+):\s*([^\n]+?),?\n/g |
| 2151 | |
| 2152 | const baseAlignAndSize = (type) => { |
| 2153 | if (['f32', 'i32', 'u32', 'bool'].includes(type)) { |
| 2154 | return { align: 4, size: 4, items: 1, baseType: type }; |
| 2155 | } |
| 2156 | if (/^vec[2-4](<f32>|f)$/.test(type)) { |
| 2157 | const n = parseInt(type.match(/^vec([2-4])/)[1]); |
| 2158 | const size = 4 * n; |
| 2159 | const align = n === 2 ? 8 : 16; |
| 2160 | return { align, size, items: n, baseType: 'f32' }; |
| 2161 | } |
| 2162 | if (/^vec[2-4]<(i32|u32)>$/.test(type)) { |
| 2163 | const n = parseInt(type.match(/^vec([2-4])/)[1]); |
| 2164 | const match = type.match(/^vec[2-4]<(i32|u32)>$/); |
| 2165 | const baseType = match[1]; // 'i32' or 'u32' |
| 2166 | const size = 4 * n; |
| 2167 | const align = n === 2 ? 8 : 16; |
| 2168 | return { align, size, items: n, baseType }; |
| 2169 | } |
| 2170 | if (/^mat[2-4](?:x[2-4])?(<f32>|f)$/.test(type)) { |
| 2171 | if (type[4] === 'x' && type[3] !== type[5]) { |
| 2172 | throw new Error('Non-square matrices not implemented yet'); |
| 2173 | } |
| 2174 | const dim = parseInt(type[3]); |
| 2175 | const align = dim === 2 ? 8 : 16; |
| 2176 | // Each column must be aligned |
| 2177 | const size = Math.ceil(dim * 4 / align) * align * dim; |
| 2178 | // For mat3, use in-place packing to avoid array allocation |
| 2179 | const pack = dim === 3 |
| 2180 | ? (data) => [ |
| 2181 | ...data.slice(0, 3), |
| 2182 | ...data.slice(3, 6), |
| 2183 | ...data.slice(6, 9), |
| 2184 | ] |
| 2185 | : undefined; |
| 2186 | const packInPlace = dim === 3; |
| 2187 | return { align, size, pack, packInPlace, items: dim * dim, baseType: 'f32' }; |
| 2188 | } |
| 2189 | if (/^array<.+>$/.test(type)) { |
| 2190 | const [, subtype, rawLength] = type.match(/^array<(.+),\s*(\d+)>/); |
| 2191 | const length = parseInt(rawLength); |
| 2192 | const { |
no outgoing calls
no test coverage detected