Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,6 @@ function makePipelines(
outputGridMutable: TgpuBufferMutable<GridData>,
) {
const initWorldPipeline = root['~unstable']
.with(inputGridSlot, outputGridMutable)
.with(outputGridSlot, outputGridMutable)
.createGuardedComputePipeline((xu, yu) => {
'use gpu';
Expand Down
2 changes: 1 addition & 1 deletion packages/typegpu/src/core/function/tgpuFn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ function createBoundFunction<ImplSchema extends AnyFn>(
slot: TgpuSlot<unknown> | TgpuAccessor,
value: unknown,
): TgpuFn<ImplSchema> {
return createBoundFunction(fn, [
return createBoundFunction(innerFn, [
...pairs,
[isAccessor(slot) ? slot.slot : slot, value],
]);
Expand Down
64 changes: 24 additions & 40 deletions packages/typegpu/src/resolutionCtx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ import type {
ItemLayer,
ItemStateStack,
ResolutionCtx,
StackLayer,
Wgsl,
} from './types.ts';
import { CodegenState, isSelfResolvable, NormalState } from './types.ts';
import type { WgslExtension } from './wgslExtensions.ts';
import { hasTinyestMetadata } from './shared/meta.ts';
import { getName, hasTinyestMetadata } from './shared/meta.ts';

/**
* Inserted into bind group entry definitions that belong
Expand All @@ -90,23 +91,8 @@ export type ResolutionCtxImplOptions = {
readonly namespace: Namespace;
};

type SlotBindingLayer = {
type: 'slotBinding';
bindingMap: WeakMap<TgpuSlot<unknown>, unknown>;
};

type BlockScopeLayer = {
type: 'blockScope';
declarations: Map<string, Snippet>;
};

class ItemStateStackImpl implements ItemStateStack {
private _stack: (
| ItemLayer
| SlotBindingLayer
| FunctionScopeLayer
| BlockScopeLayer
)[] = [];
private _stack: StackLayer[] = [];
private _itemDepth = 0;

get itemDepth(): number {
Expand All @@ -133,21 +119,14 @@ class ItemStateStackImpl implements ItemStateStack {
});
}

popItem() {
this.pop('item');
}

pushSlotBindings(pairs: SlotValuePair<unknown>[]) {
this._stack.push({
type: 'slotBinding',
bindingMap: new WeakMap(pairs),
usedSet: new WeakSet(),
});
}

popSlotBindings() {
this.pop('slotBinding');
}

pushFunctionScope(
args: Snippet[],
argAliases: Record<string, Snippet>,
Expand All @@ -167,31 +146,26 @@ class ItemStateStackImpl implements ItemStateStack {
return scope;
}

popFunctionScope() {
this.pop('functionScope');
}

pushBlockScope() {
this._stack.push({
type: 'blockScope',
declarations: new Map(),
});
}

popBlockScope() {
this.pop('blockScope');
}

pop(type?: (typeof this._stack)[number]['type']) {
pop<T extends StackLayer['type']>(type: T): Extract<StackLayer, { type: T }>;
pop(): StackLayer | undefined;
pop(type?: StackLayer['type']) {
const layer = this._stack[this._stack.length - 1];
if (!layer || (type && layer.type !== type)) {
throw new Error(`Internal error, expected a ${type} layer to be on top.`);
}

this._stack.pop();
const poppedValue = this._stack.pop();
if (type === 'item') {
this._itemDepth--;
}
return poppedValue;
}

readSlot<T>(slot: TgpuSlot<T>): T | undefined {
Expand All @@ -204,6 +178,7 @@ class ItemStateStackImpl implements ItemStateStack {
const boundValue = layer.bindingMap.get(slot);

if (boundValue !== undefined) {
layer.usedSet.add(slot);
return boundValue as T;
}
} else if (
Expand Down Expand Up @@ -433,7 +408,7 @@ export class ResolutionCtxImpl implements ResolutionCtx {
}

popBlockScope() {
this._itemStateStack.popBlockScope();
this._itemStateStack.pop('blockScope');
}

generateLog(op: string, args: Snippet[]): Snippet {
Expand Down Expand Up @@ -487,7 +462,7 @@ export class ResolutionCtxImpl implements ResolutionCtx {
returnType,
};
} finally {
this._itemStateStack.popFunctionScope();
this._itemStateStack.pop('functionScope');
}
}

Expand Down Expand Up @@ -537,7 +512,16 @@ export class ResolutionCtxImpl implements ResolutionCtx {
try {
return callback();
} finally {
this._itemStateStack.popSlotBindings();
const usedSlots = this._itemStateStack.pop('slotBinding').usedSet;
pairs.forEach((pair) => {
if (!usedSlots.has(pair[0])) {
console.warn(
`Slot '${getName(pair[0])}' with value '${
pair[1]
}' was provided in a 'with' method despite not being utilized during resolution. Please verify that this slot was intended for use and that, in case of WGSL-implemented functions, it is properly declared with the '$uses' method.`,
);
}
});
}
}

Expand Down Expand Up @@ -624,7 +608,7 @@ export class ResolutionCtxImpl implements ResolutionCtx {

throw new ResolutionError(err, [derived]);
} finally {
this._itemStateStack.popItem();
this._itemStateStack.pop('item');
}
}

Expand Down Expand Up @@ -695,7 +679,7 @@ export class ResolutionCtxImpl implements ResolutionCtx {

throw new ResolutionError(err, [item]);
} finally {
this._itemStateStack.popItem();
this._itemStateStack.pop('item');
}
}

Expand Down
26 changes: 21 additions & 5 deletions packages/typegpu/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,30 @@ export type FunctionScopeLayer = {
reportedReturnTypes: Set<AnyData>;
};

export type SlotBindingLayer = {
type: 'slotBinding';
bindingMap: WeakMap<TgpuSlot<unknown>, unknown>;
usedSet: WeakSet<TgpuSlot<unknown>>;
};

export type BlockScopeLayer = {
type: 'blockScope';
declarations: Map<string, Snippet>;
};

export type StackLayer =
| ItemLayer
| SlotBindingLayer
| FunctionScopeLayer
| BlockScopeLayer;

export interface ItemStateStack {
readonly itemDepth: number;
readonly topItem: ItemLayer;
readonly topFunctionScope: FunctionScopeLayer | undefined;

pushItem(): void;
popItem(): void;
pushSlotBindings(pairs: SlotValuePair<unknown>[]): void;
popSlotBindings(): void;
pushFunctionScope(
args: Snippet[],
argAliases: Record<string, Snippet>,
Expand All @@ -126,10 +141,11 @@ export interface ItemStateStack {
returnType: AnyData | undefined,
externalMap: Record<string, unknown>,
): FunctionScopeLayer;
popFunctionScope(): void;
pushBlockScope(): void;
popBlockScope(): void;
pop(type?: 'functionScope' | 'blockScope' | 'slotBinding' | 'item'): void;

pop<T extends StackLayer['type']>(type: T): Extract<StackLayer, { type: T }>;
pop(): StackLayer | undefined;

readSlot<T>(slot: TgpuSlot<T>): T | undefined;
getSnippetById(id: string): Snippet | undefined;
defineBlockVariable(id: string, snippet: Snippet): void;
Expand Down
Loading