dawn-cmake/src/tests/end2end/RenderPassLoadOpTests.cpp
Kai Ninomiya afa45a9176 Add tests for clears, render passes, framebuffers (#107)
* Add tests for clears, render passes, framebuffers

* Test load with a draw in it
2017-08-14 16:32:26 -07:00

189 lines
6.9 KiB
C++

// 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/NXTTest.h"
#include "utils/NXTHelpers.h"
#include <array>
constexpr static unsigned int kRTSize = 16;
class DrawQuad {
public:
DrawQuad() {}
DrawQuad(nxt::Device* device, const char* vsSource, const char* fsSource)
: device(device) {
vsModule = utils::CreateShaderModule(*device, nxt::ShaderStage::Vertex, vsSource);
fsModule = utils::CreateShaderModule(*device, nxt::ShaderStage::Fragment, fsSource);
pipelineLayout = device->CreatePipelineLayoutBuilder()
.GetResult();
}
void Draw(const nxt::RenderPass& renderpass, nxt::CommandBufferBuilder* builder) {
auto renderPipeline = device->CreateRenderPipelineBuilder()
.SetSubpass(renderpass, 0)
.SetLayout(pipelineLayout)
.SetStage(nxt::ShaderStage::Vertex, vsModule, "main")
.SetStage(nxt::ShaderStage::Fragment, fsModule, "main")
.GetResult();
builder->SetRenderPipeline(renderPipeline);
builder->DrawArrays(6, 1, 0, 0);
}
private:
nxt::Device* device = nullptr;
nxt::ShaderModule vsModule = {};
nxt::ShaderModule fsModule = {};
nxt::PipelineLayout pipelineLayout = {};
};
class RenderPassLoadOpTests : public NXTTest {
protected:
void SetUp() override {
NXTTest::SetUp();
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();
RGBA8 zero(0, 0, 0, 0);
std::fill(expectZero.begin(), expectZero.end(), zero);
RGBA8 green(0, 255, 0, 255);
std::fill(expectGreen.begin(), expectGreen.end(), green);
RGBA8 blue(0, 0, 255, 255);
std::fill(expectBlue.begin(), expectBlue.end(), blue);
// draws a blue quad on the right half of the screen
const char* vsSource = R"(
#version 450
void main() {
const vec2 pos[6] = vec2[6](
vec2(0, -1), vec2(1, -1), vec2(0, 1),
vec2(0, 1), vec2(1, -1), vec2(1, 1));
gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f);
}
)";
const char* fsSource = R"(
#version 450
out vec4 color;
void main() {
color = vec4(0.f, 0.f, 1.f, 1.f);
}
)";
blueQuad = DrawQuad(&device, vsSource, fsSource);
}
nxt::Texture renderTarget;
nxt::TextureView renderTargetView;
std::array<RGBA8, kRTSize * kRTSize> expectZero;
std::array<RGBA8, kRTSize * kRTSize> expectGreen;
std::array<RGBA8, kRTSize * kRTSize> expectBlue;
DrawQuad blueQuad = {};
};
// 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)
.GetResult();
auto commands1 = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass1, framebuffer1)
.BeginRenderSubpass()
// 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
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
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)
.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;
{
auto builder = device.CreateCommandBufferBuilder()
.BeginRenderPass(renderpass2, framebuffer2)
.BeginRenderSubpass()
// Clear should occur implicitly
.Clone();
blueQuad.Draw(renderpass2, &builder);
commands2 = builder
// Store should occur implicitly
.EndRenderSubpass()
.EndRenderPass()
.GetResult();
}
queue.Submit(1, &commands2);
// 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);
}
NXT_INSTANTIATE_TEST(RenderPassLoadOpTests, D3D12Backend, MetalBackend, OpenGLBackend)