Generate OpExtInstImport

This CL updates the SPIR-V generator to only create the GLSL import if
it's requested.

Bug: tint:5
Change-Id: I96a9100adf0a0c59dcdd82c12ac27c566ea2663f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17341
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
dan sinclair 2020-03-20 19:27:05 +00:00 committed by dan sinclair
parent d854fc1543
commit 7b7ff741c5
3 changed files with 69 additions and 10 deletions

View File

@ -35,10 +35,15 @@ Builder::Builder() = default;
Builder::~Builder() = default; Builder::~Builder() = default;
bool Builder::Build(const ast::Module&) { bool Builder::Build(const ast::Module& m) {
push_preamble(spv::Op::OpCapability, {Operand::Int(SpvCapabilityShader)}); push_preamble(spv::Op::OpCapability, {Operand::Int(SpvCapabilityShader)});
push_preamble(spv::Op::OpExtInstImport, push_preamble(spv::Op::OpCapability,
{result_op(), Operand::String("GLSL.std.450")}); {Operand::Int(SpvCapabilityVulkanMemoryModel)});
for (const auto& imp : m.imports()) {
GenerateImport(imp.get());
}
push_preamble(spv::Op::OpMemoryModel, push_preamble(spv::Op::OpMemoryModel,
{Operand::Int(SpvAddressingModelLogical), {Operand::Int(SpvAddressingModelLogical),
Operand::Int(SpvMemoryModelVulkanKHR)}); Operand::Int(SpvMemoryModelVulkanKHR)});
@ -80,6 +85,15 @@ void Builder::iterate(std::function<void(const Instruction&)> cb) const {
} }
} }
void Builder::GenerateImport(ast::Import* imp) {
auto op = result_op();
auto id = op.to_i();
push_preamble(spv::Op::OpExtInstImport, {op, Operand::String(imp->path())});
import_name_to_id_[imp->name()] = id;
}
} // namespace spirv } // namespace spirv
} // namespace writer } // namespace writer
} // namespace tint } // namespace tint

View File

@ -16,6 +16,8 @@
#define SRC_WRITER_SPIRV_BUILDER_H_ #define SRC_WRITER_SPIRV_BUILDER_H_
#include <functional> #include <functional>
#include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include "src/ast/module.h" #include "src/ast/module.h"
@ -43,6 +45,13 @@ class Builder {
/// @returns the id bound for this module /// @returns the id bound for this module
uint32_t id_bound() const { return next_id_; } uint32_t id_bound() const { return next_id_; }
/// @returns the next id to be used
uint32_t next_id() {
auto id = next_id_;
next_id_ += 1;
return id;
}
/// Iterates over all the instructions in the correct order and calls the /// Iterates over all the instructions in the correct order and calls the
/// given callback /// given callback
/// @param cb the callback to execute /// @param cb the callback to execute
@ -89,13 +98,12 @@ class Builder {
/// @returns the annotations /// @returns the annotations
const std::vector<Instruction>& annot() const { return annotations_; } const std::vector<Instruction>& annot() const { return annotations_; }
/// Generates an import instruction
/// @param imp the import
void GenerateImport(ast::Import* imp);
private: private:
Operand result_op(); Operand result_op();
uint32_t next_id() {
auto id = next_id_;
next_id_ += 1;
return id;
}
uint32_t next_id_ = 1; uint32_t next_id_ = 1;
std::vector<Instruction> preamble_; std::vector<Instruction> preamble_;
@ -103,6 +111,8 @@ class Builder {
std::vector<Instruction> types_; std::vector<Instruction> types_;
std::vector<Instruction> instructions_; std::vector<Instruction> instructions_;
std::vector<Instruction> annotations_; std::vector<Instruction> annotations_;
std::unordered_map<std::string, uint32_t> import_name_to_id_;
}; };
} // namespace spirv } // namespace spirv

View File

@ -14,8 +14,12 @@
#include "src/writer/spirv/builder.h" #include "src/writer/spirv/builder.h"
#include <memory>
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "spirv/unified1/spirv.h"
#include "spirv/unified1/spirv.hpp11" #include "spirv/unified1/spirv.hpp11"
#include "src/ast/import.h"
#include "src/ast/module.h" #include "src/ast/module.h"
namespace tint { namespace tint {
@ -24,17 +28,48 @@ namespace spirv {
using BuilderTest = testing::Test; using BuilderTest = testing::Test;
TEST_F(BuilderTest, InsertsPreamble) { TEST_F(BuilderTest, InsertsPreambleWithImport) {
ast::Module m;
m.AddImport(std::make_unique<ast::Import>("GLSL.std.450", "glsl"));
Builder b;
ASSERT_TRUE(b.Build(m));
ASSERT_EQ(b.preamble().size(), 4);
auto pre = b.preamble();
EXPECT_EQ(pre[0].opcode(), spv::Op::OpCapability);
EXPECT_EQ(pre[0].operands()[0].to_i(), SpvCapabilityShader);
EXPECT_EQ(pre[1].opcode(), spv::Op::OpCapability);
EXPECT_EQ(pre[1].operands()[0].to_i(), SpvCapabilityVulkanMemoryModel);
EXPECT_EQ(pre[2].opcode(), spv::Op::OpExtInstImport);
EXPECT_EQ(pre[2].operands()[1].to_s(), "GLSL.std.450");
EXPECT_EQ(pre[3].opcode(), spv::Op::OpMemoryModel);
}
TEST_F(BuilderTest, InsertsPreambleWithoutImport) {
ast::Module m; ast::Module m;
Builder b; Builder b;
ASSERT_TRUE(b.Build(m)); ASSERT_TRUE(b.Build(m));
ASSERT_EQ(b.preamble().size(), 3); ASSERT_EQ(b.preamble().size(), 3);
auto pre = b.preamble(); auto pre = b.preamble();
EXPECT_EQ(pre[0].opcode(), spv::Op::OpCapability); EXPECT_EQ(pre[0].opcode(), spv::Op::OpCapability);
EXPECT_EQ(pre[1].opcode(), spv::Op::OpExtInstImport); EXPECT_EQ(pre[0].operands()[0].to_i(), SpvCapabilityShader);
EXPECT_EQ(pre[1].opcode(), spv::Op::OpCapability);
EXPECT_EQ(pre[1].operands()[0].to_i(), SpvCapabilityVulkanMemoryModel);
EXPECT_EQ(pre[2].opcode(), spv::Op::OpMemoryModel); EXPECT_EQ(pre[2].opcode(), spv::Op::OpMemoryModel);
} }
TEST_F(BuilderTest, TracksIdBounds) {
Builder b;
for (size_t i = 0; i < 5; i++) {
EXPECT_EQ(b.next_id(), i + 1);
}
EXPECT_EQ(6, b.id_bound());
}
} // namespace spirv } // namespace spirv
} // namespace writer } // namespace writer
} // namespace tint } // namespace tint