| // Copyright 2017 The Dawn 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 implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "tests/unittests/validation/ValidationTest.h" |
| |
| #include "common/Constants.h" |
| #include "utils/DawnHelpers.h" |
| |
| class RenderPipelineValidationTest : public ValidationTest { |
| protected: |
| void SetUp() override { |
| ValidationTest::SetUp(); |
| |
| renderpass = CreateSimpleRenderPass(); |
| |
| dawn::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, nullptr); |
| |
| inputState = device.CreateInputStateBuilder().GetResult(); |
| |
| blendState = device.CreateBlendStateBuilder().GetResult(); |
| |
| vsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, R"( |
| #version 450 |
| void main() { |
| gl_Position = vec4(0.0, 0.0, 0.0, 1.0); |
| })" |
| ); |
| |
| fsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Fragment, R"( |
| #version 450 |
| layout(location = 0) out vec4 fragColor; |
| void main() { |
| fragColor = vec4(0.0, 1.0, 0.0, 1.0); |
| })"); |
| } |
| |
| dawn::RenderPipelineBuilder& AddDefaultStates(dawn::RenderPipelineBuilder&& builder) { |
| builder.SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm) |
| .SetLayout(pipelineLayout) |
| .SetStage(dawn::ShaderStage::Vertex, vsModule, "main") |
| .SetStage(dawn::ShaderStage::Fragment, fsModule, "main") |
| .SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList); |
| return builder; |
| } |
| |
| dawn::RenderPassDescriptor renderpass; |
| dawn::ShaderModule vsModule; |
| dawn::ShaderModule fsModule; |
| dawn::InputState inputState; |
| dawn::BlendState blendState; |
| dawn::PipelineLayout pipelineLayout; |
| }; |
| |
| // Test cases where creation should succeed |
| TEST_F(RenderPipelineValidationTest, CreationSuccess) { |
| AddDefaultStates(AssertWillBeSuccess(device.CreateRenderPipelineBuilder())) |
| .GetResult(); |
| |
| AddDefaultStates(AssertWillBeSuccess(device.CreateRenderPipelineBuilder())) |
| .SetInputState(inputState) |
| .GetResult(); |
| |
| AddDefaultStates(AssertWillBeSuccess(device.CreateRenderPipelineBuilder())) |
| .SetColorAttachmentBlendState(0, blendState) |
| .GetResult(); |
| } |
| |
| // Test creation failure when properties are missing |
| TEST_F(RenderPipelineValidationTest, CreationMissingProperty) { |
| // Vertex stage not set |
| { |
| AssertWillBeError(device.CreateRenderPipelineBuilder()) |
| .SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm) |
| .SetLayout(pipelineLayout) |
| .SetStage(dawn::ShaderStage::Fragment, fsModule, "main") |
| .SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList) |
| .GetResult(); |
| } |
| |
| // Fragment stage not set |
| { |
| AssertWillBeError(device.CreateRenderPipelineBuilder()) |
| .SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm) |
| .SetLayout(pipelineLayout) |
| .SetStage(dawn::ShaderStage::Vertex, vsModule, "main") |
| .SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList) |
| .GetResult(); |
| } |
| |
| // No attachment set |
| { |
| AssertWillBeError(device.CreateRenderPipelineBuilder()) |
| .SetLayout(pipelineLayout) |
| .SetStage(dawn::ShaderStage::Vertex, vsModule, "main") |
| .SetStage(dawn::ShaderStage::Fragment, fsModule, "main") |
| .SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList) |
| .GetResult(); |
| } |
| } |
| |
| TEST_F(RenderPipelineValidationTest, BlendState) { |
| // Fails because blend state is set on a nonexistent color attachment |
| { |
| // This one succeeds because attachment 0 is the color attachment |
| AssertWillBeSuccess(device.CreateRenderPipelineBuilder()) |
| .SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm) |
| .SetLayout(pipelineLayout) |
| .SetStage(dawn::ShaderStage::Vertex, vsModule, "main") |
| .SetStage(dawn::ShaderStage::Fragment, fsModule, "main") |
| .SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList) |
| .SetColorAttachmentBlendState(0, blendState) |
| .GetResult(); |
| |
| // This fails because attachment 1 is not one of the color attachments |
| AssertWillBeError(device.CreateRenderPipelineBuilder()) |
| .SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm) |
| .SetLayout(pipelineLayout) |
| .SetStage(dawn::ShaderStage::Vertex, vsModule, "main") |
| .SetStage(dawn::ShaderStage::Fragment, fsModule, "main") |
| .SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList) |
| .SetColorAttachmentBlendState(1, blendState) |
| .GetResult(); |
| } |
| |
| // Fails because color attachment is out of bounds |
| { |
| AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder())) |
| .SetColorAttachmentBlendState(kMaxColorAttachments, blendState) |
| .GetResult(); |
| } |
| |
| // Fails because color attachment blend state is set twice |
| { |
| AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder())) |
| .SetColorAttachmentBlendState(0, blendState) |
| .SetColorAttachmentBlendState(0, blendState) |
| .GetResult(); |
| } |
| } |
| |
| // TODO(enga@google.com): These should be added to the test above when validation is implemented |
| TEST_F(RenderPipelineValidationTest, DISABLED_TodoCreationMissingProperty) { |
| // Fails because pipeline layout is not set |
| { |
| AssertWillBeError(device.CreateRenderPipelineBuilder()) |
| .SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm) |
| .SetStage(dawn::ShaderStage::Vertex, vsModule, "main") |
| .SetStage(dawn::ShaderStage::Fragment, fsModule, "main") |
| .SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList) |
| .GetResult(); |
| } |
| |
| // Fails because primitive topology is not set |
| { |
| AssertWillBeError(device.CreateRenderPipelineBuilder()) |
| .SetColorAttachmentFormat(0, dawn::TextureFormat::R8G8B8A8Unorm) |
| .SetLayout(pipelineLayout) |
| .SetStage(dawn::ShaderStage::Vertex, vsModule, "main") |
| .SetStage(dawn::ShaderStage::Fragment, fsModule, "main") |
| .GetResult(); |
| } |
| } |
| |
| // Test creation failure when specifying properties multiple times |
| TEST_F(RenderPipelineValidationTest, DISABLED_CreationDuplicates) { |
| // Fails because input state is set twice |
| { |
| AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder())) |
| .SetInputState(inputState) |
| .GetResult(); |
| } |
| |
| // Fails because primitive topology is set twice |
| { |
| AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder())) |
| .SetPrimitiveTopology(dawn::PrimitiveTopology::TriangleList) |
| .GetResult(); |
| } |
| |
| // Fails because vertex stage is set twice |
| { |
| AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder())) |
| .SetStage(dawn::ShaderStage::Fragment, fsModule, "main") |
| .GetResult(); |
| } |
| |
| // Fails because fragment stage is set twice |
| { |
| AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder())) |
| .SetStage(dawn::ShaderStage::Vertex, vsModule, "main") |
| .GetResult(); |
| } |
| |
| // Fails because the layout is set twice |
| { |
| AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder())) |
| .SetLayout(pipelineLayout) |
| .GetResult(); |
| } |
| } |