blob: 6597fb8ede76e13ffff1bab485ee6a60258afacc [file] [log] [blame]
// Copyright 2023 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/tint/lang/core/ir/transform/multiplanar_external_texture.h"
#include <utility>
#include "src/tint/lang/core/ir/transform/helper_test.h"
#include "src/tint/lang/core/type/external_texture.h"
namespace tint::core::ir::transform {
namespace {
using namespace tint::core::fluent_types; // NOLINT
using namespace tint::core::number_suffixes; // NOLINT
using IR_MultiplanarExternalTextureTest = TransformTest;
TEST_F(IR_MultiplanarExternalTextureTest, NoRootBlock) {
auto* func = b.Function("foo", ty.void_());
func->Block()->Append(b.Return(func));
auto* expect = R"(
%foo = func():void {
$B1: {
ret
}
}
)";
ExternalTextureOptions options;
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
TEST_F(IR_MultiplanarExternalTextureTest, DeclWithNoUses) {
auto* var = b.Var("texture", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var->SetBindingPoint(1, 2);
mod.root_block->Append(var);
auto* func = b.Function("foo", ty.void_());
b.Append(func->Block(), [&] { //
b.Return(func);
});
auto* src = R"(
$B1: { # root
%texture:ptr<handle, texture_external, read> = var @binding_point(1, 2)
}
%foo = func():void {
$B2: {
ret
}
}
)";
auto* expect = R"(
tint_GammaTransferParams = struct @align(4) {
G:f32 @offset(0)
A:f32 @offset(4)
B:f32 @offset(8)
C:f32 @offset(12)
D:f32 @offset(16)
E:f32 @offset(20)
F:f32 @offset(24)
padding:u32 @offset(28)
}
tint_ExternalTextureParams = struct @align(16) {
numPlanes:u32 @offset(0)
doYuvToRgbConversionOnly:u32 @offset(4)
yuvToRgbConversionMatrix:mat3x4<f32> @offset(16)
gammaDecodeParams:tint_GammaTransferParams @offset(64)
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
loadTransformationMatrix:mat3x2<f32> @offset(200)
samplePlane0RectMin:vec2<f32> @offset(224)
samplePlane0RectMax:vec2<f32> @offset(232)
samplePlane1RectMin:vec2<f32> @offset(240)
samplePlane1RectMax:vec2<f32> @offset(248)
displayVisibleRectMax:vec2<u32> @offset(256)
plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
%texture_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 2)
%texture_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 3)
%texture_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(1, 4)
}
%foo = func():void {
$B2: {
ret
}
}
)";
EXPECT_EQ(src, str());
ExternalTextureOptions options;
options.bindings_map[{1u, 2u}] = {{1u, 3u}, {1u, 4u}};
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
TEST_F(IR_MultiplanarExternalTextureTest, LoadWithNoUses) {
auto* var = b.Var("texture", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var->SetBindingPoint(1, 2);
mod.root_block->Append(var);
auto* func = b.Function("foo", ty.void_());
b.Append(func->Block(), [&] {
b.Load(var);
b.Return(func);
});
auto* src = R"(
$B1: { # root
%texture:ptr<handle, texture_external, read> = var @binding_point(1, 2)
}
%foo = func():void {
$B2: {
%3:texture_external = load %texture
ret
}
}
)";
auto* expect = R"(
tint_GammaTransferParams = struct @align(4) {
G:f32 @offset(0)
A:f32 @offset(4)
B:f32 @offset(8)
C:f32 @offset(12)
D:f32 @offset(16)
E:f32 @offset(20)
F:f32 @offset(24)
padding:u32 @offset(28)
}
tint_ExternalTextureParams = struct @align(16) {
numPlanes:u32 @offset(0)
doYuvToRgbConversionOnly:u32 @offset(4)
yuvToRgbConversionMatrix:mat3x4<f32> @offset(16)
gammaDecodeParams:tint_GammaTransferParams @offset(64)
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
loadTransformationMatrix:mat3x2<f32> @offset(200)
samplePlane0RectMin:vec2<f32> @offset(224)
samplePlane0RectMax:vec2<f32> @offset(232)
samplePlane1RectMin:vec2<f32> @offset(240)
samplePlane1RectMax:vec2<f32> @offset(248)
displayVisibleRectMax:vec2<u32> @offset(256)
plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
%texture_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 2)
%texture_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 3)
%texture_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(1, 4)
}
%foo = func():void {
$B2: {
%5:texture_2d<f32> = load %texture_plane0
%6:texture_2d<f32> = load %texture_plane1
%7:tint_ExternalTextureParams = load %texture_params
ret
}
}
)";
EXPECT_EQ(src, str());
ExternalTextureOptions options;
options.bindings_map[{1u, 2u}] = {{1u, 3u}, {1u, 4u}};
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
TEST_F(IR_MultiplanarExternalTextureTest, TextureDimensions) {
auto* var = b.Var("texture", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var->SetBindingPoint(1, 2);
mod.root_block->Append(var);
auto* func = b.Function("foo", ty.vec2<u32>());
b.Append(func->Block(), [&] {
auto* load = b.Load(var->Result(0));
auto* result = b.Call(ty.vec2<u32>(), core::BuiltinFn::kTextureDimensions, load);
b.Return(func, result);
mod.SetName(result, "result");
});
auto* src = R"(
$B1: { # root
%texture:ptr<handle, texture_external, read> = var @binding_point(1, 2)
}
%foo = func():vec2<u32> {
$B2: {
%3:texture_external = load %texture
%result:vec2<u32> = textureDimensions %3
ret %result
}
}
)";
auto* expect = R"(
tint_GammaTransferParams = struct @align(4) {
G:f32 @offset(0)
A:f32 @offset(4)
B:f32 @offset(8)
C:f32 @offset(12)
D:f32 @offset(16)
E:f32 @offset(20)
F:f32 @offset(24)
padding:u32 @offset(28)
}
tint_ExternalTextureParams = struct @align(16) {
numPlanes:u32 @offset(0)
doYuvToRgbConversionOnly:u32 @offset(4)
yuvToRgbConversionMatrix:mat3x4<f32> @offset(16)
gammaDecodeParams:tint_GammaTransferParams @offset(64)
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
loadTransformationMatrix:mat3x2<f32> @offset(200)
samplePlane0RectMin:vec2<f32> @offset(224)
samplePlane0RectMax:vec2<f32> @offset(232)
samplePlane1RectMin:vec2<f32> @offset(240)
samplePlane1RectMax:vec2<f32> @offset(248)
displayVisibleRectMax:vec2<u32> @offset(256)
plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
%texture_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 2)
%texture_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 3)
%texture_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(1, 4)
}
%foo = func():vec2<u32> {
$B2: {
%5:texture_2d<f32> = load %texture_plane0
%6:texture_2d<f32> = load %texture_plane1
%7:tint_ExternalTextureParams = load %texture_params
%result:vec2<u32> = textureDimensions %5
ret %result
}
}
)";
EXPECT_EQ(src, str());
ExternalTextureOptions options;
options.bindings_map[{1u, 2u}] = {{1u, 3u}, {1u, 4u}};
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
TEST_F(IR_MultiplanarExternalTextureTest, TextureLoad) {
auto* var = b.Var("texture", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var->SetBindingPoint(1, 2);
mod.root_block->Append(var);
auto* func = b.Function("foo", ty.vec4<f32>());
auto* coords = b.FunctionParam("coords", ty.vec2<u32>());
func->SetParams({coords});
b.Append(func->Block(), [&] {
auto* load = b.Load(var->Result(0));
auto* result = b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureLoad, load, coords);
b.Return(func, result);
mod.SetName(result, "result");
});
auto* src = R"(
$B1: { # root
%texture:ptr<handle, texture_external, read> = var @binding_point(1, 2)
}
%foo = func(%coords:vec2<u32>):vec4<f32> {
$B2: {
%4:texture_external = load %texture
%result:vec4<f32> = textureLoad %4, %coords
ret %result
}
}
)";
auto* expect = R"(
tint_GammaTransferParams = struct @align(4) {
G:f32 @offset(0)
A:f32 @offset(4)
B:f32 @offset(8)
C:f32 @offset(12)
D:f32 @offset(16)
E:f32 @offset(20)
F:f32 @offset(24)
padding:u32 @offset(28)
}
tint_ExternalTextureParams = struct @align(16) {
numPlanes:u32 @offset(0)
doYuvToRgbConversionOnly:u32 @offset(4)
yuvToRgbConversionMatrix:mat3x4<f32> @offset(16)
gammaDecodeParams:tint_GammaTransferParams @offset(64)
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
loadTransformationMatrix:mat3x2<f32> @offset(200)
samplePlane0RectMin:vec2<f32> @offset(224)
samplePlane0RectMax:vec2<f32> @offset(232)
samplePlane1RectMin:vec2<f32> @offset(240)
samplePlane1RectMax:vec2<f32> @offset(248)
displayVisibleRectMax:vec2<u32> @offset(256)
plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
%texture_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 2)
%texture_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 3)
%texture_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(1, 4)
}
%foo = func(%coords:vec2<u32>):vec4<f32> {
$B2: {
%6:texture_2d<f32> = load %texture_plane0
%7:texture_2d<f32> = load %texture_plane1
%8:tint_ExternalTextureParams = load %texture_params
%9:vec4<f32> = call %tint_TextureLoadExternal, %6, %7, %8, %coords
ret %9
}
}
%tint_TextureLoadExternal = func(%plane_0:texture_2d<f32>, %plane_1:texture_2d<f32>, %params:tint_ExternalTextureParams, %coords_1:vec2<u32>):vec4<f32> { # %coords_1: 'coords'
$B3: {
%15:u32 = access %params, 1u
%16:mat3x4<f32> = access %params, 2u
%17:mat3x2<f32> = access %params, 7u
%18:vec2<u32> = access %params, 12u
%19:vec2<f32> = access %params, 13u
%20:vec2<u32> = min %coords_1, %18
%21:vec2<f32> = convert %20
%22:vec3<f32> = construct %21, 1.0f
%23:vec2<f32> = mul %17, %22
%24:vec2<f32> = round %23
%25:vec2<u32> = convert %24
%26:u32 = access %params, 0u
%27:bool = eq %26, 1u
%28:vec3<f32>, %29:f32 = if %27 [t: $B4, f: $B5] { # if_1
$B4: { # true
%30:vec4<f32> = textureLoad %plane_0, %25, 0u
%31:vec3<f32> = swizzle %30, xyz
%32:f32 = access %30, 3u
exit_if %31, %32 # if_1
}
$B5: { # false
%33:vec4<f32> = textureLoad %plane_0, %25, 0u
%34:f32 = access %33, 0u
%35:vec2<f32> = mul %24, %19
%36:vec2<u32> = convert %35
%37:vec4<f32> = textureLoad %plane_1, %36, 0u
%38:vec2<f32> = swizzle %37, xy
%39:vec4<f32> = construct %34, %38, 1.0f
%40:vec3<f32> = mul %39, %16
exit_if %40, 1.0f # if_1
}
}
%41:bool = eq %15, 0u
%42:vec3<f32> = if %41 [t: $B6, f: $B7] { # if_2
$B6: { # true
%43:tint_GammaTransferParams = access %params, 3u
%44:tint_GammaTransferParams = access %params, 4u
%45:mat3x3<f32> = access %params, 5u
%46:vec3<f32> = call %tint_GammaCorrection, %28, %43
%48:vec3<f32> = mul %45, %46
%49:vec3<f32> = call %tint_GammaCorrection, %48, %44
exit_if %49 # if_2
}
$B7: { # false
exit_if %28 # if_2
}
}
%50:vec4<f32> = construct %42, %29
ret %50
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B8: {
%53:f32 = access %params_1, 0u
%54:f32 = access %params_1, 1u
%55:f32 = access %params_1, 2u
%56:f32 = access %params_1, 3u
%57:f32 = access %params_1, 4u
%58:f32 = access %params_1, 5u
%59:f32 = access %params_1, 6u
%60:vec3<f32> = construct %53
%61:vec3<f32> = construct %57
%62:vec3<f32> = abs %v
%63:vec3<f32> = sign %v
%64:vec3<bool> = lt %62, %61
%65:vec3<f32> = mul %56, %62
%66:vec3<f32> = add %65, %59
%67:vec3<f32> = mul %63, %66
%68:vec3<f32> = mul %54, %62
%69:vec3<f32> = add %68, %55
%70:vec3<f32> = pow %69, %60
%71:vec3<f32> = add %70, %58
%72:vec3<f32> = mul %63, %71
%73:vec3<f32> = select %72, %67, %64
ret %73
}
}
)";
EXPECT_EQ(src, str());
ExternalTextureOptions options;
options.bindings_map[{1u, 2u}] = {{1u, 3u}, {1u, 4u}};
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
TEST_F(IR_MultiplanarExternalTextureTest, TextureLoad_SignedCoords) {
auto* var = b.Var("texture", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var->SetBindingPoint(1, 2);
mod.root_block->Append(var);
auto* func = b.Function("foo", ty.vec4<f32>());
auto* coords = b.FunctionParam("coords", ty.vec2<i32>());
func->SetParams({coords});
b.Append(func->Block(), [&] {
auto* load = b.Load(var->Result(0));
auto* result = b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureLoad, load, coords);
b.Return(func, result);
mod.SetName(result, "result");
});
auto* src = R"(
$B1: { # root
%texture:ptr<handle, texture_external, read> = var @binding_point(1, 2)
}
%foo = func(%coords:vec2<i32>):vec4<f32> {
$B2: {
%4:texture_external = load %texture
%result:vec4<f32> = textureLoad %4, %coords
ret %result
}
}
)";
auto* expect = R"(
tint_GammaTransferParams = struct @align(4) {
G:f32 @offset(0)
A:f32 @offset(4)
B:f32 @offset(8)
C:f32 @offset(12)
D:f32 @offset(16)
E:f32 @offset(20)
F:f32 @offset(24)
padding:u32 @offset(28)
}
tint_ExternalTextureParams = struct @align(16) {
numPlanes:u32 @offset(0)
doYuvToRgbConversionOnly:u32 @offset(4)
yuvToRgbConversionMatrix:mat3x4<f32> @offset(16)
gammaDecodeParams:tint_GammaTransferParams @offset(64)
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
loadTransformationMatrix:mat3x2<f32> @offset(200)
samplePlane0RectMin:vec2<f32> @offset(224)
samplePlane0RectMax:vec2<f32> @offset(232)
samplePlane1RectMin:vec2<f32> @offset(240)
samplePlane1RectMax:vec2<f32> @offset(248)
displayVisibleRectMax:vec2<u32> @offset(256)
plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
%texture_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 2)
%texture_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 3)
%texture_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(1, 4)
}
%foo = func(%coords:vec2<i32>):vec4<f32> {
$B2: {
%6:texture_2d<f32> = load %texture_plane0
%7:texture_2d<f32> = load %texture_plane1
%8:tint_ExternalTextureParams = load %texture_params
%9:vec2<u32> = convert %coords
%10:vec4<f32> = call %tint_TextureLoadExternal, %6, %7, %8, %9
ret %10
}
}
%tint_TextureLoadExternal = func(%plane_0:texture_2d<f32>, %plane_1:texture_2d<f32>, %params:tint_ExternalTextureParams, %coords_1:vec2<u32>):vec4<f32> { # %coords_1: 'coords'
$B3: {
%16:u32 = access %params, 1u
%17:mat3x4<f32> = access %params, 2u
%18:mat3x2<f32> = access %params, 7u
%19:vec2<u32> = access %params, 12u
%20:vec2<f32> = access %params, 13u
%21:vec2<u32> = min %coords_1, %19
%22:vec2<f32> = convert %21
%23:vec3<f32> = construct %22, 1.0f
%24:vec2<f32> = mul %18, %23
%25:vec2<f32> = round %24
%26:vec2<u32> = convert %25
%27:u32 = access %params, 0u
%28:bool = eq %27, 1u
%29:vec3<f32>, %30:f32 = if %28 [t: $B4, f: $B5] { # if_1
$B4: { # true
%31:vec4<f32> = textureLoad %plane_0, %26, 0u
%32:vec3<f32> = swizzle %31, xyz
%33:f32 = access %31, 3u
exit_if %32, %33 # if_1
}
$B5: { # false
%34:vec4<f32> = textureLoad %plane_0, %26, 0u
%35:f32 = access %34, 0u
%36:vec2<f32> = mul %25, %20
%37:vec2<u32> = convert %36
%38:vec4<f32> = textureLoad %plane_1, %37, 0u
%39:vec2<f32> = swizzle %38, xy
%40:vec4<f32> = construct %35, %39, 1.0f
%41:vec3<f32> = mul %40, %17
exit_if %41, 1.0f # if_1
}
}
%42:bool = eq %16, 0u
%43:vec3<f32> = if %42 [t: $B6, f: $B7] { # if_2
$B6: { # true
%44:tint_GammaTransferParams = access %params, 3u
%45:tint_GammaTransferParams = access %params, 4u
%46:mat3x3<f32> = access %params, 5u
%47:vec3<f32> = call %tint_GammaCorrection, %29, %44
%49:vec3<f32> = mul %46, %47
%50:vec3<f32> = call %tint_GammaCorrection, %49, %45
exit_if %50 # if_2
}
$B7: { # false
exit_if %29 # if_2
}
}
%51:vec4<f32> = construct %43, %30
ret %51
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B8: {
%54:f32 = access %params_1, 0u
%55:f32 = access %params_1, 1u
%56:f32 = access %params_1, 2u
%57:f32 = access %params_1, 3u
%58:f32 = access %params_1, 4u
%59:f32 = access %params_1, 5u
%60:f32 = access %params_1, 6u
%61:vec3<f32> = construct %54
%62:vec3<f32> = construct %58
%63:vec3<f32> = abs %v
%64:vec3<f32> = sign %v
%65:vec3<bool> = lt %63, %62
%66:vec3<f32> = mul %57, %63
%67:vec3<f32> = add %66, %60
%68:vec3<f32> = mul %64, %67
%69:vec3<f32> = mul %55, %63
%70:vec3<f32> = add %69, %56
%71:vec3<f32> = pow %70, %61
%72:vec3<f32> = add %71, %59
%73:vec3<f32> = mul %64, %72
%74:vec3<f32> = select %73, %68, %65
ret %74
}
}
)";
EXPECT_EQ(src, str());
ExternalTextureOptions options;
options.bindings_map[{1u, 2u}] = {{1u, 3u}, {1u, 4u}};
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
TEST_F(IR_MultiplanarExternalTextureTest, TextureSampleBaseClampToEdge) {
auto* var = b.Var("texture", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var->SetBindingPoint(1, 2);
mod.root_block->Append(var);
auto* func = b.Function("foo", ty.vec4<f32>());
auto* sampler = b.FunctionParam("sampler", ty.sampler());
auto* coords = b.FunctionParam("coords", ty.vec2<f32>());
func->SetParams({sampler, coords});
b.Append(func->Block(), [&] {
auto* load = b.Load(var->Result(0));
auto* result = b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureSampleBaseClampToEdge, load,
sampler, coords);
b.Return(func, result);
mod.SetName(result, "result");
});
auto* src = R"(
$B1: { # root
%texture:ptr<handle, texture_external, read> = var @binding_point(1, 2)
}
%foo = func(%sampler:sampler, %coords:vec2<f32>):vec4<f32> {
$B2: {
%5:texture_external = load %texture
%result:vec4<f32> = textureSampleBaseClampToEdge %5, %sampler, %coords
ret %result
}
}
)";
auto* expect = R"(
tint_GammaTransferParams = struct @align(4) {
G:f32 @offset(0)
A:f32 @offset(4)
B:f32 @offset(8)
C:f32 @offset(12)
D:f32 @offset(16)
E:f32 @offset(20)
F:f32 @offset(24)
padding:u32 @offset(28)
}
tint_ExternalTextureParams = struct @align(16) {
numPlanes:u32 @offset(0)
doYuvToRgbConversionOnly:u32 @offset(4)
yuvToRgbConversionMatrix:mat3x4<f32> @offset(16)
gammaDecodeParams:tint_GammaTransferParams @offset(64)
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
loadTransformationMatrix:mat3x2<f32> @offset(200)
samplePlane0RectMin:vec2<f32> @offset(224)
samplePlane0RectMax:vec2<f32> @offset(232)
samplePlane1RectMin:vec2<f32> @offset(240)
samplePlane1RectMax:vec2<f32> @offset(248)
displayVisibleRectMax:vec2<u32> @offset(256)
plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
%texture_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 2)
%texture_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 3)
%texture_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(1, 4)
}
%foo = func(%sampler:sampler, %coords:vec2<f32>):vec4<f32> {
$B2: {
%7:texture_2d<f32> = load %texture_plane0
%8:texture_2d<f32> = load %texture_plane1
%9:tint_ExternalTextureParams = load %texture_params
%10:vec4<f32> = call %tint_TextureSampleExternal, %7, %8, %9, %sampler, %coords
ret %10
}
}
%tint_TextureSampleExternal = func(%plane_0:texture_2d<f32>, %plane_1:texture_2d<f32>, %params:tint_ExternalTextureParams, %sampler_1:sampler, %coords_1:vec2<f32>):vec4<f32> { # %sampler_1: 'sampler', %coords_1: 'coords'
$B3: {
%17:u32 = access %params, 1u
%18:mat3x4<f32> = access %params, 2u
%19:mat3x2<f32> = access %params, 6u
%20:vec2<f32> = access %params, 8u
%21:vec2<f32> = access %params, 9u
%22:vec2<f32> = access %params, 10u
%23:vec2<f32> = access %params, 11u
%24:vec3<f32> = construct %coords_1, 1.0f
%25:vec2<f32> = mul %19, %24
%26:vec2<f32> = clamp %25, %20, %21
%27:u32 = access %params, 0u
%28:bool = eq %27, 1u
%29:vec3<f32>, %30:f32 = if %28 [t: $B4, f: $B5] { # if_1
$B4: { # true
%31:vec4<f32> = textureSampleLevel %plane_0, %sampler_1, %26, 0.0f
%32:vec3<f32> = swizzle %31, xyz
%33:f32 = access %31, 3u
exit_if %32, %33 # if_1
}
$B5: { # false
%34:vec4<f32> = textureSampleLevel %plane_0, %sampler_1, %26, 0.0f
%35:f32 = access %34, 0u
%36:vec2<f32> = clamp %25, %22, %23
%37:vec4<f32> = textureSampleLevel %plane_1, %sampler_1, %36, 0.0f
%38:vec2<f32> = swizzle %37, xy
%39:vec4<f32> = construct %35, %38, 1.0f
%40:vec3<f32> = mul %39, %18
exit_if %40, 1.0f # if_1
}
}
%41:bool = eq %17, 0u
%42:vec3<f32> = if %41 [t: $B6, f: $B7] { # if_2
$B6: { # true
%43:tint_GammaTransferParams = access %params, 3u
%44:tint_GammaTransferParams = access %params, 4u
%45:mat3x3<f32> = access %params, 5u
%46:vec3<f32> = call %tint_GammaCorrection, %29, %43
%48:vec3<f32> = mul %45, %46
%49:vec3<f32> = call %tint_GammaCorrection, %48, %44
exit_if %49 # if_2
}
$B7: { # false
exit_if %29 # if_2
}
}
%50:vec4<f32> = construct %42, %30
ret %50
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B8: {
%53:f32 = access %params_1, 0u
%54:f32 = access %params_1, 1u
%55:f32 = access %params_1, 2u
%56:f32 = access %params_1, 3u
%57:f32 = access %params_1, 4u
%58:f32 = access %params_1, 5u
%59:f32 = access %params_1, 6u
%60:vec3<f32> = construct %53
%61:vec3<f32> = construct %57
%62:vec3<f32> = abs %v
%63:vec3<f32> = sign %v
%64:vec3<bool> = lt %62, %61
%65:vec3<f32> = mul %56, %62
%66:vec3<f32> = add %65, %59
%67:vec3<f32> = mul %63, %66
%68:vec3<f32> = mul %54, %62
%69:vec3<f32> = add %68, %55
%70:vec3<f32> = pow %69, %60
%71:vec3<f32> = add %70, %58
%72:vec3<f32> = mul %63, %71
%73:vec3<f32> = select %72, %67, %64
ret %73
}
}
)";
EXPECT_EQ(src, str());
ExternalTextureOptions options;
options.bindings_map[{1u, 2u}] = {{1u, 3u}, {1u, 4u}};
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
TEST_F(IR_MultiplanarExternalTextureTest, ViaUserFunctionParameter) {
auto* var = b.Var("texture", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var->SetBindingPoint(1, 2);
mod.root_block->Append(var);
auto* foo = b.Function("foo", ty.vec4<f32>());
{
auto* texture = b.FunctionParam("texture", ty.Get<core::type::ExternalTexture>());
auto* sampler = b.FunctionParam("sampler", ty.sampler());
auto* coords = b.FunctionParam("coords", ty.vec2<f32>());
foo->SetParams({texture, sampler, coords});
b.Append(foo->Block(), [&] {
auto* result = b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureSampleBaseClampToEdge,
texture, sampler, coords);
b.Return(foo, result);
mod.SetName(result, "result");
});
}
auto* bar = b.Function("bar", ty.vec4<f32>());
{
auto* sampler = b.FunctionParam("sampler", ty.sampler());
auto* coords = b.FunctionParam("coords", ty.vec2<f32>());
bar->SetParams({sampler, coords});
b.Append(bar->Block(), [&] {
auto* load = b.Load(var->Result(0));
auto* result = b.Call(ty.vec4<f32>(), foo, load, sampler, coords);
b.Return(bar, result);
mod.SetName(result, "result");
});
}
auto* src = R"(
$B1: { # root
%texture:ptr<handle, texture_external, read> = var @binding_point(1, 2)
}
%foo = func(%texture_1:texture_external, %sampler:sampler, %coords:vec2<f32>):vec4<f32> { # %texture_1: 'texture'
$B2: {
%result:vec4<f32> = textureSampleBaseClampToEdge %texture_1, %sampler, %coords
ret %result
}
}
%bar = func(%sampler_1:sampler, %coords_1:vec2<f32>):vec4<f32> { # %sampler_1: 'sampler', %coords_1: 'coords'
$B3: {
%10:texture_external = load %texture
%result_1:vec4<f32> = call %foo, %10, %sampler_1, %coords_1 # %result_1: 'result'
ret %result_1
}
}
)";
auto* expect = R"(
tint_GammaTransferParams = struct @align(4) {
G:f32 @offset(0)
A:f32 @offset(4)
B:f32 @offset(8)
C:f32 @offset(12)
D:f32 @offset(16)
E:f32 @offset(20)
F:f32 @offset(24)
padding:u32 @offset(28)
}
tint_ExternalTextureParams = struct @align(16) {
numPlanes:u32 @offset(0)
doYuvToRgbConversionOnly:u32 @offset(4)
yuvToRgbConversionMatrix:mat3x4<f32> @offset(16)
gammaDecodeParams:tint_GammaTransferParams @offset(64)
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
loadTransformationMatrix:mat3x2<f32> @offset(200)
samplePlane0RectMin:vec2<f32> @offset(224)
samplePlane0RectMax:vec2<f32> @offset(232)
samplePlane1RectMin:vec2<f32> @offset(240)
samplePlane1RectMax:vec2<f32> @offset(248)
displayVisibleRectMax:vec2<u32> @offset(256)
plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
%texture_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 2)
%texture_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 3)
%texture_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(1, 4)
}
%foo = func(%texture_plane0_1:texture_2d<f32>, %texture_plane1_1:texture_2d<f32>, %texture_params_1:tint_ExternalTextureParams, %sampler:sampler, %coords:vec2<f32>):vec4<f32> { # %texture_plane0_1: 'texture_plane0', %texture_plane1_1: 'texture_plane1', %texture_params_1: 'texture_params'
$B2: {
%10:vec4<f32> = call %tint_TextureSampleExternal, %texture_plane0_1, %texture_plane1_1, %texture_params_1, %sampler, %coords
ret %10
}
}
%bar = func(%sampler_1:sampler, %coords_1:vec2<f32>):vec4<f32> { # %sampler_1: 'sampler', %coords_1: 'coords'
$B3: {
%15:texture_2d<f32> = load %texture_plane0
%16:texture_2d<f32> = load %texture_plane1
%17:tint_ExternalTextureParams = load %texture_params
%result:vec4<f32> = call %foo, %15, %16, %17, %sampler_1, %coords_1
ret %result
}
}
%tint_TextureSampleExternal = func(%plane_0:texture_2d<f32>, %plane_1:texture_2d<f32>, %params:tint_ExternalTextureParams, %sampler_2:sampler, %coords_2:vec2<f32>):vec4<f32> { # %sampler_2: 'sampler', %coords_2: 'coords'
$B4: {
%24:u32 = access %params, 1u
%25:mat3x4<f32> = access %params, 2u
%26:mat3x2<f32> = access %params, 6u
%27:vec2<f32> = access %params, 8u
%28:vec2<f32> = access %params, 9u
%29:vec2<f32> = access %params, 10u
%30:vec2<f32> = access %params, 11u
%31:vec3<f32> = construct %coords_2, 1.0f
%32:vec2<f32> = mul %26, %31
%33:vec2<f32> = clamp %32, %27, %28
%34:u32 = access %params, 0u
%35:bool = eq %34, 1u
%36:vec3<f32>, %37:f32 = if %35 [t: $B5, f: $B6] { # if_1
$B5: { # true
%38:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %33, 0.0f
%39:vec3<f32> = swizzle %38, xyz
%40:f32 = access %38, 3u
exit_if %39, %40 # if_1
}
$B6: { # false
%41:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %33, 0.0f
%42:f32 = access %41, 0u
%43:vec2<f32> = clamp %32, %29, %30
%44:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %43, 0.0f
%45:vec2<f32> = swizzle %44, xy
%46:vec4<f32> = construct %42, %45, 1.0f
%47:vec3<f32> = mul %46, %25
exit_if %47, 1.0f # if_1
}
}
%48:bool = eq %24, 0u
%49:vec3<f32> = if %48 [t: $B7, f: $B8] { # if_2
$B7: { # true
%50:tint_GammaTransferParams = access %params, 3u
%51:tint_GammaTransferParams = access %params, 4u
%52:mat3x3<f32> = access %params, 5u
%53:vec3<f32> = call %tint_GammaCorrection, %36, %50
%55:vec3<f32> = mul %52, %53
%56:vec3<f32> = call %tint_GammaCorrection, %55, %51
exit_if %56 # if_2
}
$B8: { # false
exit_if %36 # if_2
}
}
%57:vec4<f32> = construct %49, %37
ret %57
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B9: {
%60:f32 = access %params_1, 0u
%61:f32 = access %params_1, 1u
%62:f32 = access %params_1, 2u
%63:f32 = access %params_1, 3u
%64:f32 = access %params_1, 4u
%65:f32 = access %params_1, 5u
%66:f32 = access %params_1, 6u
%67:vec3<f32> = construct %60
%68:vec3<f32> = construct %64
%69:vec3<f32> = abs %v
%70:vec3<f32> = sign %v
%71:vec3<bool> = lt %69, %68
%72:vec3<f32> = mul %63, %69
%73:vec3<f32> = add %72, %66
%74:vec3<f32> = mul %70, %73
%75:vec3<f32> = mul %61, %69
%76:vec3<f32> = add %75, %62
%77:vec3<f32> = pow %76, %67
%78:vec3<f32> = add %77, %65
%79:vec3<f32> = mul %70, %78
%80:vec3<f32> = select %79, %74, %71
ret %80
}
}
)";
EXPECT_EQ(src, str());
ExternalTextureOptions options;
options.bindings_map[{1u, 2u}] = {{1u, 3u}, {1u, 4u}};
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
TEST_F(IR_MultiplanarExternalTextureTest, MultipleUses) {
auto* var = b.Var("texture", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var->SetBindingPoint(1, 2);
mod.root_block->Append(var);
auto* foo = b.Function("foo", ty.vec4<f32>());
{
auto* texture = b.FunctionParam("texture", ty.Get<core::type::ExternalTexture>());
auto* sampler = b.FunctionParam("sampler", ty.sampler());
auto* coords = b.FunctionParam("coords", ty.vec2<f32>());
foo->SetParams({texture, sampler, coords});
b.Append(foo->Block(), [&] {
auto* result = b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureSampleBaseClampToEdge,
texture, sampler, coords);
b.Return(foo, result);
mod.SetName(result, "result");
});
}
auto* bar = b.Function("bar", ty.vec4<f32>());
{
auto* sampler = b.FunctionParam("sampler", ty.sampler());
auto* coords_f = b.FunctionParam("coords", ty.vec2<f32>());
bar->SetParams({sampler, coords_f});
b.Append(bar->Block(), [&] {
auto* load_a = b.Load(var->Result(0));
b.Call(ty.vec2<u32>(), core::BuiltinFn::kTextureDimensions, load_a);
auto* load_b = b.Load(var->Result(0));
b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureSampleBaseClampToEdge, load_b, sampler,
coords_f);
auto* load_c = b.Load(var->Result(0));
b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureSampleBaseClampToEdge, load_c, sampler,
coords_f);
auto* load_d = b.Load(var->Result(0));
auto* result_a = b.Call(ty.vec4<f32>(), foo, load_d, sampler, coords_f);
auto* result_b = b.Call(ty.vec4<f32>(), foo, load_d, sampler, coords_f);
b.Return(bar, b.Add(ty.vec4<f32>(), result_a, result_b));
mod.SetName(result_a, "result_a");
mod.SetName(result_b, "result_b");
});
}
auto* src = R"(
$B1: { # root
%texture:ptr<handle, texture_external, read> = var @binding_point(1, 2)
}
%foo = func(%texture_1:texture_external, %sampler:sampler, %coords:vec2<f32>):vec4<f32> { # %texture_1: 'texture'
$B2: {
%result:vec4<f32> = textureSampleBaseClampToEdge %texture_1, %sampler, %coords
ret %result
}
}
%bar = func(%sampler_1:sampler, %coords_1:vec2<f32>):vec4<f32> { # %sampler_1: 'sampler', %coords_1: 'coords'
$B3: {
%10:texture_external = load %texture
%11:vec2<u32> = textureDimensions %10
%12:texture_external = load %texture
%13:vec4<f32> = textureSampleBaseClampToEdge %12, %sampler_1, %coords_1
%14:texture_external = load %texture
%15:vec4<f32> = textureSampleBaseClampToEdge %14, %sampler_1, %coords_1
%16:texture_external = load %texture
%result_a:vec4<f32> = call %foo, %16, %sampler_1, %coords_1
%result_b:vec4<f32> = call %foo, %16, %sampler_1, %coords_1
%19:vec4<f32> = add %result_a, %result_b
ret %19
}
}
)";
auto* expect = R"(
tint_GammaTransferParams = struct @align(4) {
G:f32 @offset(0)
A:f32 @offset(4)
B:f32 @offset(8)
C:f32 @offset(12)
D:f32 @offset(16)
E:f32 @offset(20)
F:f32 @offset(24)
padding:u32 @offset(28)
}
tint_ExternalTextureParams = struct @align(16) {
numPlanes:u32 @offset(0)
doYuvToRgbConversionOnly:u32 @offset(4)
yuvToRgbConversionMatrix:mat3x4<f32> @offset(16)
gammaDecodeParams:tint_GammaTransferParams @offset(64)
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
loadTransformationMatrix:mat3x2<f32> @offset(200)
samplePlane0RectMin:vec2<f32> @offset(224)
samplePlane0RectMax:vec2<f32> @offset(232)
samplePlane1RectMin:vec2<f32> @offset(240)
samplePlane1RectMax:vec2<f32> @offset(248)
displayVisibleRectMax:vec2<u32> @offset(256)
plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
%texture_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 2)
%texture_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 3)
%texture_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(1, 4)
}
%foo = func(%texture_plane0_1:texture_2d<f32>, %texture_plane1_1:texture_2d<f32>, %texture_params_1:tint_ExternalTextureParams, %sampler:sampler, %coords:vec2<f32>):vec4<f32> { # %texture_plane0_1: 'texture_plane0', %texture_plane1_1: 'texture_plane1', %texture_params_1: 'texture_params'
$B2: {
%10:vec4<f32> = call %tint_TextureSampleExternal, %texture_plane0_1, %texture_plane1_1, %texture_params_1, %sampler, %coords
ret %10
}
}
%bar = func(%sampler_1:sampler, %coords_1:vec2<f32>):vec4<f32> { # %sampler_1: 'sampler', %coords_1: 'coords'
$B3: {
%15:texture_2d<f32> = load %texture_plane0
%16:texture_2d<f32> = load %texture_plane1
%17:tint_ExternalTextureParams = load %texture_params
%18:vec2<u32> = textureDimensions %15
%19:texture_2d<f32> = load %texture_plane0
%20:texture_2d<f32> = load %texture_plane1
%21:tint_ExternalTextureParams = load %texture_params
%22:vec4<f32> = call %tint_TextureSampleExternal, %19, %20, %21, %sampler_1, %coords_1
%23:texture_2d<f32> = load %texture_plane0
%24:texture_2d<f32> = load %texture_plane1
%25:tint_ExternalTextureParams = load %texture_params
%26:vec4<f32> = call %tint_TextureSampleExternal, %23, %24, %25, %sampler_1, %coords_1
%27:texture_2d<f32> = load %texture_plane0
%28:texture_2d<f32> = load %texture_plane1
%29:tint_ExternalTextureParams = load %texture_params
%result_a:vec4<f32> = call %foo, %27, %28, %29, %sampler_1, %coords_1
%result_b:vec4<f32> = call %foo, %27, %28, %29, %sampler_1, %coords_1
%32:vec4<f32> = add %result_a, %result_b
ret %32
}
}
%tint_TextureSampleExternal = func(%plane_0:texture_2d<f32>, %plane_1:texture_2d<f32>, %params:tint_ExternalTextureParams, %sampler_2:sampler, %coords_2:vec2<f32>):vec4<f32> { # %sampler_2: 'sampler', %coords_2: 'coords'
$B4: {
%38:u32 = access %params, 1u
%39:mat3x4<f32> = access %params, 2u
%40:mat3x2<f32> = access %params, 6u
%41:vec2<f32> = access %params, 8u
%42:vec2<f32> = access %params, 9u
%43:vec2<f32> = access %params, 10u
%44:vec2<f32> = access %params, 11u
%45:vec3<f32> = construct %coords_2, 1.0f
%46:vec2<f32> = mul %40, %45
%47:vec2<f32> = clamp %46, %41, %42
%48:u32 = access %params, 0u
%49:bool = eq %48, 1u
%50:vec3<f32>, %51:f32 = if %49 [t: $B5, f: $B6] { # if_1
$B5: { # true
%52:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f
%53:vec3<f32> = swizzle %52, xyz
%54:f32 = access %52, 3u
exit_if %53, %54 # if_1
}
$B6: { # false
%55:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f
%56:f32 = access %55, 0u
%57:vec2<f32> = clamp %46, %43, %44
%58:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %57, 0.0f
%59:vec2<f32> = swizzle %58, xy
%60:vec4<f32> = construct %56, %59, 1.0f
%61:vec3<f32> = mul %60, %39
exit_if %61, 1.0f # if_1
}
}
%62:bool = eq %38, 0u
%63:vec3<f32> = if %62 [t: $B7, f: $B8] { # if_2
$B7: { # true
%64:tint_GammaTransferParams = access %params, 3u
%65:tint_GammaTransferParams = access %params, 4u
%66:mat3x3<f32> = access %params, 5u
%67:vec3<f32> = call %tint_GammaCorrection, %50, %64
%69:vec3<f32> = mul %66, %67
%70:vec3<f32> = call %tint_GammaCorrection, %69, %65
exit_if %70 # if_2
}
$B8: { # false
exit_if %50 # if_2
}
}
%71:vec4<f32> = construct %63, %51
ret %71
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B9: {
%74:f32 = access %params_1, 0u
%75:f32 = access %params_1, 1u
%76:f32 = access %params_1, 2u
%77:f32 = access %params_1, 3u
%78:f32 = access %params_1, 4u
%79:f32 = access %params_1, 5u
%80:f32 = access %params_1, 6u
%81:vec3<f32> = construct %74
%82:vec3<f32> = construct %78
%83:vec3<f32> = abs %v
%84:vec3<f32> = sign %v
%85:vec3<bool> = lt %83, %82
%86:vec3<f32> = mul %77, %83
%87:vec3<f32> = add %86, %80
%88:vec3<f32> = mul %84, %87
%89:vec3<f32> = mul %75, %83
%90:vec3<f32> = add %89, %76
%91:vec3<f32> = pow %90, %81
%92:vec3<f32> = add %91, %79
%93:vec3<f32> = mul %84, %92
%94:vec3<f32> = select %93, %88, %85
ret %94
}
}
)";
EXPECT_EQ(src, str());
ExternalTextureOptions options;
options.bindings_map[{1u, 2u}] = {{1u, 3u}, {1u, 4u}};
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
TEST_F(IR_MultiplanarExternalTextureTest, MultipleTextures) {
auto* var_a = b.Var("texture_a", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var_a->SetBindingPoint(1, 2);
mod.root_block->Append(var_a);
auto* var_b = b.Var("texture_b", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var_b->SetBindingPoint(2, 2);
mod.root_block->Append(var_b);
auto* var_c = b.Var("texture_c", ty.ptr(handle, ty.Get<core::type::ExternalTexture>()));
var_c->SetBindingPoint(3, 2);
mod.root_block->Append(var_c);
auto* foo = b.Function("foo", ty.void_());
auto* coords = b.FunctionParam("coords", ty.vec2<u32>());
foo->SetParams({coords});
b.Append(foo->Block(), [&] {
auto* load_a = b.Load(var_a->Result(0));
b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureLoad, load_a, coords);
auto* load_b = b.Load(var_b->Result(0));
b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureLoad, load_b, coords);
auto* load_c = b.Load(var_c->Result(0));
b.Call(ty.vec4<f32>(), core::BuiltinFn::kTextureLoad, load_c, coords);
b.Return(foo);
});
auto* src = R"(
$B1: { # root
%texture_a:ptr<handle, texture_external, read> = var @binding_point(1, 2)
%texture_b:ptr<handle, texture_external, read> = var @binding_point(2, 2)
%texture_c:ptr<handle, texture_external, read> = var @binding_point(3, 2)
}
%foo = func(%coords:vec2<u32>):void {
$B2: {
%6:texture_external = load %texture_a
%7:vec4<f32> = textureLoad %6, %coords
%8:texture_external = load %texture_b
%9:vec4<f32> = textureLoad %8, %coords
%10:texture_external = load %texture_c
%11:vec4<f32> = textureLoad %10, %coords
ret
}
}
)";
auto* expect = R"(
tint_GammaTransferParams = struct @align(4) {
G:f32 @offset(0)
A:f32 @offset(4)
B:f32 @offset(8)
C:f32 @offset(12)
D:f32 @offset(16)
E:f32 @offset(20)
F:f32 @offset(24)
padding:u32 @offset(28)
}
tint_ExternalTextureParams = struct @align(16) {
numPlanes:u32 @offset(0)
doYuvToRgbConversionOnly:u32 @offset(4)
yuvToRgbConversionMatrix:mat3x4<f32> @offset(16)
gammaDecodeParams:tint_GammaTransferParams @offset(64)
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
loadTransformationMatrix:mat3x2<f32> @offset(200)
samplePlane0RectMin:vec2<f32> @offset(224)
samplePlane0RectMax:vec2<f32> @offset(232)
samplePlane1RectMin:vec2<f32> @offset(240)
samplePlane1RectMax:vec2<f32> @offset(248)
displayVisibleRectMax:vec2<u32> @offset(256)
plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
%texture_a_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 2)
%texture_a_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(1, 3)
%texture_a_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(1, 4)
%texture_b_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(2, 2)
%texture_b_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(2, 3)
%texture_b_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(2, 4)
%texture_c_plane0:ptr<handle, texture_2d<f32>, read> = var @binding_point(3, 2)
%texture_c_plane1:ptr<handle, texture_2d<f32>, read> = var @binding_point(3, 3)
%texture_c_params:ptr<uniform, tint_ExternalTextureParams, read> = var @binding_point(3, 4)
}
%foo = func(%coords:vec2<u32>):void {
$B2: {
%12:texture_2d<f32> = load %texture_a_plane0
%13:texture_2d<f32> = load %texture_a_plane1
%14:tint_ExternalTextureParams = load %texture_a_params
%15:vec4<f32> = call %tint_TextureLoadExternal, %12, %13, %14, %coords
%17:texture_2d<f32> = load %texture_b_plane0
%18:texture_2d<f32> = load %texture_b_plane1
%19:tint_ExternalTextureParams = load %texture_b_params
%20:vec4<f32> = call %tint_TextureLoadExternal, %17, %18, %19, %coords
%21:texture_2d<f32> = load %texture_c_plane0
%22:texture_2d<f32> = load %texture_c_plane1
%23:tint_ExternalTextureParams = load %texture_c_params
%24:vec4<f32> = call %tint_TextureLoadExternal, %21, %22, %23, %coords
ret
}
}
%tint_TextureLoadExternal = func(%plane_0:texture_2d<f32>, %plane_1:texture_2d<f32>, %params:tint_ExternalTextureParams, %coords_1:vec2<u32>):vec4<f32> { # %coords_1: 'coords'
$B3: {
%29:u32 = access %params, 1u
%30:mat3x4<f32> = access %params, 2u
%31:mat3x2<f32> = access %params, 7u
%32:vec2<u32> = access %params, 12u
%33:vec2<f32> = access %params, 13u
%34:vec2<u32> = min %coords_1, %32
%35:vec2<f32> = convert %34
%36:vec3<f32> = construct %35, 1.0f
%37:vec2<f32> = mul %31, %36
%38:vec2<f32> = round %37
%39:vec2<u32> = convert %38
%40:u32 = access %params, 0u
%41:bool = eq %40, 1u
%42:vec3<f32>, %43:f32 = if %41 [t: $B4, f: $B5] { # if_1
$B4: { # true
%44:vec4<f32> = textureLoad %plane_0, %39, 0u
%45:vec3<f32> = swizzle %44, xyz
%46:f32 = access %44, 3u
exit_if %45, %46 # if_1
}
$B5: { # false
%47:vec4<f32> = textureLoad %plane_0, %39, 0u
%48:f32 = access %47, 0u
%49:vec2<f32> = mul %38, %33
%50:vec2<u32> = convert %49
%51:vec4<f32> = textureLoad %plane_1, %50, 0u
%52:vec2<f32> = swizzle %51, xy
%53:vec4<f32> = construct %48, %52, 1.0f
%54:vec3<f32> = mul %53, %30
exit_if %54, 1.0f # if_1
}
}
%55:bool = eq %29, 0u
%56:vec3<f32> = if %55 [t: $B6, f: $B7] { # if_2
$B6: { # true
%57:tint_GammaTransferParams = access %params, 3u
%58:tint_GammaTransferParams = access %params, 4u
%59:mat3x3<f32> = access %params, 5u
%60:vec3<f32> = call %tint_GammaCorrection, %42, %57
%62:vec3<f32> = mul %59, %60
%63:vec3<f32> = call %tint_GammaCorrection, %62, %58
exit_if %63 # if_2
}
$B7: { # false
exit_if %42 # if_2
}
}
%64:vec4<f32> = construct %56, %43
ret %64
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B8: {
%67:f32 = access %params_1, 0u
%68:f32 = access %params_1, 1u
%69:f32 = access %params_1, 2u
%70:f32 = access %params_1, 3u
%71:f32 = access %params_1, 4u
%72:f32 = access %params_1, 5u
%73:f32 = access %params_1, 6u
%74:vec3<f32> = construct %67
%75:vec3<f32> = construct %71
%76:vec3<f32> = abs %v
%77:vec3<f32> = sign %v
%78:vec3<bool> = lt %76, %75
%79:vec3<f32> = mul %70, %76
%80:vec3<f32> = add %79, %73
%81:vec3<f32> = mul %77, %80
%82:vec3<f32> = mul %68, %76
%83:vec3<f32> = add %82, %69
%84:vec3<f32> = pow %83, %74
%85:vec3<f32> = add %84, %72
%86:vec3<f32> = mul %77, %85
%87:vec3<f32> = select %86, %81, %78
ret %87
}
}
)";
EXPECT_EQ(src, str());
ExternalTextureOptions options;
options.bindings_map[{1u, 2u}] = {{1u, 3u}, {1u, 4u}};
options.bindings_map[{2u, 2u}] = {{2u, 3u}, {2u, 4u}};
options.bindings_map[{3u, 2u}] = {{3u, 3u}, {3u, 4u}};
Run(MultiplanarExternalTexture, options);
EXPECT_EQ(expect, str());
}
} // namespace
} // namespace tint::core::ir::transform