Change render passes from multi to single pass.

This as an API change to get closer to the direction in which WebGPU is
headed. The API change in next.json caused a ton of files to be changed
in the same commit to keep things compiling.

API: the Framebuffer and RenderPass objects are now merged in a single
RenderPassInfo that contains the attachments, loadOps and clear values
for a BeginRenderPass command. The concept of subpass is removed.
The RenderPass creation argument to RenderPipelines is replaced by
explicitly setting the format of attachments for RenderPipeline.

Validation: SetPipeline checks are changed to check that the attachments
info set on a RenderPipeline matches the attachments of the render pass.

Backends: Most changes are simplifications of the backends that no
longer require and indirection to query the current subpass out of the
render pass in BeginSubpass, and don't need to get the attachment info
from a RenderPass when creating RenderPipelines. In the Vulkan backend,
a VkRenderPass cache is added to reuse VkRenderPasses between
RenderPassInfos and RenderPipelines.

Tests and examples: they are updated with the simplified API. Tests
specific to the Framebuffer and RenderPass objects were removed and
validation tests for RenderPassInfo were added.

Tested by running CppHelloTriangle on all backends, end2end tests on all
platforms and all examples on the GL backend.
This commit is contained in:
Corentin Wallez
2018-05-02 18:10:13 -04:00
committed by Corentin Wallez
parent 87ec361cc2
commit 6f7749cce9
92 changed files with 1869 additions and 3168 deletions

View File

@@ -48,13 +48,12 @@ list(APPEND UNITTEST_SOURCES
${VALIDATION_TESTS_DIR}/CopyCommandsValidationTests.cpp
${VALIDATION_TESTS_DIR}/DepthStencilStateValidationTests.cpp
${VALIDATION_TESTS_DIR}/DynamicStateCommandValidationTests.cpp
${VALIDATION_TESTS_DIR}/FramebufferValidationTests.cpp
${VALIDATION_TESTS_DIR}/InputStateValidationTests.cpp
${VALIDATION_TESTS_DIR}/PushConstantsValidationTests.cpp
${VALIDATION_TESTS_DIR}/VertexBufferValidationTests.cpp
${VALIDATION_TESTS_DIR}/RenderPassValidationTests.cpp
${VALIDATION_TESTS_DIR}/RenderPassInfoValidationTests.cpp
${VALIDATION_TESTS_DIR}/RenderPipelineValidationTests.cpp
${VALIDATION_TESTS_DIR}/UsageValidationTests.cpp
${VALIDATION_TESTS_DIR}/VertexBufferValidationTests.cpp
${VALIDATION_TESTS_DIR}/ValidationTest.cpp
${VALIDATION_TESTS_DIR}/ValidationTest.h
${TESTS_DIR}/UnittestsMain.cpp

View File

@@ -45,7 +45,7 @@ class BlendStateTest : public NXTTest {
.SetBindGroupLayout(0, bindGroupLayout)
.GetResult();
fb = utils::CreateBasicFramebuffer(device, kRTSize, kRTSize);
renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
}
struct TriangleSpec {
@@ -69,14 +69,14 @@ class BlendStateTest : public NXTTest {
)");
basePipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(fb.renderPass, 0)
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.GetResult();
testPipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(fb.renderPass, 0)
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -112,29 +112,27 @@ class BlendStateTest : public NXTTest {
// Test that after drawing a triangle with the base color, and then the given triangle spec, the color is as expected
void DoSingleSourceTest(RGBA8 base, const TriangleSpec& triangle, const RGBA8& expected) {
fb.color.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
renderPass.color.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
// First use the base pipeline to draw a triangle with no blending
.SetRenderPipeline(basePipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { base } })))
.DrawArrays(3, 1, 0, 0)
.BeginRenderPass(renderPass.renderPassInfo)
// First use the base pipeline to draw a triangle with no blending
.SetRenderPipeline(basePipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { base } })))
.DrawArrays(3, 1, 0, 0)
// Then use the test pipeline to draw the test triangle with blending
.SetRenderPipeline(testPipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { triangle.color } })))
.SetBlendColor(triangle.blendFactor[0], triangle.blendFactor[1], triangle.blendFactor[2], triangle.blendFactor[3])
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
// Then use the test pipeline to draw the test triangle with blending
.SetRenderPipeline(testPipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { triangle.color } })))
.SetBlendColor(triangle.blendFactor[0], triangle.blendFactor[1], triangle.blendFactor[2], triangle.blendFactor[3])
.DrawArrays(3, 1, 0, 0)
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(expected, fb.color, kRTSize / 2, kRTSize / 2);
EXPECT_PIXEL_RGBA8_EQ(expected, renderPass.color, kRTSize / 2, kRTSize / 2);
}
// Given a vector of tests where each element is <testColor, expectedColor>, check that all expectations are true for the given blend operation
@@ -175,7 +173,7 @@ class BlendStateTest : public NXTTest {
CheckBlendFactor(base, nxt::BlendFactor::One, colorFactor, nxt::BlendFactor::One, alphaFactor, tests);
}
utils::BasicFramebuffer fb;
utils::BasicRenderPass renderPass;
nxt::RenderPipeline basePipeline;
nxt::RenderPipeline testPipeline;
nxt::ShaderModule vsModule;
@@ -679,27 +677,25 @@ TEST_P(BlendStateTest, ColorWriteMaskBlendingDisabled) {
RGBA8 base(32, 64, 128, 192);
RGBA8 expected(32, 0, 0, 0);
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(testPipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { base } })))
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(expected, fb.color, kRTSize / 2, kRTSize / 2);
EXPECT_PIXEL_RGBA8_EQ(expected, renderPass.color, kRTSize / 2, kRTSize / 2);
}
}
// Test that independent blend states on render targets works
TEST_P(BlendStateTest, IndependentBlendState) {
std::array<nxt::Texture, 5> renderTargets;
std::array<nxt::TextureView, 5> renderTargetViews;
std::array<nxt::Texture, 4> renderTargets;
std::array<nxt::TextureView, 4> renderTargetViews;
for (uint32_t i = 0; i < 5; ++i) {
for (uint32_t i = 0; i < 4; ++i) {
renderTargets[i] = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(kRTSize, kRTSize, 1)
@@ -711,30 +707,11 @@ TEST_P(BlendStateTest, IndependentBlendState) {
renderTargetViews[i] = renderTargets[i].CreateTextureViewBuilder().GetResult();
}
nxt::RenderPass renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(5)
.SetSubpassCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetFormat(1, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetFormat(2, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetFormat(3, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetFormat(4, nxt::TextureFormat::R8G8B8A8Unorm)
// Scatter these so we know indexing to the right shader location is working
.SubpassSetColorAttachment(0, 0, 2)
// We skip attachment index 1 to check the case where the blend states in the pipeline state are not tightly packed
.SubpassSetColorAttachment(0, 1, 4)
.SubpassSetColorAttachment(0, 2, 3)
.SubpassSetColorAttachment(0, 3, 0)
.GetResult();
nxt::Framebuffer framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetDimensions(kRTSize, kRTSize)
.SetAttachment(0, renderTargetViews[0])
.SetAttachment(1, renderTargetViews[1])
.SetAttachment(2, renderTargetViews[2])
.SetAttachment(3, renderTargetViews[3])
.SetAttachment(4, renderTargetViews[4])
nxt::RenderPassInfo renderpass = device.CreateRenderPassInfoBuilder()
.SetColorAttachment(0, renderTargetViews[0], nxt::LoadOp::Clear)
.SetColorAttachment(1, renderTargetViews[1], nxt::LoadOp::Clear)
.SetColorAttachment(2, renderTargetViews[2], nxt::LoadOp::Clear)
.SetColorAttachment(3, renderTargetViews[3], nxt::LoadOp::Clear)
.GetResult();
nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
@@ -778,14 +755,20 @@ TEST_P(BlendStateTest, IndependentBlendState) {
} };
basePipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(1, nxt::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(2, nxt::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(3, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.GetResult();
testPipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(1, nxt::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(2, nxt::TextureFormat::R8G8B8A8Unorm)
.SetColorAttachmentFormat(3, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -808,73 +791,40 @@ TEST_P(BlendStateTest, IndependentBlendState) {
RGBA8 expected2 = color2;
RGBA8 expected3 = min(color3, base);
renderTargets[2].TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
renderTargets[4].TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
renderTargets[3].TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
renderTargets[0].TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
renderTargets[1].TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
renderTargets[2].TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
renderTargets[3].TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.SetRenderPipeline(basePipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 4>({ { base, base, base, base } })))
.DrawArrays(3, 1, 0, 0)
.BeginRenderPass(renderpass)
.SetRenderPipeline(basePipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 4>({ { base, base, base, base } })))
.DrawArrays(3, 1, 0, 0)
.SetRenderPipeline(testPipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 4>({ { color0, color1, color2, color3 } })))
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.SetRenderPipeline(testPipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 4>({ { color0, color1, color2, color3 } })))
.DrawArrays(3, 1, 0, 0)
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(expected0, renderTargets[2], kRTSize / 2, kRTSize / 2) << "Attachment slot 0 using render target 2 should have been " << color0 << " + " << base << " = " << expected0;
EXPECT_PIXEL_RGBA8_EQ(expected1, renderTargets[4], kRTSize / 2, kRTSize / 2) << "Attachment slot 1 using render target 4 should have been " << color1 << " - " << base << " = " << expected1;
EXPECT_PIXEL_RGBA8_EQ(expected2, renderTargets[3], kRTSize / 2, kRTSize / 2) << "Attachment slot 2 using render target 3 should have been " << color2 << " = " << expected2 << "(no blending)";
EXPECT_PIXEL_RGBA8_EQ(expected3, renderTargets[0], kRTSize / 2, kRTSize / 2) << "Attachment slot 3 using render target 0 should have been min(" << color3 << ", " << base << ") = " << expected3;
EXPECT_PIXEL_RGBA8_EQ(expected0, renderTargets[0], kRTSize / 2, kRTSize / 2) << "Attachment slot 0 should have been " << color0 << " + " << base << " = " << expected0;
EXPECT_PIXEL_RGBA8_EQ(expected1, renderTargets[1], kRTSize / 2, kRTSize / 2) << "Attachment slot 1 should have been " << color1 << " - " << base << " = " << expected1;
EXPECT_PIXEL_RGBA8_EQ(expected2, renderTargets[2], kRTSize / 2, kRTSize / 2) << "Attachment slot 2 should have been " << color2 << " = " << expected2 << "(no blending)";
EXPECT_PIXEL_RGBA8_EQ(expected3, renderTargets[3], kRTSize / 2, kRTSize / 2) << "Attachment slot 3 should have been min(" << color3 << ", " << base << ") = " << expected3;
}
}
// Test that the default blend color is correctly set at the beginning of every subpass
TEST_P(BlendStateTest, DefaultBlendColor) {
if (IsVulkan()) {
std::cout << "Test skipped on Vulkan because it doesn't support multisubpass renderpasses"
<< std::endl;
return;
}
nxt::BlendState blendState = device.CreateBlendStateBuilder()
.SetBlendEnabled(true)
.SetColorBlend(nxt::BlendOperation::Add, nxt::BlendFactor::BlendColor, nxt::BlendFactor::One)
.SetAlphaBlend(nxt::BlendOperation::Add, nxt::BlendFactor::BlendColor, nxt::BlendFactor::One)
.GetResult();
nxt::RenderPass renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.SetSubpassCount(2)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SubpassSetColorAttachment(0, 0, 0)
.SubpassSetColorAttachment(1, 0, 0)
.GetResult();
nxt::Texture renderTarget = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(kRTSize, kRTSize, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
nxt::TextureView renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
nxt::Framebuffer framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetDimensions(kRTSize, kRTSize)
.SetAttachment(0, renderTargetView)
.GetResult();
nxt::ShaderModule fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
#version 450
layout(set = 0, binding = 0) uniform myBlock {
@@ -889,29 +839,14 @@ TEST_P(BlendStateTest, DefaultBlendColor) {
)");
basePipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.GetResult();
testPipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.SetColorAttachmentBlendState(0, blendState)
.GetResult();
nxt::RenderPipeline basePipeline2 = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 1)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.GetResult();
nxt::RenderPipeline testPipeline2 = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 1)
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -921,28 +856,25 @@ TEST_P(BlendStateTest, DefaultBlendColor) {
// Check that the initial blend color is (0,0,0,0)
{
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(basePipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(0, 0, 0, 0) } })))
.DrawArrays(3, 1, 0, 0)
.SetRenderPipeline(testPipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(255, 255, 255, 255) } })))
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderTarget, kRTSize / 2, kRTSize / 2);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, kRTSize / 2, kRTSize / 2);
}
// Check that setting the blend color works
{
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(basePipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(0, 0, 0, 0) } })))
.DrawArrays(3, 1, 0, 0)
@@ -950,20 +882,18 @@ TEST_P(BlendStateTest, DefaultBlendColor) {
.SetBlendColor(1, 1, 1, 1)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(255, 255, 255, 255) } })))
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(255, 255, 255, 255), renderTarget, kRTSize / 2, kRTSize / 2);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(255, 255, 255, 255), renderPass.color, kRTSize / 2, kRTSize / 2);
}
// Check that the blend color is not inherited
// Check that the blend color is not inherited between render passes
{
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(basePipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(0, 0, 0, 0) } })))
.DrawArrays(3, 1, 0, 0)
@@ -971,21 +901,20 @@ TEST_P(BlendStateTest, DefaultBlendColor) {
.SetBlendColor(1, 1, 1, 1)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(255, 255, 255, 255) } })))
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderSubpass()
.SetRenderPipeline(basePipeline2)
.EndRenderPass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(basePipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(0, 0, 0, 0) } })))
.DrawArrays(3, 1, 0, 0)
.SetRenderPipeline(testPipeline2)
.SetRenderPipeline(testPipeline)
.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(255, 255, 255, 255) } })))
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderTarget, kRTSize / 2, kRTSize / 2);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, kRTSize / 2, kRTSize / 2);
}
}

