aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan sinclair <dj2@everburning.com>2019-03-07 12:27:45 -0500
committerGitHub <noreply@github.com>2019-03-07 12:27:45 -0500
commit27fc8e36c6b43e41a0a1213474a542442f25ec0f (patch)
tree33135dacc524d5eb5764b52b270844748ba1711b /src
parent04349cb411a8e108e2d77318b8e5aafca675c964 (diff)
downloadamber-27fc8e36c6b43e41a0a1213474a542442f25ec0f.tar.gz
[amberscript] Implement RUN for compute and DRAW_RECT. (#335)
This CL adds parsing of the RUN commands for compute and DRAW_RECT instances to AmberScript.
Diffstat (limited to 'src')
-rw-r--r--src/amberscript/parser.cc115
-rw-r--r--src/amberscript/parser.h1
-rw-r--r--src/amberscript/parser_test.cc471
-rw-r--r--src/pipeline.h2
-rw-r--r--src/script.h5
5 files changed, 594 insertions, 0 deletions
diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc
index 5ff6ee0..77656c5 100644
--- a/src/amberscript/parser.cc
+++ b/src/amberscript/parser.cc
@@ -54,6 +54,8 @@ Result Parser::Parse(const std::string& data) {
r = ParsePipelineBlock();
} else if (tok == "SHADER") {
r = ParseShaderBlock();
+ } else if (tok == "RUN") {
+ r = ParseRun();
} else {
r = Result("unknown token: " + tok);
}
@@ -846,5 +848,118 @@ Result Parser::ParseBufferInitializerData(DataBuffer* buffer) {
return ValidateEndOfStatement("BUFFER data command");
}
+Result Parser::ParseRun() {
+ auto token = tokenizer_->NextToken();
+ if (!token->IsString())
+ return Result("missing pipeline name for RUN command");
+
+ auto* pipeline = script_->GetPipeline(token->AsString());
+ if (!pipeline)
+ return Result("unknown pipeline for RUN command: " + token->AsString());
+
+ token = tokenizer_->NextToken();
+ if (token->IsEOL() || token->IsEOS())
+ return Result("RUN command requires parameters");
+
+ if (token->IsInteger()) {
+ if (!pipeline->IsCompute())
+ return Result("RUN command requires compute pipeline, got graphics");
+
+ auto cmd = MakeUnique<ComputeCommand>(pipeline);
+ cmd->SetX(token->AsUint32());
+
+ token = tokenizer_->NextToken();
+ if (!token->IsInteger()) {
+ return Result("invalid parameter for RUN command: " +
+ token->ToOriginalString());
+ }
+ cmd->SetY(token->AsUint32());
+
+ token = tokenizer_->NextToken();
+ if (!token->IsInteger()) {
+ return Result("invalid parameter for RUN command: " +
+ token->ToOriginalString());
+ }
+ cmd->SetZ(token->AsUint32());
+
+ script_->AddCommand(std::move(cmd));
+ return ValidateEndOfStatement("RUN command");
+ }
+ if (!token->IsString())
+ return Result("invalid token in RUN command: " + token->ToOriginalString());
+
+ if (token->AsString() == "DRAW_RECT") {
+ if (!pipeline->IsGraphics())
+ return Result("RUN command requires graphics pipeline, got compute");
+
+ token = tokenizer_->NextToken();
+ if (token->IsEOS() || token->IsEOL())
+ return Result("RUN DRAW_RECT command requires parameters");
+
+ if (!token->IsString() || token->AsString() != "POS") {
+ return Result("invalid token in RUN command: " +
+ token->ToOriginalString() + "; expected POS");
+ }
+
+ token = tokenizer_->NextToken();
+ if (!token->IsInteger())
+ return Result("missing X position for RUN command");
+
+ auto cmd = MakeUnique<DrawRectCommand>(pipeline, PipelineData{});
+ Result r = token->ConvertToDouble();
+ if (!r.IsSuccess())
+ return r;
+ cmd->SetX(token->AsFloat());
+
+ token = tokenizer_->NextToken();
+ if (!token->IsInteger())
+ return Result("missing Y position for RUN command");
+
+ r = token->ConvertToDouble();
+ if (!r.IsSuccess())
+ return r;
+ cmd->SetY(token->AsFloat());
+
+ token = tokenizer_->NextToken();
+ if (!token->IsString() || token->AsString() != "SIZE") {
+ return Result("invalid token in RUN command: " +
+ token->ToOriginalString() + "; expected SIZE");
+ }
+
+ token = tokenizer_->NextToken();
+ if (!token->IsInteger())
+ return Result("missing width value for RUN command");
+
+ r = token->ConvertToDouble();
+ if (!r.IsSuccess())
+ return r;
+ cmd->SetWidth(token->AsFloat());
+
+ token = tokenizer_->NextToken();
+ if (!token->IsInteger())
+ return Result("missing height value for RUN command");
+
+ r = token->ConvertToDouble();
+ if (!r.IsSuccess())
+ return r;
+ cmd->SetHeight(token->AsFloat());
+
+ script_->AddCommand(std::move(cmd));
+ return ValidateEndOfStatement("RUN command");
+ }
+
+ if (token->AsString() == "DRAW_ARRAY") {
+ if (!pipeline->IsGraphics())
+ return Result("RUN command requires graphics pipeline, got compute");
+
+ auto cmd = MakeUnique<DrawArraysCommand>(pipeline, PipelineData{});
+
+ script_->AddCommand(std::move(cmd));
+ return ValidateEndOfStatement("RUN command");
+ }
+
+ return Result("invalid token in RUN command: " + token->AsString());
+}
+
} // namespace amberscript
} // namespace amber
diff --git a/src/amberscript/parser.h b/src/amberscript/parser.h
index 048297d..a7a3c70 100644
--- a/src/amberscript/parser.h
+++ b/src/amberscript/parser.h
@@ -60,6 +60,7 @@ class Parser : public amber::Parser {
Result ParsePipelineBind(Pipeline*);
Result ParsePipelineVertexData(Pipeline*);
Result ParsePipelineIndexData(Pipeline*);
+ Result ParseRun();
std::unique_ptr<Tokenizer> tokenizer_;
};
diff --git a/src/amberscript/parser_test.cc b/src/amberscript/parser_test.cc
index f7fd62c..28b3f1d 100644
--- a/src/amberscript/parser_test.cc
+++ b/src/amberscript/parser_test.cc
@@ -2935,5 +2935,476 @@ INSTANTIATE_TEST_CASE_P(
"storage",
BufferType::kStorage}), ); // NOLINT(whitespace/parens)
+TEST_F(AmberScriptParserTest, RunCompute) {
+ std::string in = R"(
+SHADER compute my_shader GLSL
+void main() {
+ gl_FragColor = vec3(2, 3, 4);
+}
+END
+
+PIPELINE compute my_pipeline
+ ATTACH my_shader
+END
+
+RUN my_pipeline 2 4 5
+)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ auto script = parser.GetScript();
+ const auto& commands = script->GetCommands();
+ ASSERT_EQ(1U, commands.size());
+
+ auto* cmd = commands[0].get();
+ ASSERT_TRUE(cmd->IsCompute());
+ EXPECT_EQ(2U, cmd->AsCompute()->GetX());
+ EXPECT_EQ(4U, cmd->AsCompute()->GetY());
+ EXPECT_EQ(5U, cmd->AsCompute()->GetZ());
+}
+
+TEST_F(AmberScriptParserTest, RunWithoutPipeline) {
+ std::string in = R"(RUN 2 4 5)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("1: missing pipeline name for RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunWithInvalidPipeline) {
+ std::string in = R"(RUN unknown_pipeline 2 4 5)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("1: unknown pipeline for RUN command: unknown_pipeline", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunComputeWithGraphicsPipeline) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline 2 4 5)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: RUN command requires compute pipeline, got graphics",
+ r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunComputeMissingParams) {
+ std::string in = R"(
+SHADER compute my_shader GLSL
+void main() {
+ gl_FragColor = vec3(2, 3, 4);
+}
+END
+
+PIPELINE compute my_pipeline
+ ATTACH my_shader
+END
+
+RUN my_pipeline)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: RUN command requires parameters", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunComputeExtraParams) {
+ std::string in = R"(
+SHADER compute my_shader GLSL
+void main() {
+ gl_FragColor = vec3(2, 3, 4);
+}
+END
+
+PIPELINE compute my_pipeline
+ ATTACH my_shader
+END
+
+RUN my_pipeline 2 4 5 EXTRA)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: extra parameters after RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunComputeInvalidZ) {
+ std::string in = R"(
+SHADER compute my_shader GLSL
+void main() {
+ gl_FragColor = vec3(2, 3, 4);
+}
+END
+
+PIPELINE compute my_pipeline
+ ATTACH my_shader
+END
+
+RUN my_pipeline 2 4 INVALID)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: invalid parameter for RUN command: INVALID", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunComputeInvalidY) {
+ std::string in = R"(
+SHADER compute my_shader GLSL
+void main() {
+ gl_FragColor = vec3(2, 3, 4);
+}
+END
+
+PIPELINE compute my_pipeline
+ ATTACH my_shader
+END
+
+RUN my_pipeline 2 INVALID 5)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: invalid parameter for RUN command: INVALID", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunComputeInvalidX) {
+ std::string in = R"(
+SHADER compute my_shader GLSL
+void main() {
+ gl_FragColor = vec3(2, 3, 4);
+}
+END
+
+PIPELINE compute my_pipeline
+ ATTACH my_shader
+END
+
+RUN my_pipeline INVALID 4 5)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: invalid token in RUN command: INVALID", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRect) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS 2 4 SIZE 10 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ auto script = parser.GetScript();
+ const auto& commands = script->GetCommands();
+ ASSERT_EQ(1U, commands.size());
+
+ auto* cmd = commands[0].get();
+ ASSERT_TRUE(cmd->IsDrawRect());
+ EXPECT_FALSE(cmd->AsDrawRect()->IsOrtho());
+ EXPECT_FALSE(cmd->AsDrawRect()->IsPatch());
+ EXPECT_FLOAT_EQ(2.f, cmd->AsDrawRect()->GetX());
+ EXPECT_FLOAT_EQ(4.f, cmd->AsDrawRect()->GetY());
+ EXPECT_FLOAT_EQ(10.f, cmd->AsDrawRect()->GetWidth());
+ EXPECT_FLOAT_EQ(20.f, cmd->AsDrawRect()->GetHeight());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectWithComputePipelineInvalid) {
+ std::string in = R"(
+SHADER compute my_shader GLSL
+void main() {
+ gl_FragColor = vec3(2, 3, 4);
+}
+END
+
+PIPELINE compute my_pipeline
+ ATTACH my_shader
+END
+
+RUN my_pipeline DRAW_RECT POS 2 4 SIZE 10 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: RUN command requires graphics pipeline, got compute",
+ r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectWithMissingPipeline) {
+ std::string in = R"(RUN my_pipeline DRAW_RECT POS 2 4 SIZE 10 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("1: unknown pipeline for RUN command: my_pipeline", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectMissingValues) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: RUN DRAW_RECT command requires parameters", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectMissingPOS) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT 2 4 SIZE 10 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: invalid token in RUN command: 2; expected POS", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectPOSMissingValues) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS SIZE 10 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: missing X position for RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectMissingPOSY) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS 2 SIZE 10 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: missing Y position for RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectInvalidPOSX) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS INVALID 4 SIZE 10 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: missing X position for RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectInavlidPOSY) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS 2 INVALID SIZE 10 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: missing Y position for RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectMissingSize) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS 2 4 10 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: invalid token in RUN command: 10; expected SIZE", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectMissingSizeValues) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS 2 4 SIZE)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: missing width value for RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectMissingSizeHeight) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS 2 4 SIZE 10)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: missing height value for RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectInvalidSizeWidth) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS 2 4 SIZE INVALID 20)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: missing width value for RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectInvalidSizeHeight) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS 2 4 SIZE 10 INVALID)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: missing height value for RUN command", r.Error());
+}
+
+TEST_F(AmberScriptParserTest, RunDrawRectExtraCommands) {
+ std::string in = R"(
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_fragment
+END
+
+RUN my_pipeline DRAW_RECT POS 2 4 SIZE 10 20 EXTRA)";
+
+ Parser parser;
+ Result r = parser.Parse(in);
+ ASSERT_FALSE(r.IsSuccess());
+ ASSERT_EQ("12: extra parameters after RUN command", r.Error());
+}
+
} // namespace amberscript
} // namespace amber
diff --git a/src/pipeline.h b/src/pipeline.h
index c4bccb9..11f6528 100644
--- a/src/pipeline.h
+++ b/src/pipeline.h
@@ -83,6 +83,8 @@ class Pipeline {
explicit Pipeline(PipelineType type);
~Pipeline();
+ bool IsGraphics() const { return pipeline_type_ == PipelineType::kGraphics; }
+ bool IsCompute() const { return pipeline_type_ == PipelineType::kCompute; }
PipelineType GetType() const { return pipeline_type_; }
void SetName(const std::string& name) { name_ = name; }
diff --git a/src/script.h b/src/script.h
index 9617f83..371ede8 100644
--- a/src/script.h
+++ b/src/script.h
@@ -141,6 +141,11 @@ class Script : public RecipeImpl {
commands_ = std::move(cmds);
}
+ /// Appends |cmd| to the end of the list of commands to execute.
+ void AddCommand(std::unique_ptr<Command> cmd) {
+ commands_.push_back(std::move(cmd));
+ }
+
/// Retrieves the list of commands to execute against the engine.
const std::vector<std::unique_ptr<Command>>& GetCommands() const {
return commands_;