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