View File

@@ -24,17 +24,6 @@ class DepthStencilStateTest : public NXTTest {
void SetUp() override {
NXTTest::SetUp();
renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(2)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.AttachmentSetFormat(1, nxt::TextureFormat::D32FloatS8Uint)
.AttachmentSetDepthStencilLoadOps(1, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.SubpassSetDepthStencilAttachment(0, 1)
.GetResult();
renderTarget = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(kRTSize, kRTSize, 1)
@@ -57,11 +46,9 @@ class DepthStencilStateTest : public NXTTest {
depthTextureView = depthTexture.CreateTextureViewBuilder().GetResult();
framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetAttachment(0, renderTargetView)
.SetAttachment(1, depthTextureView)
.SetDimensions(kRTSize, kRTSize)
renderpass = device.CreateRenderPassInfoBuilder()
.SetColorAttachment(0, renderTargetView, nxt::LoadOp::Clear)
.SetDepthStencilAttachment(depthTextureView, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.GetResult();
vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
@@ -207,8 +194,7 @@ class DepthStencilStateTest : public NXTTest {
};
renderTarget.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
builder.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass();
builder.BeginRenderPass(renderpass);
for (size_t i = 0; i < testParams.size(); ++i) {
const TestSpec& test = testParams[i];
@@ -233,7 +219,8 @@ class DepthStencilStateTest : public NXTTest {
// Create a pipeline for the triangles with the test spec's depth stencil state
nxt::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetDepthStencilAttachmentFormat(nxt::TextureFormat::D32FloatS8Uint)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -247,7 +234,6 @@ class DepthStencilStateTest : public NXTTest {
}
nxt::CommandBuffer commands = builder
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
@@ -261,12 +247,11 @@ class DepthStencilStateTest : public NXTTest {
DoTest(testParams, expected, expected);
}
nxt::RenderPass renderpass;
nxt::RenderPassInfo renderpass;
nxt::Texture renderTarget;
nxt::Texture depthTexture;
nxt::TextureView renderTargetView;
nxt::TextureView depthTextureView;
nxt::Framebuffer framebuffer;
nxt::ShaderModule vsModule;
nxt::ShaderModule fsModule;
nxt::BindGroupLayout bindGroupLayout;

View File

@@ -23,30 +23,7 @@ class DrawElementsTest : public NXTTest {
void SetUp() override {
NXTTest::SetUp();
renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
renderTarget = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(kRTSize, kRTSize, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetAttachment(0, renderTargetView)
.SetDimensions(kRTSize, kRTSize)
.GetResult();
renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
nxt::InputState inputState = device.CreateInputStateBuilder()
.SetInput(0, 4 * sizeof(float), nxt::InputStepMode::Vertex)
@@ -70,7 +47,7 @@ class DrawElementsTest : public NXTTest {
);
pipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetPrimitiveTopology(nxt::PrimitiveTopology::TriangleStrip)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -89,10 +66,7 @@ class DrawElementsTest : public NXTTest {
});
}
nxt::RenderPass renderpass;
nxt::Texture renderTarget;
nxt::TextureView renderTargetView;
nxt::Framebuffer framebuffer;
utils::BasicRenderPass renderPass;
nxt::RenderPipeline pipeline;
nxt::Buffer vertexBuffer;
nxt::Buffer indexBuffer;
@@ -101,20 +75,18 @@ class DrawElementsTest : public NXTTest {
uint32_t firstInstance, RGBA8 bottomLeftExpected, RGBA8 topRightExpected) {
uint32_t zeroOffset = 0;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset)
.SetIndexBuffer(indexBuffer, 0)
.DrawElements(indexCount, instanceCount, firstIndex, firstInstance)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(bottomLeftExpected, renderTarget, 1, 3);
EXPECT_PIXEL_RGBA8_EQ(topRightExpected, renderTarget, 3, 1);
EXPECT_PIXEL_RGBA8_EQ(bottomLeftExpected, renderPass.color, 1, 3);
EXPECT_PIXEL_RGBA8_EQ(topRightExpected, renderPass.color, 3, 1);
}
};

View File

@@ -24,36 +24,10 @@ class IndexFormatTest : public NXTTest {
void SetUp() override {
NXTTest::SetUp();
renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
renderTarget = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(kRTSize, kRTSize, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetAttachment(0, renderTargetView)
.SetDimensions(kRTSize, kRTSize)
.GetResult();
renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
}
nxt::RenderPass renderpass;
nxt::Texture renderTarget;
nxt::TextureView renderTargetView;
nxt::Framebuffer framebuffer;
utils::BasicRenderPass renderPass;
nxt::RenderPipeline MakeTestPipeline(nxt::IndexFormat format) {
nxt::InputState inputState = device.CreateInputStateBuilder()
@@ -78,7 +52,7 @@ class IndexFormatTest : public NXTTest {
);
return device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetPrimitiveTopology(nxt::PrimitiveTopology::TriangleStrip)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -105,19 +79,17 @@ TEST_P(IndexFormatTest, Uint32) {
uint32_t zeroOffset = 0;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset)
.SetIndexBuffer(indexBuffer, 0)
.DrawElements(3, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderTarget, 100, 300);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
}
// Test that the Uint16 index format is correctly interpreted
@@ -136,19 +108,17 @@ TEST_P(IndexFormatTest, Uint16) {
uint32_t zeroOffset = 0;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset)
.SetIndexBuffer(indexBuffer, 0)
.DrawElements(3, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderTarget, 100, 300);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
}
// Test for primitive restart use vertices like in the drawing and draw the following
@@ -180,21 +150,19 @@ TEST_P(IndexFormatTest, Uint32PrimitiveRestart) {
uint32_t zeroOffset = 0;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset)
.SetIndexBuffer(indexBuffer, 0)
.DrawElements(7, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderTarget, 190, 190); // A
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderTarget, 210, 210); // B
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderTarget, 210, 190); // C
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 190, 190); // A
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 210, 210); // B
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 210, 190); // C
}
// Test use of primitive restart with an Uint16 index format
@@ -214,21 +182,19 @@ TEST_P(IndexFormatTest, Uint16PrimitiveRestart) {
uint32_t zeroOffset = 0;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset)
.SetIndexBuffer(indexBuffer, 0)
.DrawElements(7, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderTarget, 190, 190); // A
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderTarget, 210, 210); // B
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderTarget, 210, 190); // C
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 190, 190); // A
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 210, 210); // B
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 210, 190); // C
}
// Test that the index format used is the format of the last set pipeline. This is to
@@ -256,20 +222,18 @@ TEST_P(IndexFormatTest, ChangePipelineAfterSetIndexBuffer) {
uint32_t zeroOffset = 0;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline16)
.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset)
.SetIndexBuffer(indexBuffer, 0)
.SetRenderPipeline(pipeline32)
.DrawElements(3, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderTarget, 100, 300);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
}
// Test that setting the index buffer before the pipeline works, this is important
@@ -291,19 +255,17 @@ TEST_P(IndexFormatTest, DISABLED_SetIndexBufferBeforeSetPipeline) {
uint32_t zeroOffset = 0;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetIndexBuffer(indexBuffer, 0)
.SetRenderPipeline(pipeline)
.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset)
.DrawElements(3, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderTarget, 100, 300);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
}
NXT_INSTANTIATE_TEST(IndexFormatTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend)

