From 4c2378d5b9dffeb21d9242e086031cd07fccee68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Suonp=C3=A4=C3=A4?= Date: Tue, 21 Apr 2020 10:58:34 +0300 Subject: [PATCH 1/2] Added DEPTH support for Amber Script. --- docs/amber_script.md | 24 + src/CMakeLists.txt | 1 + src/amberscript/parser.cc | 138 +++++ src/amberscript/parser.h | 1 + src/amberscript/parser_depth_test.cc | 557 +++++++++++++++++++ src/command_data.h | 3 +- src/vulkan/graphics_pipeline.cc | 5 +- tests/cases/draw_rectangles_depth_test.amber | 136 +++++ 8 files changed, 862 insertions(+), 3 deletions(-) create mode 100644 src/amberscript/parser_depth_test.cc create mode 100644 tests/cases/draw_rectangles_depth_test.amber diff --git a/docs/amber_script.md b/docs/amber_script.md index eef3338fd..9e3537ec9 100644 --- a/docs/amber_script.md +++ b/docs/amber_script.md @@ -378,6 +378,30 @@ The following commands are all specified within the `PIPELINE` command. POLYGON_MODE {mode} ``` +#### Compare operations + * `never` + * `less` + * `equal` + * `less_or_equal` + * `greater` + * `not_equal` + * `greater_or_equal` + * `always` + +```groovy + # Set depth test settings. All enable options are specified with keywords on and off. + # BOUNDS and BIAS values are specified with decimal numbers. |compare_op| is selected + # from the list of compare operations above. + DEPTH + TEST {test_enable} + WRITE {write_enable} + COMPARE_OP {compare_op} + CLAMP {clamp_enable} + BOUNDS min {bound_min} max {bounds_max} + BIAS constant {bias_constant} clamp {bias_clamp} slope {bias_slope} + END +``` + ```groovy # Set the size of the render buffers. |width| and |height| are integers and # default to 250x250. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0aa987e43..7cd530a16 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -137,6 +137,7 @@ if (${AMBER_ENABLE_TESTS}) amberscript/parser_clear_test.cc amberscript/parser_compile_options_test.cc amberscript/parser_copy_test.cc + amberscript/parser_depth_test.cc amberscript/parser_device_feature_test.cc amberscript/parser_expect_test.cc amberscript/parser_extension_test.cc diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc index 30c23934c..3e265b4dc 100644 --- a/src/amberscript/parser.cc +++ b/src/amberscript/parser.cc @@ -152,6 +152,27 @@ ImageDimension StrToImageDimension(const std::string& str) { return ImageDimension::kUnknown; } +CompareOp StrToCompareOp(const std::string& str) { + if (str == "never") + return CompareOp::kNever; + if (str == "less") + return CompareOp::kLess; + if (str == "equal") + return CompareOp::kEqual; + if (str == "less_or_equal") + return CompareOp::kLessOrEqual; + if (str == "greater") + return CompareOp::kGreater; + if (str == "not_equal") + return CompareOp::kNotEqual; + if (str == "greater_or_equal") + return CompareOp::kGreaterOrEqual; + if (str == "always") + return CompareOp::kAlways; + + return CompareOp::kUnknown; +} + Result ParseBufferData(Buffer* buffer, Tokenizer* tokenizer, bool from_data_file) { @@ -548,6 +569,8 @@ Result Parser::ParsePipelineBody(const std::string& cmd_name, r = ParsePipelineShaderCompileOptions(pipeline.get()); } else if (tok == "POLYGON_MODE") { r = ParsePipelinePolygonMode(pipeline.get()); + } else if (tok == "DEPTH") { + r = ParsePipelineDepth(pipeline.get()); } else { r = Result("unknown token in pipeline block: " + tok); } @@ -1169,6 +1192,121 @@ Result Parser::ParsePipelinePolygonMode(Pipeline* pipeline) { return ValidateEndOfStatement("POLYGON_MODE command"); } +Result Parser::ParsePipelineDepth(Pipeline* pipeline) { + while (true) { + auto token = tokenizer_->NextToken(); + if (token->IsEOL()) + continue; + if (token->IsEOS()) + return Result("DEPTH missing END command"); + if (!token->IsIdentifier()) + return Result("DEPTH options must be identifiers"); + if (token->AsString() == "END") + break; + + if (token->AsString() == "TEST") { + token = tokenizer_->NextToken(); + + if (!token->IsIdentifier()) + return Result("invalid value for TEST"); + + if (token->AsString() == "on") + pipeline->GetPipelineData()->SetEnableDepthTest(true); + else if (token->AsString() == "off") + pipeline->GetPipelineData()->SetEnableDepthTest(false); + else + return Result("invalid value for TEST: " + token->AsString()); + } else if (token->AsString() == "CLAMP") { + token = tokenizer_->NextToken(); + + if (!token->IsIdentifier()) + return Result("invalid value for CLAMP"); + + if (token->AsString() == "on") + pipeline->GetPipelineData()->SetEnableDepthClamp(true); + else if (token->AsString() == "off") + pipeline->GetPipelineData()->SetEnableDepthClamp(false); + else + return Result("invalid value for CLAMP: " + token->AsString()); + } else if (token->AsString() == "WRITE") { + token = tokenizer_->NextToken(); + + if (!token->IsIdentifier()) + return Result("invalid value for WRITE"); + + if (token->AsString() == "on") + pipeline->GetPipelineData()->SetEnableDepthWrite(true); + else if (token->AsString() == "off") + pipeline->GetPipelineData()->SetEnableDepthWrite(false); + else + return Result("invalid value for WRITE: " + token->AsString()); + } else if (token->AsString() == "COMPARE_OP") { + token = tokenizer_->NextToken(); + + if (!token->IsIdentifier()) + return Result("invalid value for COMPARE_OP"); + + CompareOp compare_op = StrToCompareOp(token->AsString()); + if (compare_op != CompareOp::kUnknown) { + pipeline->GetPipelineData()->SetDepthCompareOp(compare_op); + } else { + return Result("invalid value for COMPARE_OP: " + token->AsString()); + } + } else if (token->AsString() == "BOUNDS") { + token = tokenizer_->NextToken(); + if (!token->IsIdentifier() || token->AsString() != "min") + return Result("BOUNDS expecting min"); + + token = tokenizer_->NextToken(); + if (!token->IsDouble()) + return Result("BOUNDS invalid value for min"); + pipeline->GetPipelineData()->SetMinDepthBounds(token->AsFloat()); + + token = tokenizer_->NextToken(); + if (!token->IsIdentifier() || token->AsString() != "max") + return Result("BOUNDS expecting max"); + + token = tokenizer_->NextToken(); + if (!token->IsDouble()) + return Result("BOUNDS invalid value for max"); + pipeline->GetPipelineData()->SetMaxDepthBounds(token->AsFloat()); + } else if (token->AsString() == "BIAS") { + pipeline->GetPipelineData()->SetEnableDepthBias(true); + + token = tokenizer_->NextToken(); + if (!token->IsIdentifier() || token->AsString() != "constant") + return Result("BIAS expecting constant"); + + token = tokenizer_->NextToken(); + if (!token->IsDouble()) + return Result("BIAS invalid value for constant"); + pipeline->GetPipelineData()->SetDepthBiasConstantFactor(token->AsFloat()); + + token = tokenizer_->NextToken(); + if (!token->IsIdentifier() || token->AsString() != "clamp") + return Result("BIAS expecting clamp"); + + token = tokenizer_->NextToken(); + if (!token->IsDouble()) + return Result("BIAS invalid value for clamp"); + pipeline->GetPipelineData()->SetDepthBiasClamp(token->AsFloat()); + + token = tokenizer_->NextToken(); + if (!token->IsIdentifier() || token->AsString() != "slope") + return Result("BIAS expecting slope"); + + token = tokenizer_->NextToken(); + if (!token->IsDouble()) + return Result("BIAS invalid value for slope"); + pipeline->GetPipelineData()->SetDepthBiasSlopeFactor(token->AsFloat()); + } else { + return Result("invalid value for DEPTH: " + token->AsString()); + } + } + + return ValidateEndOfStatement("DEPTH command"); +} + Result Parser::ParseStruct() { auto token = tokenizer_->NextToken(); if (!token->IsIdentifier()) diff --git a/src/amberscript/parser.h b/src/amberscript/parser.h index bfe37b52f..543bccd5a 100644 --- a/src/amberscript/parser.h +++ b/src/amberscript/parser.h @@ -69,6 +69,7 @@ class Parser : public amber::Parser { Result ParsePipelineIndexData(Pipeline*); Result ParsePipelineSet(Pipeline*); Result ParsePipelinePolygonMode(Pipeline*); + Result ParsePipelineDepth(Pipeline* pipeline); Result ParseRun(); Result ParseDebug(); Result ParseDebugThread(debug::Events*); diff --git a/src/amberscript/parser_depth_test.cc b/src/amberscript/parser_depth_test.cc new file mode 100644 index 000000000..68ddf4b44 --- /dev/null +++ b/src/amberscript/parser_depth_test.cc @@ -0,0 +1,557 @@ +// Copyright 2020 The Amber 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 parseried. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "gtest/gtest.h" +#include "src/amberscript/parser.h" + +namespace amber { +namespace amberscript { + +using AmberScriptParserTest = testing::Test; + +TEST_F(AmberScriptParserTest, DepthAllValues) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + WRITE on + COMPARE_OP less_or_equal + CLAMP on + BOUNDS min 1.5 max 6.7 + BIAS constant 2.1 clamp 3.5 slope 5.5 + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_TRUE(r.IsSuccess()) << r.Error(); + + auto script = parser.GetScript(); + const auto& pipelines = script->GetPipelines(); + ASSERT_EQ(1U, pipelines.size()); + + auto* pipeline = pipelines[0].get(); + ASSERT_NE(nullptr, pipeline->GetDepthStencilBuffer().buffer); + + ASSERT_TRUE(pipeline->GetPipelineData()->GetEnableDepthTest()); + ASSERT_TRUE(pipeline->GetPipelineData()->GetEnableDepthWrite()); + ASSERT_TRUE(pipeline->GetPipelineData()->GetEnableDepthClamp()); + ASSERT_FLOAT_EQ(1.5f, pipeline->GetPipelineData()->GetMinDepthBounds()); + ASSERT_FLOAT_EQ(6.7f, pipeline->GetPipelineData()->GetMaxDepthBounds()); + ASSERT_FLOAT_EQ(2.1f, + pipeline->GetPipelineData()->GetDepthBiasConstantFactor()); + ASSERT_FLOAT_EQ(3.5f, pipeline->GetPipelineData()->GetDepthBiasClamp()); + ASSERT_FLOAT_EQ(5.5f, pipeline->GetPipelineData()->GetDepthBiasSlopeFactor()); +} + +TEST_F(AmberScriptParserTest, DepthTestMissingValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST + WRITE on + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: invalid value for TEST", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthTestInvalidValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST foo + WRITE on + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("16: invalid value for TEST: foo", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthWriteMissingValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + WRITE + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("18: invalid value for WRITE", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthWriteInvalidValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + WRITE foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: invalid value for WRITE: foo", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthClampMissingValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + CLAMP + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("18: invalid value for CLAMP", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthClampInvalidValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + CLAMP foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: invalid value for CLAMP: foo", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthCompareMissingValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + COMPARE_OP + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("18: invalid value for COMPARE_OP", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthCompareInvalidValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + COMPARE_OP foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: invalid value for COMPARE_OP: foo", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBoundsExpectingMin) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BOUNDS + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("18: BOUNDS expecting min", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBoundsMinInvalidValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BOUNDS min foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: BOUNDS invalid value for min", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBoundsExpectingMax) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BOUNDS min 0.0 foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: BOUNDS expecting max", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBoundsMaxInvalidValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BOUNDS min 0.0 max foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: BOUNDS invalid value for max", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBiasExpectingConstant) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BIAS + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("18: BIAS expecting constant", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBiasConstantInvalidValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BIAS constant foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: BIAS invalid value for constant", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBiasExpectingClamp) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BIAS constant 0.0 foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: BIAS expecting clamp", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBiasClampInvalidValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BIAS constant 0.0 clamp foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: BIAS invalid value for clamp", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBiasExpectingSlope) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BIAS constant 0.0 clamp 0.0 + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("18: BIAS expecting slope", r.Error()); +} + +TEST_F(AmberScriptParserTest, DepthBiasSlopeInvalidValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_fb FORMAT R32G32B32A32_SFLOAT +BUFFER my_ds FORMAT D32_SFLOAT_S8_UINT + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + BIND BUFFER my_fb AS color LOCATION 0 + BIND BUFFER my_ds AS depth_stencil + + DEPTH + TEST on + BIAS constant 0.0 clamp 0.0 slope foo + END +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()) << r.Error(); + EXPECT_EQ("17: BIAS invalid value for slope", r.Error()); +} + +} // namespace amberscript +} // namespace amber diff --git a/src/command_data.h b/src/command_data.h index 430533cd1..103c092a6 100644 --- a/src/command_data.h +++ b/src/command_data.h @@ -61,7 +61,8 @@ enum ColorMask { }; enum class CompareOp : uint8_t { - kNever = 0, + kUnknown = 0, + kNever, kLess, kEqual, kLessOrEqual, diff --git a/src/vulkan/graphics_pipeline.cc b/src/vulkan/graphics_pipeline.cc index 6c7245bc0..dbc2dd258 100644 --- a/src/vulkan/graphics_pipeline.cc +++ b/src/vulkan/graphics_pipeline.cc @@ -113,9 +113,10 @@ VkCompareOp ToVkCompareOp(CompareOp op) { return VK_COMPARE_OP_GREATER_OR_EQUAL; case CompareOp::kAlways: return VK_COMPARE_OP_ALWAYS; + default: + assert(false && "Vulkan::Unknown CompareOp"); + return VK_COMPARE_OP_NEVER; } - assert(false && "Vulkan::Unknown CompareOp"); - return VK_COMPARE_OP_NEVER; } VkPolygonMode ToVkPolygonMode(PolygonMode mode) { diff --git a/tests/cases/draw_rectangles_depth_test.amber b/tests/cases/draw_rectangles_depth_test.amber new file mode 100644 index 000000000..797e99b3f --- /dev/null +++ b/tests/cases/draw_rectangles_depth_test.amber @@ -0,0 +1,136 @@ +#!amber +# +# Copyright 2020 The Amber 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 +# +# https://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. + +SHADER vertex vert_shader GLSL +#version 430 + +layout(location = 0) in vec4 position; +layout(location = 0) out vec4 frag_color; + +layout(set = 0, binding = 0) readonly buffer block1 { + vec4 in_color; + float depth; +}; + +void main() { + gl_Position = vec4(position.xy, depth, 1.0); + frag_color = in_color; +} +END + +SHADER fragment frag_shader GLSL +#version 430 + +layout(location = 0) in vec4 frag_color; +layout(location = 0) out vec4 final_color; + +void main() { + final_color = frag_color; +} +END + +SHADER vertex vert_shader_tex GLSL +#version 430 +layout(location = 0) in vec4 position; +layout(location = 1) in vec2 texcoords_in; +layout(location = 0) out vec2 texcoords_out; +void main() { + gl_Position = position; + texcoords_out = texcoords_in; +} +END + +SHADER fragment frag_shader_tex GLSL +#version 430 +layout(location = 0) in vec2 texcoords_in; +layout(location = 0) out vec4 color_out; +uniform layout(set=0, binding=0) sampler2D tex_sampler; +void main() { + float f = texture(tex_sampler, texcoords_in).r; + color_out = vec4(f, f, f, 1); +} +END + +BUFFER data_buf1 DATA_TYPE float DATA 1.0 0.0 0.0 1.0 0.3 END +BUFFER data_buf2 DATA_TYPE float DATA 0.0 1.0 0.0 1.0 0.5 END + +BUFFER position DATA_TYPE vec2 DATA +-1.0 -1.0 + 1.0 -1.0 + 1.0 1.0 +-1.0 1.0 +END +BUFFER texcoords DATA_TYPE vec2 DATA +0.0 0.0 +1.0 0.0 +1.0 1.0 +0.0 1.0 +END + +BUFFER framebuffer FORMAT B8G8R8A8_UNORM +BUFFER ddump FORMAT B8G8R8A8_UNORM +BUFFER depthstencil FORMAT D32_SFLOAT_S8_UINT + +SAMPLER sampler + +PIPELINE graphics pipeline1 + ATTACH vert_shader + ATTACH frag_shader + + FRAMEBUFFER_SIZE 256 256 + BIND BUFFER framebuffer AS color LOCATION 0 + BIND BUFFER depthstencil AS depth_stencil + BIND BUFFER data_buf1 AS storage DESCRIPTOR_SET 0 BINDING 0 + + DEPTH + TEST on + WRITE on + COMPARE_OP less + CLAMP off + BOUNDS min 0.0 max 1.0 + BIAS constant 0.0 clamp 0.0 slope 0.0 + END +END + +DERIVE_PIPELINE pipeline2 FROM pipeline1 + BIND BUFFER data_buf2 AS storage DESCRIPTOR_SET 0 BINDING 0 +END + +PIPELINE graphics depthdump + ATTACH vert_shader_tex + ATTACH frag_shader_tex + BIND BUFFER depthstencil AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0 + VERTEX_DATA position LOCATION 0 + VERTEX_DATA texcoords LOCATION 1 + FRAMEBUFFER_SIZE 256 256 + BIND BUFFER ddump AS color LOCATION 0 +END + +CLEAR_DEPTH pipeline1 1.0 +CLEAR_COLOR pipeline1 255 255 255 255 +CLEAR pipeline1 +RUN pipeline1 DRAW_RECT POS 0 0 SIZE 200 200 +RUN pipeline2 DRAW_RECT POS 56 56 SIZE 200 200 +RUN depthdump DRAW_ARRAY AS TRIANGLE_FAN START_IDX 0 COUNT 4 + +EXPECT framebuffer IDX 0 0 SIZE 1 1 EQ_RGBA 255 0 0 255 +EXPECT framebuffer IDX 128 128 SIZE 1 1 EQ_RGBA 255 0 0 255 +EXPECT framebuffer IDX 255 255 SIZE 1 1 EQ_RGBA 0 255 0 255 +EXPECT depthstencil IDX 0 EQ 0.3 +EXPECT ddump IDX 0 0 SIZE 1 1 EQ_RGBA 76 76 76 255 TOLERANCE 5% 5% 5% 0 +EXPECT ddump IDX 255 0 SIZE 1 1 EQ_RGBA 255 255 255 255 TOLERANCE 5% 5% 5% 0 +EXPECT ddump IDX 0 255 SIZE 1 1 EQ_RGBA 255 255 255 255 TOLERANCE 5% 5% 5% 0 +EXPECT ddump IDX 255 255 SIZE 1 1 EQ_RGBA 128 128 128 255 TOLERANCE 5% 5% 5% 0 From acbd8339f89cba601e3c70b4f78a6e754482a2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Suonp=C3=A4=C3=A4?= Date: Wed, 22 Apr 2020 07:40:31 +0300 Subject: [PATCH 2/2] Modify handling of unknown compare op. --- src/vulkan/graphics_pipeline.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vulkan/graphics_pipeline.cc b/src/vulkan/graphics_pipeline.cc index dbc2dd258..6f03799db 100644 --- a/src/vulkan/graphics_pipeline.cc +++ b/src/vulkan/graphics_pipeline.cc @@ -113,10 +113,11 @@ VkCompareOp ToVkCompareOp(CompareOp op) { return VK_COMPARE_OP_GREATER_OR_EQUAL; case CompareOp::kAlways: return VK_COMPARE_OP_ALWAYS; - default: - assert(false && "Vulkan::Unknown CompareOp"); - return VK_COMPARE_OP_NEVER; + case CompareOp::kUnknown: + break; } + assert(false && "Vulkan::Unknown CompareOp"); + return VK_COMPARE_OP_NEVER; } VkPolygonMode ToVkPolygonMode(PolygonMode mode) {