From df2d92d5bb06f1358d7d514c5a8f8dc8a3f0ecea Mon Sep 17 00:00:00 2001 From: David Neto Date: Mon, 16 Nov 2020 16:44:17 +0000 Subject: [PATCH] spirv-reader: add conversions for image Dim and Format Change-Id: I9ad499aaa4683ce9a3ed702f21babaf24a15a8e8 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32741 Reviewed-by: dan sinclair Auto-Submit: David Neto Commit-Queue: dan sinclair --- src/reader/spirv/enum_converter.cc | 81 +++++++++ src/reader/spirv/enum_converter.h | 15 ++ src/reader/spirv/enum_converter_test.cc | 208 ++++++++++++++++++++++++ 3 files changed, 304 insertions(+) diff --git a/src/reader/spirv/enum_converter.cc b/src/reader/spirv/enum_converter.cc index 1efc52354f..c0ea85f3cf 100644 --- a/src/reader/spirv/enum_converter.cc +++ b/src/reader/spirv/enum_converter.cc @@ -94,6 +94,87 @@ ast::Builtin EnumConverter::ToBuiltin(SpvBuiltIn b) { return ast::Builtin::kNone; } +ast::type::TextureDimension EnumConverter::ToDim(SpvDim dim, bool arrayed) { + if (arrayed) { + switch (dim) { + case SpvDim1D: + return ast::type::TextureDimension::k1dArray; + case SpvDim2D: + return ast::type::TextureDimension::k2dArray; + case SpvDimCube: + return ast::type::TextureDimension::kCubeArray; + default: + break; + } + Fail() << "arrayed dimension must be 1D, 2D, or Cube. Got " << int(dim); + return ast::type::TextureDimension::kNone; + } + // Assume non-arrayed + switch (dim) { + case SpvDim1D: + return ast::type::TextureDimension::k1d; + case SpvDim2D: + return ast::type::TextureDimension::k2d; + case SpvDim3D: + return ast::type::TextureDimension::k3d; + case SpvDimCube: + return ast::type::TextureDimension::kCube; + default: + break; + } + Fail() << "invalid dimension: " << int(dim); + return ast::type::TextureDimension::kNone; +} + +ast::type::ImageFormat EnumConverter::ToImageFormat(SpvImageFormat fmt) { + switch (fmt) { + case SpvImageFormatUnknown: + return ast::type::ImageFormat::kNone; + + // 8 bit channels + case SpvImageFormatRgba8: + return ast::type::ImageFormat::kRgba8Unorm; + case SpvImageFormatRgba8Snorm: + return ast::type::ImageFormat::kRgba8Snorm; + case SpvImageFormatRgba8ui: + return ast::type::ImageFormat::kRgba8Uint; + case SpvImageFormatRgba8i: + return ast::type::ImageFormat::kRgba8Sint; + + // 16 bit channels + case SpvImageFormatRgba16ui: + return ast::type::ImageFormat::kRgba16Uint; + case SpvImageFormatRgba16i: + return ast::type::ImageFormat::kRgba16Sint; + case SpvImageFormatRgba16f: + return ast::type::ImageFormat::kRgba16Float; + + // 32 bit channels + case SpvImageFormatR32ui: + return ast::type::ImageFormat::kR32Uint; + case SpvImageFormatR32i: + return ast::type::ImageFormat::kR32Sint; + case SpvImageFormatR32f: + return ast::type::ImageFormat::kR32Float; + case SpvImageFormatRg32ui: + return ast::type::ImageFormat::kRg32Uint; + case SpvImageFormatRg32i: + return ast::type::ImageFormat::kRg32Sint; + case SpvImageFormatRg32f: + return ast::type::ImageFormat::kRg32Float; + case SpvImageFormatRgba32ui: + return ast::type::ImageFormat::kRgba32Uint; + case SpvImageFormatRgba32i: + return ast::type::ImageFormat::kRgba32Sint; + case SpvImageFormatRgba32f: + return ast::type::ImageFormat::kRgba32Float; + default: + break; + } + Fail() << "invalid image format: " << int(fmt); + return ast::type::ImageFormat::kNone; +} + } // namespace spirv } // namespace reader } // namespace tint diff --git a/src/reader/spirv/enum_converter.h b/src/reader/spirv/enum_converter.h index cdf922ff69..fdcef1f526 100644 --- a/src/reader/spirv/enum_converter.h +++ b/src/reader/spirv/enum_converter.h @@ -19,6 +19,8 @@ #include "src/ast/builtin.h" #include "src/ast/pipeline_stage.h" #include "src/ast/storage_class.h" +#include "src/ast/type/storage_texture_type.h" +#include "src/ast/type/texture_type.h" #include "src/reader/spirv/fail_stream.h" namespace tint { @@ -52,6 +54,19 @@ class EnumConverter { /// @returns a Tint AST builtin ast::Builtin ToBuiltin(SpvBuiltIn b); + /// Converts a possibly arrayed SPIR-V Dim to a Tint texture dimension. + /// On failure, logs an error and returns kNone + /// @param dim the SPIR-V Dim value + /// @param arrayed true if the texture is arrayed + /// @returns a Tint AST texture dimension + ast::type::TextureDimension ToDim(SpvDim dim, bool arrayed); + + /// Converts a SPIR-V Image Format to a Tint ImageFormat + /// On failure, logs an error and returns kNone + /// @param fmt the SPIR-V format + /// @returns a Tint AST format + ast::type::ImageFormat ToImageFormat(SpvImageFormat fmt); + private: /// Registers a failure and returns a stream for log diagnostics. /// @returns a failure stream diff --git a/src/reader/spirv/enum_converter_test.cc b/src/reader/spirv/enum_converter_test.cc index 6d542255cd..280b231c6b 100644 --- a/src/reader/spirv/enum_converter_test.cc +++ b/src/reader/spirv/enum_converter_test.cc @@ -229,6 +229,214 @@ INSTANTIATE_TEST_SUITE_P( BuiltinCase{static_cast(9999), false, ast::Builtin::kNone}, BuiltinCase{SpvBuiltInNumWorkgroups, false, ast::Builtin::kNone})); +// Dim + +struct DimCase { + SpvDim dim; + bool arrayed; + bool expect_success; + ast::type::TextureDimension expected; +}; +inline std::ostream& operator<<(std::ostream& out, DimCase dc) { + out << "DimCase{ SpvDim:" << int(dc.dim) << " arrayed?:" << int(dc.arrayed) + << " expect_success?:" << int(dc.expect_success) + << " expected:" << int(dc.expected) << "}"; + return out; +} + +class SpvDimTest : public testing::TestWithParam { + public: + SpvDimTest() + : success_(true), + fail_stream_(&success_, &errors_), + converter_(fail_stream_) {} + + std::string error() const { return errors_.str(); } + + protected: + bool success_ = true; + std::stringstream errors_; + FailStream fail_stream_; + EnumConverter converter_; +}; + +TEST_P(SpvDimTest, Samples) { + const auto params = GetParam(); + + const auto result = converter_.ToDim(params.dim, params.arrayed); + EXPECT_EQ(success_, params.expect_success); + if (params.expect_success) { + EXPECT_EQ(result, params.expected); + EXPECT_TRUE(error().empty()); + } else { + EXPECT_EQ(result, params.expected); + EXPECT_THAT(error(), ::testing::HasSubstr("dimension")); + } +} + +INSTANTIATE_TEST_SUITE_P( + EnumConverterGood, + SpvDimTest, + testing::Values( + // Non-arrayed + DimCase{SpvDim1D, false, true, ast::type::TextureDimension::k1d}, + DimCase{SpvDim2D, false, true, ast::type::TextureDimension::k2d}, + DimCase{SpvDim3D, false, true, ast::type::TextureDimension::k3d}, + DimCase{SpvDimCube, false, true, ast::type::TextureDimension::kCube}, + // Arrayed + DimCase{SpvDim1D, true, true, ast::type::TextureDimension::k1dArray}, + DimCase{SpvDim2D, true, true, ast::type::TextureDimension::k2dArray}, + DimCase{SpvDimCube, true, true, + ast::type::TextureDimension::kCubeArray})); + +INSTANTIATE_TEST_SUITE_P( + EnumConverterBad, + SpvDimTest, + testing::Values( + // Invalid SPIR-V dimensionality. + DimCase{SpvDimMax, false, false, ast::type::TextureDimension::kNone}, + DimCase{SpvDimMax, true, false, ast::type::TextureDimension::kNone}, + // Vulkan non-arrayed dimensionalities not supported by WGSL. + DimCase{SpvDimRect, false, false, ast::type::TextureDimension::kNone}, + DimCase{SpvDimBuffer, false, false, ast::type::TextureDimension::kNone}, + DimCase{SpvDimSubpassData, false, false, + ast::type::TextureDimension::kNone}, + // Arrayed dimensionalities not supported by WGSL + DimCase{SpvDim3D, true, false, ast::type::TextureDimension::kNone}, + DimCase{SpvDimRect, true, false, ast::type::TextureDimension::kNone}, + DimCase{SpvDimBuffer, true, false, ast::type::TextureDimension::kNone}, + DimCase{SpvDimSubpassData, true, false, + ast::type::TextureDimension::kNone})); + +// ImageFormat + +struct ImageFormatCase { + SpvImageFormat format; + bool expect_success; + ast::type::ImageFormat expected; +}; +inline std::ostream& operator<<(std::ostream& out, ImageFormatCase ifc) { + out << "ImageFormatCase{ SpvImageFormat:" << int(ifc.format) + << " expect_success?:" << int(ifc.expect_success) + << " expected:" << int(ifc.expected) << "}"; + return out; +} + +class SpvImageFormatTest : public testing::TestWithParam { + public: + SpvImageFormatTest() + : success_(true), + fail_stream_(&success_, &errors_), + converter_(fail_stream_) {} + + std::string error() const { return errors_.str(); } + + protected: + bool success_ = true; + std::stringstream errors_; + FailStream fail_stream_; + EnumConverter converter_; +}; + +TEST_P(SpvImageFormatTest, Samples) { + const auto params = GetParam(); + + const auto result = converter_.ToImageFormat(params.format); + EXPECT_EQ(success_, params.expect_success) << params; + if (params.expect_success) { + EXPECT_EQ(result, params.expected); + EXPECT_TRUE(error().empty()); + } else { + EXPECT_EQ(result, params.expected); + EXPECT_THAT(error(), ::testing::StartsWith("invalid image format: ")); + } +} + +INSTANTIATE_TEST_SUITE_P( + EnumConverterGood, + SpvImageFormatTest, + testing::Values( + // Unknown. This is used for sampled images. + ImageFormatCase{SpvImageFormatUnknown, true, + ast::type::ImageFormat::kNone}, + // 8 bit channels + ImageFormatCase{SpvImageFormatRgba8, true, + ast::type::ImageFormat::kRgba8Unorm}, + ImageFormatCase{SpvImageFormatRgba8Snorm, true, + ast::type::ImageFormat::kRgba8Snorm}, + ImageFormatCase{SpvImageFormatRgba8ui, true, + ast::type::ImageFormat::kRgba8Uint}, + ImageFormatCase{SpvImageFormatRgba8i, true, + ast::type::ImageFormat::kRgba8Sint}, + // 16 bit channels + ImageFormatCase{SpvImageFormatRgba16ui, true, + ast::type::ImageFormat::kRgba16Uint}, + ImageFormatCase{SpvImageFormatRgba16i, true, + ast::type::ImageFormat::kRgba16Sint}, + ImageFormatCase{SpvImageFormatRgba16f, true, + ast::type::ImageFormat::kRgba16Float}, + // 32 bit channels + // ... 1 channel + ImageFormatCase{SpvImageFormatR32ui, true, + ast::type::ImageFormat::kR32Uint}, + ImageFormatCase{SpvImageFormatR32i, true, + ast::type::ImageFormat::kR32Sint}, + ImageFormatCase{SpvImageFormatR32f, true, + ast::type::ImageFormat::kR32Float}, + // ... 2 channels + ImageFormatCase{SpvImageFormatRg32ui, true, + ast::type::ImageFormat::kRg32Uint}, + ImageFormatCase{SpvImageFormatRg32i, true, + ast::type::ImageFormat::kRg32Sint}, + ImageFormatCase{SpvImageFormatRg32f, true, + ast::type::ImageFormat::kRg32Float}, + // ... 4 channels + ImageFormatCase{SpvImageFormatRgba32ui, true, + ast::type::ImageFormat::kRgba32Uint}, + ImageFormatCase{SpvImageFormatRgba32i, true, + ast::type::ImageFormat::kRgba32Sint}, + ImageFormatCase{SpvImageFormatRgba32f, true, + ast::type::ImageFormat::kRgba32Float})); + +INSTANTIATE_TEST_SUITE_P(EnumConverterBad, + SpvImageFormatTest, + testing::Values( + // Scanning in order from the SPIR-V spec. + ImageFormatCase{SpvImageFormatRg16f, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatR11fG11fB10f, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatR16f, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRgb10A2, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRg16, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRg8, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatR16, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatR8, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRgba16Snorm, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRg16Snorm, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRg8Snorm, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRg16i, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRg8i, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatR8i, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRgb10a2ui, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRg16ui, false, + ast::type::ImageFormat::kNone}, + ImageFormatCase{SpvImageFormatRg8ui, false, + ast::type::ImageFormat::kNone})); + } // namespace } // namespace spirv } // namespace reader