View File

@@ -37,7 +37,7 @@ class InputStateTest : public NXTTest {
void SetUp() override {
NXTTest::SetUp();
fb = utils::CreateBasicFramebuffer(device, kRTSize, kRTSize);
renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
}
bool ShouldComponentBeDefault(VertexFormat format, int component) {
@@ -121,7 +121,7 @@ class InputStateTest : public NXTTest {
);
return device.CreateRenderPipelineBuilder()
.SetSubpass(fb.renderPass, 0)
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.SetInputState(inputState)
@@ -168,9 +168,8 @@ class InputStateTest : public NXTTest {
nxt::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
fb.color.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
builder.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
renderPass.color.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
builder.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline);
uint32_t zeroOffset = 0;
@@ -180,7 +179,6 @@ class InputStateTest : public NXTTest {
nxt::CommandBuffer commands = builder
.DrawArrays(triangles * 3, instances, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
@@ -193,15 +191,15 @@ class InputStateTest : public NXTTest {
unsigned int x = kRTCellOffset + kRTCellSize * triangle;
unsigned int y = kRTCellOffset + kRTCellSize * instance;
if (triangle < triangles && instance < instances) {
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, x, y);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, x, y);
} else {
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, x, y);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, x, y);
}
}
}
}
utils::BasicFramebuffer fb;
utils::BasicRenderPass renderPass;
};
// Test compilation and usage of the fixture :)

View File

@@ -147,30 +147,7 @@ class PrimitiveTopologyTest : public NXTTest {
void SetUp() override {
NXTTest::SetUp();
renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
renderTarget = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(kRTSize, kRTSize, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetAttachment(0, renderTargetView)
.SetDimensions(kRTSize, kRTSize)
.GetResult();
renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
#version 450
@@ -209,22 +186,20 @@ class PrimitiveTopologyTest : public NXTTest {
// Draw the vertices with the given primitive topology and check the pixel values of the test locations
void DoTest(nxt::PrimitiveTopology primitiveTopology, const std::vector<LocationSpec> &locationSpecs) {
nxt::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.SetInputState(inputState)
.SetPrimitiveTopology(primitiveTopology)
.GetResult();
renderTarget.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
renderPass.color.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
static const uint32_t zeroOffset = 0;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset)
.DrawArrays(6, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
@@ -234,16 +209,13 @@ class PrimitiveTopologyTest : public NXTTest {
for (size_t i = 0; i < locationSpec.count; ++i) {
// If this pixel is included, check that it is green. Otherwise, check that it is black
RGBA8 color = locationSpec.include ? RGBA8(0, 255, 0, 255) : RGBA8(0, 0, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(color, renderTarget, locationSpec.locations[i].x, locationSpec.locations[i].y)
EXPECT_PIXEL_RGBA8_EQ(color, renderPass.color, locationSpec.locations[i].x, locationSpec.locations[i].y)
<< "Expected (" << locationSpec.locations[i].x << ", " << locationSpec.locations[i].y << ") to be " << color;
}
}
}
nxt::RenderPass renderpass;
nxt::Texture renderTarget;
nxt::TextureView renderTargetView;
nxt::Framebuffer framebuffer;
utils::BasicRenderPass renderPass;
nxt::ShaderModule vsModule;
nxt::ShaderModule fsModule;
nxt::InputState inputState;

View File

@@ -160,8 +160,7 @@ class PushConstantTest: public NXTTest {
// The render pipeline adds one to the red channel for successful vertex push constant test
// and adds one to green for the frgament test.
nxt::RenderPipeline MakeTestRenderPipeline(nxt::PipelineLayout& layout, nxt::RenderPass& renderPass, uint32_t subpass,
PushConstantSpec vsSpec, PushConstantSpec fsSpec) {
nxt::RenderPipeline MakeTestRenderPipeline(nxt::PipelineLayout& layout, PushConstantSpec vsSpec, PushConstantSpec fsSpec) {
nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, (R"(
#version 450
)" + MakePushConstantBlock(vsSpec) + R"(
@@ -192,7 +191,7 @@ class PushConstantTest: public NXTTest {
.GetResult();
return device.CreateRenderPipelineBuilder()
.SetSubpass(renderPass, subpass)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(layout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -233,63 +232,26 @@ TEST_P(PushConstantTest, ComputePassDefaultsToZero) {
EXPECT_BUFFER_U32_EQ(1, binding.resultBuffer, 0);
}
// Test that push constants default to zero at the beginning of every render subpasses.
TEST_P(PushConstantTest, RenderSubpassDefaultsToZero) {
// Change the renderpass to be a two subpass renderpass just for this test.
nxt::RenderPass renderPass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SetSubpassCount(2)
.SubpassSetColorAttachment(0, 0, 0)
.SubpassSetColorAttachment(1, 0, 0)
.GetResult();
nxt::Texture renderTarget = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(1, 1, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::TransferSrc)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
nxt::TextureView renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
nxt::Framebuffer framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderPass)
.SetAttachment(0, renderTargetView)
.SetDimensions(1, 1)
.GetResult();
// Test that push constants default to zero at the beginning of render passes.
TEST_P(PushConstantTest, RenderPassDefaultsToZero) {
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
// Expect push constants to be zero in all draws of this test.
PushConstantSpec allZeros = MakeAllZeroSpec();
nxt::PipelineLayout layout = MakeEmptyLayout();
nxt::RenderPipeline pipeline1 = MakeTestRenderPipeline(layout, renderPass, 0, MakeAllZeroSpec(), MakeAllZeroSpec());
nxt::RenderPipeline pipeline2 = MakeTestRenderPipeline(layout, renderPass, 1, MakeAllZeroSpec(), MakeAllZeroSpec());
nxt::RenderPipeline pipeline = MakeTestRenderPipeline(layout, MakeAllZeroSpec(), MakeAllZeroSpec());
uint32_t notZero = 42;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderPass, framebuffer)
.BeginRenderSubpass()
// Test render push constants are set to zero by default.
.SetRenderPipeline(pipeline1)
.DrawArrays(1, 1, 0, 0)
// Set push constants to non-zero value to check they will be reset to zero
// on the next subpass. This tests both fragment and vertex as they write to different
// color channels on error.
.SetPushConstants(nxt::ShaderStageBit::Fragment | nxt::ShaderStageBit::Vertex, 0, 1, &notZero)
.EndRenderSubpass()
.BeginRenderSubpass()
.SetRenderPipeline(pipeline2)
.DrawArrays(1, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
// Test render push constants are set to zero by default.
.SetRenderPipeline(pipeline)
.DrawArrays(1, 1, 0, 0)
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(2, 2, 0, 0), renderTarget, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), renderPass.color, 0, 0);
}
// Test setting push constants of various 32bit types.
@@ -389,51 +351,47 @@ TEST_P(PushConstantTest, SeparateVertexAndFragmentConstants) {
PushConstantSpec vsSpec = {{Int, 1}};
PushConstantSpec fsSpec = {{Int, 2}};
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 1, 1);
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
nxt::PipelineLayout layout = MakeEmptyLayout();
nxt::RenderPipeline pipeline = MakeTestRenderPipeline(layout, fb.renderPass, 0, vsSpec, fsSpec);
nxt::RenderPipeline pipeline = MakeTestRenderPipeline(layout, vsSpec, fsSpec);
uint32_t one = 1;
uint32_t two = 2;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.SetPushConstants(nxt::ShaderStageBit::Vertex, 0, 1, &one)
.SetPushConstants(nxt::ShaderStageBit::Fragment, 0, 1, &two)
.SetRenderPipeline(pipeline)
.DrawArrays(1, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetPushConstants(nxt::ShaderStageBit::Vertex, 0, 1, &one)
.SetPushConstants(nxt::ShaderStageBit::Fragment, 0, 1, &two)
.SetRenderPipeline(pipeline)
.DrawArrays(1, 1, 0, 0)
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), fb.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), renderPass.color, 0, 0);
}
// Try setting push constants for vertex and fragment stage simulteanously
TEST_P(PushConstantTest, SimultaneousVertexAndFragmentConstants) {
PushConstantSpec spec = {{Int, 2}};
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 1, 1);
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
nxt::PipelineLayout layout = MakeEmptyLayout();
nxt::RenderPipeline pipeline = MakeTestRenderPipeline(layout, fb.renderPass, 0, spec, spec);
nxt::RenderPipeline pipeline = MakeTestRenderPipeline(layout, spec, spec);
uint32_t two = 2;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.SetPushConstants(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment, 0, 1, &two)
.SetRenderPipeline(pipeline)
.DrawArrays(1, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetPushConstants(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment, 0, 1, &two)
.SetRenderPipeline(pipeline)
.DrawArrays(1, 1, 0, 0)
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), fb.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), renderPass.color, 0, 0);
}
NXT_INSTANTIATE_TEST(PushConstantTest, MetalBackend, OpenGLBackend)

View File

@@ -32,9 +32,9 @@ class DrawQuad {
.GetResult();
}
void Draw(const nxt::RenderPass& renderpass, nxt::CommandBufferBuilder* builder) {
void Draw(nxt::CommandBufferBuilder* builder) {
auto renderPipeline = device->CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -108,127 +108,63 @@ class RenderPassLoadOpTests : public NXTTest {
// Tests clearing, loading, and drawing into color attachments
TEST_P(RenderPassLoadOpTests, ColorClearThenLoadAndDraw) {
if (IsOpenGL()) {
// TODO(kainino@chromium.org): currently fails on OpenGL backend
return;
}
// Part 1: clear once, check to make sure it's cleared
auto renderpass1 = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.SetSubpassCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
auto framebuffer1 = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass1)
.SetDimensions(kRTSize, kRTSize)
.SetAttachment(0, renderTargetView)
auto renderPassClearZero = device.CreateRenderPassInfoBuilder()
.SetColorAttachment(0, renderTargetView, nxt::LoadOp::Clear)
.SetColorAttachmentClearColor(0, 0.0f, 0.0f, 0.0f, 0.0f)
.GetResult();
auto commands1 = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass1, framebuffer1)
.BeginRenderSubpass()
auto commandsClearZero = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderPassClearZero)
// Clear should occur implicitly
// Store should occur implicitly
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
framebuffer1.AttachmentSetClearColor(0, 0.0f, 0.0f, 0.0f, 0.0f); // zero
queue.Submit(1, &commands1);
// Cleared to zero
auto renderPassClearGreen = device.CreateRenderPassInfoBuilder()
.SetColorAttachment(0, renderTargetView, nxt::LoadOp::Clear)
.SetColorAttachmentClearColor(0, 0.0f, 1.0f, 0.0f, 1.0f)
.GetResult();
auto commandsClearGreen = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderPassClearGreen)
// Clear should occur implicitly
// Store should occur implicitly
.EndRenderPass()
.GetResult();
queue.Submit(1, &commandsClearZero);
EXPECT_TEXTURE_RGBA8_EQ(expectZero.data(), renderTarget, 0, 0, kRTSize, kRTSize, 0);
framebuffer1.AttachmentSetClearColor(0, 0.0f, 1.0f, 0.0f, 1.0f); // green
queue.Submit(1, &commands1);
// Now cleared to green
queue.Submit(1, &commandsClearGreen);
EXPECT_TEXTURE_RGBA8_EQ(expectGreen.data(), renderTarget, 0, 0, kRTSize, kRTSize, 0);
// Part 2: draw a blue quad into the right half of the render target, and check result
auto renderpass2 = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.SetSubpassCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Load)
.SubpassSetColorAttachment(0, 0, 0)
auto renderPassLoad = device.CreateRenderPassInfoBuilder()
.SetColorAttachment(0, renderTargetView, nxt::LoadOp::Load)
.GetResult();
auto framebuffer2 = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass2)
.SetDimensions(kRTSize, kRTSize)
.SetAttachment(0, renderTargetView)
.GetResult();
framebuffer2.AttachmentSetClearColor(0, 1.0f, 0.0f, 0.0f, 1.0f); // red
nxt::CommandBuffer commands2;
nxt::CommandBuffer commandsLoad;
{
auto builder = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass2, framebuffer2)
.BeginRenderSubpass()
// Clear should occur implicitly
.BeginRenderPass(renderPassLoad)
// Load should occur implicitly
.Clone();
blueQuad.Draw(renderpass2, &builder);
commands2 = builder
blueQuad.Draw(&builder);
commandsLoad = builder
// Store should occur implicitly
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
}
queue.Submit(1, &commands2);
queue.Submit(1, &commandsLoad);
// Left half should still be green
EXPECT_TEXTURE_RGBA8_EQ(expectGreen.data(), renderTarget, 0, 0, kRTSize / 2, kRTSize, 0);
// Right half should now be blue
EXPECT_TEXTURE_RGBA8_EQ(expectBlue.data(), renderTarget, kRTSize / 2, 0, kRTSize / 2, kRTSize, 0);
}
// Tests that an attachment is cleared only on the first subpass that uses it in a renderpass
TEST_P(RenderPassLoadOpTests, ClearsOnlyOnFirstUsePerRenderPass) {
if (IsOpenGL()) {
// TODO(kainino@chromium.org): currently fails on OpenGL backend
return;
}
auto renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.SetSubpassCount(2)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SubpassSetColorAttachment(0, 0, 0)
.SubpassSetColorAttachment(1, 0, 0)
.GetResult();
auto framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetDimensions(kRTSize, kRTSize)
.SetAttachment(0, renderTargetView)
.GetResult();
nxt::CommandBuffer commands;
auto builder = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
// Clear should occur implicitly
.Clone();
blueQuad.Draw(renderpass, &builder);
commands = builder
// Store should occur implicitly
.EndRenderSubpass()
.BeginRenderSubpass()
// Load (not clear!) should occur implicitly
// Store should occur implicitly
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
framebuffer.AttachmentSetClearColor(0, 0.0f, 1.0f, 0.0f, 1.0f); // green
queue.Submit(1, &commands);
// Left half should still be green from the first clear
EXPECT_TEXTURE_RGBA8_EQ(expectGreen.data(), renderTarget, 0, 0, kRTSize / 2, kRTSize, 0);
// Right half should be blue, not cleared by the second subpass
EXPECT_TEXTURE_RGBA8_EQ(expectBlue.data(), renderTarget, kRTSize / 2, 0, kRTSize / 2, kRTSize, 0);
}
NXT_INSTANTIATE_TEST(RenderPassLoadOpTests, D3D12Backend, MetalBackend, OpenGLBackend)

