| // Copyright 2023 The Tint Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #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 { |
| %b1 = block { |
| 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); |
| b.RootBlock()->Append(var); |
| |
| auto* func = b.Function("foo", ty.void_()); |
| b.Append(func->Block(), [&] { // |
| b.Return(func); |
| }); |
| |
| auto* src = R"( |
| %b1 = block { # root |
| %texture:ptr<handle, texture_external, read_write> = var @binding_point(1, 2) |
| } |
| |
| %foo = func():void -> %b2 { |
| %b2 = block { |
| 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) |
| } |
| |
| %b1 = block { # root |
| %texture_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 2) |
| %texture_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 3) |
| %texture_params:ptr<uniform, tint_ExternalTextureParams, read_write> = var @binding_point(1, 4) |
| } |
| |
| %foo = func():void -> %b2 { |
| %b2 = block { |
| 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); |
| b.RootBlock()->Append(var); |
| |
| auto* func = b.Function("foo", ty.void_()); |
| b.Append(func->Block(), [&] { |
| b.Load(var); |
| b.Return(func); |
| }); |
| |
| auto* src = R"( |
| %b1 = block { # root |
| %texture:ptr<handle, texture_external, read_write> = var @binding_point(1, 2) |
| } |
| |
| %foo = func():void -> %b2 { |
| %b2 = block { |
| %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) |
| } |
| |
| %b1 = block { # root |
| %texture_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 2) |
| %texture_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 3) |
| %texture_params:ptr<uniform, tint_ExternalTextureParams, read_write> = var @binding_point(1, 4) |
| } |
| |
| %foo = func():void -> %b2 { |
| %b2 = block { |
| %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); |
| b.RootBlock()->Append(var); |
| |
| auto* func = b.Function("foo", ty.vec2<u32>()); |
| b.Append(func->Block(), [&] { |
| auto* load = b.Load(var->Result()); |
| auto* result = b.Call(ty.vec2<u32>(), core::Function::kTextureDimensions, load); |
| b.Return(func, result); |
| mod.SetName(result, "result"); |
| }); |
| |
| auto* src = R"( |
| %b1 = block { # root |
| %texture:ptr<handle, texture_external, read_write> = var @binding_point(1, 2) |
| } |
| |
| %foo = func():vec2<u32> -> %b2 { |
| %b2 = block { |
| %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) |
| } |
| |
| %b1 = block { # root |
| %texture_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 2) |
| %texture_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 3) |
| %texture_params:ptr<uniform, tint_ExternalTextureParams, read_write> = var @binding_point(1, 4) |
| } |
| |
| %foo = func():vec2<u32> -> %b2 { |
| %b2 = block { |
| %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); |
| b.RootBlock()->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()); |
| auto* result = b.Call(ty.vec4<f32>(), core::Function::kTextureLoad, load, coords); |
| b.Return(func, result); |
| mod.SetName(result, "result"); |
| }); |
| |
| auto* src = R"( |
| %b1 = block { # root |
| %texture:ptr<handle, texture_external, read_write> = var @binding_point(1, 2) |
| } |
| |
| %foo = func(%coords:vec2<u32>):vec4<f32> -> %b2 { |
| %b2 = block { |
| %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) |
| } |
| |
| %b1 = block { # root |
| %texture_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 2) |
| %texture_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 3) |
| %texture_params:ptr<uniform, tint_ExternalTextureParams, read_write> = var @binding_point(1, 4) |
| } |
| |
| %foo = func(%coords:vec2<u32>):vec4<f32> -> %b2 { |
| %b2 = block { |
| %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> -> %b3 { # %coords_1: 'coords' |
| %b3 = block { |
| %15:u32 = access %params, 1u |
| %16:mat3x4<f32> = access %params, 2u |
| %17:u32 = access %params, 0u |
| %18:bool = eq %17, 1u |
| %19:vec3<f32>, %20:f32 = if %18 [t: %b4, f: %b5] { # if_1 |
| %b4 = block { # true |
| %21:vec4<f32> = textureLoad %plane_0, %coords_1, 0u |
| %22:vec3<f32> = swizzle %21, xyz |
| %23:f32 = access %21, 3u |
| exit_if %22, %23 # if_1 |
| } |
| %b5 = block { # false |
| %24:vec4<f32> = textureLoad %plane_0, %coords_1, 0u |
| %25:f32 = access %24, 0u |
| %26:vec2<u32> = shiftr %coords_1, vec2<u32>(1u) |
| %27:vec4<f32> = textureLoad %plane_1, %26, 0u |
| %28:vec2<f32> = swizzle %27, xy |
| %29:vec4<f32> = construct %25, %28, 1.0f |
| %30:vec3<f32> = mul %29, %16 |
| exit_if %30, 1.0f # if_1 |
| } |
| } |
| %31:bool = eq %15, 0u |
| %32:vec3<f32> = if %31 [t: %b6, f: %b7] { # if_2 |
| %b6 = block { # true |
| %33:tint_GammaTransferParams = access %params, 3u |
| %34:tint_GammaTransferParams = access %params, 4u |
| %35:mat3x3<f32> = access %params, 5u |
| %36:vec3<f32> = call %tint_GammaCorrection, %19, %33 |
| %38:vec3<f32> = mul %35, %36 |
| %39:vec3<f32> = call %tint_GammaCorrection, %38, %34 |
| exit_if %39 # if_2 |
| } |
| %b7 = block { # false |
| exit_if %19 # if_2 |
| } |
| } |
| %40:vec4<f32> = construct %32, %20 |
| ret %40 |
| } |
| } |
| %tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> -> %b8 { # %params_1: 'params' |
| %b8 = block { |
| %43:f32 = access %params_1, 0u |
| %44:f32 = access %params_1, 1u |
| %45:f32 = access %params_1, 2u |
| %46:f32 = access %params_1, 3u |
| %47:f32 = access %params_1, 4u |
| %48:f32 = access %params_1, 5u |
| %49:f32 = access %params_1, 6u |
| %50:vec3<f32> = construct %43 |
| %51:vec3<f32> = construct %47 |
| %52:vec3<f32> = abs %v |
| %53:vec3<f32> = sign %v |
| %54:vec3<bool> = lt %52, %51 |
| %55:vec3<f32> = mul %46, %52 |
| %56:vec3<f32> = add %55, %49 |
| %57:vec3<f32> = mul %53, %56 |
| %58:vec3<f32> = mul %44, %52 |
| %59:vec3<f32> = add %58, %45 |
| %60:vec3<f32> = pow %59, %50 |
| %61:vec3<f32> = add %60, %48 |
| %62:vec3<f32> = mul %53, %61 |
| %63:vec3<f32> = select %62, %57, %54 |
| ret %63 |
| } |
| } |
| )"; |
| |
| 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); |
| b.RootBlock()->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()); |
| auto* result = b.Call(ty.vec4<f32>(), core::Function::kTextureLoad, load, coords); |
| b.Return(func, result); |
| mod.SetName(result, "result"); |
| }); |
| |
| auto* src = R"( |
| %b1 = block { # root |
| %texture:ptr<handle, texture_external, read_write> = var @binding_point(1, 2) |
| } |
| |
| %foo = func(%coords:vec2<i32>):vec4<f32> -> %b2 { |
| %b2 = block { |
| %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) |
| } |
| |
| %b1 = block { # root |
| %texture_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 2) |
| %texture_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 3) |
| %texture_params:ptr<uniform, tint_ExternalTextureParams, read_write> = var @binding_point(1, 4) |
| } |
| |
| %foo = func(%coords:vec2<i32>):vec4<f32> -> %b2 { |
| %b2 = block { |
| %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> -> %b3 { # %coords_1: 'coords' |
| %b3 = block { |
| %16:u32 = access %params, 1u |
| %17:mat3x4<f32> = access %params, 2u |
| %18:u32 = access %params, 0u |
| %19:bool = eq %18, 1u |
| %20:vec3<f32>, %21:f32 = if %19 [t: %b4, f: %b5] { # if_1 |
| %b4 = block { # true |
| %22:vec4<f32> = textureLoad %plane_0, %coords_1, 0u |
| %23:vec3<f32> = swizzle %22, xyz |
| %24:f32 = access %22, 3u |
| exit_if %23, %24 # if_1 |
| } |
| %b5 = block { # false |
| %25:vec4<f32> = textureLoad %plane_0, %coords_1, 0u |
| %26:f32 = access %25, 0u |
| %27:vec2<u32> = shiftr %coords_1, vec2<u32>(1u) |
| %28:vec4<f32> = textureLoad %plane_1, %27, 0u |
| %29:vec2<f32> = swizzle %28, xy |
| %30:vec4<f32> = construct %26, %29, 1.0f |
| %31:vec3<f32> = mul %30, %17 |
| exit_if %31, 1.0f # if_1 |
| } |
| } |
| %32:bool = eq %16, 0u |
| %33:vec3<f32> = if %32 [t: %b6, f: %b7] { # if_2 |
| %b6 = block { # true |
| %34:tint_GammaTransferParams = access %params, 3u |
| %35:tint_GammaTransferParams = access %params, 4u |
| %36:mat3x3<f32> = access %params, 5u |
| %37:vec3<f32> = call %tint_GammaCorrection, %20, %34 |
| %39:vec3<f32> = mul %36, %37 |
| %40:vec3<f32> = call %tint_GammaCorrection, %39, %35 |
| exit_if %40 # if_2 |
| } |
| %b7 = block { # false |
| exit_if %20 # if_2 |
| } |
| } |
| %41:vec4<f32> = construct %33, %21 |
| ret %41 |
| } |
| } |
| %tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> -> %b8 { # %params_1: 'params' |
| %b8 = block { |
| %44:f32 = access %params_1, 0u |
| %45:f32 = access %params_1, 1u |
| %46:f32 = access %params_1, 2u |
| %47:f32 = access %params_1, 3u |
| %48:f32 = access %params_1, 4u |
| %49:f32 = access %params_1, 5u |
| %50:f32 = access %params_1, 6u |
| %51:vec3<f32> = construct %44 |
| %52:vec3<f32> = construct %48 |
| %53:vec3<f32> = abs %v |
| %54:vec3<f32> = sign %v |
| %55:vec3<bool> = lt %53, %52 |
| %56:vec3<f32> = mul %47, %53 |
| %57:vec3<f32> = add %56, %50 |
| %58:vec3<f32> = mul %54, %57 |
| %59:vec3<f32> = mul %45, %53 |
| %60:vec3<f32> = add %59, %46 |
| %61:vec3<f32> = pow %60, %51 |
| %62:vec3<f32> = add %61, %49 |
| %63:vec3<f32> = mul %54, %62 |
| %64:vec3<f32> = select %63, %58, %55 |
| ret %64 |
| } |
| } |
| )"; |
| |
| 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); |
| b.RootBlock()->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()); |
| auto* result = b.Call(ty.vec4<f32>(), core::Function::kTextureSampleBaseClampToEdge, load, |
| sampler, coords); |
| b.Return(func, result); |
| mod.SetName(result, "result"); |
| }); |
| |
| auto* src = R"( |
| %b1 = block { # root |
| %texture:ptr<handle, texture_external, read_write> = var @binding_point(1, 2) |
| } |
| |
| %foo = func(%sampler:sampler, %coords:vec2<f32>):vec4<f32> -> %b2 { |
| %b2 = block { |
| %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) |
| } |
| |
| %b1 = block { # root |
| %texture_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 2) |
| %texture_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 3) |
| %texture_params:ptr<uniform, tint_ExternalTextureParams, read_write> = var @binding_point(1, 4) |
| } |
| |
| %foo = func(%sampler:sampler, %coords:vec2<f32>):vec4<f32> -> %b2 { |
| %b2 = block { |
| %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> -> %b3 { # %sampler_1: 'sampler', %coords_1: 'coords' |
| %b3 = block { |
| %17:u32 = access %params, 1u |
| %18:mat3x4<f32> = access %params, 2u |
| %19:mat3x2<f32> = access %params, 6u |
| %20:vec3<f32> = construct %coords_1, 1.0f |
| %21:vec2<f32> = mul %19, %20 |
| %22:vec2<u32> = textureDimensions %plane_0 |
| %23:vec2<f32> = convert %22 |
| %24:vec2<f32> = div vec2<f32>(0.5f), %23 |
| %25:vec2<f32> = sub 1.0f, %24 |
| %26:vec2<f32> = clamp %21, %24, %25 |
| %27:vec2<u32> = textureDimensions %plane_1 |
| %28:vec2<f32> = convert %27 |
| %29:vec2<f32> = div vec2<f32>(0.5f), %28 |
| %30:vec2<f32> = sub 1.0f, %29 |
| %31:vec2<f32> = clamp %21, %29, %30 |
| %32:u32 = access %params, 0u |
| %33:bool = eq %32, 1u |
| %34:vec3<f32>, %35:f32 = if %33 [t: %b4, f: %b5] { # if_1 |
| %b4 = block { # true |
| %36:vec4<f32> = textureSampleLevel %plane_0, %sampler_1, %26, 0.0f |
| %37:vec3<f32> = swizzle %36, xyz |
| %38:f32 = access %36, 3u |
| exit_if %37, %38 # if_1 |
| } |
| %b5 = block { # false |
| %39:vec4<f32> = textureSampleLevel %plane_0, %sampler_1, %26, 0.0f |
| %40:f32 = access %39, 0u |
| %41:vec4<f32> = textureSampleLevel %plane_1, %sampler_1, %31, 0.0f |
| %42:vec2<f32> = swizzle %41, xy |
| %43:vec4<f32> = construct %40, %42, 1.0f |
| %44:vec3<f32> = mul %43, %18 |
| exit_if %44, 1.0f # if_1 |
| } |
| } |
| %45:bool = eq %17, 0u |
| %46:vec3<f32> = if %45 [t: %b6, f: %b7] { # if_2 |
| %b6 = block { # true |
| %47:tint_GammaTransferParams = access %params, 3u |
| %48:tint_GammaTransferParams = access %params, 4u |
| %49:mat3x3<f32> = access %params, 5u |
| %50:vec3<f32> = call %tint_GammaCorrection, %34, %47 |
| %52:vec3<f32> = mul %49, %50 |
| %53:vec3<f32> = call %tint_GammaCorrection, %52, %48 |
| exit_if %53 # if_2 |
| } |
| %b7 = block { # false |
| exit_if %34 # if_2 |
| } |
| } |
| %54:vec4<f32> = construct %46, %35 |
| ret %54 |
| } |
| } |
| %tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> -> %b8 { # %params_1: 'params' |
| %b8 = block { |
| %57:f32 = access %params_1, 0u |
| %58:f32 = access %params_1, 1u |
| %59:f32 = access %params_1, 2u |
| %60:f32 = access %params_1, 3u |
| %61:f32 = access %params_1, 4u |
| %62:f32 = access %params_1, 5u |
| %63:f32 = access %params_1, 6u |
| %64:vec3<f32> = construct %57 |
| %65:vec3<f32> = construct %61 |
| %66:vec3<f32> = abs %v |
| %67:vec3<f32> = sign %v |
| %68:vec3<bool> = lt %66, %65 |
| %69:vec3<f32> = mul %60, %66 |
| %70:vec3<f32> = add %69, %63 |
| %71:vec3<f32> = mul %67, %70 |
| %72:vec3<f32> = mul %58, %66 |
| %73:vec3<f32> = add %72, %59 |
| %74:vec3<f32> = pow %73, %64 |
| %75:vec3<f32> = add %74, %62 |
| %76:vec3<f32> = mul %67, %75 |
| %77:vec3<f32> = select %76, %71, %68 |
| ret %77 |
| } |
| } |
| )"; |
| |
| 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); |
| b.RootBlock()->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::Function::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()); |
| auto* result = b.Call(ty.vec4<f32>(), foo, load, sampler, coords); |
| b.Return(bar, result); |
| mod.SetName(result, "result"); |
| }); |
| } |
| |
| auto* src = R"( |
| %b1 = block { # root |
| %texture:ptr<handle, texture_external, read_write> = var @binding_point(1, 2) |
| } |
| |
| %foo = func(%texture_1:texture_external, %sampler:sampler, %coords:vec2<f32>):vec4<f32> -> %b2 { # %texture_1: 'texture' |
| %b2 = block { |
| %result:vec4<f32> = textureSampleBaseClampToEdge %texture_1, %sampler, %coords |
| ret %result |
| } |
| } |
| %bar = func(%sampler_1:sampler, %coords_1:vec2<f32>):vec4<f32> -> %b3 { # %sampler_1: 'sampler', %coords_1: 'coords' |
| %b3 = block { |
| %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) |
| } |
| |
| %b1 = block { # root |
| %texture_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 2) |
| %texture_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 3) |
| %texture_params:ptr<uniform, tint_ExternalTextureParams, read_write> = 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> -> %b2 { # %texture_plane0_1: 'texture_plane0', %texture_plane1_1: 'texture_plane1', %texture_params_1: 'texture_params' |
| %b2 = block { |
| %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> -> %b3 { # %sampler_1: 'sampler', %coords_1: 'coords' |
| %b3 = block { |
| %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> -> %b4 { # %sampler_2: 'sampler', %coords_2: 'coords' |
| %b4 = block { |
| %24:u32 = access %params, 1u |
| %25:mat3x4<f32> = access %params, 2u |
| %26:mat3x2<f32> = access %params, 6u |
| %27:vec3<f32> = construct %coords_2, 1.0f |
| %28:vec2<f32> = mul %26, %27 |
| %29:vec2<u32> = textureDimensions %plane_0 |
| %30:vec2<f32> = convert %29 |
| %31:vec2<f32> = div vec2<f32>(0.5f), %30 |
| %32:vec2<f32> = sub 1.0f, %31 |
| %33:vec2<f32> = clamp %28, %31, %32 |
| %34:vec2<u32> = textureDimensions %plane_1 |
| %35:vec2<f32> = convert %34 |
| %36:vec2<f32> = div vec2<f32>(0.5f), %35 |
| %37:vec2<f32> = sub 1.0f, %36 |
| %38:vec2<f32> = clamp %28, %36, %37 |
| %39:u32 = access %params, 0u |
| %40:bool = eq %39, 1u |
| %41:vec3<f32>, %42:f32 = if %40 [t: %b5, f: %b6] { # if_1 |
| %b5 = block { # true |
| %43:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %33, 0.0f |
| %44:vec3<f32> = swizzle %43, xyz |
| %45:f32 = access %43, 3u |
| exit_if %44, %45 # if_1 |
| } |
| %b6 = block { # false |
| %46:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %33, 0.0f |
| %47:f32 = access %46, 0u |
| %48:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %38, 0.0f |
| %49:vec2<f32> = swizzle %48, xy |
| %50:vec4<f32> = construct %47, %49, 1.0f |
| %51:vec3<f32> = mul %50, %25 |
| exit_if %51, 1.0f # if_1 |
| } |
| } |
| %52:bool = eq %24, 0u |
| %53:vec3<f32> = if %52 [t: %b7, f: %b8] { # if_2 |
| %b7 = block { # true |
| %54:tint_GammaTransferParams = access %params, 3u |
| %55:tint_GammaTransferParams = access %params, 4u |
| %56:mat3x3<f32> = access %params, 5u |
| %57:vec3<f32> = call %tint_GammaCorrection, %41, %54 |
| %59:vec3<f32> = mul %56, %57 |
| %60:vec3<f32> = call %tint_GammaCorrection, %59, %55 |
| exit_if %60 # if_2 |
| } |
| %b8 = block { # false |
| exit_if %41 # if_2 |
| } |
| } |
| %61:vec4<f32> = construct %53, %42 |
| ret %61 |
| } |
| } |
| %tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> -> %b9 { # %params_1: 'params' |
| %b9 = block { |
| %64:f32 = access %params_1, 0u |
| %65:f32 = access %params_1, 1u |
| %66:f32 = access %params_1, 2u |
| %67:f32 = access %params_1, 3u |
| %68:f32 = access %params_1, 4u |
| %69:f32 = access %params_1, 5u |
| %70:f32 = access %params_1, 6u |
| %71:vec3<f32> = construct %64 |
| %72:vec3<f32> = construct %68 |
| %73:vec3<f32> = abs %v |
| %74:vec3<f32> = sign %v |
| %75:vec3<bool> = lt %73, %72 |
| %76:vec3<f32> = mul %67, %73 |
| %77:vec3<f32> = add %76, %70 |
| %78:vec3<f32> = mul %74, %77 |
| %79:vec3<f32> = mul %65, %73 |
| %80:vec3<f32> = add %79, %66 |
| %81:vec3<f32> = pow %80, %71 |
| %82:vec3<f32> = add %81, %69 |
| %83:vec3<f32> = mul %74, %82 |
| %84:vec3<f32> = select %83, %78, %75 |
| ret %84 |
| } |
| } |
| )"; |
| |
| 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); |
| b.RootBlock()->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::Function::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()); |
| b.Call(ty.vec2<u32>(), core::Function::kTextureDimensions, load_a); |
| auto* load_b = b.Load(var->Result()); |
| b.Call(ty.vec4<f32>(), core::Function::kTextureSampleBaseClampToEdge, load_b, sampler, |
| coords_f); |
| auto* load_c = b.Load(var->Result()); |
| b.Call(ty.vec4<f32>(), core::Function::kTextureSampleBaseClampToEdge, load_c, sampler, |
| coords_f); |
| auto* load_d = b.Load(var->Result()); |
| 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 = block { # root |
| %texture:ptr<handle, texture_external, read_write> = var @binding_point(1, 2) |
| } |
| |
| %foo = func(%texture_1:texture_external, %sampler:sampler, %coords:vec2<f32>):vec4<f32> -> %b2 { # %texture_1: 'texture' |
| %b2 = block { |
| %result:vec4<f32> = textureSampleBaseClampToEdge %texture_1, %sampler, %coords |
| ret %result |
| } |
| } |
| %bar = func(%sampler_1:sampler, %coords_1:vec2<f32>):vec4<f32> -> %b3 { # %sampler_1: 'sampler', %coords_1: 'coords' |
| %b3 = block { |
| %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) |
| } |
| |
| %b1 = block { # root |
| %texture_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 2) |
| %texture_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 3) |
| %texture_params:ptr<uniform, tint_ExternalTextureParams, read_write> = 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> -> %b2 { # %texture_plane0_1: 'texture_plane0', %texture_plane1_1: 'texture_plane1', %texture_params_1: 'texture_params' |
| %b2 = block { |
| %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> -> %b3 { # %sampler_1: 'sampler', %coords_1: 'coords' |
| %b3 = block { |
| %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> -> %b4 { # %sampler_2: 'sampler', %coords_2: 'coords' |
| %b4 = block { |
| %38:u32 = access %params, 1u |
| %39:mat3x4<f32> = access %params, 2u |
| %40:mat3x2<f32> = access %params, 6u |
| %41:vec3<f32> = construct %coords_2, 1.0f |
| %42:vec2<f32> = mul %40, %41 |
| %43:vec2<u32> = textureDimensions %plane_0 |
| %44:vec2<f32> = convert %43 |
| %45:vec2<f32> = div vec2<f32>(0.5f), %44 |
| %46:vec2<f32> = sub 1.0f, %45 |
| %47:vec2<f32> = clamp %42, %45, %46 |
| %48:vec2<u32> = textureDimensions %plane_1 |
| %49:vec2<f32> = convert %48 |
| %50:vec2<f32> = div vec2<f32>(0.5f), %49 |
| %51:vec2<f32> = sub 1.0f, %50 |
| %52:vec2<f32> = clamp %42, %50, %51 |
| %53:u32 = access %params, 0u |
| %54:bool = eq %53, 1u |
| %55:vec3<f32>, %56:f32 = if %54 [t: %b5, f: %b6] { # if_1 |
| %b5 = block { # true |
| %57:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f |
| %58:vec3<f32> = swizzle %57, xyz |
| %59:f32 = access %57, 3u |
| exit_if %58, %59 # if_1 |
| } |
| %b6 = block { # false |
| %60:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f |
| %61:f32 = access %60, 0u |
| %62:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %52, 0.0f |
| %63:vec2<f32> = swizzle %62, xy |
| %64:vec4<f32> = construct %61, %63, 1.0f |
| %65:vec3<f32> = mul %64, %39 |
| exit_if %65, 1.0f # if_1 |
| } |
| } |
| %66:bool = eq %38, 0u |
| %67:vec3<f32> = if %66 [t: %b7, f: %b8] { # if_2 |
| %b7 = block { # true |
| %68:tint_GammaTransferParams = access %params, 3u |
| %69:tint_GammaTransferParams = access %params, 4u |
| %70:mat3x3<f32> = access %params, 5u |
| %71:vec3<f32> = call %tint_GammaCorrection, %55, %68 |
| %73:vec3<f32> = mul %70, %71 |
| %74:vec3<f32> = call %tint_GammaCorrection, %73, %69 |
| exit_if %74 # if_2 |
| } |
| %b8 = block { # false |
| exit_if %55 # if_2 |
| } |
| } |
| %75:vec4<f32> = construct %67, %56 |
| ret %75 |
| } |
| } |
| %tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> -> %b9 { # %params_1: 'params' |
| %b9 = block { |
| %78:f32 = access %params_1, 0u |
| %79:f32 = access %params_1, 1u |
| %80:f32 = access %params_1, 2u |
| %81:f32 = access %params_1, 3u |
| %82:f32 = access %params_1, 4u |
| %83:f32 = access %params_1, 5u |
| %84:f32 = access %params_1, 6u |
| %85:vec3<f32> = construct %78 |
| %86:vec3<f32> = construct %82 |
| %87:vec3<f32> = abs %v |
| %88:vec3<f32> = sign %v |
| %89:vec3<bool> = lt %87, %86 |
| %90:vec3<f32> = mul %81, %87 |
| %91:vec3<f32> = add %90, %84 |
| %92:vec3<f32> = mul %88, %91 |
| %93:vec3<f32> = mul %79, %87 |
| %94:vec3<f32> = add %93, %80 |
| %95:vec3<f32> = pow %94, %85 |
| %96:vec3<f32> = add %95, %83 |
| %97:vec3<f32> = mul %88, %96 |
| %98:vec3<f32> = select %97, %92, %89 |
| ret %98 |
| } |
| } |
| )"; |
| |
| 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); |
| b.RootBlock()->Append(var_a); |
| |
| auto* var_b = b.Var("texture_b", ty.ptr(handle, ty.Get<core::type::ExternalTexture>())); |
| var_b->SetBindingPoint(2, 2); |
| b.RootBlock()->Append(var_b); |
| |
| auto* var_c = b.Var("texture_c", ty.ptr(handle, ty.Get<core::type::ExternalTexture>())); |
| var_c->SetBindingPoint(3, 2); |
| b.RootBlock()->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()); |
| b.Call(ty.vec4<f32>(), core::Function::kTextureLoad, load_a, coords); |
| auto* load_b = b.Load(var_b->Result()); |
| b.Call(ty.vec4<f32>(), core::Function::kTextureLoad, load_b, coords); |
| auto* load_c = b.Load(var_c->Result()); |
| b.Call(ty.vec4<f32>(), core::Function::kTextureLoad, load_c, coords); |
| b.Return(foo); |
| }); |
| |
| auto* src = R"( |
| %b1 = block { # root |
| %texture_a:ptr<handle, texture_external, read_write> = var @binding_point(1, 2) |
| %texture_b:ptr<handle, texture_external, read_write> = var @binding_point(2, 2) |
| %texture_c:ptr<handle, texture_external, read_write> = var @binding_point(3, 2) |
| } |
| |
| %foo = func(%coords:vec2<u32>):void -> %b2 { |
| %b2 = block { |
| %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) |
| } |
| |
| %b1 = block { # root |
| %texture_a_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 2) |
| %texture_a_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(1, 3) |
| %texture_a_params:ptr<uniform, tint_ExternalTextureParams, read_write> = var @binding_point(1, 4) |
| %texture_b_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(2, 2) |
| %texture_b_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(2, 3) |
| %texture_b_params:ptr<uniform, tint_ExternalTextureParams, read_write> = var @binding_point(2, 4) |
| %texture_c_plane0:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(3, 2) |
| %texture_c_plane1:ptr<handle, texture_2d<f32>, read_write> = var @binding_point(3, 3) |
| %texture_c_params:ptr<uniform, tint_ExternalTextureParams, read_write> = var @binding_point(3, 4) |
| } |
| |
| %foo = func(%coords:vec2<u32>):void -> %b2 { |
| %b2 = block { |
| %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> -> %b3 { # %coords_1: 'coords' |
| %b3 = block { |
| %29:u32 = access %params, 1u |
| %30:mat3x4<f32> = access %params, 2u |
| %31:u32 = access %params, 0u |
| %32:bool = eq %31, 1u |
| %33:vec3<f32>, %34:f32 = if %32 [t: %b4, f: %b5] { # if_1 |
| %b4 = block { # true |
| %35:vec4<f32> = textureLoad %plane_0, %coords_1, 0u |
| %36:vec3<f32> = swizzle %35, xyz |
| %37:f32 = access %35, 3u |
| exit_if %36, %37 # if_1 |
| } |
| %b5 = block { # false |
| %38:vec4<f32> = textureLoad %plane_0, %coords_1, 0u |
| %39:f32 = access %38, 0u |
| %40:vec2<u32> = shiftr %coords_1, vec2<u32>(1u) |
| %41:vec4<f32> = textureLoad %plane_1, %40, 0u |
| %42:vec2<f32> = swizzle %41, xy |
| %43:vec4<f32> = construct %39, %42, 1.0f |
| %44:vec3<f32> = mul %43, %30 |
| exit_if %44, 1.0f # if_1 |
| } |
| } |
| %45:bool = eq %29, 0u |
| %46:vec3<f32> = if %45 [t: %b6, f: %b7] { # if_2 |
| %b6 = block { # true |
| %47:tint_GammaTransferParams = access %params, 3u |
| %48:tint_GammaTransferParams = access %params, 4u |
| %49:mat3x3<f32> = access %params, 5u |
| %50:vec3<f32> = call %tint_GammaCorrection, %33, %47 |
| %52:vec3<f32> = mul %49, %50 |
| %53:vec3<f32> = call %tint_GammaCorrection, %52, %48 |
| exit_if %53 # if_2 |
| } |
| %b7 = block { # false |
| exit_if %33 # if_2 |
| } |
| } |
| %54:vec4<f32> = construct %46, %34 |
| ret %54 |
| } |
| } |
| %tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> -> %b8 { # %params_1: 'params' |
| %b8 = block { |
| %57:f32 = access %params_1, 0u |
| %58:f32 = access %params_1, 1u |
| %59:f32 = access %params_1, 2u |
| %60:f32 = access %params_1, 3u |
| %61:f32 = access %params_1, 4u |
| %62:f32 = access %params_1, 5u |
| %63:f32 = access %params_1, 6u |
| %64:vec3<f32> = construct %57 |
| %65:vec3<f32> = construct %61 |
| %66:vec3<f32> = abs %v |
| %67:vec3<f32> = sign %v |
| %68:vec3<bool> = lt %66, %65 |
| %69:vec3<f32> = mul %60, %66 |
| %70:vec3<f32> = add %69, %63 |
| %71:vec3<f32> = mul %67, %70 |
| %72:vec3<f32> = mul %58, %66 |
| %73:vec3<f32> = add %72, %59 |
| %74:vec3<f32> = pow %73, %64 |
| %75:vec3<f32> = add %74, %62 |
| %76:vec3<f32> = mul %67, %75 |
| %77:vec3<f32> = select %76, %71, %68 |
| ret %77 |
| } |
| } |
| )"; |
| |
| 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 |