Skip to content
Merged
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
8 changes: 5 additions & 3 deletions packages/typegpu/src/core/function/autoIO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { BaseData, v4f } from '../../data/wgslTypes.ts';
import { getName, setName } from '../../shared/meta.ts';
import type { InferGPU, InferGPURecord, InferRecord } from '../../shared/repr.ts';
import { $internal, $resolve } from '../../shared/symbols.ts';
import type { Assume } from '../../shared/utilityTypes.ts';
import type { Assume, RemoveIndexSignature } from '../../shared/utilityTypes.ts';
import type { TgpuVertexAttrib } from '../../shared/vertexFormat.ts';
import type { ResolutionCtx, SelfResolvable } from '../../types.ts';
import { shaderStageSlot } from '../slot/internalSlots.ts';
Expand All @@ -21,7 +21,8 @@ const builtinVertexIn = {
$instanceIndex: builtin.instanceIndex,
} as const;

export type AutoVertexIn<T extends AnyAutoCustoms> = T & InferRecord<typeof builtinVertexIn>;
export type AutoVertexIn<T extends AnyAutoCustoms> = RemoveIndexSignature<T> &
InferRecord<typeof builtinVertexIn>;

export type _AutoVertexIn<T> = AutoVertexIn<{
[Key in keyof T]: T[Key] extends TgpuVertexAttrib
Expand All @@ -47,7 +48,8 @@ const builtinFragmentIn = {
$subgroupSize: builtin.subgroupSize,
} as const;

export type AutoFragmentIn<T extends AnyAutoCustoms> = T & InferRecord<typeof builtinFragmentIn>;
export type AutoFragmentIn<T extends AnyAutoCustoms> = RemoveIndexSignature<T> &
InferRecord<typeof builtinFragmentIn>;

const builtinFragmentOut = {
$fragDepth: builtin.fragDepth,
Expand Down
2 changes: 2 additions & 0 deletions packages/typegpu/src/core/function/tgpuFragmentFn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ export declare namespace TgpuFragmentFn {
type Out = Record<string, BaseData> | BaseData;
type AutoIn<T extends AnyAutoCustoms> = AutoFragmentIn<T>;
type AutoOut<T extends AnyAutoCustoms = AnyAutoCustoms> = AutoFragmentOut<T>;

type AutoInEmpty = AutoFragmentIn<Record<string, never>>;
}

export function fragmentFn<FragmentOut extends FragmentOutConstrained>(options: {
Expand Down
2 changes: 2 additions & 0 deletions packages/typegpu/src/core/function/tgpuVertexFn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ export declare namespace TgpuVertexFn {
type Out = Record<string, BaseData>;
type AutoIn<T> = _AutoVertexIn<T>;
type AutoOut<T extends AnyAutoCustoms = AnyAutoCustoms> = AutoVertexOut<T>;

type AutoInEmpty = _AutoVertexIn<Record<string, never>>;
}

export function vertexFn<VertexOut extends VertexOutConstrained>(options: {
Expand Down
15 changes: 14 additions & 1 deletion packages/typegpu/src/shared/utilityTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export type Mutable<T> = {
};

/**
* Source: https://code.lol/post/programming/higher-kinded-types/
* Source: https://code.lol/post/programming/higher-kinded-types
*/
export type Assume<T, U> = T extends U ? T : U;

Expand All @@ -74,3 +74,16 @@ export type TypedArray =
export function assertExhaustive(x: never, location: string): never {
throw new Error(`Failed to handle ${x} at ${location}`);
}

/**
* Source: https://futurestud.io/tutorials/typescript-how-to-remove-index-signature-from-a-type
*/
export type RemoveIndexSignature<T> = {
[K in keyof T as string extends K
? never
: number extends K
? never
: symbol extends K
? never
: K]: T[K];
};
59 changes: 56 additions & 3 deletions packages/typegpu/tests/renderPipeline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import tgpu, {
common,
d,
MissingBindGroupsError,
type TgpuFragmentFn,
type TgpuFragmentFnShell,
type TgpuRenderPipeline,
type TgpuVertexFn,
type TgpuVertexFnShell,
} from '../src/index.js';
import { $internal } from '../src/shared/symbols.ts';
Expand Down Expand Up @@ -1591,7 +1593,7 @@ describe('root.createRenderPipeline', () => {
attribs: { vertexIndex: vertexLayout.attrib },
vertex: ({ vertexIndex, $vertexIndex }) => {
'use gpu';
return { $position: d.vec4f() };
return { $position: d.vec4f(vertexIndex, $vertexIndex, 0, 1) };
},
fragment: () => {
'use gpu';
Expand Down Expand Up @@ -1619,7 +1621,7 @@ describe('root.createRenderPipeline', () => {
},
fragment: ({ position }) => {
'use gpu';
return d.vec4f();
return position;
},
targets: { format: 'rgba8unorm' },
});
Expand All @@ -1641,7 +1643,10 @@ describe('root.createRenderPipeline', () => {
},
fragment: ({ $frontFacing, frontFacing }) => {
'use gpu';
return d.vec4f();
if ($frontFacing && frontFacing === 1) {
return d.vec4f(0, 1, 0, 1);
}
return d.vec4f(1, 0, 0, 1);
},
targets: { format: 'rgba8unorm' },
});
Expand Down Expand Up @@ -1774,6 +1779,54 @@ describe('root.createRenderPipeline', () => {
]
`);
});

it('accepts entry functions with no attributes or varyings', ({ root }) => {
const positions = tgpu.const(d.arrayOf(d.vec2f, 3), [
d.vec2f(0, 0),
d.vec2f(1, 0),
d.vec2f(0, 1),
]);
const vertex = ({ $vertexIndex }: TgpuVertexFn.AutoInEmpty) => {
'use gpu';
return {
$position: d.vec4f(positions.$[$vertexIndex]!, 0, 1),
} satisfies TgpuVertexFn.AutoOut;
};

const fragment = ({ $position }: TgpuFragmentFn.AutoInEmpty) => {
'use gpu';
return $position;
};

const pipeline = root.createRenderPipeline({
vertex,
fragment,
});

expect(tgpu.resolve([pipeline])).toMatchInlineSnapshot(`
"const positions: array<vec2f, 3> = array<vec2f, 3>(vec2f(), vec2f(1, 0), vec2f(0, 1));

struct VertexOut {
@builtin(position) position: vec4f,
}

struct VertexIn {
@builtin(vertex_index) vertexIndex: u32,
}

@vertex fn vertex(_arg_0: VertexIn) -> VertexOut {
return VertexOut(vec4f(positions[_arg_0.vertexIndex], 0f, 1f));
}

struct FragmentIn {
@builtin(position) position: vec4f,
}

@fragment fn fragment(_arg_0: FragmentIn) -> @location(0) vec4f {
return _arg_0.position;
}"
`);
});
});

describe('matchUpVaryingLocations', () => {
Expand Down
Loading