View File

@@ -40,8 +40,8 @@ class SamplerTest : public NXTTest {
protected:
void SetUp() override {
NXTTest::SetUp();
mFB = utils::CreateBasicFramebuffer(device, kRTSize, kRTSize);
mFB.color.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
mRenderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
mRenderPass.color.TransitionUsage(nxt::TextureUsageBit::OutputAttachment);
mBindGroupLayout = device.CreateBindGroupLayoutBuilder()
.SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::Sampler, 0, 1)
@@ -76,7 +76,7 @@ protected:
)");
mPipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(mFB.renderPass, 0)
.SetColorAttachmentFormat(0, mRenderPass.colorFormat)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -123,12 +123,10 @@ protected:
.GetResult();
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(mFB.renderPass, mFB.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(mRenderPass.renderPassInfo)
.SetRenderPipeline(mPipeline)
.SetBindGroup(0, bindGroup)
.DrawArrays(6, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
@@ -140,18 +138,18 @@ protected:
RGBA8 expectedV3(v.mExpected3, v.mExpected3, v.mExpected3, 255);
RGBA8 black(0, 0, 0, 255);
RGBA8 white(255, 255, 255, 255);
EXPECT_PIXEL_RGBA8_EQ(black, mFB.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(white, mFB.color, 0, 1);
EXPECT_PIXEL_RGBA8_EQ(white, mFB.color, 1, 0);
EXPECT_PIXEL_RGBA8_EQ(black, mFB.color, 1, 1);
EXPECT_PIXEL_RGBA8_EQ(expectedU2, mFB.color, 2, 0);
EXPECT_PIXEL_RGBA8_EQ(expectedU3, mFB.color, 3, 0);
EXPECT_PIXEL_RGBA8_EQ(expectedV2, mFB.color, 0, 2);
EXPECT_PIXEL_RGBA8_EQ(expectedV3, mFB.color, 0, 3);
EXPECT_PIXEL_RGBA8_EQ(black, mRenderPass.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(white, mRenderPass.color, 0, 1);
EXPECT_PIXEL_RGBA8_EQ(white, mRenderPass.color, 1, 0);
EXPECT_PIXEL_RGBA8_EQ(black, mRenderPass.color, 1, 1);
EXPECT_PIXEL_RGBA8_EQ(expectedU2, mRenderPass.color, 2, 0);
EXPECT_PIXEL_RGBA8_EQ(expectedU3, mRenderPass.color, 3, 0);
EXPECT_PIXEL_RGBA8_EQ(expectedV2, mRenderPass.color, 0, 2);
EXPECT_PIXEL_RGBA8_EQ(expectedV3, mRenderPass.color, 0, 3);
// TODO: add tests for W address mode, once NXT supports 3D textures
}
utils::BasicFramebuffer mFB;
utils::BasicRenderPass mRenderPass;
nxt::BindGroupLayout mBindGroupLayout;
nxt::RenderPipeline mPipeline;
nxt::TextureView mTextureView;

View File

@@ -18,7 +18,7 @@
class ScissorTest: public NXTTest {
protected:
nxt::RenderPipeline CreateQuadPipeline(const nxt::RenderPass& renderPass) {
nxt::RenderPipeline CreateQuadPipeline(nxt::TextureFormat format) {
nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
#version 450
const vec2 pos[6] = vec2[6](
@@ -37,7 +37,7 @@ class ScissorTest: public NXTTest {
})");
nxt::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(renderPass, 0)
.SetColorAttachmentFormat(0, format)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.GetResult();
@@ -48,47 +48,43 @@ class ScissorTest: public NXTTest {
// Test that by default the scissor test is disabled and the whole attachment can be drawn to.
TEST_P(ScissorTest, DefaultsToWholeRenderTarget) {
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 100, 100);
nxt::RenderPipeline pipeline = CreateQuadPipeline(fb.renderPass);
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 100, 100);
nxt::RenderPipeline pipeline = CreateQuadPipeline(renderPass.colorFormat);
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.DrawArrays(6, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 0, 99);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 99, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 99, 99);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 99);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 99, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 99, 99);
}
// Test setting the scissor to something larger than the attachments.
TEST_P(ScissorTest, LargerThanAttachment) {
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 100, 100);
nxt::RenderPipeline pipeline = CreateQuadPipeline(fb.renderPass);
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 100, 100);
nxt::RenderPipeline pipeline = CreateQuadPipeline(renderPass.colorFormat);
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.SetScissorRect(0, 0, 200, 200)
.DrawArrays(6, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 0, 99);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 99, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 99, 99);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 99);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 99, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 99, 99);
}
// Test setting an empty scissor rect
@@ -98,86 +94,76 @@ TEST_P(ScissorTest, EmptyRect) {
return;
}
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 2, 2);
nxt::RenderPipeline pipeline = CreateQuadPipeline(fb.renderPass);
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 2, 2);
nxt::RenderPipeline pipeline = CreateQuadPipeline(renderPass.colorFormat);
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.SetScissorRect(0, 0, 0, 0)
.DrawArrays(6, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, 0, 1);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, 1, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, 1, 1);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 0, 1);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 1, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 1, 1);
}
// Test setting a partial scissor (not empty, not full attachment)
TEST_P(ScissorTest, PartialRect) {
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 100, 100);
nxt::RenderPipeline pipeline = CreateQuadPipeline(fb.renderPass);
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 100, 100);
nxt::RenderPipeline pipeline = CreateQuadPipeline(renderPass.colorFormat);
constexpr uint32_t kX = 3;
constexpr uint32_t kY = 7;
constexpr uint32_t kW = 5;
constexpr uint32_t kH = 13;
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.SetScissorRect(kX, kY, kW, kH)
.DrawArrays(6, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
// Test the two opposite corners of the scissor box. With one pixel inside and on outside
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, kX - 1, kY - 1);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, kX, kY);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, kX - 1, kY - 1);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, kX, kY);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, kX + kW, kY + kH);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, kX + kW - 1, kY + kH - 1);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, kX + kW, kY + kH);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, kX + kW - 1, kY + kH - 1);
}
// Test that the scissor setting doesn't get inherited between renderpasses
// TODO(cwallez@chromium.org): do the same between subpasses?
TEST_P(ScissorTest, NoInheritanceBetweenRenderPass) {
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 100, 100);
nxt::RenderPipeline pipeline = CreateQuadPipeline(fb.renderPass);
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 100, 100);
nxt::RenderPipeline pipeline = CreateQuadPipeline(renderPass.colorFormat);
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
// RenderPass 1 set the scissor
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetScissorRect(0, 0, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
// RenderPass 2 draw a full quad, it shouldn't be scissored
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.DrawArrays(6, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 0, 99);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 99, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 99, 99);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 99);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 99, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 99, 99);
}
NXT_INSTANTIATE_TEST(ScissorTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend)

