diff --git a/src/BUILD.gn b/src/BUILD.gn index 4bb3d8165d..80a0c3a1b6 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -515,6 +515,8 @@ libtint_source_set("libtint_core_all_src") { "transform/decompose_storage_access.h", "transform/emit_vertex_point_size.cc", "transform/emit_vertex_point_size.h", + "transform/external_texture_transform.cc", + "transform/external_texture_transform.h", "transform/first_index_offset.cc", "transform/first_index_offset.h", "transform/manager.cc", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 85a6f3f9ca..514a04c8c2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -271,6 +271,8 @@ set(TINT_LIB_SRCS transform/decompose_storage_access.h transform/emit_vertex_point_size.cc transform/emit_vertex_point_size.h + transform/external_texture_transform.cc + transform/external_texture_transform.h transform/first_index_offset.cc transform/first_index_offset.h transform/manager.cc @@ -796,6 +798,7 @@ if(${TINT_BUILD_TESTS}) transform/canonicalize_entry_point_io_test.cc transform/decompose_storage_access_test.cc transform/emit_vertex_point_size_test.cc + transform/external_texture_transform_test.cc transform/first_index_offset_test.cc transform/renamer_test.cc transform/single_entry_point.cc diff --git a/src/transform/external_texture_transform.cc b/src/transform/external_texture_transform.cc new file mode 100644 index 0000000000..841b38640b --- /dev/null +++ b/src/transform/external_texture_transform.cc @@ -0,0 +1,59 @@ +// Copyright 2021 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/transform/external_texture_transform.h" +#include "src/program_builder.h" + +namespace tint { +namespace transform { + +ExternalTextureTransform::ExternalTextureTransform() = default; +ExternalTextureTransform::~ExternalTextureTransform() = default; + +Output ExternalTextureTransform::Run(const Program* in, const DataMap&) { + ProgramBuilder out; + CloneContext ctx(&out, in); + + // Scan the AST nodes for external texture declarations. + for (auto* node : ctx.src->ASTNodes().Objects()) { + if (auto* var = node->As()) { + if (var->type().ast->Is()) { + // Replace a single-plane external texture with a 2D, f32 sampled + // texture. + auto* newAstType = ctx.dst->create( + ast::TextureDimension::k2d, ctx.dst->create()); + auto* newSemType = ctx.dst->create( + ast::TextureDimension::k2d, ctx.dst->ty.f32()); + + auto clonedSrc = ctx.Clone(var->source()); + auto clonedSym = ctx.Clone(var->symbol()); + auto* clonedConstructor = ctx.Clone(var->constructor()); + auto clonedDecorations = ctx.Clone(var->decorations()); + + auto* newVar = ctx.dst->create( + clonedSrc, clonedSym, var->declared_storage_class(), + typ::Type(newAstType, newSemType), var->is_const(), + clonedConstructor, clonedDecorations); + + ctx.Replace(var, newVar); + } + } + } + + ctx.Clone(); + return Output{Program(std::move(out))}; +} + +} // namespace transform +} // namespace tint diff --git a/src/transform/external_texture_transform.h b/src/transform/external_texture_transform.h new file mode 100644 index 0000000000..7c0001ea64 --- /dev/null +++ b/src/transform/external_texture_transform.h @@ -0,0 +1,47 @@ +// Copyright 2021 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. + +#ifndef SRC_TRANSFORM_EXTERNAL_TEXTURE_TRANSFORM_H_ +#define SRC_TRANSFORM_EXTERNAL_TEXTURE_TRANSFORM_H_ + +#include + +#include "src/transform/transform.h" + +namespace tint { +namespace transform { + +// Because an external texture is comprised of 1-3 texture views we can simply +// transform external textures into the appropriate number of sampled textures. +// This allows us to share SPIR-V/HLSL writer paths for sampled textures instead +// of adding dedicated writer paths for external textures. +// ExternalTextureTransform performs this transformation. +class ExternalTextureTransform : public Transform { + public: + /// Constructor + ExternalTextureTransform(); + /// Destructor + ~ExternalTextureTransform() override; + + /// Runs the transform on `program`, returning the transformation result. + /// @param program the source program to transform + /// @param data optional extra transform-specific data + /// @returns the transformation result + Output Run(const Program* program, const DataMap& data = {}) override; +}; + +} // namespace transform +} // namespace tint + +#endif // SRC_TRANSFORM_EXTERNAL_TEXTURE_TRANSFORM_H_ diff --git a/src/transform/external_texture_transform_test.cc b/src/transform/external_texture_transform_test.cc new file mode 100644 index 0000000000..bf16dddfe3 --- /dev/null +++ b/src/transform/external_texture_transform_test.cc @@ -0,0 +1,64 @@ +// Copyright 2021 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/transform/external_texture_transform.h" + +#include "src/transform/test_helper.h" + +namespace tint { +namespace transform { +namespace { + +using ExternalTextureTransformTest = TransformTest; + +TEST_F(ExternalTextureTransformTest, SinglePlane) { + auto* src = R"( +[[builtin(frag_coord)]] var FragCoord : vec4; + +[[group(0), binding(0)]] var s : sampler; + +[[group(0), binding(1)]] var t : texture_external; + +[[location(0)]] var FragColor : vec4; +[[stage(fragment)]] +fn main() { + FragColor = textureSample(t, s, (FragCoord.xy / vec2(4.0, 4.0))); + return; +} +)"; + + auto* expect = R"( +[[builtin(frag_coord)]] var FragCoord : vec4; + +[[group(0), binding(0)]] var s : sampler; + +[[group(0), binding(1)]] var t : texture_2d; + +[[location(0)]] var FragColor : vec4; + +[[stage(fragment)]] +fn main() { + FragColor = textureSample(t, s, (FragCoord.xy / vec2(4.0, 4.0))); + return; +} +)"; + + auto got = Run(src); + + EXPECT_EQ(expect, str(got)); +} + +} // namespace +} // namespace transform +} // namespace tint diff --git a/test/BUILD.gn b/test/BUILD.gn index 96dabc3ff5..f53b746253 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -296,6 +296,7 @@ tint_unittests_source_set("tint_unittests_core_src") { "../src/transform/canonicalize_entry_point_io_test.cc", "../src/transform/decompose_storage_access_test.cc", "../src/transform/emit_vertex_point_size_test.cc", + "../src/transform/external_texture_transform_test.cc", "../src/transform/first_index_offset_test.cc", "../src/transform/renamer_test.cc", "../src/transform/single_entry_point_test.cc",