aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorasuonpaa <34128694+asuonpaa@users.noreply.github.com>2021-09-25 15:02:21 +0300
committerGitHub <noreply@github.com>2021-09-25 13:02:21 +0100
commit6b3fcb0353533d1236035c4aa3b587be5d8b37cd (patch)
tree2d8161e7c49e1e5874d01d0bcd52db37b6ef5770
parent51ef48a2d7c239af32c16d3d72ec5f00a6618d81 (diff)
downloadamber-6b3fcb0353533d1236035c4aa3b587be5d8b37cd.tar.gz
Add PATCH_CONTROL_POINTS to AmberScript (#963)
Previously only VkScript had the access to set the number of patch control points. Now this can also be set in AmberScript pipeline settings.
-rw-r--r--docs/amber_script.md5
-rw-r--r--src/amberscript/parser.cc16
-rw-r--r--src/amberscript/parser.h1
-rw-r--r--src/amberscript/parser_pipeline_test.cc82
-rw-r--r--src/pipeline_data.h7
-rw-r--r--src/vulkan/engine_vulkan.cc3
-rw-r--r--tests/cases/tessellation_isolines.amber130
-rwxr-xr-xtests/run_tests.py2
8 files changed, 246 insertions, 0 deletions
diff --git a/docs/amber_script.md b/docs/amber_script.md
index bdb2b76..4161101 100644
--- a/docs/amber_script.md
+++ b/docs/amber_script.md
@@ -441,6 +441,11 @@ The following commands are all specified within the `PIPELINE` command.
POLYGON_MODE {mode}
```
+```groovy
+ # Set the number of patch control points used by tessellation. The default value is 3.
+ PATCH_CONTROL_POINTS {control_points}
+```
+
#### Compare operations
* `never`
* `less`
diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc
index 809baa1..dfc2cfb 100644
--- a/src/amberscript/parser.cc
+++ b/src/amberscript/parser.cc
@@ -622,6 +622,8 @@ Result Parser::ParsePipelineBody(const std::string& cmd_name,
r = ParsePipelineStencil(pipeline.get());
} else if (tok == "SUBGROUP") {
r = ParsePipelineSubgroup(pipeline.get());
+ } else if (tok == "PATCH_CONTROL_POINTS") {
+ r = ParsePipelinePatchControlPoints(pipeline.get());
} else {
r = Result("unknown token in pipeline block: " + tok);
}
@@ -931,6 +933,20 @@ Result Parser::ParsePipelineSubgroup(Pipeline* pipeline) {
return ValidateEndOfStatement("SUBGROUP command");
}
+Result Parser::ParsePipelinePatchControlPoints(Pipeline* pipeline) {
+ auto token = tokenizer_->NextToken();
+ if (token->IsEOL() || token->IsEOS())
+ return Result(
+ "missing number of control points in PATCH_CONTROL_POINTS command");
+
+ if (!token->IsInteger())
+ return Result("expecting integer for the number of control points");
+
+ pipeline->GetPipelineData()->SetPatchControlPoints(token->AsUint32());
+
+ return ValidateEndOfStatement("PATCH_CONTROL_POINTS command");
+}
+
Result Parser::ParsePipelineFramebufferSize(Pipeline* pipeline) {
auto token = tokenizer_->NextToken();
if (token->IsEOL() || token->IsEOS())
diff --git a/src/amberscript/parser.h b/src/amberscript/parser.h
index 6fb25ce..8f59351 100644
--- a/src/amberscript/parser.h
+++ b/src/amberscript/parser.h
@@ -64,6 +64,7 @@ class Parser : public amber::Parser {
Result ParsePipelineShaderOptimizations(Pipeline*);
Result ParsePipelineShaderCompileOptions(Pipeline*);
Result ParsePipelineSubgroup(Pipeline* pipeline);
+ Result ParsePipelinePatchControlPoints(Pipeline* pipeline);
Result ParsePipelineFramebufferSize(Pipeline*);
Result ParsePipelineViewport(Pipeline*);
Result ParsePipelineBind(Pipeline*);
diff --git a/src/amberscript/parser_pipeline_test.cc b/src/amberscript/parser_pipeline_test.cc
index 2b56e2e..4707dd9 100644
--- a/src/amberscript/parser_pipeline_test.cc
+++ b/src/amberscript/parser_pipeline_test.cc
@@ -61,6 +61,8 @@ END
EXPECT_EQ(kShaderTypeFragment, shaders[1].GetShader()->GetType());
EXPECT_EQ(static_cast<uint32_t>(0),
shaders[1].GetShaderOptimizations().size());
+
+ EXPECT_EQ(pipelines[0]->GetPipelineData()->GetPatchControlPoints(), 3u);
}
TEST_F(AmberScriptParserTest, PipelineMissingEnd) {
@@ -541,5 +543,85 @@ END
EXPECT_EQ(4u, s2[0].GetSpecialization().at(3));
}
+TEST_F(AmberScriptParserTest, PipelinePatchControlPoints) {
+ std::string in = R"(
+DEVICE_FEATURE tessellationShader
+
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+SHADER tessellation_control my_tesc GLSL
+# GLSL Shader
+END
+
+SHADER tessellation_evaluation my_tese GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_tesc
+ ATTACH my_tese
+ ATTACH my_fragment
+
+ PATCH_CONTROL_POINTS 4
+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());
+
+ EXPECT_EQ(pipelines[0]->GetPipelineData()->GetPatchControlPoints(), 4u);
+}
+
+TEST_F(AmberScriptParserTest, PipelineDerivePatchControlPoints) {
+ std::string in = R"(
+DEVICE_FEATURE tessellationShader
+
+SHADER vertex my_shader PASSTHROUGH
+SHADER fragment my_fragment GLSL
+# GLSL Shader
+END
+
+SHADER tessellation_control my_tesc GLSL
+# GLSL Shader
+END
+
+SHADER tessellation_evaluation my_tese GLSL
+# GLSL Shader
+END
+
+PIPELINE graphics my_pipeline
+ ATTACH my_shader
+ ATTACH my_tesc
+ ATTACH my_tese
+ ATTACH my_fragment
+
+ PATCH_CONTROL_POINTS 4
+END
+
+DERIVE_PIPELINE child_pipeline FROM my_pipeline
+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(2U, pipelines.size());
+
+ EXPECT_EQ(pipelines[0]->GetPipelineData()->GetPatchControlPoints(), 4u);
+ EXPECT_EQ(pipelines[1]->GetPipelineData()->GetPatchControlPoints(), 4u);
+}
+
} // namespace amberscript
} // namespace amber
diff --git a/src/pipeline_data.h b/src/pipeline_data.h
index 9a3b4d1..c763f37 100644
--- a/src/pipeline_data.h
+++ b/src/pipeline_data.h
@@ -178,6 +178,11 @@ class PipelineData {
bool HasViewportData() const { return has_viewport_data; }
const Viewport& GetViewport() const { return vp; }
+ void SetPatchControlPoints(uint32_t control_points) {
+ patch_control_points_ = control_points;
+ }
+ uint32_t GetPatchControlPoints() const { return patch_control_points_; }
+
private:
StencilOp front_fail_op_ = StencilOp::kKeep;
StencilOp front_pass_op_ = StencilOp::kKeep;
@@ -233,6 +238,8 @@ class PipelineData {
bool has_viewport_data = false;
Viewport vp;
+
+ uint32_t patch_control_points_ = 3u;
};
} // namespace amber
diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc
index 6bed716..8d16545 100644
--- a/src/vulkan/engine_vulkan.cc
+++ b/src/vulkan/engine_vulkan.cc
@@ -180,6 +180,9 @@ Result EngineVulkan::CreatePipeline(amber::Pipeline* pipeline) {
pipeline->GetDepthStencilBuffer(), engine_data.fence_timeout_ms,
stage_create_info);
+ vk_pipeline->AsGraphics()->SetPatchControlPoints(
+ pipeline->GetPipelineData()->GetPatchControlPoints());
+
r = vk_pipeline->AsGraphics()->Initialize(pipeline->GetFramebufferWidth(),
pipeline->GetFramebufferHeight(),
pool_.get());
diff --git a/tests/cases/tessellation_isolines.amber b/tests/cases/tessellation_isolines.amber
new file mode 100644
index 0000000..dd3f298
--- /dev/null
+++ b/tests/cases/tessellation_isolines.amber
@@ -0,0 +1,130 @@
+#!amber
+# Copyright 2021 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.
+
+DEVICE_FEATURE tessellationShader
+
+SHADER vertex vert GLSL
+#version 450
+
+layout (location = 0) in vec3 inPosition;
+
+void main(void)
+{
+ gl_Position = vec4(inPosition, 1.0);
+}
+END
+
+SHADER tessellation_control tesc GLSL
+#version 450
+
+layout (vertices = 4) out;
+
+void main(void)
+{
+ gl_TessLevelOuter[0] = 6.0;
+ gl_TessLevelOuter[1] = 2.0;
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+}
+END
+
+SHADER tessellation_evaluation tese GLSL
+#version 450
+
+layout (isolines, equal_spacing, cw) in;
+
+void main(void)
+{
+ vec4 p1 = mix(gl_in[0].gl_Position,
+ gl_in[1].gl_Position,
+ gl_TessCoord.x);
+
+ vec4 p2 = mix(gl_in[2].gl_Position,
+ gl_in[3].gl_Position,
+ gl_TessCoord.x);
+
+ gl_Position = mix(p1, p2, gl_TessCoord.y);
+}
+END
+
+SHADER fragment frag GLSL
+#version 450
+
+layout (location = 0) out vec4 outColor;
+
+void main(void)
+{
+ outColor = vec4(1, 0, 0, 1);
+}
+END
+
+SHADER compute comp_shader GLSL
+#version 450
+layout(local_size_x=10,local_size_y=10) in;
+uniform layout(set=0, binding=0, rgba8) image2D resultImage;
+
+layout(set = 0, binding = 1) buffer block0
+{
+ int counter;
+};
+
+void main()
+{
+ ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
+ vec4 color = imageLoad(resultImage, uv);
+ if(color.r > 0.0) atomicAdd(counter, 1);
+}
+END
+
+BUFFER vertexPosition DATA_TYPE vec3<float> DATA
+-1.0 -1.0 0.0
+ 1.0 -1.0 0.0
+-1.0 1.0 0.0
+ 1.0 1.0 0.0
+END
+
+BUFFER counter DATA_TYPE int32 DATA 0 END
+
+BUFFER framebuffer FORMAT B8G8R8A8_UNORM
+
+PIPELINE graphics pipeline
+ ATTACH vert
+ ATTACH tesc
+ ATTACH tese
+ ATTACH frag
+
+ PATCH_CONTROL_POINTS 4
+
+ FRAMEBUFFER_SIZE 100 100
+ VERTEX_DATA vertexPosition LOCATION 0
+ BIND BUFFER framebuffer AS color LOCATION 0
+END
+
+CLEAR_COLOR pipeline 0 0 0 255
+CLEAR pipeline
+
+RUN pipeline DRAW_ARRAY AS PATCH_LIST START_IDX 0 COUNT 4
+
+PIPELINE compute verify_pipeline
+ ATTACH comp_shader
+ BIND BUFFER framebuffer AS storage_image DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER counter AS storage DESCRIPTOR_SET 0 BINDING 1
+ FRAMEBUFFER_SIZE 100 100
+END
+
+# Count the number of red pixels as the line position might differ between implementations.
+RUN verify_pipeline 10 10 1
+
+EXPECT counter IDX 0 TOLERANCE 50 EQ 500
diff --git a/tests/run_tests.py b/tests/run_tests.py
index 1fb7eb6..6cd8fc3 100755
--- a/tests/run_tests.py
+++ b/tests/run_tests.py
@@ -96,6 +96,8 @@ SUPPRESSIONS_SWIFTSHADER = [
# Unsupported depth/stencil formats
"draw_rectangles_depth_test_d24s8.amber",
"draw_rectangles_depth_test_x8d24.amber",
+ # Tessellation not supported
+ "tessellation_isolines.amber",
]
OPENCL_CASES = [