View File

@@ -20,7 +20,7 @@ class ViewportOrientationTests : public NXTTest {};
// Test that the pixel in viewport coordinate (-1, -1) matches texel (0, 0)
TEST_P(ViewportOrientationTests, OriginAt0x0) {
utils::BasicFramebuffer fb = utils::CreateBasicFramebuffer(device, 2, 2);
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 2, 2);
nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
#version 450
@@ -36,27 +36,25 @@ TEST_P(ViewportOrientationTests, OriginAt0x0) {
})");
nxt::RenderPipeline pipeline = device.CreateRenderPipelineBuilder()
.SetSubpass(fb.renderPass, 0)
.SetColorAttachmentFormat(0, renderPass.colorFormat)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(nxt::PrimitiveTopology::PointList)
.GetResult();
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.BeginRenderPass(fb.renderPass, fb.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPassInfo)
.SetRenderPipeline(pipeline)
.DrawArrays(1, 1, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), fb.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, 0, 1);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, 1, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), fb.color, 1, 1);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 0, 1);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 1, 0);
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 1, 1);
}
NXT_INSTANTIATE_TEST(ViewportOrientationTests, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend)

View File

@@ -23,43 +23,15 @@ TEST_F(CommandBufferValidationTest, Empty) {
.GetResult();
}
// Tests for null arguments to the command buffer builder
TEST_F(CommandBufferValidationTest, NullArguments) {
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(0)
.GetResult();
auto framebuffer = AssertWillBeSuccess(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetDimensions(100, 100)
.GetResult();
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpass, nullptr)
.EndRenderPass()
.GetResult();
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(nullptr, framebuffer)
.EndRenderPass()
.GetResult();
}
// Tests for basic render pass usage
TEST_F(CommandBufferValidationTest, RenderPass) {
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetAttachmentCount(0)
.SetSubpassCount(1)
.GetResult();
auto framebuffer = AssertWillBeSuccess(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetDimensions(100, 100)
.GetResult();
auto renderpass = CreateSimpleRenderPass();
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderPass(renderpass)
.EndRenderPass()
.GetResult();
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderPass(renderpass)
.GetResult();
}

View File

@@ -17,23 +17,13 @@
class SetScissorRectTest : public ValidationTest {
};
// Test to check that SetScissor can only be used inside render subpasses
TEST_F(SetScissorRectTest, AllowedOnlyInRenderSubpass) {
// Test to check that SetScissor can only be used inside render passes
TEST_F(SetScissorRectTest, AllowedOnlyInRenderPass) {
DummyRenderPass renderPass = CreateDummyRenderPass();
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPass)
.SetScissorRect(0, 0, 1, 1)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.SetScissorRect(0, 0, 1, 1)
.BeginRenderSubpass()
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
@@ -53,10 +43,8 @@ TEST_F(SetScissorRectTest, EmptyScissor) {
DummyRenderPass renderPass = CreateDummyRenderPass();
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPass)
.SetScissorRect(0, 0, 0, 0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
}
@@ -68,10 +56,8 @@ TEST_F(SetScissorRectTest, ScissorLargerThanFramebuffer) {
DummyRenderPass renderPass = CreateDummyRenderPass();
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPass)
.SetScissorRect(0, 0, renderPass.width + 1, renderPass.height + 1)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
}
@@ -79,23 +65,13 @@ TEST_F(SetScissorRectTest, ScissorLargerThanFramebuffer) {
class SetBlendColorTest : public ValidationTest {
};
// Test to check that SetBlendColor can only be used inside render subpasses
TEST_F(SetBlendColorTest, AllowedOnlyInRenderSubpass) {
// Test to check that SetBlendColor can only be used inside render passes
TEST_F(SetBlendColorTest, AllowedOnlyInRenderPass) {
DummyRenderPass renderPass = CreateDummyRenderPass();
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPass)
.SetBlendColor(0.0f, 0.0f, 0.0f, 0.0f)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.SetBlendColor(0.0f, 0.0f, 0.0f, 0.0f)
.BeginRenderSubpass()
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
@@ -115,10 +91,8 @@ TEST_F(SetBlendColorTest, AnyValueAllowed) {
DummyRenderPass renderPass = CreateDummyRenderPass();
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPass)
.SetBlendColor(-1.0f, 42.0f, -0.0f, 0.0f)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
}
@@ -126,23 +100,13 @@ TEST_F(SetBlendColorTest, AnyValueAllowed) {
class SetStencilReferenceTest : public ValidationTest {
};
// Test to check that SetStencilReference can only be used inside render subpasses
TEST_F(SetStencilReferenceTest, AllowedOnlyInRenderSubpass) {
// Test to check that SetStencilReference can only be used inside render passes
TEST_F(SetStencilReferenceTest, AllowedOnlyInRenderPass) {
DummyRenderPass renderPass = CreateDummyRenderPass();
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPass)
.SetStencilReference(0)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.SetStencilReference(0)
.BeginRenderSubpass()
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
@@ -162,10 +126,8 @@ TEST_F(SetStencilReferenceTest, AllBitsAllowed) {
DummyRenderPass renderPass = CreateDummyRenderPass();
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderPass.renderPass, renderPass.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderPass.renderPass)
.SetStencilReference(0xFFFFFFFF)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
}

View File

@@ -1,227 +0,0 @@
// 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 FramebufferValidationTest : public ValidationTest {
protected:
nxt::TextureView Create2DAttachment(uint32_t width, uint32_t height, nxt::TextureFormat format) {
nxt::Texture attachment = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(width, height, 1)
.SetFormat(format)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
return attachment.CreateTextureViewBuilder()
.GetResult();
}
nxt::Framebuffer CreateFramebufferWithAttachment(uint32_t width, uint32_t height, nxt::TextureFormat format) {
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetAttachmentCount(1)
.AttachmentSetFormat(0, format)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
nxt::TextureView attachment = Create2DAttachment(width, height, format);
return AssertWillBeSuccess(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetAttachment(0, attachment)
.SetDimensions(100, 100)
.GetResult();
}
};
// Test for an empty framebuffer builder
TEST_F(FramebufferValidationTest, Empty) {
auto framebuffer = AssertWillBeError(device.CreateFramebufferBuilder())
.GetResult();
}
// Tests for null arguments to a framebuffer builder
TEST_F(FramebufferValidationTest, NullArguments) {
AssertWillBeError(device.CreateFramebufferBuilder())
.SetRenderPass(nullptr)
.GetResult();
}
// Tests for passing error-valued arguments to a framebuffer builder
TEST_F(FramebufferValidationTest, ErrorValues) {
auto renderpass = AssertWillBeError(device.CreateRenderPassBuilder())
.GetResult();
AssertWillBeError(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.GetResult();
}
// Tests for basic framebuffer construction
TEST_F(FramebufferValidationTest, Basic) {
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(0)
.GetResult();
auto framebuffer = AssertWillBeSuccess(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetDimensions(100, 100)
.GetResult();
}
// Tests for framebuffer construction with an (empty) attachment
TEST_F(FramebufferValidationTest, BasicWithEmptyAttachment) {
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
AssertWillBeError(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetDimensions(100, 100)
.GetResult();
}
// Test for a basic framebuffer with one attachment
TEST_F(FramebufferValidationTest, BasicWithOneAttachment) {
CreateFramebufferWithAttachment(100, 100, nxt::TextureFormat::R8G8B8A8Unorm);
}
// Tests for setting clear values
TEST_F(FramebufferValidationTest, ClearValues) {
auto framebuffer = CreateFramebufferWithAttachment(100, 100, nxt::TextureFormat::R8G8B8A8Unorm);
// Set clear color value for attachment 0
framebuffer.AttachmentSetClearColor(0, 0.0f, 0.0f, 0.0f, 0.0f);
// Set clear depth/stencil values for attachment 0 - ok, but ignored, since it's a color attachment
framebuffer.AttachmentSetClearDepthStencil(0, 0.0f, 0);
// Set clear color value for attachment 1 - should fail
ASSERT_DEVICE_ERROR(framebuffer.AttachmentSetClearColor(1, 0.0f, 0.0f, 0.0f, 0.0f));
}
// Check validation that the attachment size must be the same as the framebuffer size.
// TODO(cwallez@chromium.org): Investigate this constraint more, for example Vulkan requires
// that the attachment sizes are *at least* the framebuffer size.
TEST_F(FramebufferValidationTest, AttachmentSizeMatchFramebufferSize) {
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
nxt::TextureView attachment = Create2DAttachment(100, 100, nxt::TextureFormat::R8G8B8A8Unorm);
// Control case: two attachments of the same size
{
auto framebuffer = AssertWillBeSuccess(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetAttachment(0, attachment)
.SetDimensions(100, 100)
.GetResult();
}
// Error: case, size mismatch (framebuffer bigger than attachments)
{
auto framebuffer = AssertWillBeError(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetAttachment(0, attachment)
.SetDimensions(200, 200)
.GetResult();
}
// Error: case, size mismatch (framebuffer smaller than attachments)
{
auto framebuffer = AssertWillBeError(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetAttachment(0, attachment)
.SetDimensions(50, 50)
.GetResult();
}
// TODO(cwallez@chromium.org): also test with a mismatches depth / stencil
}
TEST_F(FramebufferValidationTest, AttachmentFormatMatchTextureFormat) {
// Control case: attach color attachment to color slot
{
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
nxt::TextureView attachment = Create2DAttachment(100, 100, nxt::TextureFormat::R8G8B8A8Unorm);
auto framebuffer = AssertWillBeSuccess(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetAttachment(0, attachment)
.SetDimensions(100, 100)
.GetResult();
}
// Error: attach color attachment to depth slot, setting the attachment format first
{
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetAttachmentCount(1)
.SetSubpassCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::D32FloatS8Uint)
.SubpassSetDepthStencilAttachment(0, 0)
.GetResult();
nxt::TextureView attachment = Create2DAttachment(100, 100, nxt::TextureFormat::R8G8B8A8Unorm);
auto framebuffer = AssertWillBeError(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetAttachment(0, attachment)
.SetDimensions(100, 100)
.GetResult();
}
// Error: attach color attachment to depth slot, but setting the attachment format last
{
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.SubpassSetDepthStencilAttachment(0, 0)
.AttachmentSetFormat(0, nxt::TextureFormat::D32FloatS8Uint)
.GetResult();
nxt::TextureView attachment = Create2DAttachment(100, 100, nxt::TextureFormat::R8G8B8A8Unorm);
auto framebuffer = AssertWillBeError(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetAttachment(0, attachment)
.SetDimensions(100, 100)
.GetResult();
}
// Error: attach depth texture to color slot
{
auto renderpass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
nxt::TextureView attachment = Create2DAttachment(100, 100, nxt::TextureFormat::D32FloatS8Uint);
auto framebuffer = AssertWillBeError(device.CreateFramebufferBuilder())
.SetRenderPass(renderpass)
.SetAttachment(0, attachment)
.SetDimensions(100, 100)
.GetResult();
}
// TODO(kainino@chromium.org): also check attachment samples, etc.
}

View File

@@ -46,7 +46,7 @@ class InputStateTest : public ValidationTest {
builder = AssertWillBeError(device.CreateRenderPipelineBuilder());
}
return builder.SetSubpass(renderpassData.renderPass, 0)
return builder.SetColorAttachmentFormat(0, renderpassData.attachmentFormat)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.SetInputState(inputState)

View File

@@ -54,11 +54,9 @@ TEST_F(PushConstantTest, Success) {
.SetPushConstants(nxt::ShaderStageBit::Compute, 0, 1, constants)
.EndComputePass()
// PushConstants in a render subpass
.BeginRenderPass(renderpassData.renderPass, renderpassData.framebuffer)
.BeginRenderSubpass()
// PushConstants in a render pass
.BeginRenderPass(renderpassData.renderPass)
.SetPushConstants(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment, 0, 1, constants)
.EndRenderSubpass()
.EndRenderPass()
// Setting all constants
@@ -120,36 +118,9 @@ TEST_F(PushConstantTest, NotInPass) {
.SetPushConstants(nxt::ShaderStageBit::Vertex, 0, 1, constants)
.GetResult();
}
// Setting in renderpass but outside subpass is invalid
{
// Control to check the error is caused by the SetPushConstants
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpassData.renderPass, renderpassData.framebuffer)
.BeginRenderSubpass()
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpassData.renderPass, renderpassData.framebuffer)
.SetPushConstants(nxt::ShaderStageBit::Vertex, 0, 1, constants)
.BeginRenderSubpass()
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpassData.renderPass, renderpassData.framebuffer)
.BeginRenderSubpass()
.EndRenderSubpass()
.SetPushConstants(nxt::ShaderStageBit::Vertex, 0, 1, constants)
.EndRenderPass()
.GetResult();
}
}
// Test valid stages for subpass
// Test valid stages for compute pass
TEST_F(PushConstantTest, StageForComputePass) {
// Control case: setting to the compute stage in compute passes
{
@@ -179,17 +150,15 @@ TEST_F(PushConstantTest, StageForComputePass) {
}
}
// Test valid stages for compute passes
TEST_F(PushConstantTest, StageForSubpass) {
// Test valid stages for render passes
TEST_F(PushConstantTest, StageForRenderPass) {
DummyRenderPass renderpassData = CreateDummyRenderPass();
// Control case: setting to vertex and fragment in subpass
// Control case: setting to vertex and fragment in render pass
{
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpassData.renderPass, renderpassData.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderpassData.renderPass)
.SetPushConstants(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment, 0, 1, constants)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
}
@@ -197,10 +166,8 @@ TEST_F(PushConstantTest, StageForSubpass) {
// Compute stage is disallowed
{
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpassData.renderPass, renderpassData.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderpassData.renderPass)
.SetPushConstants(nxt::ShaderStageBit::Compute, 0, 1, constants)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
}
@@ -208,10 +175,8 @@ TEST_F(PushConstantTest, StageForSubpass) {
// A None shader stage mask is valid.
{
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpassData.renderPass, renderpassData.framebuffer)
.BeginRenderSubpass()
.BeginRenderPass(renderpassData.renderPass)
.SetPushConstants(nxt::ShaderStageBit::None, 0, 1, constants)
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
}

View File

@@ -0,0 +1,181 @@
// Copyright 2018 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"
#include "common/Constants.h"
namespace {
class RenderPassInfoValidationTest : public ValidationTest {
};
nxt::TextureView Create2DAttachment(nxt::Device& device, uint32_t width, uint32_t height, nxt::TextureFormat format) {
nxt::Texture attachment = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(width, height, 1)
.SetFormat(format)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment)
.SetInitialUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
return attachment.CreateTextureViewBuilder()
.GetResult();
}
// A render pass with no attachments isn't valid
TEST_F(RenderPassInfoValidationTest, Empty) {
AssertWillBeError(device.CreateRenderPassInfoBuilder())
.GetResult();
}
// A render pass with only one color or one depth attachment is ok
TEST_F(RenderPassInfoValidationTest, OneAttachment) {
// One color attachment
{
nxt::TextureView color = Create2DAttachment(device, 1, 1, nxt::TextureFormat::R8G8B8A8Unorm);
AssertWillBeSuccess(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, color, nxt::LoadOp::Clear)
.GetResult();
}
// One depth-stencil attachment
{
nxt::TextureView depthStencil = Create2DAttachment(device, 1, 1, nxt::TextureFormat::D32FloatS8Uint);
AssertWillBeSuccess(device.CreateRenderPassInfoBuilder())
.SetDepthStencilAttachment(depthStencil, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.GetResult();
}
}
// Test OOB color attachment indices are handled
TEST_F(RenderPassInfoValidationTest, ColorAttachmentOutOfBounds) {
// For setting the color attachment, control case
{
nxt::TextureView color = Create2DAttachment(device, 1, 1, nxt::TextureFormat::R8G8B8A8Unorm);
AssertWillBeSuccess(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(kMaxColorAttachments - 1, color, nxt::LoadOp::Clear)
.GetResult();
}
// For setting the color attachment, OOB
{
nxt::TextureView color = Create2DAttachment(device, 1, 1, nxt::TextureFormat::R8G8B8A8Unorm);
AssertWillBeError(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(kMaxColorAttachments, color, nxt::LoadOp::Clear)
.GetResult();
}
nxt::TextureView color = Create2DAttachment(device, 1, 1, nxt::TextureFormat::R8G8B8A8Unorm);
// For setting the clear color, control case
{
AssertWillBeSuccess(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, color, nxt::LoadOp::Clear)
.SetColorAttachmentClearColor(kMaxColorAttachments - 1, 0.0f, 0.0f, 0.0f, 0.0f)
.GetResult();
}
// For setting the clear color, OOB
{
AssertWillBeError(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, color, nxt::LoadOp::Clear)
.SetColorAttachmentClearColor(kMaxColorAttachments, 0.0f, 0.0f, 0.0f, 0.0f)
.GetResult();
}
}
// Test setting a clear value without an attachment and vice-versa is ok.
TEST_F(RenderPassInfoValidationTest, ClearAndAttachmentMismatchIsOk) {
nxt::TextureView color = Create2DAttachment(device, 1, 1, nxt::TextureFormat::R8G8B8A8Unorm);
// For cleared attachment 0 doesn't get a color, clear color for 1 is unused
{
AssertWillBeSuccess(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, color, nxt::LoadOp::Clear)
.SetColorAttachmentClearColor(1, 0.0f, 0.0f, 0.0f, 0.0f)
.GetResult();
}
// Clear depth stencil doesn't get values
{
nxt::TextureView depthStencil = Create2DAttachment(device, 1, 1, nxt::TextureFormat::D32FloatS8Uint);
AssertWillBeSuccess(device.CreateRenderPassInfoBuilder())
.SetDepthStencilAttachment(depthStencil, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.GetResult();
}
// Clear values for depth-stencil when it isn't used
{
AssertWillBeSuccess(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, color, nxt::LoadOp::Clear)
.SetDepthStencilAttachmentClearValue(0.0f, 0)
.GetResult();
}
}
// Attachments must have the same size
TEST_F(RenderPassInfoValidationTest, SizeMustMatch) {
nxt::TextureView color1x1A = Create2DAttachment(device, 1, 1, nxt::TextureFormat::R8G8B8A8Unorm);
nxt::TextureView color1x1B = Create2DAttachment(device, 1, 1, nxt::TextureFormat::R8G8B8A8Unorm);
nxt::TextureView color2x2 = Create2DAttachment(device, 2, 2, nxt::TextureFormat::R8G8B8A8Unorm);
nxt::TextureView depthStencil1x1 = Create2DAttachment(device, 1, 1, nxt::TextureFormat::D32FloatS8Uint);
nxt::TextureView depthStencil2x2 = Create2DAttachment(device, 2, 2, nxt::TextureFormat::D32FloatS8Uint);
// Control case: all the same size (1x1)
{
AssertWillBeSuccess(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, color1x1A, nxt::LoadOp::Clear)
.SetColorAttachment(1, color1x1B, nxt::LoadOp::Clear)
.SetDepthStencilAttachment(depthStencil1x1, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.GetResult();
}
// One of the color attachments has a different size
{
AssertWillBeError(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, color1x1A, nxt::LoadOp::Clear)
.SetColorAttachment(1, color2x2, nxt::LoadOp::Clear)
.SetDepthStencilAttachment(depthStencil1x1, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.GetResult();
}
// The depth stencil attachment has a different size
{
AssertWillBeError(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, color1x1A, nxt::LoadOp::Clear)
.SetColorAttachment(1, color1x1B, nxt::LoadOp::Clear)
.SetDepthStencilAttachment(depthStencil2x2, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.GetResult();
}
}
// Attachments formats must match whether they are used for color or depth-stencil
TEST_F(RenderPassInfoValidationTest, FormatMismatch) {
nxt::TextureView color = Create2DAttachment(device, 1, 1, nxt::TextureFormat::R8G8B8A8Unorm);
nxt::TextureView depthStencil = Create2DAttachment(device, 1, 1, nxt::TextureFormat::D32FloatS8Uint);
// Using depth-stencil for color
{
AssertWillBeError(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, depthStencil, nxt::LoadOp::Clear)
.GetResult();
}
// Using color for depth-stencil
{
AssertWillBeError(device.CreateRenderPassInfoBuilder())
.SetDepthStencilAttachment(color, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.GetResult();
}
}
// TODO(cwallez@chromium.org): Constraints on attachment aliasing?
} // anonymous namespace

View File

@@ -1,159 +0,0 @@
// 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 RenderPassValidationTest : public ValidationTest {
};
// Test for an empty render pass builder
TEST_F(RenderPassValidationTest, Empty) {
AssertWillBeError(device.CreateRenderPassBuilder())
.GetResult();
}
// Test for a render pass with one subpass and no attachments
TEST_F(RenderPassValidationTest, OneSubpass) {
AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(0)
.GetResult();
}
// Test for a render pass with one subpass and one attachment
TEST_F(RenderPassValidationTest, OneSubpassOneAttachment) {
AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
// without a load op
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
}
// Tests for setting attachment load ops
TEST_F(RenderPassValidationTest, AttachmentLoadOps) {
AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
// with a load op
.AttachmentSetColorLoadOp(0, nxt::LoadOp::Clear)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
// with a load op of the wrong type - this is okay, just ignored
.AttachmentSetDepthStencilLoadOps(0, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
}
// Test for attachment slot arguments out of bounds
TEST_F(RenderPassValidationTest, AttachmentOutOfBounds) {
// Control case
AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.GetResult();
AssertWillBeError(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
// Test AttachmentSetFormat slot out of bounds
.AttachmentSetFormat(1, nxt::TextureFormat::R8G8B8A8Unorm)
.GetResult();
AssertWillBeError(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
// Test AttachmentSetColorLoadOp slot out of bounds
.AttachmentSetColorLoadOp(1, nxt::LoadOp::Clear)
.GetResult();
AssertWillBeError(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
// Test AttachmentSetDepthStencilLoadOps slot out of bounds
.AttachmentSetDepthStencilLoadOps(1, nxt::LoadOp::Clear, nxt::LoadOp::Clear)
.GetResult();
AssertWillBeError(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
// Test SubpassSetColorAttachment attachment slot out of bounds
.SubpassSetColorAttachment(0, 0, 1)
.GetResult();
AssertWillBeError(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
// Test SubpassSetDepthStencilAttachment attachment slot out of bounds
.SubpassSetDepthStencilAttachment(0, 1)
.GetResult();
}
// Test for subpass arguments out of bounds
TEST_F(RenderPassValidationTest, SubpassOutOfBounds) {
// Control case
AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
AssertWillBeError(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SubpassSetColorAttachment(0, 0, 0)
// Test SubpassSetColorAttachment subpass out of bounds
.SubpassSetColorAttachment(1, 0, 0)
.GetResult();
AssertWillBeError(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::D32FloatS8Uint)
// Test SubpassSetDepthStencilAttachment subpass out of bounds
.SubpassSetDepthStencilAttachment(1, 0)
.GetResult();
}
// Test attaching depth/stencil textures to color attachments and vice versa
TEST_F(RenderPassValidationTest, SubpassAttachmentWrongAspect) {
AssertWillBeError(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SubpassSetDepthStencilAttachment(0, 0)
.GetResult();
AssertWillBeError(device.CreateRenderPassBuilder())
.SetSubpassCount(1)
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::D32FloatS8Uint)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
}

View File

@@ -14,6 +14,7 @@
#include "tests/unittests/validation/ValidationTest.h"
#include "common/Constants.h"
#include "utils/NXTHelpers.h"
class RenderPipelineValidationTest : public ValidationTest {
@@ -21,7 +22,7 @@ class RenderPipelineValidationTest : public ValidationTest {
void SetUp() override {
ValidationTest::SetUp();
CreateSimpleRenderPassAndFramebuffer(device, &renderpass, &framebuffer);
renderpass = CreateSimpleRenderPass();
pipelineLayout = device.CreatePipelineLayoutBuilder().GetResult();
@@ -45,7 +46,7 @@ class RenderPipelineValidationTest : public ValidationTest {
}
nxt::RenderPipelineBuilder& AddDefaultStates(nxt::RenderPipelineBuilder&& builder) {
builder.SetSubpass(renderpass, 0)
builder.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -53,8 +54,7 @@ class RenderPipelineValidationTest : public ValidationTest {
return builder;
}
nxt::RenderPass renderpass;
nxt::Framebuffer framebuffer;
nxt::RenderPassInfo renderpass;
nxt::ShaderModule vsModule;
nxt::ShaderModule fsModule;
nxt::InputState inputState;
@@ -81,7 +81,7 @@ TEST_F(RenderPipelineValidationTest, CreationMissingProperty) {
// Vertex stage not set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(nxt::PrimitiveTopology::TriangleList)
@@ -91,14 +91,14 @@ TEST_F(RenderPipelineValidationTest, CreationMissingProperty) {
// Fragment stage not set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetPrimitiveTopology(nxt::PrimitiveTopology::TriangleList)
.GetResult();
}
// Subpass not set
// No attachment set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetLayout(pipelineLayout)
@@ -112,47 +112,9 @@ 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
// This one succeeds because attachment 0 is the color attachment
AssertWillBeSuccess(device.CreateRenderPipelineBuilder())
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -160,9 +122,9 @@ TEST_F(RenderPipelineValidationTest, BlendState) {
.SetColorAttachmentBlendState(0, blendState)
.GetResult();
// This fails because attachment 1 is not one of the subpass's color attachments
// This fails because attachment 1 is not one of the color attachments
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -174,7 +136,7 @@ TEST_F(RenderPipelineValidationTest, BlendState) {
// Fails because color attachment is out of bounds
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))
.SetColorAttachmentBlendState(1, blendState)
.SetColorAttachmentBlendState(kMaxColorAttachments, blendState)
.GetResult();
}
@@ -192,7 +154,7 @@ TEST_F(RenderPipelineValidationTest, DISABLED_TodoCreationMissingProperty) {
// Fails because pipeline layout is not set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.SetPrimitiveTopology(nxt::PrimitiveTopology::TriangleList)
@@ -202,7 +164,7 @@ TEST_F(RenderPipelineValidationTest, DISABLED_TodoCreationMissingProperty) {
// Fails because primitive topology is not set
{
AssertWillBeError(device.CreateRenderPipelineBuilder())
.SetSubpass(renderpass, 0)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
@@ -240,13 +202,6 @@ TEST_F(RenderPipelineValidationTest, DISABLED_CreationDuplicates) {
.GetResult();
}
// Fails because subpass is set twice
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))
.SetSubpass(renderpass, 0)
.GetResult();
}
// Fails because the layout is set twice
{
AddDefaultStates(AssertWillBeError(device.CreateRenderPipelineBuilder()))

View File

@@ -69,7 +69,7 @@ bool ValidationTest::EndExpectDeviceError() {
return mError;
}
void ValidationTest::CreateSimpleRenderPassAndFramebuffer(const nxt::Device& device, nxt::RenderPass* renderpass, nxt::Framebuffer* framebuffer) {
nxt::RenderPassInfo ValidationTest::CreateSimpleRenderPass() {
auto colorBuffer = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(640, 480, 1)
@@ -81,17 +81,8 @@ void ValidationTest::CreateSimpleRenderPassAndFramebuffer(const nxt::Device& dev
auto colorView = colorBuffer.CreateTextureViewBuilder()
.GetResult();
*renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
*framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(*renderpass)
.SetDimensions(640, 480)
.SetAttachment(0, colorView)
return device.CreateRenderPassInfoBuilder()
.SetColorAttachment(0, colorView, nxt::LoadOp::Clear)
.GetResult();
}
@@ -128,13 +119,6 @@ ValidationTest::DummyRenderPass ValidationTest::CreateDummyRenderPass() {
dummy.height = 400;
dummy.attachmentFormat = nxt::TextureFormat::R8G8B8A8Unorm;
dummy.renderPass = AssertWillBeSuccess(device.CreateRenderPassBuilder())
.SetAttachmentCount(1)
.AttachmentSetFormat(0, dummy.attachmentFormat)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
dummy.attachment = AssertWillBeSuccess(device.CreateTextureBuilder())
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(dummy.width, dummy.height, 1)
@@ -146,10 +130,8 @@ ValidationTest::DummyRenderPass ValidationTest::CreateDummyRenderPass() {
nxt::TextureView view = AssertWillBeSuccess(dummy.attachment.CreateTextureViewBuilder()).GetResult();
dummy.framebuffer = AssertWillBeSuccess(device.CreateFramebufferBuilder())
.SetRenderPass(dummy.renderPass)
.SetAttachment(0, view)
.SetDimensions(dummy.width, dummy.height)
dummy.renderPass = AssertWillBeSuccess(device.CreateRenderPassInfoBuilder())
.SetColorAttachment(0, view, nxt::LoadOp::Clear)
.GetResult();
return dummy;

View File

@@ -48,13 +48,12 @@ class ValidationTest : public testing::Test {
void StartExpectDeviceError();
bool EndExpectDeviceError();
void CreateSimpleRenderPassAndFramebuffer(const nxt::Device& device, nxt::RenderPass* renderpass, nxt::Framebuffer* framebuffer);
nxt::RenderPassInfo CreateSimpleRenderPass();
// Helper functions to create objects to test validation.
struct DummyRenderPass {
nxt::RenderPass renderPass;
nxt::Framebuffer framebuffer;
nxt::RenderPassInfo renderPass;
nxt::Texture attachment;
nxt::TextureFormat attachmentFormat;
uint32_t width;

View File

@@ -23,6 +23,8 @@ class VertexBufferValidationTest : public ValidationTest {
void SetUp() override {
ValidationTest::SetUp();
renderpass = CreateSimpleRenderPass();
fsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Fragment, R"(
#version 450
layout(location = 0) out vec4 fragColor;
@@ -31,36 +33,6 @@ class VertexBufferValidationTest : public ValidationTest {
})");
}
void MakeRenderPassAndFrameBuffer(uint32_t subpassCount) {
auto colorBuffer = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(640, 480, 1)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
colorBuffer.FreezeUsage(nxt::TextureUsageBit::OutputAttachment);
auto colorView = colorBuffer.CreateTextureViewBuilder()
.GetResult();
auto renderpassBuilder = device.CreateRenderPassBuilder();
renderpassBuilder.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetSubpassCount(subpassCount);
for (uint32_t i = 0; i < subpassCount; ++i) {
renderpassBuilder.SubpassSetColorAttachment(i, 0, 0);
}
renderpass = renderpassBuilder.GetResult();
framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
.SetDimensions(640, 480)
.SetAttachment(0, colorView)
.GetResult();
}
template <unsigned int N>
std::array<nxt::Buffer, N> MakeVertexBuffers() {
std::array<nxt::Buffer, N> buffers;
@@ -105,102 +77,89 @@ class VertexBufferValidationTest : public ValidationTest {
return builder.GetResult();
}
nxt::RenderPipeline MakeRenderPipeline(uint32_t subpass, const nxt::ShaderModule& vsModule, const nxt::InputState& inputState) {
nxt::RenderPipeline MakeRenderPipeline(const nxt::ShaderModule& vsModule, const nxt::InputState& inputState) {
return device.CreateRenderPipelineBuilder()
.SetSubpass(renderpass, subpass)
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.SetInputState(inputState)
.GetResult();
}
nxt::RenderPass renderpass;
nxt::Framebuffer framebuffer;
nxt::RenderPassInfo renderpass;
nxt::ShaderModule fsModule;
};
TEST_F(VertexBufferValidationTest, VertexInputsInheritedBetweenPipelines) {
MakeRenderPassAndFrameBuffer(1);
auto vsModule2 = MakeVertexShader(2);
auto vsModule1 = MakeVertexShader(1);
auto inputState2 = MakeInputState(2);
auto inputState1 = MakeInputState(1);
auto pipeline2 = MakeRenderPipeline(0, vsModule2, inputState2);
auto pipeline1 = MakeRenderPipeline(0, vsModule1, inputState1);
auto pipeline2 = MakeRenderPipeline(vsModule2, inputState2);
auto pipeline1 = MakeRenderPipeline(vsModule1, inputState1);
auto vertexBuffers = MakeVertexBuffers<2>();
uint32_t offsets[] = { 0, 0 };
// Check failure when vertex buffer is not set
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.SetRenderPipeline(pipeline1)
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderPass(renderpass)
.SetRenderPipeline(pipeline1)
.DrawArrays(3, 1, 0, 0)
.EndRenderPass()
.GetResult();
// Check success when vertex buffer is inherited from previous pipeline
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.SetRenderPipeline(pipeline2)
.SetVertexBuffers(0, 2, vertexBuffers.data(), offsets)
.DrawArrays(3, 1, 0, 0)
.SetRenderPipeline(pipeline1)
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderPass(renderpass)
.SetRenderPipeline(pipeline2)
.SetVertexBuffers(0, 2, vertexBuffers.data(), offsets)
.DrawArrays(3, 1, 0, 0)
.SetRenderPipeline(pipeline1)
.DrawArrays(3, 1, 0, 0)
.EndRenderPass()
.GetResult();
}
TEST_F(VertexBufferValidationTest, VertexInputsNotInheritedBetweenSubpasses) {
MakeRenderPassAndFrameBuffer(2);
TEST_F(VertexBufferValidationTest, VertexInputsNotInheritedBetweenRendePasses) {
auto vsModule2 = MakeVertexShader(2);
auto vsModule1 = MakeVertexShader(1);
auto inputState2 = MakeInputState(2);
auto inputState1 = MakeInputState(1);
auto pipeline2 = MakeRenderPipeline(0, vsModule2, inputState2);
auto pipeline1 = MakeRenderPipeline(1, vsModule1, inputState1);
auto pipeline2 = MakeRenderPipeline(vsModule2, inputState2);
auto pipeline1 = MakeRenderPipeline(vsModule1, inputState1);
auto vertexBuffers = MakeVertexBuffers<2>();
uint32_t offsets[] = { 0, 0 };
// Check success when vertex buffer is set for each subpass
// Check success when vertex buffer is set for each render pass
AssertWillBeSuccess(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.SetRenderPipeline(pipeline2)
.SetVertexBuffers(0, 2, vertexBuffers.data(), offsets)
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderSubpass()
.SetRenderPipeline(pipeline1)
.SetVertexBuffers(0, 1, vertexBuffers.data(), offsets)
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderPass(renderpass)
.SetRenderPipeline(pipeline2)
.SetVertexBuffers(0, 2, vertexBuffers.data(), offsets)
.DrawArrays(3, 1, 0, 0)
.EndRenderPass()
.BeginRenderPass(renderpass)
.SetRenderPipeline(pipeline1)
.SetVertexBuffers(0, 1, vertexBuffers.data(), offsets)
.DrawArrays(3, 1, 0, 0)
.EndRenderPass()
.GetResult();
// Check failure because vertex buffer is not inherited in second subpass
AssertWillBeError(device.CreateCommandBufferBuilder())
.BeginRenderPass(renderpass, framebuffer)
.BeginRenderSubpass()
.SetRenderPipeline(pipeline2)
.SetVertexBuffers(0, 2, vertexBuffers.data(), offsets)
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderSubpass()
.SetRenderPipeline(pipeline1)
.DrawArrays(3, 1, 0, 0)
.EndRenderSubpass()
.BeginRenderPass(renderpass)
.SetRenderPipeline(pipeline2)
.SetVertexBuffers(0, 2, vertexBuffers.data(), offsets)
.DrawArrays(3, 1, 0, 0)
.EndRenderPass()
.BeginRenderPass(renderpass)
.SetRenderPipeline(pipeline1)
.DrawArrays(3, 1, 0, 0)
.EndRenderPass()
.GetResult();
}