Skip to content

Commit 0160840

Browse files
committed
Support full-object assignment to array indices
1 parent 8c2970f commit 0160840

4 files changed

Lines changed: 54 additions & 0 deletions

File tree

src/strands/strands_node.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,17 @@ export class StrandsNode {
197197
throw new Error('set() can only be used on storage buffers with an identifier');
198198
}
199199

200+
// If value is a plain object (struct literal), expand to per-field assignments
201+
// e.g. buf[idx] = { position: pos, velocity: vel }
202+
// becomes buf[idx].position = pos; buf[idx].velocity = vel;
203+
if (value !== null && typeof value === 'object' && !value.isStrandsNode && this._schema) {
204+
const proxy = createStructArrayElementProxy(this.strandsContext, this, index, this._schema);
205+
for (const [fieldName, fieldValue] of Object.entries(value)) {
206+
proxy[fieldName] = fieldValue;
207+
}
208+
return this;
209+
}
210+
200211
// Create array assignment node: buffer.set(index, value) -> buffer[index] = value
201212
// This creates an ASSIGNMENT node and records it in the CFG basic block
202213
// CFG preserves sequential order, preventing reordering of assignments

test/unit/visual/cases/webgpu.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,5 +1353,45 @@ visualSuite("WebGPU", function () {
13531353
await screenshot();
13541354
}
13551355
);
1356+
1357+
visualTest(
1358+
'Compute shader writes a whole struct element as an object literal',
1359+
async function(p5, screenshot) {
1360+
await p5.createCanvas(50, 50, p5.WEBGPU);
1361+
1362+
const particles = p5.createStorage([
1363+
{ position: [0, 0], velocity: [15, -10] },
1364+
]);
1365+
1366+
const computeShader = p5.buildComputeShader(() => {
1367+
const buf = p5.uniformStorage('buf', particles);
1368+
const idx = iteration.index.x;
1369+
let pos = buf[idx].position;
1370+
let vel = buf[idx].velocity;
1371+
pos = pos + vel;
1372+
buf[idx] = { position: pos, velocity: vel };
1373+
}, { p5, particles });
1374+
p5.compute(computeShader, 1);
1375+
1376+
const sphereShader = p5.baseMaterialShader().modify(() => {
1377+
const buf = p5.uniformStorage('buf', particles);
1378+
p5.getWorldInputs((inputs) => {
1379+
const pos = buf[0].position;
1380+
inputs.position.x += pos.x;
1381+
inputs.position.y += pos.y;
1382+
return inputs;
1383+
});
1384+
}, { p5, particles });
1385+
1386+
const geo = p5.buildGeometry(() => p5.sphere(5));
1387+
p5.background(200);
1388+
p5.noStroke();
1389+
p5.fill(255, 0, 0);
1390+
p5.shader(sphereShader);
1391+
p5.model(geo, 1);
1392+
1393+
await screenshot();
1394+
}
1395+
);
13561396
});
13571397
});
304 Bytes
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"numScreenshots": 1
3+
}

0 commit comments

Comments
 (0)