• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/transform/multiplanar_external_texture.h"
16 #include "src/transform/test_helper.h"
17 
18 namespace tint {
19 namespace transform {
20 namespace {
21 
22 using MultiplanarExternalTextureTest = TransformTest;
23 
24 // Running the transform without passing in data for the new bindings should
25 // result in an error.
TEST_F(MultiplanarExternalTextureTest,ErrorNoPassedData)26 TEST_F(MultiplanarExternalTextureTest, ErrorNoPassedData) {
27   auto* src = R"(
28 [[group(0), binding(0)]] var s : sampler;
29 [[group(0), binding(1)]] var ext_tex : texture_external;
30 
31 [[stage(fragment)]]
32 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
33   return textureSampleLevel(ext_tex, s, coord.xy);
34 }
35 )";
36   auto* expect =
37       R"(error: missing new binding point data for tint::transform::MultiplanarExternalTexture)";
38 
39   auto got = Run<MultiplanarExternalTexture>(src);
40   EXPECT_EQ(expect, str(got));
41 }
42 
43 // Running the transform with incorrect binding data should result in an error.
TEST_F(MultiplanarExternalTextureTest,ErrorIncorrectBindingPont)44 TEST_F(MultiplanarExternalTextureTest, ErrorIncorrectBindingPont) {
45   auto* src = R"(
46 [[group(0), binding(0)]] var s : sampler;
47 [[group(0), binding(1)]] var ext_tex : texture_external;
48 
49 [[stage(fragment)]]
50 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
51   return textureSampleLevel(ext_tex, s, coord.xy);
52 }
53 )";
54 
55   auto* expect =
56       R"(error: missing new binding points for texture_external at binding {0,1})";
57 
58   DataMap data;
59   // This bindings map specifies 0,0 as the location of the texture_external,
60   // which is incorrect.
61   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
62       MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
63   auto got = Run<MultiplanarExternalTexture>(src, data);
64   EXPECT_EQ(expect, str(got));
65 }
66 
67 // Tests that the transform works with a textureDimensions call.
TEST_F(MultiplanarExternalTextureTest,Dimensions)68 TEST_F(MultiplanarExternalTextureTest, Dimensions) {
69   auto* src = R"(
70 [[group(0), binding(0)]] var ext_tex : texture_external;
71 
72 [[stage(fragment)]]
73 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
74   var dim : vec2<i32>;
75   dim = textureDimensions(ext_tex);
76   return vec4<f32>(0.0, 0.0, 0.0, 0.0);
77 }
78 )";
79 
80   auto* expect = R"(
81 [[block]]
82 struct ExternalTextureParams {
83   numPlanes : u32;
84   vr : f32;
85   ug : f32;
86   vg : f32;
87   ub : f32;
88 };
89 
90 [[group(0), binding(1)]] var ext_tex_plane_1 : texture_2d<f32>;
91 
92 [[group(0), binding(2)]] var<uniform> ext_tex_params : ExternalTextureParams;
93 
94 [[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
95 
96 [[stage(fragment)]]
97 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
98   var dim : vec2<i32>;
99   dim = textureDimensions(ext_tex);
100   return vec4<f32>(0.0, 0.0, 0.0, 0.0);
101 }
102 )";
103 
104   DataMap data;
105   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
106       MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
107   auto got = Run<MultiplanarExternalTexture>(src, data);
108   EXPECT_EQ(expect, str(got));
109 }
110 
111 // Test that the transform works with a textureSampleLevel call.
TEST_F(MultiplanarExternalTextureTest,BasicTextureSampleLevel)112 TEST_F(MultiplanarExternalTextureTest, BasicTextureSampleLevel) {
113   auto* src = R"(
114 [[group(0), binding(0)]] var s : sampler;
115 [[group(0), binding(1)]] var ext_tex : texture_external;
116 
117 [[stage(fragment)]]
118 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
119   return textureSampleLevel(ext_tex, s, coord.xy);
120 }
121 )";
122 
123   auto* expect = R"(
124 [[group(0), binding(0)]] var s : sampler;
125 
126 [[block]]
127 struct ExternalTextureParams {
128   numPlanes : u32;
129   vr : f32;
130   ug : f32;
131   vg : f32;
132   ub : f32;
133 };
134 
135 [[group(0), binding(2)]] var ext_tex_plane_1 : texture_2d<f32>;
136 
137 [[group(0), binding(3)]] var<uniform> ext_tex_params : ExternalTextureParams;
138 
139 [[group(0), binding(1)]] var ext_tex : texture_2d<f32>;
140 
141 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
142   if ((params.numPlanes == 1u)) {
143     return textureSampleLevel(plane0, smp, coord, 0.0);
144   }
145   let y = (textureSampleLevel(plane0, smp, coord, 0.0).r - 0.0625);
146   let uv = (textureSampleLevel(plane1, smp, coord, 0.0).rg - 0.5);
147   let u = uv.x;
148   let v = uv.y;
149   let r = ((1.164000034 * y) + (params.vr * v));
150   let g = (((1.164000034 * y) - (params.ug * u)) - (params.vg * v));
151   let b = ((1.164000034 * y) + (params.ub * u));
152   return vec4<f32>(r, g, b, 1.0);
153 }
154 
155 [[stage(fragment)]]
156 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
157   return textureSampleExternal(ext_tex, ext_tex_plane_1, s, coord.xy, ext_tex_params);
158 }
159 )";
160 
161   DataMap data;
162   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
163       MultiplanarExternalTexture::BindingsMap{{{0, 1}, {{0, 2}, {0, 3}}}});
164   auto got = Run<MultiplanarExternalTexture>(src, data);
165   EXPECT_EQ(expect, str(got));
166 }
167 
168 // Tests that the transform works with a textureLoad call.
TEST_F(MultiplanarExternalTextureTest,BasicTextureLoad)169 TEST_F(MultiplanarExternalTextureTest, BasicTextureLoad) {
170   auto* src = R"(
171 [[group(0), binding(0)]] var ext_tex : texture_external;
172 
173 [[stage(fragment)]]
174 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
175   return textureLoad(ext_tex, vec2<i32>(1, 1));
176 }
177 )";
178 
179   auto* expect = R"(
180 [[block]]
181 struct ExternalTextureParams {
182   numPlanes : u32;
183   vr : f32;
184   ug : f32;
185   vg : f32;
186   ub : f32;
187 };
188 
189 [[group(0), binding(1)]] var ext_tex_plane_1 : texture_2d<f32>;
190 
191 [[group(0), binding(2)]] var<uniform> ext_tex_params : ExternalTextureParams;
192 
193 [[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
194 
195 fn textureLoadExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<i32>, params : ExternalTextureParams) -> vec4<f32> {
196   if ((params.numPlanes == 1u)) {
197     return textureLoad(plane0, coord, 0);
198   }
199   let y = (textureLoad(plane0, coord, 0).r - 0.0625);
200   let uv = (textureLoad(plane1, coord, 0).rg - 0.5);
201   let u = uv.x;
202   let v = uv.y;
203   let r = ((1.164000034 * y) + (params.vr * v));
204   let g = (((1.164000034 * y) - (params.ug * u)) - (params.vg * v));
205   let b = ((1.164000034 * y) + (params.ub * u));
206   return vec4<f32>(r, g, b, 1.0);
207 }
208 
209 [[stage(fragment)]]
210 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
211   return textureLoadExternal(ext_tex, ext_tex_plane_1, vec2<i32>(1, 1), ext_tex_params);
212 }
213 )";
214 
215   DataMap data;
216   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
217       MultiplanarExternalTexture::BindingsMap{{{0, 0}, {{0, 1}, {0, 2}}}});
218   auto got = Run<MultiplanarExternalTexture>(src, data);
219   EXPECT_EQ(expect, str(got));
220 }
221 
222 // Tests that the transform works with both a textureSampleLevel and textureLoad
223 // call.
TEST_F(MultiplanarExternalTextureTest,TextureSampleAndTextureLoad)224 TEST_F(MultiplanarExternalTextureTest, TextureSampleAndTextureLoad) {
225   auto* src = R"(
226 [[group(0), binding(0)]] var s : sampler;
227 [[group(0), binding(1)]] var ext_tex : texture_external;
228 
229 [[stage(fragment)]]
230 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
231   return textureSampleLevel(ext_tex, s, coord.xy) + textureLoad(ext_tex, vec2<i32>(1, 1));
232 }
233 )";
234 
235   auto* expect = R"(
236 [[group(0), binding(0)]] var s : sampler;
237 
238 [[block]]
239 struct ExternalTextureParams {
240   numPlanes : u32;
241   vr : f32;
242   ug : f32;
243   vg : f32;
244   ub : f32;
245 };
246 
247 [[group(0), binding(2)]] var ext_tex_plane_1 : texture_2d<f32>;
248 
249 [[group(0), binding(3)]] var<uniform> ext_tex_params : ExternalTextureParams;
250 
251 [[group(0), binding(1)]] var ext_tex : texture_2d<f32>;
252 
253 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
254   if ((params.numPlanes == 1u)) {
255     return textureSampleLevel(plane0, smp, coord, 0.0);
256   }
257   let y = (textureSampleLevel(plane0, smp, coord, 0.0).r - 0.0625);
258   let uv = (textureSampleLevel(plane1, smp, coord, 0.0).rg - 0.5);
259   let u = uv.x;
260   let v = uv.y;
261   let r = ((1.164000034 * y) + (params.vr * v));
262   let g = (((1.164000034 * y) - (params.ug * u)) - (params.vg * v));
263   let b = ((1.164000034 * y) + (params.ub * u));
264   return vec4<f32>(r, g, b, 1.0);
265 }
266 
267 fn textureLoadExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<i32>, params : ExternalTextureParams) -> vec4<f32> {
268   if ((params.numPlanes == 1u)) {
269     return textureLoad(plane0, coord, 0);
270   }
271   let y = (textureLoad(plane0, coord, 0).r - 0.0625);
272   let uv = (textureLoad(plane1, coord, 0).rg - 0.5);
273   let u = uv.x;
274   let v = uv.y;
275   let r = ((1.164000034 * y) + (params.vr * v));
276   let g = (((1.164000034 * y) - (params.ug * u)) - (params.vg * v));
277   let b = ((1.164000034 * y) + (params.ub * u));
278   return vec4<f32>(r, g, b, 1.0);
279 }
280 
281 [[stage(fragment)]]
282 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
283   return (textureSampleExternal(ext_tex, ext_tex_plane_1, s, coord.xy, ext_tex_params) + textureLoadExternal(ext_tex, ext_tex_plane_1, vec2<i32>(1, 1), ext_tex_params));
284 }
285 )";
286 
287   DataMap data;
288   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
289       MultiplanarExternalTexture::BindingsMap{{{0, 1}, {{0, 2}, {0, 3}}}});
290   auto got = Run<MultiplanarExternalTexture>(src, data);
291   EXPECT_EQ(expect, str(got));
292 }
293 
294 // Tests that the transform works with many instances of texture_external.
TEST_F(MultiplanarExternalTextureTest,ManyTextureSampleLevel)295 TEST_F(MultiplanarExternalTextureTest, ManyTextureSampleLevel) {
296   auto* src = R"(
297 [[group(0), binding(0)]] var s : sampler;
298 [[group(0), binding(1)]] var ext_tex : texture_external;
299 [[group(0), binding(2)]] var ext_tex_1 : texture_external;
300 [[group(0), binding(3)]] var ext_tex_2 : texture_external;
301 [[group(1), binding(0)]] var ext_tex_3 : texture_external;
302 
303 [[stage(fragment)]]
304 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
305   return textureSampleLevel(ext_tex, s, coord.xy) + textureSampleLevel(ext_tex_1, s, coord.xy) + textureSampleLevel(ext_tex_2, s, coord.xy) + textureSampleLevel(ext_tex_3, s, coord.xy);
306 }
307 )";
308 
309   auto* expect = R"(
310 [[group(0), binding(0)]] var s : sampler;
311 
312 [[block]]
313 struct ExternalTextureParams {
314   numPlanes : u32;
315   vr : f32;
316   ug : f32;
317   vg : f32;
318   ub : f32;
319 };
320 
321 [[group(0), binding(4)]] var ext_tex_plane_1 : texture_2d<f32>;
322 
323 [[group(0), binding(5)]] var<uniform> ext_tex_params : ExternalTextureParams;
324 
325 [[group(0), binding(1)]] var ext_tex : texture_2d<f32>;
326 
327 [[group(0), binding(6)]] var ext_tex_plane_1_1 : texture_2d<f32>;
328 
329 [[group(0), binding(7)]] var<uniform> ext_tex_params_1 : ExternalTextureParams;
330 
331 [[group(0), binding(2)]] var ext_tex_1 : texture_2d<f32>;
332 
333 [[group(0), binding(8)]] var ext_tex_plane_1_2 : texture_2d<f32>;
334 
335 [[group(0), binding(9)]] var<uniform> ext_tex_params_2 : ExternalTextureParams;
336 
337 [[group(0), binding(3)]] var ext_tex_2 : texture_2d<f32>;
338 
339 [[group(1), binding(1)]] var ext_tex_plane_1_3 : texture_2d<f32>;
340 
341 [[group(1), binding(2)]] var<uniform> ext_tex_params_3 : ExternalTextureParams;
342 
343 [[group(1), binding(0)]] var ext_tex_3 : texture_2d<f32>;
344 
345 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
346   if ((params.numPlanes == 1u)) {
347     return textureSampleLevel(plane0, smp, coord, 0.0);
348   }
349   let y = (textureSampleLevel(plane0, smp, coord, 0.0).r - 0.0625);
350   let uv = (textureSampleLevel(plane1, smp, coord, 0.0).rg - 0.5);
351   let u = uv.x;
352   let v = uv.y;
353   let r = ((1.164000034 * y) + (params.vr * v));
354   let g = (((1.164000034 * y) - (params.ug * u)) - (params.vg * v));
355   let b = ((1.164000034 * y) + (params.ub * u));
356   return vec4<f32>(r, g, b, 1.0);
357 }
358 
359 [[stage(fragment)]]
360 fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
361   return (((textureSampleExternal(ext_tex, ext_tex_plane_1, s, coord.xy, ext_tex_params) + textureSampleExternal(ext_tex_1, ext_tex_plane_1_1, s, coord.xy, ext_tex_params_1)) + textureSampleExternal(ext_tex_2, ext_tex_plane_1_2, s, coord.xy, ext_tex_params_2)) + textureSampleExternal(ext_tex_3, ext_tex_plane_1_3, s, coord.xy, ext_tex_params_3));
362 }
363 )";
364 
365   DataMap data;
366   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
367       MultiplanarExternalTexture::BindingsMap{
368           {{0, 1}, {{0, 4}, {0, 5}}},
369           {{0, 2}, {{0, 6}, {0, 7}}},
370           {{0, 3}, {{0, 8}, {0, 9}}},
371           {{1, 0}, {{1, 1}, {1, 2}}},
372       });
373   auto got = Run<MultiplanarExternalTexture>(src, data);
374   EXPECT_EQ(expect, str(got));
375 }
376 
377 // Tests that the texture_external passed as a function parameter produces the
378 // correct output.
TEST_F(MultiplanarExternalTextureTest,ExternalTexturePassedAsParam)379 TEST_F(MultiplanarExternalTextureTest, ExternalTexturePassedAsParam) {
380   auto* src = R"(
381 fn f(t : texture_external, s : sampler) {
382   textureSampleLevel(t, s, vec2<f32>(1.0, 2.0));
383 }
384 
385 [[group(0), binding(0)]] var ext_tex : texture_external;
386 [[group(0), binding(1)]] var smp : sampler;
387 
388 [[stage(fragment)]]
389 fn main() {
390   f(ext_tex, smp);
391 }
392 )";
393 
394   auto* expect = R"(
395 [[block]]
396 struct ExternalTextureParams {
397   numPlanes : u32;
398   vr : f32;
399   ug : f32;
400   vg : f32;
401   ub : f32;
402 };
403 
404 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
405   if ((params.numPlanes == 1u)) {
406     return textureSampleLevel(plane0, smp, coord, 0.0);
407   }
408   let y = (textureSampleLevel(plane0, smp, coord, 0.0).r - 0.0625);
409   let uv = (textureSampleLevel(plane1, smp, coord, 0.0).rg - 0.5);
410   let u = uv.x;
411   let v = uv.y;
412   let r = ((1.164000034 * y) + (params.vr * v));
413   let g = (((1.164000034 * y) - (params.ug * u)) - (params.vg * v));
414   let b = ((1.164000034 * y) + (params.ub * u));
415   return vec4<f32>(r, g, b, 1.0);
416 }
417 
418 fn f(t : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams, s : sampler) {
419   textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
420 }
421 
422 [[group(0), binding(2)]] var ext_tex_plane_1_1 : texture_2d<f32>;
423 
424 [[group(0), binding(3)]] var<uniform> ext_tex_params_1 : ExternalTextureParams;
425 
426 [[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
427 
428 [[group(0), binding(1)]] var smp : sampler;
429 
430 [[stage(fragment)]]
431 fn main() {
432   f(ext_tex, ext_tex_plane_1_1, ext_tex_params_1, smp);
433 }
434 )";
435   DataMap data;
436   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
437       MultiplanarExternalTexture::BindingsMap{
438           {{0, 0}, {{0, 2}, {0, 3}}},
439       });
440   auto got = Run<MultiplanarExternalTexture>(src, data);
441   EXPECT_EQ(expect, str(got));
442 }
443 
444 // Tests that the texture_external passed as a parameter not in the first
445 // position produces the correct output.
TEST_F(MultiplanarExternalTextureTest,ExternalTexturePassedAsSecondParam)446 TEST_F(MultiplanarExternalTextureTest, ExternalTexturePassedAsSecondParam) {
447   auto* src = R"(
448 fn f(s : sampler, t : texture_external) {
449   textureSampleLevel(t, s, vec2<f32>(1.0, 2.0));
450 }
451 
452 [[group(0), binding(0)]] var ext_tex : texture_external;
453 [[group(0), binding(1)]] var smp : sampler;
454 
455 [[stage(fragment)]]
456 fn main() {
457   f(smp, ext_tex);
458 }
459 )";
460 
461   auto* expect = R"(
462 [[block]]
463 struct ExternalTextureParams {
464   numPlanes : u32;
465   vr : f32;
466   ug : f32;
467   vg : f32;
468   ub : f32;
469 };
470 
471 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
472   if ((params.numPlanes == 1u)) {
473     return textureSampleLevel(plane0, smp, coord, 0.0);
474   }
475   let y = (textureSampleLevel(plane0, smp, coord, 0.0).r - 0.0625);
476   let uv = (textureSampleLevel(plane1, smp, coord, 0.0).rg - 0.5);
477   let u = uv.x;
478   let v = uv.y;
479   let r = ((1.164000034 * y) + (params.vr * v));
480   let g = (((1.164000034 * y) - (params.ug * u)) - (params.vg * v));
481   let b = ((1.164000034 * y) + (params.ub * u));
482   return vec4<f32>(r, g, b, 1.0);
483 }
484 
485 fn f(s : sampler, t : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams) {
486   textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
487 }
488 
489 [[group(0), binding(2)]] var ext_tex_plane_1_1 : texture_2d<f32>;
490 
491 [[group(0), binding(3)]] var<uniform> ext_tex_params_1 : ExternalTextureParams;
492 
493 [[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
494 
495 [[group(0), binding(1)]] var smp : sampler;
496 
497 [[stage(fragment)]]
498 fn main() {
499   f(smp, ext_tex, ext_tex_plane_1_1, ext_tex_params_1);
500 }
501 )";
502   DataMap data;
503   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
504       MultiplanarExternalTexture::BindingsMap{
505           {{0, 0}, {{0, 2}, {0, 3}}},
506       });
507   auto got = Run<MultiplanarExternalTexture>(src, data);
508   EXPECT_EQ(expect, str(got));
509 }
510 
511 // Tests that multiple texture_external params passed to a function produces the
512 // correct output.
TEST_F(MultiplanarExternalTextureTest,ExternalTexturePassedAsParamMultiple)513 TEST_F(MultiplanarExternalTextureTest, ExternalTexturePassedAsParamMultiple) {
514   auto* src = R"(
515 fn f(t : texture_external, s : sampler, t2 : texture_external) {
516   textureSampleLevel(t, s, vec2<f32>(1.0, 2.0));
517   textureSampleLevel(t2, s, vec2<f32>(1.0, 2.0));
518 }
519 
520 [[group(0), binding(0)]] var ext_tex : texture_external;
521 [[group(0), binding(1)]] var smp : sampler;
522 [[group(0), binding(2)]] var ext_tex2 : texture_external;
523 
524 [[stage(fragment)]]
525 fn main() {
526   f(ext_tex, smp, ext_tex2);
527 }
528 )";
529 
530   auto* expect = R"(
531 [[block]]
532 struct ExternalTextureParams {
533   numPlanes : u32;
534   vr : f32;
535   ug : f32;
536   vg : f32;
537   ub : f32;
538 };
539 
540 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
541   if ((params.numPlanes == 1u)) {
542     return textureSampleLevel(plane0, smp, coord, 0.0);
543   }
544   let y = (textureSampleLevel(plane0, smp, coord, 0.0).r - 0.0625);
545   let uv = (textureSampleLevel(plane1, smp, coord, 0.0).rg - 0.5);
546   let u = uv.x;
547   let v = uv.y;
548   let r = ((1.164000034 * y) + (params.vr * v));
549   let g = (((1.164000034 * y) - (params.ug * u)) - (params.vg * v));
550   let b = ((1.164000034 * y) + (params.ub * u));
551   return vec4<f32>(r, g, b, 1.0);
552 }
553 
554 fn f(t : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams, s : sampler, t2 : texture_2d<f32>, ext_tex_plane_1_1 : texture_2d<f32>, ext_tex_params_1 : ExternalTextureParams) {
555   textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
556   textureSampleExternal(t2, ext_tex_plane_1_1, s, vec2<f32>(1.0, 2.0), ext_tex_params_1);
557 }
558 
559 [[group(0), binding(3)]] var ext_tex_plane_1_2 : texture_2d<f32>;
560 
561 [[group(0), binding(4)]] var<uniform> ext_tex_params_2 : ExternalTextureParams;
562 
563 [[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
564 
565 [[group(0), binding(1)]] var smp : sampler;
566 
567 [[group(0), binding(5)]] var ext_tex_plane_1_3 : texture_2d<f32>;
568 
569 [[group(0), binding(6)]] var<uniform> ext_tex_params_3 : ExternalTextureParams;
570 
571 [[group(0), binding(2)]] var ext_tex2 : texture_2d<f32>;
572 
573 [[stage(fragment)]]
574 fn main() {
575   f(ext_tex, ext_tex_plane_1_2, ext_tex_params_2, smp, ext_tex2, ext_tex_plane_1_3, ext_tex_params_3);
576 }
577 )";
578   DataMap data;
579   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
580       MultiplanarExternalTexture::BindingsMap{
581           {{0, 0}, {{0, 3}, {0, 4}}},
582           {{0, 2}, {{0, 5}, {0, 6}}},
583       });
584   auto got = Run<MultiplanarExternalTexture>(src, data);
585   EXPECT_EQ(expect, str(got));
586 }
587 
588 // Tests that the texture_external passed to as a parameter to multiple
589 // functions produces the correct output.
TEST_F(MultiplanarExternalTextureTest,ExternalTexturePassedAsParamNested)590 TEST_F(MultiplanarExternalTextureTest, ExternalTexturePassedAsParamNested) {
591   auto* src = R"(
592 fn nested(t : texture_external, s : sampler) {
593   textureSampleLevel(t, s, vec2<f32>(1.0, 2.0));
594 }
595 
596 fn f(t : texture_external, s : sampler) {
597   nested(t, s);
598 }
599 
600 [[group(0), binding(0)]] var ext_tex : texture_external;
601 [[group(0), binding(1)]] var smp : sampler;
602 
603 [[stage(fragment)]]
604 fn main() {
605   f(ext_tex, smp);
606 }
607 )";
608 
609   auto* expect = R"(
610 [[block]]
611 struct ExternalTextureParams {
612   numPlanes : u32;
613   vr : f32;
614   ug : f32;
615   vg : f32;
616   ub : f32;
617 };
618 
619 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
620   if ((params.numPlanes == 1u)) {
621     return textureSampleLevel(plane0, smp, coord, 0.0);
622   }
623   let y = (textureSampleLevel(plane0, smp, coord, 0.0).r - 0.0625);
624   let uv = (textureSampleLevel(plane1, smp, coord, 0.0).rg - 0.5);
625   let u = uv.x;
626   let v = uv.y;
627   let r = ((1.164000034 * y) + (params.vr * v));
628   let g = (((1.164000034 * y) - (params.ug * u)) - (params.vg * v));
629   let b = ((1.164000034 * y) + (params.ub * u));
630   return vec4<f32>(r, g, b, 1.0);
631 }
632 
633 fn nested(t : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams, s : sampler) {
634   textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
635 }
636 
637 fn f(t : texture_2d<f32>, ext_tex_plane_1_1 : texture_2d<f32>, ext_tex_params_1 : ExternalTextureParams, s : sampler) {
638   nested(t, ext_tex_plane_1_1, ext_tex_params_1, s);
639 }
640 
641 [[group(0), binding(2)]] var ext_tex_plane_1_2 : texture_2d<f32>;
642 
643 [[group(0), binding(3)]] var<uniform> ext_tex_params_2 : ExternalTextureParams;
644 
645 [[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
646 
647 [[group(0), binding(1)]] var smp : sampler;
648 
649 [[stage(fragment)]]
650 fn main() {
651   f(ext_tex, ext_tex_plane_1_2, ext_tex_params_2, smp);
652 }
653 )";
654   DataMap data;
655   data.Add<MultiplanarExternalTexture::NewBindingPoints>(
656       MultiplanarExternalTexture::BindingsMap{
657           {{0, 0}, {{0, 2}, {0, 3}}},
658       });
659   auto got = Run<MultiplanarExternalTexture>(src, data);
660   EXPECT_EQ(expect, str(got));
661 }
662 
663 }  // namespace
664 }  // namespace transform
665 }  // namespace tint
666