mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-05 04:36:02 +00:00
spv: Parse OpExtInst for GLSL.std.450
It will always use the "std::glsl" import name. Remember all the IDs of such imports. Never add more than one GLSL.std.450 import to the AST. Also refactor the Assemble test helper into its own file. Bug: tint:3 Change-Id: I5b2b70ea0f00d44aacf553aa009756dff2a4cecf Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/16662 Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
parent
c83578038a
commit
3ac99398b5
@ -353,8 +353,11 @@ endif()
|
||||
if(${TINT_BUILD_SPV_PARSER})
|
||||
list (APPEND TINT_TEST_SRCS
|
||||
reader/spv/fail_stream_test.cc
|
||||
reader/spv/parser_impl_import_test.cc
|
||||
reader/spv/parser_impl_test.cc
|
||||
reader/spv/parser_test.cc
|
||||
reader/spv/spirv_tools_helpers_test.cc
|
||||
reader/spv/spirv_tools_helpers_test.h
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2020 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.
|
||||
|
@ -104,6 +104,45 @@ bool ParserImpl::BuildInternalModule() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParserImpl::ResetInternalModule() {
|
||||
ir_context_.reset(nullptr);
|
||||
module_ = nullptr;
|
||||
def_use_mgr_ = nullptr;
|
||||
constant_mgr_ = nullptr;
|
||||
type_mgr_ = nullptr;
|
||||
deco_mgr_ = nullptr;
|
||||
|
||||
import_map_.clear();
|
||||
glsl_std_450_imports_.clear();
|
||||
}
|
||||
|
||||
bool ParserImpl::ParseInternalModule() {
|
||||
return ParseExtendedInstructionImports();
|
||||
// TODO(dneto): fill in the rest
|
||||
}
|
||||
|
||||
bool ParserImpl::ParseExtendedInstructionImports() {
|
||||
for (const spvtools::opt::Instruction& import : module_->ext_inst_imports()) {
|
||||
std::string name(
|
||||
reinterpret_cast<const char*>(import.GetInOperand(0).words.data()));
|
||||
// TODO(dneto): Handle other extended instruction sets when needed.
|
||||
if (name == "GLSL.std.450") {
|
||||
// Only create the AST import once, so we can use import name 'std::glsl'.
|
||||
// This is a canonicalization.
|
||||
if (glsl_std_450_imports_.empty()) {
|
||||
auto ast_import =
|
||||
std::make_unique<tint::ast::Import>(name, "std::glsl");
|
||||
import_map_[import.result_id()] = ast_import.get();
|
||||
ast_module_.AddImport(std::move(ast_import));
|
||||
}
|
||||
glsl_std_450_imports_.insert(import.result_id());
|
||||
} else {
|
||||
return Fail() << "Unrecognized extended instruction set: " << name;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace spv
|
||||
} // namespace reader
|
||||
} // namespace tint
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "source/opt/constants.h"
|
||||
@ -26,6 +28,8 @@
|
||||
#include "source/opt/module.h"
|
||||
#include "source/opt/type_manager.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "src/ast/import.h"
|
||||
#include "src/ast/module.h"
|
||||
#include "src/reader/reader.h"
|
||||
#include "src/reader/spv/fail_stream.h"
|
||||
|
||||
@ -61,6 +65,20 @@ class ParserImpl : Reader {
|
||||
/// @returns the accumulated error string
|
||||
const std::string error() { return errors_.str(); }
|
||||
|
||||
/// Builds an internal representation of the SPIR-V binary,
|
||||
/// and parses it into a Tint AST module. Diagnostics are emitted
|
||||
/// to the error stream.
|
||||
/// @returns true if it was successful.
|
||||
bool BuildAndParseInternalModule() {
|
||||
return BuildInternalModule() && ParseInternalModule();
|
||||
}
|
||||
|
||||
/// @returns the set of SPIR-V IDs for imports of the "GLSL.std.450"
|
||||
/// extended instruction set.
|
||||
const std::unordered_set<uint32_t>& glsl_std_450_imports() const {
|
||||
return glsl_std_450_imports_;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Builds the internal representation of the SPIR-V module.
|
||||
/// Assumes the module is somewhat well-formed. Normally you
|
||||
@ -69,6 +87,17 @@ class ParserImpl : Reader {
|
||||
/// @returns true if successful.
|
||||
bool BuildInternalModule();
|
||||
|
||||
/// Walks the internal representation of the module to populate
|
||||
/// the AST form of the module.
|
||||
/// @returns true on success
|
||||
bool ParseInternalModule();
|
||||
|
||||
/// Destroys the internal representation of the SPIR-V module.
|
||||
void ResetInternalModule();
|
||||
|
||||
/// Parses OpExtInstImport instructions.
|
||||
bool ParseExtendedInstructionImports();
|
||||
|
||||
// The SPIR-V binary we're parsing
|
||||
std::vector<uint32_t> spv_binary_;
|
||||
|
||||
@ -93,6 +122,12 @@ class ParserImpl : Reader {
|
||||
spvtools::opt::analysis::ConstantManager* constant_mgr_ = nullptr;
|
||||
spvtools::opt::analysis::TypeManager* type_mgr_ = nullptr;
|
||||
spvtools::opt::analysis::DecorationManager* deco_mgr_ = nullptr;
|
||||
|
||||
/// Maps a SPIR-V ID for an external instruction import to an AST import
|
||||
std::unordered_map<uint32_t, ast::Import*> import_map_;
|
||||
// The set of IDs that are imports of the GLSL.std.450 extended instruction
|
||||
// sets.
|
||||
std::unordered_set<uint32_t> glsl_std_450_imports_;
|
||||
};
|
||||
|
||||
} // namespace spv
|
||||
|
74
src/reader/spv/parser_impl_import_test.cc
Normal file
74
src/reader/spv/parser_impl_import_test.cc
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2020 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/reader/spv/parser_impl.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/reader/spv/spirv_tools_helpers_test.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace spv {
|
||||
namespace {
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::Eq;
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::Not;
|
||||
using ::testing::UnorderedElementsAre;
|
||||
|
||||
using SpvParseImport = ::testing::Test;
|
||||
|
||||
TEST_F(SpvParseImport, NoImport) {
|
||||
ParserImpl p(test::Assemble("%1 = OpTypeVoid"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
const auto module_ast = p.module().to_str();
|
||||
EXPECT_THAT(module_ast, Not(HasSubstr("Import")));
|
||||
}
|
||||
|
||||
TEST_F(SpvParseImport, ImportGlslStd450) {
|
||||
ParserImpl p(test::Assemble(R"(%1 = OpExtInstImport "GLSL.std.450")"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_THAT(p.glsl_std_450_imports(), ElementsAre(1));
|
||||
const auto module_ast = p.module().to_str();
|
||||
EXPECT_THAT(module_ast, HasSubstr(R"(Import{"GLSL.std.450" as std::glsl})"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParseImport, ImportGlslStd450Twice) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
%42 = OpExtInstImport "GLSL.std.450"
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_THAT(p.glsl_std_450_imports(), UnorderedElementsAre(1, 42));
|
||||
const auto module = p.module();
|
||||
EXPECT_EQ(module.imports().size(), 1);
|
||||
const auto module_ast = module.to_str();
|
||||
// TODO(dneto): Use a matcher to show there is only one import.
|
||||
EXPECT_THAT(module_ast, HasSubstr(R"(Import{"GLSL.std.450" as std::glsl})"));
|
||||
}
|
||||
|
||||
// TODO(dneto): We don't currently support other kinds of extended instruction
|
||||
// imports.
|
||||
|
||||
} // namespace
|
||||
} // namespace spv
|
||||
} // namespace reader
|
||||
} // namespace tint
|
@ -18,7 +18,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "src/reader/spv/spirv_tools_helpers_test.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
@ -37,31 +37,8 @@ TEST_F(SpvParserImplTest, Uint32VecEmpty) {
|
||||
// TODO(dneto): What message?
|
||||
}
|
||||
|
||||
/// @returns the SPIR-V module assembled from the given text. Numeric IDs
|
||||
/// are preserved.
|
||||
std::vector<uint32_t> Assemble(const std::string& spirv_assembly) {
|
||||
// TODO(dneto): Use ScopedTrace?
|
||||
|
||||
// (The target environment doesn't affect assembly.
|
||||
spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
|
||||
std::stringstream errors;
|
||||
std::vector<uint32_t> result;
|
||||
tools.SetMessageConsumer([&errors](spv_message_level_t, const char*,
|
||||
const spv_position_t& position,
|
||||
const char* message) {
|
||||
errors << "assembly error:" << position.line << ":" << position.column
|
||||
<< ": " << message;
|
||||
});
|
||||
|
||||
const auto success = tools.Assemble(
|
||||
spirv_assembly, &result, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
EXPECT_TRUE(success) << errors.str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST_F(SpvParserImplTest, InvalidModuleFails) {
|
||||
auto invalid_spv = Assemble("%ty = OpTypeInt 3 0");
|
||||
auto invalid_spv = test::Assemble("%ty = OpTypeInt 3 0");
|
||||
ParserImpl p{invalid_spv};
|
||||
EXPECT_FALSE(p.Parse());
|
||||
EXPECT_THAT(
|
||||
|
55
src/reader/spv/spirv_tools_helpers_test.cc
Normal file
55
src/reader/spv/spirv_tools_helpers_test.cc
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2020 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/reader/spv/spirv_tools_helpers_test.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace spv {
|
||||
namespace test {
|
||||
|
||||
/// @returns the SPIR-V module assembled from the given text. Numeric IDs
|
||||
/// are preserved.
|
||||
std::vector<uint32_t> Assemble(const std::string& spirv_assembly) {
|
||||
// TODO(dneto): Use ScopedTrace?
|
||||
|
||||
// (The target environment doesn't affect assembly.
|
||||
spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
|
||||
std::stringstream errors;
|
||||
std::vector<uint32_t> result;
|
||||
tools.SetMessageConsumer([&errors](spv_message_level_t, const char*,
|
||||
const spv_position_t& position,
|
||||
const char* message) {
|
||||
errors << "assembly error:" << position.line << ":" << position.column
|
||||
<< ": " << message;
|
||||
});
|
||||
|
||||
const auto success = tools.Assemble(
|
||||
spirv_assembly, &result, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
EXPECT_TRUE(success) << errors.str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace spv
|
||||
} // namespace reader
|
||||
} // namespace tint
|
36
src/reader/spv/spirv_tools_helpers_test.h
Normal file
36
src/reader/spv/spirv_tools_helpers_test.h
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2020 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_READER_SPV_SPIRV_TOOLS_HELPERS_TEST_H_
|
||||
#define SRC_READER_SPV_SPIRV_TOOLS_HELPERS_TEST_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace spv {
|
||||
namespace test {
|
||||
|
||||
/// @returns the SPIR-V module assembled from the given text. Numeric IDs
|
||||
/// are preserved.
|
||||
std::vector<uint32_t> Assemble(const std::string& spirv_assembly);
|
||||
|
||||
} // namespace test
|
||||
} // namespace spv
|
||||
} // namespace reader
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_READER_SPV_SPIRV_TOOLS_HELPERS_TEST_H_
|
Loading…
x
Reference in New Issue
Block a user