2020-01-23 09:20:38 -08:00
|
|
|
// 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.
|
|
|
|
|
2022-02-09 06:54:31 -08:00
|
|
|
#include "dawn/tests/DawnTest.h"
|
2020-01-23 09:20:38 -08:00
|
|
|
|
2022-02-04 04:51:25 -08:00
|
|
|
#include "dawn/common/Constants.h"
|
|
|
|
#include "dawn/common/Log.h"
|
2022-02-04 04:51:25 -08:00
|
|
|
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
|
|
|
#include "dawn/utils/WGPUHelpers.h"
|
2022-08-14 08:59:25 -07:00
|
|
|
#include "webgpu/webgpu_glfw.h"
|
2020-01-23 09:20:38 -08:00
|
|
|
|
|
|
|
#include "GLFW/glfw3.h"
|
|
|
|
|
2023-05-17 11:41:02 -07:00
|
|
|
namespace dawn {
|
|
|
|
namespace {
|
|
|
|
|
2020-03-20 10:07:20 -07:00
|
|
|
class SwapChainValidationTests : public DawnTest {
|
2020-01-23 09:20:38 -08:00
|
|
|
public:
|
2020-05-15 15:06:35 -07:00
|
|
|
void SetUp() override {
|
|
|
|
DawnTest::SetUp();
|
2021-05-25 18:04:32 -07:00
|
|
|
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
|
|
|
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));
|
2020-03-20 10:07:20 -07:00
|
|
|
|
2020-01-23 09:20:38 -08:00
|
|
|
glfwSetErrorCallback([](int code, const char* message) {
|
2023-05-17 11:41:02 -07:00
|
|
|
ErrorLog() << "GLFW error " << code << " " << message;
|
2020-01-23 09:20:38 -08:00
|
|
|
});
|
2021-05-25 18:04:32 -07:00
|
|
|
DAWN_TEST_UNSUPPORTED_IF(!glfwInit());
|
2020-01-23 09:20:38 -08:00
|
|
|
|
2022-06-29 08:29:41 -07:00
|
|
|
// Set GLFW_NO_API to avoid GLFW bringing up a GL context that we won't use.
|
2020-01-23 09:20:38 -08:00
|
|
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
|
|
|
window = glfwCreateWindow(400, 400, "SwapChainValidationTests window", nullptr, nullptr);
|
|
|
|
|
2022-08-14 08:59:25 -07:00
|
|
|
surface = wgpu::glfw::CreateSurfaceForWindow(GetInstance(), window);
|
2020-01-23 09:20:38 -08:00
|
|
|
ASSERT_NE(surface, nullptr);
|
|
|
|
|
|
|
|
goodDescriptor.width = 1;
|
|
|
|
goodDescriptor.height = 1;
|
2020-10-27 08:35:56 -07:00
|
|
|
goodDescriptor.usage = wgpu::TextureUsage::RenderAttachment;
|
2020-01-23 09:20:38 -08:00
|
|
|
goodDescriptor.format = wgpu::TextureFormat::BGRA8Unorm;
|
2020-03-20 09:47:50 -07:00
|
|
|
goodDescriptor.presentMode = wgpu::PresentMode::Mailbox;
|
2020-01-23 09:20:38 -08:00
|
|
|
|
|
|
|
badDescriptor = goodDescriptor;
|
|
|
|
badDescriptor.width = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TearDown() override {
|
|
|
|
// Destroy the surface before the window as required by webgpu-native.
|
|
|
|
surface = wgpu::Surface();
|
2020-03-20 10:07:20 -07:00
|
|
|
if (window != nullptr) {
|
|
|
|
glfwDestroyWindow(window);
|
|
|
|
}
|
2020-05-15 15:06:35 -07:00
|
|
|
DawnTest::TearDown();
|
2020-01-23 09:20:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
GLFWwindow* window = nullptr;
|
|
|
|
wgpu::Surface surface;
|
|
|
|
wgpu::SwapChainDescriptor goodDescriptor;
|
|
|
|
wgpu::SwapChainDescriptor badDescriptor;
|
|
|
|
|
2021-05-13 10:51:23 -07:00
|
|
|
// Checks that a RenderAttachment view is an error by trying to create a render pass on it.
|
2023-05-26 03:32:17 -07:00
|
|
|
void CheckTextureIsError(wgpu::Texture texture) { CheckTexture(texture, true, false); }
|
2020-01-25 02:05:40 -08:00
|
|
|
|
2021-05-13 10:51:23 -07:00
|
|
|
// Checks that a RenderAttachment view is an error by trying to submit a render pass on it.
|
2023-05-26 03:32:17 -07:00
|
|
|
void CheckTextureIsDestroyed(wgpu::Texture texture) { CheckTexture(texture, false, true); }
|
2020-10-27 04:31:26 -07:00
|
|
|
|
2021-05-13 10:51:23 -07:00
|
|
|
// Checks that a RenderAttachment view is valid by submitting a render pass on it.
|
2023-05-26 03:32:17 -07:00
|
|
|
void CheckTextureIsValid(wgpu::Texture texture) { CheckTexture(texture, false, false); }
|
2020-10-27 04:31:26 -07:00
|
|
|
|
|
|
|
private:
|
2023-05-26 03:32:17 -07:00
|
|
|
void CheckTexture(wgpu::Texture texture, bool error, bool destroyed) {
|
|
|
|
wgpu::TextureView view;
|
|
|
|
if (error) {
|
|
|
|
ASSERT_DEVICE_ERROR(view = texture.CreateView());
|
|
|
|
} else {
|
|
|
|
view = texture.CreateView();
|
|
|
|
}
|
2020-01-25 02:05:40 -08:00
|
|
|
utils::ComboRenderPassDescriptor renderPassDesc({view});
|
|
|
|
|
|
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
2022-12-20 13:03:16 -08:00
|
|
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassDesc);
|
|
|
|
pass.End();
|
2020-01-25 02:05:40 -08:00
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
if (error) {
|
2022-12-20 13:03:16 -08:00
|
|
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
2020-10-27 04:31:26 -07:00
|
|
|
} else {
|
|
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
if (destroyed) {
|
2020-10-27 04:31:26 -07:00
|
|
|
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
|
|
|
} else {
|
|
|
|
queue.Submit(1, &commands);
|
|
|
|
}
|
|
|
|
}
|
2020-01-25 02:05:40 -08:00
|
|
|
}
|
2020-01-23 09:20:38 -08:00
|
|
|
};
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
void CheckTextureMatchesDescriptor(const wgpu::Texture& tex,
|
|
|
|
const wgpu::SwapChainDescriptor& desc) {
|
|
|
|
EXPECT_EQ(desc.width, tex.GetWidth());
|
|
|
|
EXPECT_EQ(desc.height, tex.GetHeight());
|
|
|
|
EXPECT_EQ(desc.usage, tex.GetUsage());
|
|
|
|
EXPECT_EQ(desc.format, tex.GetFormat());
|
|
|
|
EXPECT_EQ(1u, tex.GetDepthOrArrayLayers());
|
|
|
|
EXPECT_EQ(1u, tex.GetMipLevelCount());
|
|
|
|
EXPECT_EQ(1u, tex.GetSampleCount());
|
|
|
|
EXPECT_EQ(wgpu::TextureDimension::e2D, tex.GetDimension());
|
|
|
|
}
|
|
|
|
|
2020-01-25 02:05:40 -08:00
|
|
|
// Control case for a successful swapchain creation and presenting.
|
2020-03-20 10:07:20 -07:00
|
|
|
TEST_P(SwapChainValidationTests, CreationSuccess) {
|
2020-01-25 02:05:40 -08:00
|
|
|
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
2023-05-26 03:32:17 -07:00
|
|
|
swapchain.GetCurrentTexture();
|
2020-01-25 02:05:40 -08:00
|
|
|
swapchain.Present();
|
2020-01-23 09:20:38 -08:00
|
|
|
}
|
|
|
|
|
2022-05-31 13:55:39 -07:00
|
|
|
// Test that creating a swapchain with an invalid surface is an error.
|
|
|
|
TEST_P(SwapChainValidationTests, InvalidSurface) {
|
|
|
|
wgpu::SurfaceDescriptor surface_desc = {};
|
|
|
|
wgpu::Surface surface = GetInstance().CreateSurface(&surface_desc);
|
|
|
|
|
|
|
|
ASSERT_DEVICE_ERROR_MSG(device.CreateSwapChain(surface, &goodDescriptor),
|
|
|
|
testing::HasSubstr("[Surface] is invalid"));
|
|
|
|
}
|
|
|
|
|
2020-01-23 09:20:38 -08:00
|
|
|
// Checks that the creation size must be a valid 2D texture size.
|
2020-03-20 10:07:20 -07:00
|
|
|
TEST_P(SwapChainValidationTests, InvalidCreationSize) {
|
2021-10-13 11:57:18 -07:00
|
|
|
wgpu::Limits supportedLimits = GetSupportedLimits().limits;
|
2020-01-23 09:20:38 -08:00
|
|
|
// 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));
|
|
|
|
}
|
|
|
|
|
2021-10-13 11:57:18 -07:00
|
|
|
// A width of maxTextureDimension2D is valid but maxTextureDimension2D + 1 isn't.
|
2020-01-23 09:20:38 -08:00
|
|
|
{
|
|
|
|
wgpu::SwapChainDescriptor desc = goodDescriptor;
|
2021-10-13 11:57:18 -07:00
|
|
|
desc.width = supportedLimits.maxTextureDimension2D;
|
2020-01-23 09:20:38 -08:00
|
|
|
device.CreateSwapChain(surface, &desc);
|
|
|
|
|
2021-10-13 11:57:18 -07:00
|
|
|
desc.width = supportedLimits.maxTextureDimension2D + 1;
|
2020-01-23 09:20:38 -08:00
|
|
|
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
|
|
|
|
}
|
|
|
|
|
2021-10-13 11:57:18 -07:00
|
|
|
// A height of maxTextureDimension2D is valid but maxTextureDimension2D + 1 isn't.
|
2020-01-23 09:20:38 -08:00
|
|
|
{
|
|
|
|
wgpu::SwapChainDescriptor desc = goodDescriptor;
|
2021-10-13 11:57:18 -07:00
|
|
|
desc.height = supportedLimits.maxTextureDimension2D;
|
2020-01-23 09:20:38 -08:00
|
|
|
device.CreateSwapChain(surface, &desc);
|
|
|
|
|
2021-10-13 11:57:18 -07:00
|
|
|
desc.height = supportedLimits.maxTextureDimension2D + 1;
|
2020-01-23 09:20:38 -08:00
|
|
|
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-27 08:35:56 -07:00
|
|
|
// Checks that the creation usage must be RenderAttachment
|
2020-03-20 10:07:20 -07:00
|
|
|
TEST_P(SwapChainValidationTests, InvalidCreationUsage) {
|
2020-01-23 09:20:38 -08:00
|
|
|
wgpu::SwapChainDescriptor desc = goodDescriptor;
|
2021-08-09 21:07:37 -07:00
|
|
|
desc.usage = wgpu::TextureUsage::TextureBinding;
|
2020-01-23 09:20:38 -08:00
|
|
|
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Checks that the creation format must (currently) be BGRA8Unorm
|
2020-03-20 10:07:20 -07:00
|
|
|
TEST_P(SwapChainValidationTests, InvalidCreationFormat) {
|
2020-01-23 09:20:38 -08:00
|
|
|
wgpu::SwapChainDescriptor desc = goodDescriptor;
|
|
|
|
desc.format = wgpu::TextureFormat::RGBA8Unorm;
|
|
|
|
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check swapchain operations with an error swapchain are errors
|
2020-03-20 10:07:20 -07:00
|
|
|
TEST_P(SwapChainValidationTests, OperationsOnErrorSwapChain) {
|
2020-01-23 09:20:38 -08:00
|
|
|
wgpu::SwapChain swapchain;
|
|
|
|
ASSERT_DEVICE_ERROR(swapchain = device.CreateSwapChain(surface, &badDescriptor));
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
wgpu::Texture texture;
|
|
|
|
ASSERT_DEVICE_ERROR(texture = swapchain.GetCurrentTexture());
|
|
|
|
CheckTextureIsError(texture);
|
2020-01-23 09:20:38 -08:00
|
|
|
|
|
|
|
ASSERT_DEVICE_ERROR(swapchain.Present());
|
|
|
|
}
|
2020-01-25 02:05:40 -08:00
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
// Check it is invalid to call present without getting a current texture.
|
|
|
|
TEST_P(SwapChainValidationTests, PresentWithoutCurrentTexture) {
|
2020-01-25 02:05:40 -08:00
|
|
|
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
// Check it is invalid if we never called GetCurrentTexture
|
2020-01-25 02:05:40 -08:00
|
|
|
ASSERT_DEVICE_ERROR(swapchain.Present());
|
|
|
|
|
|
|
|
// Check it is invalid if we never called since the last present.
|
2023-05-26 03:32:17 -07:00
|
|
|
swapchain.GetCurrentTexture();
|
2020-01-25 02:05:40 -08:00
|
|
|
swapchain.Present();
|
|
|
|
ASSERT_DEVICE_ERROR(swapchain.Present());
|
|
|
|
}
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
// Check that the current texture isn't destroyed when the ref to the swapchain is lost because the
|
2020-10-27 04:31:26 -07:00
|
|
|
// swapchain is kept alive by the surface. Also check after we lose all refs to the surface, the
|
|
|
|
// texture is destroyed.
|
2023-05-26 03:32:17 -07:00
|
|
|
TEST_P(SwapChainValidationTests, TextureValidAfterSwapChainRefLost) {
|
2020-01-25 02:05:40 -08:00
|
|
|
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
2023-05-26 03:32:17 -07:00
|
|
|
wgpu::Texture texture = swapchain.GetCurrentTexture();
|
2020-10-27 04:31:26 -07:00
|
|
|
|
2020-01-25 02:05:40 -08:00
|
|
|
swapchain = nullptr;
|
2023-05-26 03:32:17 -07:00
|
|
|
CheckTextureIsValid(texture);
|
2020-01-25 02:05:40 -08:00
|
|
|
|
2020-10-27 04:31:26 -07:00
|
|
|
surface = nullptr;
|
2023-05-26 03:32:17 -07:00
|
|
|
CheckTextureIsDestroyed(texture);
|
2020-01-25 02:05:40 -08:00
|
|
|
}
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
// Check that the current texture is the destroyed state after present.
|
|
|
|
TEST_P(SwapChainValidationTests, TextureDestroyedAfterPresent) {
|
2020-01-25 02:05:40 -08:00
|
|
|
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
2023-05-26 03:32:17 -07:00
|
|
|
wgpu::Texture texture = swapchain.GetCurrentTexture();
|
2020-01-25 02:05:40 -08:00
|
|
|
swapchain.Present();
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
CheckTextureIsDestroyed(texture);
|
2020-01-25 02:05:40 -08:00
|
|
|
}
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
// Check that returned texture is of the current format / usage / dimension / size / sample count
|
|
|
|
TEST_P(SwapChainValidationTests, ReturnedTextureCharacteristics) {
|
2021-05-20 22:01:38 -07:00
|
|
|
utils::ComboRenderPipelineDescriptor pipelineDesc;
|
2021-03-24 08:55:32 -07:00
|
|
|
pipelineDesc.vertex.module = utils::CreateShaderModule(device, R"(
|
2023-02-02 12:17:46 -08:00
|
|
|
@vertex fn main() -> @builtin(position) vec4f {
|
|
|
|
return vec4f(0.0, 0.0, 0.0, 1.0);
|
2020-11-26 04:43:15 -08:00
|
|
|
})");
|
2021-03-24 08:55:32 -07:00
|
|
|
pipelineDesc.cFragment.module = utils::CreateShaderModule(device, R"(
|
2021-07-26 12:43:19 -07:00
|
|
|
struct FragmentOut {
|
2023-02-02 12:17:46 -08:00
|
|
|
@location(0) target0 : vec4f,
|
2022-04-05 11:41:23 -07:00
|
|
|
@location(1) target1 : f32,
|
|
|
|
}
|
2022-06-07 08:23:04 -07:00
|
|
|
@fragment fn main() -> FragmentOut {
|
2021-07-26 12:43:19 -07:00
|
|
|
var out : FragmentOut;
|
2023-02-02 12:17:46 -08:00
|
|
|
out.target0 = vec4f(0.0, 1.0, 0.0, 1.0);
|
2021-07-26 12:43:19 -07:00
|
|
|
out.target1 = 0.5;
|
|
|
|
return out;
|
2020-11-26 04:43:15 -08:00
|
|
|
})");
|
2020-01-25 02:05:40 -08:00
|
|
|
// Validation will check that the sample count of the view matches this format.
|
2021-03-17 19:54:27 -07:00
|
|
|
pipelineDesc.multisample.count = 1;
|
|
|
|
pipelineDesc.cFragment.targetCount = 2;
|
2020-01-25 02:05:40 -08:00
|
|
|
// Validation will check that the format of the view matches this format.
|
2021-03-17 19:54:27 -07:00
|
|
|
pipelineDesc.cTargets[0].format = wgpu::TextureFormat::BGRA8Unorm;
|
|
|
|
pipelineDesc.cTargets[1].format = wgpu::TextureFormat::R8Unorm;
|
2021-05-20 22:01:38 -07:00
|
|
|
device.CreateRenderPipeline(&pipelineDesc);
|
2020-01-25 02:05:40 -08:00
|
|
|
|
|
|
|
// Create a second texture to be used as render pass attachment. Validation will check that the
|
|
|
|
// size of the view matches the size of this texture.
|
|
|
|
wgpu::TextureDescriptor textureDesc;
|
2020-10-27 08:35:56 -07:00
|
|
|
textureDesc.usage = wgpu::TextureUsage::RenderAttachment;
|
2020-01-25 02:05:40 -08:00
|
|
|
textureDesc.dimension = wgpu::TextureDimension::e2D;
|
|
|
|
textureDesc.size = {1, 1, 1};
|
|
|
|
textureDesc.format = wgpu::TextureFormat::R8Unorm;
|
|
|
|
textureDesc.sampleCount = 1;
|
|
|
|
wgpu::Texture secondTexture = device.CreateTexture(&textureDesc);
|
|
|
|
|
|
|
|
// Get the swapchain view and try to use it in the render pass to trigger all the validation.
|
|
|
|
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
2023-05-26 03:32:17 -07:00
|
|
|
wgpu::TextureView view = swapchain.GetCurrentTexture().CreateView();
|
2020-01-25 02:05:40 -08:00
|
|
|
|
|
|
|
// Validation will also check the dimension of the view is 2D, and it's usage contains
|
2020-10-27 08:35:56 -07:00
|
|
|
// RenderAttachment
|
2020-01-25 02:05:40 -08:00
|
|
|
utils::ComboRenderPassDescriptor renderPassDesc({view, secondTexture.CreateView()});
|
|
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
|
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassDesc);
|
2022-02-07 11:48:39 -08:00
|
|
|
pass.End();
|
2020-01-25 02:05:40 -08:00
|
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
|
|
|
|
|
|
queue.Submit(1, &commands);
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
// Check that view doesn't have an extra Sampled usage.
|
2020-01-25 02:05:40 -08:00
|
|
|
wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
|
2020-12-16 16:19:34 -08:00
|
|
|
device, {{0, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Float}});
|
2020-01-25 02:05:40 -08:00
|
|
|
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, bgl, {{0, view}}));
|
2023-05-26 03:32:17 -07:00
|
|
|
|
|
|
|
// Check that view doesn't have an extra Storage usage.
|
|
|
|
bgl = utils::MakeBindGroupLayout(
|
|
|
|
device, {{0, wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::WriteOnly,
|
|
|
|
wgpu::TextureFormat::R32Uint}});
|
|
|
|
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, bgl, {{0, view}}));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the reflection of textures returned by GetCurrentTexture on valid swapchain.
|
|
|
|
TEST_P(SwapChainValidationTests, ReflectionValidGetCurrentTexture) {
|
|
|
|
// Check with the goodDescriptor.
|
|
|
|
{
|
|
|
|
wgpu::SwapChain swapChain = device.CreateSwapChain(surface, &goodDescriptor);
|
|
|
|
CheckTextureMatchesDescriptor(swapChain.GetCurrentTexture(), goodDescriptor);
|
|
|
|
}
|
|
|
|
// Check with properties that can be changed while keeping a valid descriptor.
|
|
|
|
{
|
|
|
|
wgpu::SwapChainDescriptor otherDescriptor = goodDescriptor;
|
|
|
|
otherDescriptor.width = 2;
|
|
|
|
otherDescriptor.height = 7;
|
|
|
|
wgpu::SwapChain swapChain = device.CreateSwapChain(surface, &goodDescriptor);
|
|
|
|
CheckTextureMatchesDescriptor(swapChain.GetCurrentTexture(), goodDescriptor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the reflection of textures returned by GetCurrentTexture on valid swapchain.
|
|
|
|
TEST_P(SwapChainValidationTests, ReflectionErrorGetCurrentTexture) {
|
|
|
|
wgpu::SwapChain swapChain;
|
|
|
|
ASSERT_DEVICE_ERROR(swapChain = device.CreateSwapChain(surface, &badDescriptor));
|
|
|
|
wgpu::Texture texture;
|
|
|
|
ASSERT_DEVICE_ERROR(texture = swapChain.GetCurrentTexture());
|
|
|
|
CheckTextureMatchesDescriptor(texture, badDescriptor);
|
2020-01-25 02:05:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check that failing to create a new swapchain doesn't replace the previous one.
|
2020-03-20 10:07:20 -07:00
|
|
|
TEST_P(SwapChainValidationTests, ErrorSwapChainDoesntReplacePreviousOne) {
|
2020-01-25 02:05:40 -08:00
|
|
|
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
|
|
|
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &badDescriptor));
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
swapchain.GetCurrentTexture();
|
2020-01-25 02:05:40 -08:00
|
|
|
swapchain.Present();
|
|
|
|
}
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
// Check that after replacement, all swapchain operations are errors and the texture is destroyed.
|
2020-03-20 10:07:20 -07:00
|
|
|
TEST_P(SwapChainValidationTests, ReplacedSwapChainIsInvalid) {
|
2020-01-25 02:05:40 -08:00
|
|
|
{
|
|
|
|
wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
|
|
|
|
device.CreateSwapChain(surface, &goodDescriptor);
|
2023-05-26 03:32:17 -07:00
|
|
|
ASSERT_DEVICE_ERROR(replacedSwapChain.GetCurrentTexture());
|
2020-01-25 02:05:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
|
2023-05-26 03:32:17 -07:00
|
|
|
wgpu::Texture texture = replacedSwapChain.GetCurrentTexture();
|
2020-01-25 02:05:40 -08:00
|
|
|
device.CreateSwapChain(surface, &goodDescriptor);
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
CheckTextureIsDestroyed(texture);
|
2020-01-25 02:05:40 -08:00
|
|
|
ASSERT_DEVICE_ERROR(replacedSwapChain.Present());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
// Check that after surface destruction, all swapchain operations are errors and the texture is
|
2020-01-25 02:05:40 -08:00
|
|
|
// destroyed. The test is split in two to reset the wgpu::Surface in the middle.
|
2023-05-26 03:32:17 -07:00
|
|
|
TEST_P(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_GetTexture) {
|
2020-01-25 02:05:40 -08:00
|
|
|
wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
|
|
|
|
surface = nullptr;
|
2023-05-26 03:32:17 -07:00
|
|
|
ASSERT_DEVICE_ERROR(replacedSwapChain.GetCurrentTexture());
|
2020-01-25 02:05:40 -08:00
|
|
|
}
|
2023-05-26 03:32:17 -07:00
|
|
|
TEST_P(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_AfterGetTexture) {
|
2020-01-25 02:05:40 -08:00
|
|
|
wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
|
2023-05-26 03:32:17 -07:00
|
|
|
wgpu::Texture texture = replacedSwapChain.GetCurrentTexture();
|
2020-01-25 02:05:40 -08:00
|
|
|
surface = nullptr;
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
CheckTextureIsDestroyed(texture);
|
2020-01-25 02:05:40 -08:00
|
|
|
ASSERT_DEVICE_ERROR(replacedSwapChain.Present());
|
|
|
|
}
|
2020-02-11 13:30:25 -08:00
|
|
|
|
|
|
|
// Test that new swap chain present fails after device is lost
|
2023-04-07 06:30:50 -07:00
|
|
|
TEST_P(SwapChainValidationTests, SwapChainPresentFailsAfterDeviceLost) {
|
2020-02-11 13:30:25 -08:00
|
|
|
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
2023-05-26 03:32:17 -07:00
|
|
|
swapchain.GetCurrentTexture();
|
2020-02-11 13:30:25 -08:00
|
|
|
|
2022-04-28 14:55:33 -07:00
|
|
|
LoseDeviceForTesting();
|
2020-02-11 13:30:25 -08:00
|
|
|
ASSERT_DEVICE_ERROR(swapchain.Present());
|
|
|
|
}
|
|
|
|
|
2023-05-26 03:32:17 -07:00
|
|
|
// Test that new swap chain get current texture fails after device is lost
|
|
|
|
TEST_P(SwapChainValidationTests, SwapChainGetCurrentTextureFailsAfterDevLost) {
|
2020-02-11 13:30:25 -08:00
|
|
|
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
|
|
|
|
2022-04-28 14:55:33 -07:00
|
|
|
LoseDeviceForTesting();
|
2023-05-26 03:32:17 -07:00
|
|
|
ASSERT_DEVICE_ERROR(swapchain.GetCurrentTexture());
|
2020-02-11 13:30:25 -08:00
|
|
|
}
|
|
|
|
|
2020-03-20 10:07:20 -07:00
|
|
|
// Test that creation of a new swapchain fails after device is lost
|
2023-04-07 06:30:50 -07:00
|
|
|
TEST_P(SwapChainValidationTests, CreateSwapChainFailsAfterDevLost) {
|
2022-04-28 14:55:33 -07:00
|
|
|
LoseDeviceForTesting();
|
2020-02-11 13:30:25 -08:00
|
|
|
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &goodDescriptor));
|
|
|
|
}
|
2020-03-20 10:07:20 -07:00
|
|
|
|
|
|
|
DAWN_INSTANTIATE_TEST(SwapChainValidationTests, MetalBackend(), NullBackend());
|
2023-05-17 11:41:02 -07:00
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
} // namespace dawn
|