[wgsl-writer] Emit texture types. This CL adds texture type emission to the WGSL writer. Bug: tint:144 Change-Id: I18e40a587b77b953f17a6d0ad1a75a1bc4158ef0 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28460 Reviewed-by: David Neto <dneto@google.com> Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc index 9acde4f..ec38eb9 100644 --- a/src/writer/wgsl/generator_impl.cc +++ b/src/writer/wgsl/generator_impl.cc
@@ -50,8 +50,12 @@ #include "src/ast/struct_member_offset_decoration.h" #include "src/ast/switch_statement.h" #include "src/ast/type/array_type.h" +#include "src/ast/type/depth_texture_type.h" #include "src/ast/type/matrix_type.h" #include "src/ast/type/pointer_type.h" +#include "src/ast/type/sampled_texture_type.h" +#include "src/ast/type/sampler_type.h" +#include "src/ast/type/storage_texture_type.h" #include "src/ast/type/struct_type.h" #include "src/ast/type/vector_type.h" #include "src/ast/type_constructor_expression.h" @@ -445,6 +449,120 @@ return EmitBlockAndNewline(func->body()); } +bool GeneratorImpl::EmitImageFormat(const ast::type::ImageFormat fmt) { + switch (fmt) { + case ast::type::ImageFormat::kBgra8Unorm: + out_ << "bgra8unorm"; + break; + case ast::type::ImageFormat::kBgra8UnormSrgb: + out_ << "bgra8unorm_srgb"; + break; + case ast::type::ImageFormat::kR16Float: + out_ << "r16float"; + break; + case ast::type::ImageFormat::kR16Sint: + out_ << "r16sint"; + break; + case ast::type::ImageFormat::kR16Uint: + out_ << "r16uint"; + break; + case ast::type::ImageFormat::kR32Float: + out_ << "r32float"; + break; + case ast::type::ImageFormat::kR32Sint: + out_ << "r32sint"; + break; + case ast::type::ImageFormat::kR32Uint: + out_ << "r32uint"; + break; + case ast::type::ImageFormat::kR8Sint: + out_ << "r8sint"; + break; + case ast::type::ImageFormat::kR8Snorm: + out_ << "r8snorm"; + break; + case ast::type::ImageFormat::kR8Uint: + out_ << "r8uint"; + break; + case ast::type::ImageFormat::kR8Unorm: + out_ << "r8unorm"; + break; + case ast::type::ImageFormat::kRg11B10Float: + out_ << "rg11b10float"; + break; + case ast::type::ImageFormat::kRg16Float: + out_ << "rg16float"; + break; + case ast::type::ImageFormat::kRg16Sint: + out_ << "rg16sint"; + break; + case ast::type::ImageFormat::kRg16Uint: + out_ << "rg16uint"; + break; + case ast::type::ImageFormat::kRg32Float: + out_ << "rg32float"; + break; + case ast::type::ImageFormat::kRg32Sint: + out_ << "rg32sint"; + break; + case ast::type::ImageFormat::kRg32Uint: + out_ << "rg32uint"; + break; + case ast::type::ImageFormat::kRg8Sint: + out_ << "rg8sint"; + break; + case ast::type::ImageFormat::kRg8Snorm: + out_ << "rg8snorm"; + break; + case ast::type::ImageFormat::kRg8Uint: + out_ << "rg8uint"; + break; + case ast::type::ImageFormat::kRg8Unorm: + out_ << "rg8unorm"; + break; + case ast::type::ImageFormat::kRgb10A2Unorm: + out_ << "rgb10a2unorm"; + break; + case ast::type::ImageFormat::kRgba16Float: + out_ << "rgba16float"; + break; + case ast::type::ImageFormat::kRgba16Sint: + out_ << "rgba16sint"; + break; + case ast::type::ImageFormat::kRgba16Uint: + out_ << "rgba16uint"; + break; + case ast::type::ImageFormat::kRgba32Float: + out_ << "rgba32float"; + break; + case ast::type::ImageFormat::kRgba32Sint: + out_ << "rgba32sint"; + break; + case ast::type::ImageFormat::kRgba32Uint: + out_ << "rgba32uint"; + break; + case ast::type::ImageFormat::kRgba8Sint: + out_ << "rgba8sint"; + break; + case ast::type::ImageFormat::kRgba8Snorm: + out_ << "rgba8snorm"; + break; + case ast::type::ImageFormat::kRgba8Uint: + out_ << "rgba8uint"; + break; + case ast::type::ImageFormat::kRgba8Unorm: + out_ << "rgba8unorm"; + break; + case ast::type::ImageFormat::kRgba8UnormSrgb: + out_ << "rgba8unorm_srgb"; + break; + default: + error_ = "unknown image format"; + return false; + } + return true; +} + bool GeneratorImpl::EmitType(ast::type::Type* type) { if (type->IsAlias()) { auto* alias = type->AsAlias(); @@ -485,6 +603,13 @@ return false; } out_ << ">"; + } else if (type->IsSampler()) { + auto* sampler = type->AsSampler(); + out_ << "sampler"; + + if (sampler->IsComparison()) { + out_ << "_comparison"; + } } else if (type->IsStruct()) { auto* str = type->AsStruct()->impl(); if (str->decoration() != ast::StructDecoration::kNone) { @@ -522,6 +647,81 @@ make_indent(); out_ << "}"; + } else if (type->IsTexture()) { + auto* texture = type->AsTexture(); + + out_ << "texture_"; + if (texture->IsDepth()) { + out_ << "depth_"; + } else if (texture->IsSampled()) { + out_ << "sampled_"; + } else if (texture->IsStorage()) { + auto* storage = texture->AsStorage(); + + if (storage->access() == ast::type::StorageAccess::kRead) { + out_ << "ro_"; + } else if (storage->access() == ast::type::StorageAccess::kWrite) { + out_ << "wo_"; + } else { + error_ = "unknown storage texture access"; + return false; + } + } else { + error_ = "unknown texture type"; + return false; + } + + switch (texture->dim()) { + case ast::type::TextureDimension::k1d: + out_ << "1d"; + break; + case ast::type::TextureDimension::k1dArray: + out_ << "1d_array"; + break; + case ast::type::TextureDimension::k2d: + out_ << "2d"; + break; + case ast::type::TextureDimension::k2dArray: + out_ << "2d_array"; + break; + case ast::type::TextureDimension::k2dMs: + out_ << "2d_ms"; + break; + case ast::type::TextureDimension::k2dMsArray: + out_ << "2d_ms_array"; + break; + case ast::type::TextureDimension::k3d: + out_ << "3d"; + break; + case ast::type::TextureDimension::kCube: + out_ << "cube"; + break; + case ast::type::TextureDimension::kCubeArray: + out_ << "cube_array"; + break; + default: + error_ = "unknown texture dimension"; + return false; + } + + if (texture->IsSampled()) { + auto* sampled = texture->AsSampled(); + + out_ << "<"; + if (!EmitType(sampled->type())) { + return false; + } + out_ << ">"; + } else if (texture->IsStorage()) { + auto* storage = texture->AsStorage(); + + out_ << "<"; + if (!EmitImageFormat(storage->image_format())) { + return false; + } + out_ << ">"; + } + } else if (type->IsU32()) { out_ << "u32"; } else if (type->IsVector()) {
diff --git a/src/writer/wgsl/generator_impl.h b/src/writer/wgsl/generator_impl.h index 778698b..e01b66b 100644 --- a/src/writer/wgsl/generator_impl.h +++ b/src/writer/wgsl/generator_impl.h
@@ -26,6 +26,7 @@ #include "src/ast/module.h" #include "src/ast/scalar_constructor_expression.h" #include "src/ast/type/alias_type.h" +#include "src/ast/type/storage_texture_type.h" #include "src/ast/type/type.h" #include "src/ast/type_constructor_expression.h" #include "src/ast/variable.h" @@ -179,6 +180,10 @@ /// @param type the type to generate /// @returns true if the type is emitted bool EmitType(ast::type::Type* type); + /// Handles emitting an image format + /// @param fmt the format to generate + /// @returns true if the format is emitted + bool EmitImageFormat(const ast::type::ImageFormat fmt); /// Handles emitting a type constructor /// @param expr the type constructor expression /// @returns true if the constructor is emitted
diff --git a/src/writer/wgsl/generator_impl_type_test.cc b/src/writer/wgsl/generator_impl_type_test.cc index 48c8fc3..46e06fc 100644 --- a/src/writer/wgsl/generator_impl_type_test.cc +++ b/src/writer/wgsl/generator_impl_type_test.cc
@@ -20,10 +20,14 @@ #include "src/ast/struct_member_offset_decoration.h" #include "src/ast/type/array_type.h" #include "src/ast/type/bool_type.h" +#include "src/ast/type/depth_texture_type.h" #include "src/ast/type/f32_type.h" #include "src/ast/type/i32_type.h" #include "src/ast/type/matrix_type.h" #include "src/ast/type/pointer_type.h" +#include "src/ast/type/sampled_texture_type.h" +#include "src/ast/type/sampler_type.h" +#include "src/ast/type/storage_texture_type.h" #include "src/ast/type/struct_type.h" #include "src/ast/type/u32_type.h" #include "src/ast/type/vector_type.h" @@ -194,6 +198,219 @@ EXPECT_EQ(g.result(), "void"); } +struct TextureData { + ast::type::TextureDimension dim; + const char* name; +}; +inline std::ostream& operator<<(std::ostream& out, TextureData data) { + out << data.name; + return out; +} +using WgslGenerator_DepthTextureTest = testing::TestWithParam<TextureData>; + +TEST_P(WgslGenerator_DepthTextureTest, EmitType_DepthTexture) { + auto param = GetParam(); + + ast::type::DepthTextureType d(param.dim); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&d)) << g.error(); + EXPECT_EQ(g.result(), param.name); +} +INSTANTIATE_TEST_SUITE_P( + WgslGeneratorImplTest, + WgslGenerator_DepthTextureTest, + testing::Values( + TextureData{ast::type::TextureDimension::k2d, "texture_depth_2d"}, + TextureData{ast::type::TextureDimension::k2dArray, + "texture_depth_2d_array"}, + TextureData{ast::type::TextureDimension::kCube, "texture_depth_cube"}, + TextureData{ast::type::TextureDimension::kCubeArray, + "texture_depth_cube_array"})); + +using WgslGenerator_SampledTextureTest = testing::TestWithParam<TextureData>; +TEST_P(WgslGenerator_SampledTextureTest, EmitType_SampledTexture_F32) { + auto param = GetParam(); + + ast::type::F32Type f32; + ast::type::SampledTextureType t(param.dim, &f32); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&t)) << g.error(); + EXPECT_EQ(g.result(), std::string(param.name) + "<f32>"); +} + +TEST_P(WgslGenerator_SampledTextureTest, EmitType_SampledTexture_I32) { + auto param = GetParam(); + + ast::type::I32Type i32; + ast::type::SampledTextureType t(param.dim, &i32); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&t)) << g.error(); + EXPECT_EQ(g.result(), std::string(param.name) + "<i32>"); +} + +TEST_P(WgslGenerator_SampledTextureTest, EmitType_SampledTexture_U32) { + auto param = GetParam(); + + ast::type::U32Type u32; + ast::type::SampledTextureType t(param.dim, &u32); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&t)) << g.error(); + EXPECT_EQ(g.result(), std::string(param.name) + "<u32>"); +} +INSTANTIATE_TEST_SUITE_P( + WgslGeneratorImplTest, + WgslGenerator_SampledTextureTest, + testing::Values( + TextureData{ast::type::TextureDimension::k1d, "texture_sampled_1d"}, + TextureData{ast::type::TextureDimension::k1dArray, + "texture_sampled_1d_array"}, + TextureData{ast::type::TextureDimension::k2d, "texture_sampled_2d"}, + TextureData{ast::type::TextureDimension::k2dArray, + "texture_sampled_2d_array"}, + TextureData{ast::type::TextureDimension::k3d, "texture_sampled_3d"}, + TextureData{ast::type::TextureDimension::kCube, "texture_sampled_cube"}, + TextureData{ast::type::TextureDimension::kCubeArray, + "texture_sampled_cube_array"})); + +struct StorageTextureData { + ast::type::ImageFormat fmt; + ast::type::TextureDimension dim; + ast::type::StorageAccess access; + const char* name; +}; +inline std::ostream& operator<<(std::ostream& out, StorageTextureData data) { + out << data.name; + return out; +} +using WgslGenerator_StorageTextureTest = + testing::TestWithParam<StorageTextureData>; +TEST_P(WgslGenerator_StorageTextureTest, EmitType_StorageTexture) { + auto param = GetParam(); + + ast::type::StorageTextureType t(param.dim, param.access, param.fmt); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&t)) << g.error(); + EXPECT_EQ(g.result(), param.name); +} +INSTANTIATE_TEST_SUITE_P( + WgslGeneratorImplTest, + WgslGenerator_StorageTextureTest, + testing::Values( + StorageTextureData{ + ast::type::ImageFormat::kR8Unorm, ast::type::TextureDimension::k1d, + ast::type::StorageAccess::kRead, "texture_ro_1d<r8unorm>"}, + StorageTextureData{ast::type::ImageFormat::kR8Unorm, + ast::type::TextureDimension::k1dArray, + ast::type::StorageAccess::kRead, + "texture_ro_1d_array<r8unorm>"}, + StorageTextureData{ + ast::type::ImageFormat::kR8Unorm, ast::type::TextureDimension::k2d, + ast::type::StorageAccess::kRead, "texture_ro_2d<r8unorm>"}, + StorageTextureData{ast::type::ImageFormat::kR8Unorm, + ast::type::TextureDimension::k2dArray, + ast::type::StorageAccess::kRead, + "texture_ro_2d_array<r8unorm>"}, + StorageTextureData{ + ast::type::ImageFormat::kR8Unorm, ast::type::TextureDimension::k3d, + ast::type::StorageAccess::kRead, "texture_ro_3d<r8unorm>"}, + StorageTextureData{ + ast::type::ImageFormat::kR8Unorm, ast::type::TextureDimension::k1d, + ast::type::StorageAccess::kWrite, "texture_wo_1d<r8unorm>"}, + StorageTextureData{ast::type::ImageFormat::kR8Unorm, + ast::type::TextureDimension::k1dArray, + ast::type::StorageAccess::kWrite, + "texture_wo_1d_array<r8unorm>"}, + StorageTextureData{ + ast::type::ImageFormat::kR8Unorm, ast::type::TextureDimension::k2d, + ast::type::StorageAccess::kWrite, "texture_wo_2d<r8unorm>"}, + StorageTextureData{ast::type::ImageFormat::kR8Unorm, + ast::type::TextureDimension::k2dArray, + ast::type::StorageAccess::kWrite, + "texture_wo_2d_array<r8unorm>"}, + StorageTextureData{ + ast::type::ImageFormat::kR8Unorm, ast::type::TextureDimension::k3d, + ast::type::StorageAccess::kWrite, "texture_wo_3d<r8unorm>"})); + +struct ImageFormatData { + ast::type::ImageFormat fmt; + const char* name; +}; +inline std::ostream& operator<<(std::ostream& out, ImageFormatData data) { + out << data.name; + return out; +} +using WgslGenerator_ImageFormatTest = testing::TestWithParam<ImageFormatData>; +TEST_P(WgslGenerator_ImageFormatTest, EmitType_StorageTexture_ImageFormat) { + auto param = GetParam(); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitImageFormat(param.fmt)) << g.error(); + EXPECT_EQ(g.result(), param.name); +} + +INSTANTIATE_TEST_SUITE_P( + WgslGeneratorImplTest, + WgslGenerator_ImageFormatTest, + testing::Values( + ImageFormatData{ast::type::ImageFormat::kR8Unorm, "r8unorm"}, + ImageFormatData{ast::type::ImageFormat::kR8Snorm, "r8snorm"}, + ImageFormatData{ast::type::ImageFormat::kR8Uint, "r8uint"}, + ImageFormatData{ast::type::ImageFormat::kR8Sint, "r8sint"}, + ImageFormatData{ast::type::ImageFormat::kR16Uint, "r16uint"}, + ImageFormatData{ast::type::ImageFormat::kR16Sint, "r16sint"}, + ImageFormatData{ast::type::ImageFormat::kR16Float, "r16float"}, + ImageFormatData{ast::type::ImageFormat::kRg8Unorm, "rg8unorm"}, + ImageFormatData{ast::type::ImageFormat::kRg8Snorm, "rg8snorm"}, + ImageFormatData{ast::type::ImageFormat::kRg8Uint, "rg8uint"}, + ImageFormatData{ast::type::ImageFormat::kRg8Sint, "rg8sint"}, + ImageFormatData{ast::type::ImageFormat::kR32Uint, "r32uint"}, + ImageFormatData{ast::type::ImageFormat::kR32Sint, "r32sint"}, + ImageFormatData{ast::type::ImageFormat::kR32Float, "r32float"}, + ImageFormatData{ast::type::ImageFormat::kRg16Uint, "rg16uint"}, + ImageFormatData{ast::type::ImageFormat::kRg16Sint, "rg16sint"}, + ImageFormatData{ast::type::ImageFormat::kRg16Float, "rg16float"}, + ImageFormatData{ast::type::ImageFormat::kRgba8Unorm, "rgba8unorm"}, + ImageFormatData{ast::type::ImageFormat::kRgba8UnormSrgb, + "rgba8unorm_srgb"}, + ImageFormatData{ast::type::ImageFormat::kRgba8Snorm, "rgba8snorm"}, + ImageFormatData{ast::type::ImageFormat::kRgba8Uint, "rgba8uint"}, + ImageFormatData{ast::type::ImageFormat::kRgba8Sint, "rgba8sint"}, + ImageFormatData{ast::type::ImageFormat::kBgra8Unorm, "bgra8unorm"}, + ImageFormatData{ast::type::ImageFormat::kBgra8UnormSrgb, + "bgra8unorm_srgb"}, + ImageFormatData{ast::type::ImageFormat::kRgb10A2Unorm, "rgb10a2unorm"}, + ImageFormatData{ast::type::ImageFormat::kRg11B10Float, "rg11b10float"}, + ImageFormatData{ast::type::ImageFormat::kRg32Uint, "rg32uint"}, + ImageFormatData{ast::type::ImageFormat::kRg32Sint, "rg32sint"}, + ImageFormatData{ast::type::ImageFormat::kRg32Float, "rg32float"}, + ImageFormatData{ast::type::ImageFormat::kRgba16Uint, "rgba16uint"}, + ImageFormatData{ast::type::ImageFormat::kRgba16Sint, "rgba16sint"}, + ImageFormatData{ast::type::ImageFormat::kRgba16Float, "rgba16float"}, + ImageFormatData{ast::type::ImageFormat::kRgba32Uint, "rgba32uint"}, + ImageFormatData{ast::type::ImageFormat::kRgba32Sint, "rgba32sint"}, + ImageFormatData{ast::type::ImageFormat::kRgba32Float, "rgba32float"})); + +TEST_F(WgslGeneratorImplTest, EmitType_Sampler) { + ast::type::SamplerType sampler(ast::type::SamplerKind::kSampler); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&sampler)) << g.error(); + EXPECT_EQ(g.result(), "sampler"); +} + +TEST_F(WgslGeneratorImplTest, EmitType_SamplerComparison) { + ast::type::SamplerType sampler(ast::type::SamplerKind::kComparisonSampler); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&sampler)) << g.error(); + EXPECT_EQ(g.result(), "sampler_comparison"); +} + } // namespace } // namespace wgsl } // namespace writer