diff options
author | asuonpaa <34128694+asuonpaa@users.noreply.github.com> | 2021-09-25 15:02:21 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-25 13:02:21 +0100 |
commit | 6b3fcb0353533d1236035c4aa3b587be5d8b37cd (patch) | |
tree | 2d8161e7c49e1e5874d01d0bcd52db37b6ef5770 | |
parent | 51ef48a2d7c239af32c16d3d72ec5f00a6618d81 (diff) | |
download | amber-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.md | 5 | ||||
-rw-r--r-- | src/amberscript/parser.cc | 16 | ||||
-rw-r--r-- | src/amberscript/parser.h | 1 | ||||
-rw-r--r-- | src/amberscript/parser_pipeline_test.cc | 82 | ||||
-rw-r--r-- | src/pipeline_data.h | 7 | ||||
-rw-r--r-- | src/vulkan/engine_vulkan.cc | 3 | ||||
-rw-r--r-- | tests/cases/tessellation_isolines.amber | 130 | ||||
-rwxr-xr-x | tests/run_tests.py | 2 |
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 = [ |