Add the webgpu.h swapchain creation path

This commit changes wgpu::Device::CreateSwapChain to take an additional
wgpu::Surface argument. Passing nullptr is enough to stay on the
previous swapchain implementation, until the new one is ready.

In order to support both the "old" implementation-based swapchains and
the "new" surface-based swapchains. SwapChainBase is now split into
three abstract classes:

 - SwapChainBase that has a virtual method for each of the
wgpu::SwapChain methods.
 - OldSwapChainBase that corresponds to the implementation-based
swapchains.
 - NewSwapChainBase that will contain the surface-based swapchain
implementation and will eventually just be renamed to SwapChainBase.

The interaction of the surface-based swapchains with the Surface objects
aren't implemented yet, neither are the swapchain methods. Only creation
works.

Validation tests for surface-based swapchain creation are added in the
end2end test target because they need to create OS windows.

Bug: dawn:269

Change-Id: I7e07d6c666479867b9a16d7b1b8c181d5dbd69a0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15281
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Corentin Wallez
2020-01-23 17:20:38 +00:00
committed by Commit Bot service account
parent a5a6e4f5bb
commit d87e676845
31 changed files with 460 additions and 73 deletions

View File

@@ -188,7 +188,7 @@ TEST_P(DeviceLostTest, CreateSwapChainFails) {
wgpu::SwapChainDescriptor descriptor;
descriptor.nextInChain = nullptr;
ASSERT_DEVICE_ERROR(device.CreateSwapChain(&descriptor));
ASSERT_DEVICE_ERROR(device.CreateSwapChain(nullptr, &descriptor));
}
// Tests that CreateTexture fails when device is lost
@@ -212,4 +212,4 @@ TEST_P(DeviceLostTest, TickFails) {
ASSERT_DEVICE_ERROR(device.Tick());
}
DAWN_INSTANTIATE_TEST(DeviceLostTest, D3D12Backend, VulkanBackend);
DAWN_INSTANTIATE_TEST(DeviceLostTest, D3D12Backend, VulkanBackend);

View File

@@ -0,0 +1,146 @@
// Copyright 2020 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tests/unittests/validation/ValidationTest.h"
#include "common/Constants.h"
#include "common/Log.h"
#include "utils/GLFWUtils.h"
#include "utils/WGPUHelpers.h"
#include "GLFW/glfw3.h"
class SwapChainValidationTests : public ValidationTest {
public:
void SetUp() override {
glfwSetErrorCallback([](int code, const char* message) {
dawn::ErrorLog() << "GLFW error " << code << " " << message;
});
glfwInit();
// The SwapChainValidationTests tests don't create devices so we don't need to call
// SetupGLFWWindowHintsForBackend. Set GLFW_NO_API anyway to avoid GLFW bringing up a GL
// context that we won't use.
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
window = glfwCreateWindow(400, 400, "SwapChainValidationTests window", nullptr, nullptr);
surface = utils::CreateSurfaceForWindow(instance->Get(), window);
ASSERT_NE(surface, nullptr);
goodDescriptor.width = 1;
goodDescriptor.height = 1;
goodDescriptor.usage = wgpu::TextureUsage::OutputAttachment;
goodDescriptor.format = wgpu::TextureFormat::BGRA8Unorm;
goodDescriptor.presentMode = wgpu::PresentMode::VSync;
badDescriptor = goodDescriptor;
badDescriptor.width = 0;
}
void TearDown() override {
// Destroy the surface before the window as required by webgpu-native.
surface = wgpu::Surface();
glfwDestroyWindow(window);
}
protected:
GLFWwindow* window = nullptr;
wgpu::Surface surface;
wgpu::SwapChainDescriptor goodDescriptor;
wgpu::SwapChainDescriptor badDescriptor;
// Checks that an OutputAttachment view is an error by trying to create a render pass on it.
void CheckTextureViewIsError(wgpu::TextureView view) {
utils::ComboRenderPassDescriptor renderPassDesc({view});
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassDesc);
pass.EndPass();
ASSERT_DEVICE_ERROR(encoder.Finish());
}
};
// Control case for a successful swapchain creation.
TEST_F(SwapChainValidationTests, CreationSuccess) {
device.CreateSwapChain(surface, &goodDescriptor);
}
// Checks that the creation size must be a valid 2D texture size.
TEST_F(SwapChainValidationTests, InvalidCreationSize) {
// A width of 0 is invalid.
{
wgpu::SwapChainDescriptor desc = goodDescriptor;
desc.width = 0;
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
}
// A height of 0 is invalid.
{
wgpu::SwapChainDescriptor desc = goodDescriptor;
desc.height = 0;
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
}
// A width of kMaxTextureSize is valid but kMaxTextureSize + 1 isn't.
{
wgpu::SwapChainDescriptor desc = goodDescriptor;
desc.width = kMaxTextureSize;
device.CreateSwapChain(surface, &desc);
desc.width = kMaxTextureSize + 1;
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
}
// A height of kMaxTextureSize is valid but kMaxTextureSize + 1 isn't.
{
wgpu::SwapChainDescriptor desc = goodDescriptor;
desc.height = kMaxTextureSize;
device.CreateSwapChain(surface, &desc);
desc.height = kMaxTextureSize + 1;
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
}
}
// Checks that the creation usage must be OutputAttachment
TEST_F(SwapChainValidationTests, InvalidCreationUsage) {
wgpu::SwapChainDescriptor desc = goodDescriptor;
desc.usage = wgpu::TextureUsage::Sampled;
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
}
// Checks that the creation format must (currently) be BGRA8Unorm
TEST_F(SwapChainValidationTests, InvalidCreationFormat) {
wgpu::SwapChainDescriptor desc = goodDescriptor;
desc.format = wgpu::TextureFormat::RGBA8Unorm;
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
}
// Checks that the implementation must be zero.
TEST_F(SwapChainValidationTests, InvalidWithImplementation) {
wgpu::SwapChainDescriptor desc = goodDescriptor;
desc.implementation = 1;
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
}
// Check swapchain operations with an error swapchain are errors
TEST_F(SwapChainValidationTests, OperationsOnErrorSwapChain) {
wgpu::SwapChain swapchain;
ASSERT_DEVICE_ERROR(swapchain = device.CreateSwapChain(surface, &badDescriptor));
wgpu::TextureView view;
ASSERT_DEVICE_ERROR(view = swapchain.GetCurrentTextureView());
CheckTextureViewIsError(view);
ASSERT_DEVICE_ERROR(swapchain.Present());
}

View File

@@ -39,6 +39,8 @@
#include "GLFW/glfw3native.h"
// Test for wgpu::Surface creation that only need an instance (no devices) and don't need all the
// complexity of DawnTest.
class WindowSurfaceInstanceTests : public testing::Test {
public:
void SetUp() override {