@@ -3,12 +3,13 @@ import type {
33 AnyFragmentOutputBuiltin ,
44 OmitBuiltins ,
55} from '../../builtin.ts' ;
6+ import type { InstanceToSchema } from '../../data/instanceToSchema.ts' ;
67import type { ResolvedSnippet } from '../../data/snippet.ts' ;
78import type {
9+ BaseData ,
810 Decorated ,
911 Interpolate ,
1012 Location ,
11- v4f ,
1213 Vec4f ,
1314 Vec4i ,
1415 Vec4u ,
@@ -20,7 +21,6 @@ import {
2021 setName ,
2122 type TgpuNamable ,
2223} from '../../shared/meta.ts' ;
23- import type { InferGPU } from '../../shared/repr.ts' ;
2424import { $getNameForward , $internal , $resolve } from '../../shared/symbols.ts' ;
2525import type { ResolutionCtx , SelfResolvable } from '../../types.ts' ;
2626import { addReturnTypeToExternals } from '../resolve/externals.ts' ;
@@ -45,6 +45,10 @@ export type FragmentInConstrained = IORecord<
4545 | AnyFragmentInputBuiltin
4646> ;
4747
48+ export type FragmentInFromVertexOut < T > =
49+ & OmitBuiltins < { [ K in keyof T ] : InstanceToSchema < T [ K ] > } >
50+ & Record < string , AnyFragmentInputBuiltin > ;
51+
4852type FragmentColorValue = Vec4f | Vec4i | Vec4u ;
4953
5054export type FragmentOutConstrained = IOLayout <
@@ -53,17 +57,12 @@ export type FragmentOutConstrained = IOLayout<
5357 | AnyFragmentOutputBuiltin
5458> ;
5559
56- export type FragmentOutInferred =
57- | undefined
58- | v4f
59- | Record < string , v4f | InferGPU < AnyFragmentOutputBuiltin > > ;
60-
6160/**
6261 * Describes a fragment entry function signature (its arguments, return type and targets)
6362 */
6463type TgpuFragmentFnShellHeader <
65- FragmentIn extends FragmentInConstrained ,
66- FragmentOut extends FragmentOutConstrained ,
64+ FragmentIn extends TgpuFragmentFn . In = TgpuFragmentFn . In ,
65+ FragmentOut extends TgpuFragmentFn . Out = TgpuFragmentFn . Out ,
6766> = {
6867 readonly in : FragmentIn | undefined ;
6968 readonly out : FragmentOut ;
@@ -76,35 +75,42 @@ type TgpuFragmentFnShellHeader<
7675 * Allows creating tgpu fragment functions by calling this shell
7776 * and passing the implementation (as WGSL string or JS function) as the argument.
7877 */
79- export type TgpuFragmentFnShell <
80- FragmentIn extends FragmentInConstrained ,
81- FragmentOut extends FragmentOutConstrained ,
82- > =
83- & TgpuFragmentFnShellHeader < FragmentIn , FragmentOut > /**
78+ export interface TgpuFragmentFnShell <
79+ // We force the variance to be covariant, since shells are just containers of
80+ // schemas that conincidentally can be called to create a fragment function.
81+ // @ts -expect-error: We override the variance
82+ out TIn extends TgpuFragmentFn . In = TgpuFragmentFn . In ,
83+ // @ts -expect-error: We override the variance
84+ out TOut extends TgpuFragmentFn . Out = TgpuFragmentFn . Out ,
85+ > extends TgpuFragmentFnShellHeader < TIn , TOut > {
86+ /**
8487 * Creates a type-safe implementation of this signature
8588 */
86- & ( (
89+ (
8790 implementation : (
88- input : InferIO < FragmentIn > ,
89- out : FragmentOut extends IORecord ? WgslStruct < FragmentOut > : FragmentOut ,
90- ) => InferIO < FragmentOut > ,
91- ) => TgpuFragmentFn < OmitBuiltins < FragmentIn > , FragmentOut > )
92- & /**
91+ input : InferIO < TIn > ,
92+ out : TOut extends IORecord ? WgslStruct < TOut > : TOut ,
93+ ) => InferIO < TOut > ,
94+ ) : TgpuFragmentFn < OmitBuiltins < TIn > , TOut > ;
95+ /**
9396 * @param implementation
9497 * Raw WGSL function implementation with header and body
9598 * without `fn` keyword and function name
9699 * e.g. `"(x: f32) -> f32 { return x; }"`;
97- */ ( (
100+ */
101+ (
98102 implementation : string ,
99- ) => TgpuFragmentFn < OmitBuiltins < FragmentIn > , FragmentOut > )
100- & ( (
103+ ) : TgpuFragmentFn < OmitBuiltins < TIn > , TOut > ;
104+ (
101105 strings : TemplateStringsArray ,
102106 ...values : unknown [ ]
103- ) => TgpuFragmentFn < OmitBuiltins < FragmentIn > , FragmentOut > ) ;
107+ ) : TgpuFragmentFn < OmitBuiltins < TIn > , TOut > ;
108+ }
104109
105110export interface TgpuFragmentFn <
106- Varying extends FragmentInConstrained = FragmentInConstrained ,
107- Output extends FragmentOutConstrained = FragmentOutConstrained ,
111+ // @ts -expect-error: We override the variance
112+ in Varying extends TgpuFragmentFn . In = Record < string , never > ,
113+ out Output extends TgpuFragmentFn . Out = TgpuFragmentFn . Out ,
108114> extends TgpuNamable {
109115 readonly [ $internal ] : true ;
110116 readonly shell : TgpuFragmentFnShellHeader < Varying , Output > ;
@@ -113,6 +119,13 @@ export interface TgpuFragmentFn<
113119 $uses ( dependencyMap : Record < string , unknown > ) : this;
114120}
115121
122+ export declare namespace TgpuFragmentFn {
123+ // Not allowing single-value input, as using objects here is more
124+ // readable, and refactoring to use a builtin argument is too much hassle.
125+ type In = Record < string , BaseData > ;
126+ type Out = Record < string , BaseData > | BaseData ;
127+ }
128+
116129export function fragmentFn <
117130 FragmentOut extends FragmentOutConstrained ,
118131> ( options : {
@@ -140,10 +153,8 @@ export function fragmentFn<
140153 * A `vec4f`, signaling this function outputs a color for one target, or a record containing colors for multiple targets.
141154 */
142155export function fragmentFn <
143- // Not allowing single-value input, as using objects here is more
144- // readable, and refactoring to use a builtin argument is too much hassle.
145- FragmentIn extends FragmentInConstrained ,
146- FragmentOut extends FragmentOutConstrained ,
156+ FragmentIn extends TgpuFragmentFn . In ,
157+ FragmentOut extends TgpuFragmentFn . Out ,
147158> ( options : {
148159 in ?: FragmentIn ;
149160 out : FragmentOut ;
@@ -160,7 +171,7 @@ export function fragmentFn<
160171 ...values : unknown [ ]
161172 ) => createFragmentFn ( shell , stripTemplate ( arg , ...values ) ) ;
162173
163- return Object . assign ( call , shell ) as TgpuFragmentFnShell <
174+ return Object . assign ( call , shell ) as unknown as TgpuFragmentFnShell <
164175 FragmentIn ,
165176 FragmentOut
166177 > ;
@@ -171,16 +182,16 @@ export function fragmentFn<
171182// --------------
172183
173184function createFragmentFn (
174- shell : TgpuFragmentFnShellHeader <
175- FragmentInConstrained ,
176- FragmentOutConstrained
177- > ,
185+ shell : TgpuFragmentFnShellHeader ,
178186 implementation : Implementation ,
179187) : TgpuFragmentFn {
180- type This = TgpuFragmentFn & SelfResolvable & {
181- [ $internal ] : true ;
182- [ $getNameForward ] : FnCore ;
183- } ;
188+ type This =
189+ & TgpuFragmentFn < TgpuFragmentFn . In , TgpuFragmentFn . Out >
190+ & SelfResolvable
191+ & {
192+ [ $internal ] : true ;
193+ [ $getNameForward ] : FnCore ;
194+ } ;
184195
185196 const core = createFnCore ( implementation , '@fragment ' ) ;
186197 const outputType = shell . returnType ;
@@ -214,10 +225,10 @@ function createFragmentFn(
214225 [ $resolve ] ( ctx : ResolutionCtx ) : ResolvedSnippet {
215226 const inputWithLocation = shell . in
216227 ? createIoSchema ( shell . in , ctx . varyingLocations )
217- . $name ( `${ getName ( this ) ?? '' } _Input` )
218228 : undefined ;
219229
220230 if ( inputWithLocation ) {
231+ setName ( inputWithLocation , `${ getName ( this ) ?? '' } _Input` ) ;
221232 core . applyExternals ( { In : inputWithLocation } ) ;
222233 }
223234 core . applyExternals ( { Out : outputType } ) ;
0 commit comments