diff options
author | dan sinclair <dj2@everburning.com> | 2019-03-07 12:27:45 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-07 12:27:45 -0500 |
commit | 27fc8e36c6b43e41a0a1213474a542442f25ec0f (patch) | |
tree | 33135dacc524d5eb5764b52b270844748ba1711b /src | |
parent | 04349cb411a8e108e2d77318b8e5aafca675c964 (diff) | |
download | amber-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.cc | 115 | ||||
-rw-r--r-- | src/amberscript/parser.h | 1 | ||||
-rw-r--r-- | src/amberscript/parser_test.cc | 471 | ||||
-rw-r--r-- | src/pipeline.h | 2 | ||||
-rw-r--r-- | src/script.h | 5 |
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_; |