mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-20 10:25:28 +00:00
Implement the webgpu.h swapchains on Metal
The webgpu.h surface-based swapchains are implement on Metal which required adding the present mode to NewSwapChainBase. Additional automated tests are added which require getting the Instance so a new getter is added to DawnTest. Additional some the state tracking of swapchains is performed in the backend, so the SwapChainValidationTests are turned into regular DawnTests so they can check backends do the correct state tracking. To not lose coverage of the Null backend, a NullBackend() DawnTestParam factory is added. Finally swapchains cannot be entirely tested in an automated fashion, so a new example is added called "ManualSwapChainTests" that allows manually checking a number of properties. Documentation of the controls and a manual test plan is in a comment at the top of the example's source. Bug: dawn:269 Change-Id: If62fffc29a6cefdbec62747d01c523e2a5475715 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/17181 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
527045fe55
commit
11652ff8f8
@@ -110,6 +110,12 @@ DawnTestParam MetalBackend(std::initializer_list<const char*> forceEnabledWorkar
|
||||
forceDisabledWorkarounds);
|
||||
}
|
||||
|
||||
DawnTestParam NullBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
|
||||
std::initializer_list<const char*> forceDisabledWorkarounds) {
|
||||
return DawnTestParam(wgpu::BackendType::Null, forceEnabledWorkarounds,
|
||||
forceDisabledWorkarounds);
|
||||
}
|
||||
|
||||
DawnTestParam OpenGLBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
|
||||
std::initializer_list<const char*> forceDisabledWorkarounds) {
|
||||
return DawnTestParam(wgpu::BackendType::OpenGL, forceEnabledWorkarounds,
|
||||
@@ -446,6 +452,10 @@ bool DawnTestBase::IsMetal() const {
|
||||
return mParam.backendType == wgpu::BackendType::Metal;
|
||||
}
|
||||
|
||||
bool DawnTestBase::IsNull() const {
|
||||
return mParam.backendType == wgpu::BackendType::Null;
|
||||
}
|
||||
|
||||
bool DawnTestBase::IsOpenGL() const {
|
||||
return mParam.backendType == wgpu::BackendType::OpenGL;
|
||||
}
|
||||
@@ -526,6 +536,14 @@ uint32_t DawnTestBase::GetVendorIdFilter() const {
|
||||
return gTestEnv->GetVendorIdFilter();
|
||||
}
|
||||
|
||||
wgpu::Instance DawnTestBase::GetInstance() const {
|
||||
return gTestEnv->GetInstance()->Get();
|
||||
}
|
||||
|
||||
dawn_native::Adapter DawnTestBase::GetAdapter() const {
|
||||
return mBackendAdapter;
|
||||
}
|
||||
|
||||
std::vector<const char*> DawnTestBase::GetRequiredExtensions() {
|
||||
return {};
|
||||
}
|
||||
@@ -958,6 +976,9 @@ namespace detail {
|
||||
#if defined(DAWN_ENABLE_BACKEND_METAL)
|
||||
case wgpu::BackendType::Metal:
|
||||
#endif
|
||||
#if defined(DAWN_ENABLE_BACKEND_NULL)
|
||||
case wgpu::BackendType::Null:
|
||||
#endif
|
||||
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||
case wgpu::BackendType::OpenGL:
|
||||
#endif
|
||||
|
||||
@@ -104,6 +104,9 @@ DawnTestParam D3D12Backend(std::initializer_list<const char*> forceEnabledWorkar
|
||||
DawnTestParam MetalBackend(std::initializer_list<const char*> forceEnabledWorkarounds = {},
|
||||
std::initializer_list<const char*> forceDisabledWorkarounds = {});
|
||||
|
||||
DawnTestParam NullBackend(std::initializer_list<const char*> forceEnabledWorkarounds = {},
|
||||
std::initializer_list<const char*> forceDisabledWorkarounds = {});
|
||||
|
||||
DawnTestParam OpenGLBackend(std::initializer_list<const char*> forceEnabledWorkarounds = {},
|
||||
std::initializer_list<const char*> forceDisabledWorkarounds = {});
|
||||
|
||||
@@ -177,6 +180,7 @@ class DawnTestBase {
|
||||
|
||||
bool IsD3D12() const;
|
||||
bool IsMetal() const;
|
||||
bool IsNull() const;
|
||||
bool IsOpenGL() const;
|
||||
bool IsVulkan() const;
|
||||
|
||||
@@ -202,6 +206,9 @@ class DawnTestBase {
|
||||
bool HasVendorIdFilter() const;
|
||||
uint32_t GetVendorIdFilter() const;
|
||||
|
||||
wgpu::Instance GetInstance() const;
|
||||
dawn_native::Adapter GetAdapter() const;
|
||||
|
||||
protected:
|
||||
wgpu::Device device;
|
||||
wgpu::Queue queue;
|
||||
|
||||
219
src/tests/end2end/SwapChainTests.cpp
Normal file
219
src/tests/end2end/SwapChainTests.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
// 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/DawnTest.h"
|
||||
|
||||
#include "common/Constants.h"
|
||||
#include "common/Log.h"
|
||||
#include "utils/GLFWUtils.h"
|
||||
#include "utils/WGPUHelpers.h"
|
||||
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
class SwapChainTests : public DawnTest {
|
||||
public:
|
||||
void TestSetUp() override {
|
||||
DAWN_SKIP_TEST_IF(UsesWire());
|
||||
|
||||
glfwSetErrorCallback([](int code, const char* message) {
|
||||
dawn::ErrorLog() << "GLFW error " << code << " " << message;
|
||||
});
|
||||
glfwInit();
|
||||
|
||||
// The SwapChainTests don't create OpenGL contexts 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.
|
||||
ASSERT_TRUE(!IsOpenGL());
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
window = glfwCreateWindow(400, 400, "SwapChainValidationTests window", nullptr, nullptr);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
|
||||
surface = utils::CreateSurfaceForWindow(GetInstance(), window);
|
||||
ASSERT_NE(surface, nullptr);
|
||||
|
||||
baseDescriptor.width = width;
|
||||
baseDescriptor.height = height;
|
||||
baseDescriptor.usage = wgpu::TextureUsage::OutputAttachment;
|
||||
baseDescriptor.format = wgpu::TextureFormat::BGRA8Unorm;
|
||||
baseDescriptor.presentMode = wgpu::PresentMode::Mailbox;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// Destroy the surface before the window as required by webgpu-native.
|
||||
surface = wgpu::Surface();
|
||||
if (window != nullptr) {
|
||||
glfwDestroyWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearTexture(wgpu::TextureView view, wgpu::Color color) {
|
||||
utils::ComboRenderPassDescriptor desc({view});
|
||||
desc.cColorAttachments[0].loadOp = wgpu::LoadOp::Clear;
|
||||
desc.cColorAttachments[0].clearColor = color;
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&desc);
|
||||
pass.EndPass();
|
||||
|
||||
wgpu::CommandBuffer commands = encoder.Finish();
|
||||
queue.Submit(1, &commands);
|
||||
}
|
||||
|
||||
protected:
|
||||
GLFWwindow* window = nullptr;
|
||||
wgpu::Surface surface;
|
||||
|
||||
wgpu::SwapChainDescriptor baseDescriptor;
|
||||
};
|
||||
|
||||
// Basic test for creating a swapchain and presenting one frame.
|
||||
TEST_P(SwapChainTests, Basic) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
|
||||
ClearTexture(swapchain.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
|
||||
swapchain.Present();
|
||||
}
|
||||
|
||||
// Test replacing the swapchain
|
||||
TEST_P(SwapChainTests, ReplaceBasic) {
|
||||
wgpu::SwapChain swapchain1 = device.CreateSwapChain(surface, &baseDescriptor);
|
||||
ClearTexture(swapchain1.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
|
||||
swapchain1.Present();
|
||||
|
||||
wgpu::SwapChain swapchain2 = device.CreateSwapChain(surface, &baseDescriptor);
|
||||
ClearTexture(swapchain2.GetCurrentTextureView(), {0.0, 1.0, 0.0, 1.0});
|
||||
swapchain2.Present();
|
||||
}
|
||||
|
||||
// Test replacing the swapchain after GetCurrentTextureView
|
||||
TEST_P(SwapChainTests, ReplaceAfterGet) {
|
||||
wgpu::SwapChain swapchain1 = device.CreateSwapChain(surface, &baseDescriptor);
|
||||
ClearTexture(swapchain1.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
|
||||
|
||||
wgpu::SwapChain swapchain2 = device.CreateSwapChain(surface, &baseDescriptor);
|
||||
ClearTexture(swapchain2.GetCurrentTextureView(), {0.0, 1.0, 0.0, 1.0});
|
||||
swapchain2.Present();
|
||||
}
|
||||
|
||||
// Test destroying the swapchain after GetCurrentTextureView
|
||||
TEST_P(SwapChainTests, DestroyAfterGet) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
|
||||
ClearTexture(swapchain.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
|
||||
}
|
||||
|
||||
// Test destroying the surface before the swapchain
|
||||
TEST_P(SwapChainTests, DestroySurface) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
|
||||
surface = nullptr;
|
||||
}
|
||||
|
||||
// Test destroying the surface before the swapchain but after GetCurrentTextureView
|
||||
TEST_P(SwapChainTests, DestroySurfaceAfterGet) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
|
||||
ClearTexture(swapchain.GetCurrentTextureView(), {1.0, 0.0, 0.0, 1.0});
|
||||
surface = nullptr;
|
||||
}
|
||||
|
||||
// Test switching between present modes.
|
||||
TEST_P(SwapChainTests, SwitchPresentMode) {
|
||||
constexpr wgpu::PresentMode kAllPresentModes[] = {
|
||||
wgpu::PresentMode::Immediate,
|
||||
wgpu::PresentMode::Fifo,
|
||||
wgpu::PresentMode::Mailbox,
|
||||
};
|
||||
|
||||
for (wgpu::PresentMode mode1 : kAllPresentModes) {
|
||||
for (wgpu::PresentMode mode2 : kAllPresentModes) {
|
||||
wgpu::SwapChainDescriptor desc = baseDescriptor;
|
||||
|
||||
desc.presentMode = mode1;
|
||||
wgpu::SwapChain swapchain1 = device.CreateSwapChain(surface, &desc);
|
||||
ClearTexture(swapchain1.GetCurrentTextureView(), {0.0, 0.0, 0.0, 1.0});
|
||||
swapchain1.Present();
|
||||
|
||||
desc.presentMode = mode2;
|
||||
wgpu::SwapChain swapchain2 = device.CreateSwapChain(surface, &desc);
|
||||
ClearTexture(swapchain2.GetCurrentTextureView(), {0.0, 0.0, 0.0, 1.0});
|
||||
swapchain2.Present();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test resizing the swapchain and without resizing the window.
|
||||
TEST_P(SwapChainTests, ResizingSwapChainOnly) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
wgpu::SwapChainDescriptor desc = baseDescriptor;
|
||||
desc.width += i * 10;
|
||||
desc.height -= i * 10;
|
||||
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
|
||||
ClearTexture(swapchain.GetCurrentTextureView(), {0.05 * i, 0.0, 0.0, 1.0});
|
||||
swapchain.Present();
|
||||
}
|
||||
}
|
||||
|
||||
// Test resizing the window but not the swapchain.
|
||||
TEST_P(SwapChainTests, ResizingWindowOnly) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
glfwSetWindowSize(window, 400 - 10 * i, 400 + 10 * i);
|
||||
glfwPollEvents();
|
||||
|
||||
ClearTexture(swapchain.GetCurrentTextureView(), {0.05 * i, 0.0, 0.0, 1.0});
|
||||
swapchain.Present();
|
||||
}
|
||||
}
|
||||
|
||||
// Test resizing both the window and the swapchain at the same time.
|
||||
TEST_P(SwapChainTests, ResizingWindowAndSwapChain) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
glfwSetWindowSize(window, 400 - 10 * i, 400 + 10 * i);
|
||||
glfwPollEvents();
|
||||
|
||||
int width;
|
||||
int height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
|
||||
wgpu::SwapChainDescriptor desc = baseDescriptor;
|
||||
desc.width = width;
|
||||
desc.height = height;
|
||||
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
|
||||
ClearTexture(swapchain.GetCurrentTextureView(), {0.05 * i, 0.0, 0.0, 1.0});
|
||||
swapchain.Present();
|
||||
}
|
||||
}
|
||||
|
||||
// Test switching devices on the same adapter.
|
||||
TEST_P(SwapChainTests, SwitchingDevice) {
|
||||
wgpu::Device device2 = GetAdapter().CreateDevice();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
wgpu::Device deviceToUse;
|
||||
if (i % 2 == 0) {
|
||||
deviceToUse = device;
|
||||
} else {
|
||||
deviceToUse = device2;
|
||||
}
|
||||
|
||||
wgpu::SwapChain swapchain = deviceToUse.CreateSwapChain(surface, &baseDescriptor);
|
||||
swapchain.GetCurrentTextureView();
|
||||
swapchain.Present();
|
||||
}
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(SwapChainTests, MetalBackend());
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "tests/unittests/validation/ValidationTest.h"
|
||||
#include "tests/DawnTest.h"
|
||||
|
||||
#include "common/Constants.h"
|
||||
#include "common/Log.h"
|
||||
@@ -22,21 +22,25 @@
|
||||
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
class SwapChainValidationTests : public ValidationTest {
|
||||
class SwapChainValidationTests : public DawnTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
void TestSetUp() override {
|
||||
DAWN_SKIP_TEST_IF(UsesWire());
|
||||
DAWN_SKIP_TEST_IF(IsDawnValidationSkipped());
|
||||
|
||||
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
|
||||
// The SwapChainValidationTests 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.
|
||||
ASSERT_TRUE(!IsOpenGL());
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
window = glfwCreateWindow(400, 400, "SwapChainValidationTests window", nullptr, nullptr);
|
||||
|
||||
surface = utils::CreateSurfaceForWindow(instance->Get(), window);
|
||||
surface = utils::CreateSurfaceForWindow(GetInstance(), window);
|
||||
ASSERT_NE(surface, nullptr);
|
||||
|
||||
goodDescriptor.width = 1;
|
||||
@@ -52,7 +56,9 @@ class SwapChainValidationTests : public ValidationTest {
|
||||
void TearDown() override {
|
||||
// Destroy the surface before the window as required by webgpu-native.
|
||||
surface = wgpu::Surface();
|
||||
glfwDestroyWindow(window);
|
||||
if (window != nullptr) {
|
||||
glfwDestroyWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -86,14 +92,14 @@ class SwapChainValidationTests : public ValidationTest {
|
||||
};
|
||||
|
||||
// Control case for a successful swapchain creation and presenting.
|
||||
TEST_F(SwapChainValidationTests, CreationSuccess) {
|
||||
TEST_P(SwapChainValidationTests, CreationSuccess) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
wgpu::TextureView view = swapchain.GetCurrentTextureView();
|
||||
swapchain.Present();
|
||||
}
|
||||
|
||||
// Checks that the creation size must be a valid 2D texture size.
|
||||
TEST_F(SwapChainValidationTests, InvalidCreationSize) {
|
||||
TEST_P(SwapChainValidationTests, InvalidCreationSize) {
|
||||
// A width of 0 is invalid.
|
||||
{
|
||||
wgpu::SwapChainDescriptor desc = goodDescriptor;
|
||||
@@ -129,28 +135,28 @@ TEST_F(SwapChainValidationTests, InvalidCreationSize) {
|
||||
}
|
||||
|
||||
// Checks that the creation usage must be OutputAttachment
|
||||
TEST_F(SwapChainValidationTests, InvalidCreationUsage) {
|
||||
TEST_P(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) {
|
||||
TEST_P(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) {
|
||||
TEST_P(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) {
|
||||
TEST_P(SwapChainValidationTests, OperationsOnErrorSwapChain) {
|
||||
wgpu::SwapChain swapchain;
|
||||
ASSERT_DEVICE_ERROR(swapchain = device.CreateSwapChain(surface, &badDescriptor));
|
||||
|
||||
@@ -162,7 +168,7 @@ TEST_F(SwapChainValidationTests, OperationsOnErrorSwapChain) {
|
||||
}
|
||||
|
||||
// Check it is invalid to call present without getting a current view.
|
||||
TEST_F(SwapChainValidationTests, PresentWithoutCurrentView) {
|
||||
TEST_P(SwapChainValidationTests, PresentWithoutCurrentView) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
|
||||
// Check it is invalid if we never called GetCurrentTextureView
|
||||
@@ -175,7 +181,7 @@ TEST_F(SwapChainValidationTests, PresentWithoutCurrentView) {
|
||||
}
|
||||
|
||||
// Check that the current view is in the destroyed state after the swapchain is destroyed.
|
||||
TEST_F(SwapChainValidationTests, ViewDestroyedAfterSwapChainDestruction) {
|
||||
TEST_P(SwapChainValidationTests, ViewDestroyedAfterSwapChainDestruction) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
wgpu::TextureView view = swapchain.GetCurrentTextureView();
|
||||
swapchain = nullptr;
|
||||
@@ -184,7 +190,7 @@ TEST_F(SwapChainValidationTests, ViewDestroyedAfterSwapChainDestruction) {
|
||||
}
|
||||
|
||||
// Check that the current view is the destroyed state after present.
|
||||
TEST_F(SwapChainValidationTests, ViewDestroyedAfterPresent) {
|
||||
TEST_P(SwapChainValidationTests, ViewDestroyedAfterPresent) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
wgpu::TextureView view = swapchain.GetCurrentTextureView();
|
||||
swapchain.Present();
|
||||
@@ -193,7 +199,7 @@ TEST_F(SwapChainValidationTests, ViewDestroyedAfterPresent) {
|
||||
}
|
||||
|
||||
// Check that returned view is of the current format / usage / dimension / size / sample count
|
||||
TEST_F(SwapChainValidationTests, ReturnedViewCharacteristics) {
|
||||
TEST_P(SwapChainValidationTests, ReturnedViewCharacteristics) {
|
||||
utils::ComboRenderPipelineDescriptor pipelineDesc(device);
|
||||
pipelineDesc.vertexStage.module =
|
||||
utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"(
|
||||
@@ -249,7 +255,7 @@ TEST_F(SwapChainValidationTests, ReturnedViewCharacteristics) {
|
||||
}
|
||||
|
||||
// Check that failing to create a new swapchain doesn't replace the previous one.
|
||||
TEST_F(SwapChainValidationTests, ErrorSwapChainDoesntReplacePreviousOne) {
|
||||
TEST_P(SwapChainValidationTests, ErrorSwapChainDoesntReplacePreviousOne) {
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &badDescriptor));
|
||||
|
||||
@@ -258,7 +264,7 @@ TEST_F(SwapChainValidationTests, ErrorSwapChainDoesntReplacePreviousOne) {
|
||||
}
|
||||
|
||||
// Check that after replacement, all swapchain operations are errors and the view is destroyed.
|
||||
TEST_F(SwapChainValidationTests, ReplacedSwapChainIsInvalid) {
|
||||
TEST_P(SwapChainValidationTests, ReplacedSwapChainIsInvalid) {
|
||||
{
|
||||
wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
device.CreateSwapChain(surface, &goodDescriptor);
|
||||
@@ -277,12 +283,12 @@ TEST_F(SwapChainValidationTests, ReplacedSwapChainIsInvalid) {
|
||||
|
||||
// Check that after surface destruction, all swapchain operations are errors and the view is
|
||||
// destroyed. The test is split in two to reset the wgpu::Surface in the middle.
|
||||
TEST_F(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_GetView) {
|
||||
TEST_P(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_GetView) {
|
||||
wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
surface = nullptr;
|
||||
ASSERT_DEVICE_ERROR(replacedSwapChain.GetCurrentTextureView());
|
||||
}
|
||||
TEST_F(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_AfterGetView) {
|
||||
TEST_P(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_AfterGetView) {
|
||||
wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
wgpu::TextureView view = replacedSwapChain.GetCurrentTextureView();
|
||||
surface = nullptr;
|
||||
@@ -293,12 +299,12 @@ TEST_F(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_After
|
||||
|
||||
// Test that after Device is Lost, all swap chain operations fail
|
||||
static void ToMockDeviceLostCallback(const char* message, void* userdata) {
|
||||
ValidationTest* self = static_cast<ValidationTest*>(userdata);
|
||||
DawnTest* self = static_cast<DawnTest*>(userdata);
|
||||
self->StartExpectDeviceError();
|
||||
}
|
||||
|
||||
// Test that new swap chain present fails after device is lost
|
||||
TEST_F(SwapChainValidationTests, NewSwapChainPresentFailsAfterDeviceLost) {
|
||||
TEST_P(SwapChainValidationTests, NewSwapChainPresentFailsAfterDeviceLost) {
|
||||
device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
wgpu::TextureView view = swapchain.GetCurrentTextureView();
|
||||
@@ -308,7 +314,7 @@ TEST_F(SwapChainValidationTests, NewSwapChainPresentFailsAfterDeviceLost) {
|
||||
}
|
||||
|
||||
// Test that new swap chain get current texture view fails after device is lost
|
||||
TEST_F(SwapChainValidationTests, NewSwapChainGetCurrentTextureViewFailsAfterDevLost) {
|
||||
TEST_P(SwapChainValidationTests, NewSwapChainGetCurrentTextureViewFailsAfterDevLost) {
|
||||
device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
|
||||
@@ -316,10 +322,12 @@ TEST_F(SwapChainValidationTests, NewSwapChainGetCurrentTextureViewFailsAfterDevL
|
||||
ASSERT_DEVICE_ERROR(swapchain.GetCurrentTextureView());
|
||||
}
|
||||
|
||||
// Test that creation of a new swapchain fails
|
||||
TEST_F(SwapChainValidationTests, CreateNewSwapChainFailsAfterDevLost) {
|
||||
// Test that creation of a new swapchain fails after device is lost
|
||||
TEST_P(SwapChainValidationTests, CreateNewSwapChainFailsAfterDevLost) {
|
||||
device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
|
||||
device.LoseForTesting();
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &goodDescriptor));
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(SwapChainValidationTests, MetalBackend(), NullBackend());
|
||||
|
||||
Reference in New Issue
Block a user