From e69a2893b313ad73deb341b3b40e6b3af500f4a5 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Fri, 4 Aug 2017 11:38:47 -0400 Subject: [PATCH] Add BlendState validation tests --- src/tests/CMakeLists.txt | 1 + .../validation/BlendStateValidationTests.cpp | 73 ++++++++++++++ .../DepthStencilStateValidationTests.cpp | 2 - .../RenderPipelineValidationTests.cpp | 96 +++++++++++++++++++ 4 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 src/tests/unittests/validation/BlendStateValidationTests.cpp diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index b61a014215..02a469bf8c 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -40,6 +40,7 @@ list(APPEND UNITTEST_SOURCES ${UNITTESTS_DIR}/SerialQueueTests.cpp ${UNITTESTS_DIR}/ToBackendTests.cpp ${UNITTESTS_DIR}/WireTests.cpp + ${VALIDATION_TESTS_DIR}/BlendStateValidationTests.cpp ${VALIDATION_TESTS_DIR}/BufferValidationTests.cpp ${VALIDATION_TESTS_DIR}/CommandBufferValidationTests.cpp ${VALIDATION_TESTS_DIR}/ComputeValidationTests.cpp diff --git a/src/tests/unittests/validation/BlendStateValidationTests.cpp b/src/tests/unittests/validation/BlendStateValidationTests.cpp new file mode 100644 index 0000000000..17bcfe8e97 --- /dev/null +++ b/src/tests/unittests/validation/BlendStateValidationTests.cpp @@ -0,0 +1,73 @@ +// Copyright 2017 The NXT 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" + +class BlendStateValidationTest : public ValidationTest { +}; + +// Test cases where creation should succeed +TEST_F(BlendStateValidationTest, CreationSuccess) { + // Success for setting all properties + { + nxt::BlendState state = AssertWillBeSuccess(device.CreateBlendStateBuilder()) + .SetBlendEnabled(true) + .SetAlphaBlend(nxt::BlendOperation::Add, nxt::BlendFactor::One, nxt::BlendFactor::One) + .SetColorBlend(nxt::BlendOperation::Add, nxt::BlendFactor::One, nxt::BlendFactor::One) + .SetColorWriteMask(nxt::ColorWriteMask::Red) + .GetResult(); + } + + // Success for empty builder + { + nxt::BlendState state = AssertWillBeSuccess(device.CreateBlendStateBuilder()) + .GetResult(); + } +} + +// Test creation failure when specifying properties multiple times +TEST_F(BlendStateValidationTest, CreationDuplicates) { + // Test failure when specifying blend enabled multiple times + { + nxt::BlendState state = AssertWillBeError(device.CreateBlendStateBuilder()) + .SetBlendEnabled(true) + .SetBlendEnabled(false) + .GetResult(); + } + + // Test failure when specifying alpha blend multiple times + { + nxt::BlendState state = AssertWillBeError(device.CreateBlendStateBuilder()) + .SetAlphaBlend(nxt::BlendOperation::Add, nxt::BlendFactor::One, nxt::BlendFactor::One) + .SetAlphaBlend(nxt::BlendOperation::Add, nxt::BlendFactor::Zero, nxt::BlendFactor::Zero) + .GetResult(); + } + + // Test failure when specifying color blend multiple times + { + nxt::BlendState state = AssertWillBeError(device.CreateBlendStateBuilder()) + .SetColorBlend(nxt::BlendOperation::Add, nxt::BlendFactor::One, nxt::BlendFactor::One) + .SetColorBlend(nxt::BlendOperation::Add, nxt::BlendFactor::Zero, nxt::BlendFactor::Zero) + .GetResult(); + } + + // Test failure when specifying color write mask multiple times + { + nxt::BlendState state = AssertWillBeError(device.CreateBlendStateBuilder()) + .SetColorWriteMask(nxt::ColorWriteMask::Red) + .SetColorWriteMask(nxt::ColorWriteMask::Green) + .GetResult(); + } + +} diff --git a/src/tests/unittests/validation/DepthStencilStateValidationTests.cpp b/src/tests/unittests/validation/DepthStencilStateValidationTests.cpp index a96189029f..45e6cb4fe4 100644 --- a/src/tests/unittests/validation/DepthStencilStateValidationTests.cpp +++ b/src/tests/unittests/validation/DepthStencilStateValidationTests.cpp @@ -93,5 +93,3 @@ TEST_F(DepthStencilStateValidationTest, CreationDuplicates) { .GetResult(); } } - -// TODO(enga@google.com) Test failure when set in a compute pipeline diff --git a/src/tests/unittests/validation/RenderPipelineValidationTests.cpp b/src/tests/unittests/validation/RenderPipelineValidationTests.cpp index 994215325e..39cfdee3f3 100644 --- a/src/tests/unittests/validation/RenderPipelineValidationTests.cpp +++ b/src/tests/unittests/validation/RenderPipelineValidationTests.cpp @@ -27,6 +27,8 @@ class RenderPipelineValidationTest : public ValidationTest { inputState = device.CreateInputStateBuilder().GetResult(); + blendState = device.CreateBlendStateBuilder().GetResult(); + vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"( #version 450 void main() { @@ -57,6 +59,7 @@ class RenderPipelineValidationTest : public ValidationTest { nxt::ShaderModule vsModule; nxt::ShaderModule fsModule; nxt::InputState inputState; + nxt::BlendState blendState; nxt::PipelineLayout pipelineLayout; }; @@ -64,6 +67,14 @@ class RenderPipelineValidationTest : public ValidationTest { 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 @@ -99,6 +110,84 @@ TEST_F(RenderPipelineValidationTest, CreationMissingProperty) { } } +TEST_F(RenderPipelineValidationTest, BlendState) { + // Fails because blend state is set on a nonexistent color attachment + { + auto texture1 = device.CreateTextureBuilder() + .SetDimension(nxt::TextureDimension::e2D) + .SetExtent(640, 480, 1) + .SetFormat(nxt::TextureFormat::R8G8B8A8Unorm) + .SetMipLevels(1) + .SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment) + .GetResult(); + texture1.FreezeUsage(nxt::TextureUsageBit::OutputAttachment); + auto textureView1 = texture1.CreateTextureViewBuilder() + .GetResult(); + + auto texture2 = device.CreateTextureBuilder() + .SetDimension(nxt::TextureDimension::e2D) + .SetExtent(640, 480, 1) + .SetFormat(nxt::TextureFormat::R8G8B8A8Unorm) + .SetMipLevels(1) + .SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment) + .GetResult(); + texture2.FreezeUsage(nxt::TextureUsageBit::OutputAttachment); + auto textureView2 = texture2.CreateTextureViewBuilder() + .GetResult(); + + auto renderpass = device.CreateRenderPassBuilder() + .SetAttachmentCount(2) + .AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm) + .AttachmentSetFormat(1, nxt::TextureFormat::R8G8B8A8Unorm) + .SetSubpassCount(1) + .SubpassSetColorAttachment(0, 0, 0) + .GetResult(); + + auto framebuffer = device.CreateFramebufferBuilder() + .SetRenderPass(renderpass) + .SetDimensions(640, 480) + .SetAttachment(0, textureView1) + .SetAttachment(1, textureView2) + .GetResult(); + + + // This one succeeds because attachment 0 is the subpass's color attachment + AssertWillBeSuccess(device.CreateRenderPipelineBuilder()) + .SetSubpass(renderpass, 0) + .SetLayout(pipelineLayout) + .SetStage(nxt::ShaderStage::Vertex, vsModule, "main") + .SetStage(nxt::ShaderStage::Fragment, fsModule, "main") + .SetPrimitiveTopology(nxt::PrimitiveTopology::TriangleList) + .SetColorAttachmentBlendState(0, blendState) + .GetResult(); + + // This fails because attachment 1 is not one of the subpass's color attachments + AssertWillBeError(device.CreateRenderPipelineBuilder()) + .SetSubpass(renderpass, 0) + .SetLayout(pipelineLayout) + .SetStage(nxt::ShaderStage::Vertex, vsModule, "main") + .SetStage(nxt::ShaderStage::Fragment, fsModule, "main") + .SetPrimitiveTopology(nxt::PrimitiveTopology::TriangleList) + .SetColorAttachmentBlendState(1, blendState) + .GetResult(); + } + + // Fails because color attachment is out of bounds + { + AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder())) + .SetColorAttachmentBlendState(1, 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 @@ -158,4 +247,11 @@ TEST_F(RenderPipelineValidationTest, DISABLED_CreationDuplicates) { .SetSubpass(renderpass, 0) .GetResult(); } + + // Fails because the layout is set twice + { + AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder())) + .SetLayout(pipelineLayout) + .GetResult(); + } }