@@ -44,7 +44,7 @@ describe('ref', () => {
4444 ` ) ;
4545 } ) ;
4646
47- it ( 'fails when creating a ref with a reference' , ( ) => {
47+ it ( 'fails when creating a ref with a reference, and assigning it to a variable ' , ( ) => {
4848 const hello = ( ) => {
4949 'use gpu' ;
5050 const position = d . vec3f ( 1 , 2 , 3 ) ;
@@ -58,4 +58,118 @@ describe('ref', () => {
5858 - fn*:hello(): Cannot store d.ref() in a variable if it references another value. Copy the value passed into d.ref() instead.]
5959 ` ) ;
6060 } ) ;
61+
62+ it ( 'allows updating a whole struct from another function' , ( ) => {
63+ type Entity = d . Infer < typeof Entity > ;
64+ const Entity = d . struct ( { pos : d . vec3f } ) ;
65+
66+ const clearEntity = ( entity : d . ref < Entity > ) => {
67+ 'use gpu' ;
68+ entity . $ = Entity ( { pos : d . vec3f ( 0 , 0 , 0 ) } ) ;
69+ } ;
70+
71+ const main = ( ) => {
72+ 'use gpu' ;
73+ const entity = Entity ( { pos : d . vec3f ( 1 , 2 , 3 ) } ) ;
74+ clearEntity ( d . ref ( entity ) ) ;
75+ // entity.pos should be vec3f(0, 0, 0)
76+ return entity ;
77+ } ;
78+
79+ // Works in JS
80+ expect ( main ( ) . pos ) . toStrictEqual ( d . vec3f ( 0 , 0 , 0 ) ) ;
81+
82+ // And on the GPU
83+ expect ( asWgsl ( main ) ) . toMatchInlineSnapshot ( `
84+ "struct Entity {
85+ pos: vec3f,
86+ }
87+
88+ fn clearEntity(entity: ptr<function, Entity>) {
89+ (*entity) = Entity(vec3f());
90+ }
91+
92+ fn main() -> Entity {
93+ var entity = Entity(vec3f(1, 2, 3));
94+ clearEntity((&entity));
95+ return entity;
96+ }"
97+ ` ) ;
98+ } ) ;
99+
100+ it ( 'allows updating a number from another function' , ( ) => {
101+ const increment = ( value : d . ref < number > ) => {
102+ 'use gpu' ;
103+ value . $ += 1 ;
104+ } ;
105+
106+ const main = ( ) => {
107+ 'use gpu' ;
108+ const value = d . ref ( 0 ) ;
109+ increment ( value ) ;
110+ return value . $ ;
111+ } ;
112+
113+ // Works in JS
114+ expect ( main ( ) ) . toBe ( 1 ) ;
115+
116+ // And on the GPU
117+ expect ( asWgsl ( main ) ) . toMatchInlineSnapshot ( `
118+ "fn increment(value: ptr<function, i32>) {
119+ (*value) += 1i;
120+ }
121+
122+ fn main() -> i32 {
123+ var value = 0;
124+ increment((&value));
125+ return value;
126+ }"
127+ ` ) ;
128+ } ) ;
129+
130+ it ( 'rejects passing d.ref created from non-refs directly into functions' , ( ) => {
131+ const increment = ( value : d . ref < number > ) => {
132+ 'use gpu' ;
133+ value . $ += 1 ;
134+ } ;
135+
136+ const main = ( ) => {
137+ 'use gpu' ;
138+ increment ( d . ref ( 0 ) ) ;
139+ } ;
140+
141+ expect ( ( ) => asWgsl ( main ) ) . toThrowErrorMatchingInlineSnapshot ( `
142+ [Error: Resolution of the following tree failed:
143+ - <root>
144+ - fn*:main
145+ - fn*:main(): d.ref() created with primitive types must be stored in a variable before use]
146+ ` ) ;
147+ } ) ;
148+
149+ it ( 'fails when returning a ref' , ( ) => {
150+ const foo = ( ) => {
151+ 'use gpu' ;
152+ const value = d . ref ( 0 ) ;
153+ return value ;
154+ } ;
155+
156+ const bar = ( ) => {
157+ 'use gpu' ;
158+ return d . ref ( 0 ) ;
159+ } ;
160+
161+ expect ( ( ) => asWgsl ( foo ) ) . toThrowErrorMatchingInlineSnapshot ( `
162+ [Error: Resolution of the following tree failed:
163+ - <root>
164+ - fn*:foo
165+ - fn*:foo(): Cannot return references, returning 'value']
166+ ` ) ;
167+
168+ expect ( ( ) => asWgsl ( bar ) ) . toThrowErrorMatchingInlineSnapshot ( `
169+ [Error: Resolution of the following tree failed:
170+ - <root>
171+ - fn*:bar
172+ - fn*:bar(): Cannot return references, returning '0']
173+ ` ) ;
174+ } ) ;
61175} ) ;
0 commit comments