Add multiple device testing capability in DawnTest.
- Factors out device creation code to helper. - Updates callbacks and test infra to support different devices and use mock callbacks. - Updates some tests that were using outdated device lost callbacks and multiple devices. Change-Id: I4210280420b8dadbc6355d27995ccf0cd864108c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/87480 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Loko Kung <lokokung@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
bd8de5d2a4
commit
04912aa836
|
@ -30,6 +30,7 @@
|
|||
#include "dawn/common/Platform.h"
|
||||
#include "dawn/common/SystemUtils.h"
|
||||
#include "dawn/dawn_proc.h"
|
||||
#include "dawn/native/Device.h"
|
||||
#include "dawn/native/Instance.h"
|
||||
#include "dawn/native/dawn_platform.h"
|
||||
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
||||
|
@ -903,31 +904,9 @@ bool DawnTestBase::SupportsFeatures(const std::vector<wgpu::FeatureName>& featur
|
|||
return true;
|
||||
}
|
||||
|
||||
void DawnTestBase::SetUp() {
|
||||
{
|
||||
// Find the adapter that exactly matches our adapter properties.
|
||||
const auto& adapters = gTestEnv->GetInstance()->GetAdapters();
|
||||
const auto& it = std::find_if(
|
||||
adapters.begin(), adapters.end(), [&](const dawn::native::Adapter& adapter) {
|
||||
wgpu::AdapterProperties properties;
|
||||
adapter.GetProperties(&properties);
|
||||
|
||||
return (mParam.adapterProperties.selected &&
|
||||
properties.deviceID == mParam.adapterProperties.deviceID &&
|
||||
properties.vendorID == mParam.adapterProperties.vendorID &&
|
||||
properties.adapterType == mParam.adapterProperties.adapterType &&
|
||||
properties.backendType == mParam.adapterProperties.backendType &&
|
||||
strcmp(properties.name, mParam.adapterProperties.adapterName.c_str()) == 0);
|
||||
});
|
||||
ASSERT(it != adapters.end());
|
||||
mBackendAdapter = *it;
|
||||
}
|
||||
|
||||
// Setup the per-test platform. Tests can provide one by overloading CreateTestPlatform. This is
|
||||
// NOT a thread-safe operation and is allowed here for testing only.
|
||||
mTestPlatform = CreateTestPlatform();
|
||||
dawn::native::FromAPI(gTestEnv->GetInstance()->Get())
|
||||
->SetPlatformForTesting(mTestPlatform.get());
|
||||
std::pair<wgpu::Device, WGPUDevice> DawnTestBase::CreateDeviceImpl(std::string isolationKey) {
|
||||
// TODO(dawn:1399) Always flush wire before creating to avoid reuse of the same handle.
|
||||
FlushWire();
|
||||
|
||||
// Create the device from the adapter
|
||||
for (const char* forceEnabledWorkaround : mParam.forceEnabledWorkarounds) {
|
||||
|
@ -975,30 +954,16 @@ void DawnTestBase::SetUp() {
|
|||
togglesDesc.forceDisabledToggles = forceDisabledToggles.data();
|
||||
togglesDesc.forceDisabledTogglesCount = forceDisabledToggles.size();
|
||||
|
||||
std::tie(device, backendDevice) =
|
||||
mWireHelper->RegisterDevice(mBackendAdapter.CreateDevice(&deviceDescriptor));
|
||||
ASSERT_NE(nullptr, backendDevice);
|
||||
|
||||
std::string traceName =
|
||||
std::string(::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name()) +
|
||||
"_" + ::testing::UnitTest::GetInstance()->current_test_info()->name();
|
||||
mWireHelper->BeginWireTrace(traceName.c_str());
|
||||
|
||||
queue = device.GetQueue();
|
||||
|
||||
device.SetUncapturedErrorCallback(OnDeviceError, this);
|
||||
device.SetDeviceLostCallback(OnDeviceLost, this);
|
||||
#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
|
||||
if (IsOpenGL()) {
|
||||
glfwMakeContextCurrent(gTestEnv->GetOpenGLWindow());
|
||||
}
|
||||
#endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
|
||||
#if defined(DAWN_ENABLE_BACKEND_OPENGLES)
|
||||
if (IsOpenGLES()) {
|
||||
glfwMakeContextCurrent(gTestEnv->GetOpenGLESWindow());
|
||||
}
|
||||
#endif // defined(DAWN_ENABLE_BACKEND_OPENGLES)
|
||||
wgpu::DawnCacheDeviceDescriptor cacheDesc = {};
|
||||
togglesDesc.nextInChain = &cacheDesc;
|
||||
cacheDesc.isolationKey = isolationKey.c_str();
|
||||
|
||||
auto devices = mWireHelper->RegisterDevice(mBackendAdapter.CreateDevice(&deviceDescriptor));
|
||||
wgpu::Device device = devices.first;
|
||||
device.SetUncapturedErrorCallback(mDeviceErrorCallback.Callback(),
|
||||
mDeviceErrorCallback.MakeUserdata(device.Get()));
|
||||
device.SetDeviceLostCallback(mDeviceLostCallback.Callback(),
|
||||
mDeviceLostCallback.MakeUserdata(device.Get()));
|
||||
device.SetLoggingCallback(
|
||||
[](WGPULoggingType type, char const* message, void*) {
|
||||
switch (type) {
|
||||
|
@ -1017,6 +982,60 @@ void DawnTestBase::SetUp() {
|
|||
}
|
||||
},
|
||||
nullptr);
|
||||
return devices;
|
||||
}
|
||||
|
||||
wgpu::Device DawnTestBase::CreateDevice(std::string isolationKey) {
|
||||
return CreateDeviceImpl(isolationKey).first;
|
||||
}
|
||||
|
||||
void DawnTestBase::SetUp() {
|
||||
{
|
||||
// Find the adapter that exactly matches our adapter properties.
|
||||
const auto& adapters = gTestEnv->GetInstance()->GetAdapters();
|
||||
const auto& it = std::find_if(
|
||||
adapters.begin(), adapters.end(), [&](const dawn::native::Adapter& adapter) {
|
||||
wgpu::AdapterProperties properties;
|
||||
adapter.GetProperties(&properties);
|
||||
|
||||
return (mParam.adapterProperties.selected &&
|
||||
properties.deviceID == mParam.adapterProperties.deviceID &&
|
||||
properties.vendorID == mParam.adapterProperties.vendorID &&
|
||||
properties.adapterType == mParam.adapterProperties.adapterType &&
|
||||
properties.backendType == mParam.adapterProperties.backendType &&
|
||||
strcmp(properties.name, mParam.adapterProperties.adapterName.c_str()) == 0);
|
||||
});
|
||||
ASSERT(it != adapters.end());
|
||||
mBackendAdapter = *it;
|
||||
}
|
||||
|
||||
// Setup the per-test platform. Tests can provide one by overloading CreateTestPlatform. This is
|
||||
// NOT a thread-safe operation and is allowed here for testing only.
|
||||
mTestPlatform = CreateTestPlatform();
|
||||
dawn::native::FromAPI(gTestEnv->GetInstance()->Get())
|
||||
->SetPlatformForTesting(mTestPlatform.get());
|
||||
|
||||
std::string traceName =
|
||||
std::string(::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name()) +
|
||||
"_" + ::testing::UnitTest::GetInstance()->current_test_info()->name();
|
||||
mWireHelper->BeginWireTrace(traceName.c_str());
|
||||
|
||||
// Create the device from the adapter
|
||||
std::tie(device, backendDevice) = CreateDeviceImpl();
|
||||
ASSERT_NE(nullptr, backendDevice);
|
||||
|
||||
queue = device.GetQueue();
|
||||
|
||||
#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
|
||||
if (IsOpenGL()) {
|
||||
glfwMakeContextCurrent(gTestEnv->GetOpenGLWindow());
|
||||
}
|
||||
#endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
|
||||
#if defined(DAWN_ENABLE_BACKEND_OPENGLES)
|
||||
if (IsOpenGLES()) {
|
||||
glfwMakeContextCurrent(gTestEnv->GetOpenGLESWindow());
|
||||
}
|
||||
#endif // defined(DAWN_ENABLE_BACKEND_OPENGLES)
|
||||
}
|
||||
|
||||
void DawnTestBase::TearDown() {
|
||||
|
@ -1033,50 +1052,36 @@ void DawnTestBase::TearDown() {
|
|||
EXPECT_EQ(mLastWarningCount,
|
||||
dawn::native::GetDeprecationWarningCountForTesting(device.Get()));
|
||||
}
|
||||
|
||||
// The device will be destroyed soon after, so we want to set the expectation.
|
||||
ExpectDeviceDestruction();
|
||||
}
|
||||
|
||||
void DawnTestBase::StartExpectDeviceError(testing::Matcher<std::string> errorMatcher) {
|
||||
mExpectError = true;
|
||||
mError = false;
|
||||
mErrorMatcher = errorMatcher;
|
||||
}
|
||||
|
||||
bool DawnTestBase::EndExpectDeviceError() {
|
||||
mExpectError = false;
|
||||
mErrorMatcher = testing::_;
|
||||
return mError;
|
||||
}
|
||||
|
||||
void DawnTestBase::ExpectDeviceDestruction() {
|
||||
mExpectDestruction = true;
|
||||
}
|
||||
|
||||
// static
|
||||
void DawnTestBase::OnDeviceError(WGPUErrorType type, const char* message, void* userdata) {
|
||||
ASSERT(type != WGPUErrorType_NoError);
|
||||
DawnTestBase* self = static_cast<DawnTestBase*>(userdata);
|
||||
|
||||
ASSERT_TRUE(self->mExpectError) << "Got unexpected device error: " << message;
|
||||
ASSERT_FALSE(self->mError) << "Got two errors in expect block";
|
||||
if (self->mExpectError) {
|
||||
ASSERT_THAT(message, self->mErrorMatcher);
|
||||
void DawnTestBase::DestroyDevice(wgpu::Device device) {
|
||||
wgpu::Device resolvedDevice;
|
||||
if (device != nullptr) {
|
||||
resolvedDevice = device;
|
||||
} else {
|
||||
resolvedDevice = this->device;
|
||||
}
|
||||
self->mError = true;
|
||||
EXPECT_CALL(mDeviceLostCallback,
|
||||
Call(WGPUDeviceLostReason_Destroyed, testing::_, resolvedDevice.Get()))
|
||||
.Times(1);
|
||||
resolvedDevice.Destroy();
|
||||
FlushWire();
|
||||
testing::Mock::VerifyAndClearExpectations(&mDeviceLostCallback);
|
||||
}
|
||||
|
||||
void DawnTestBase::OnDeviceLost(WGPUDeviceLostReason reason, const char* message, void* userdata) {
|
||||
DawnTestBase* self = static_cast<DawnTestBase*>(userdata);
|
||||
if (self->mExpectDestruction) {
|
||||
EXPECT_EQ(reason, WGPUDeviceLostReason_Destroyed);
|
||||
return;
|
||||
void DawnTestBase::LoseDeviceForTesting(wgpu::Device device) {
|
||||
wgpu::Device resolvedDevice;
|
||||
if (device != nullptr) {
|
||||
resolvedDevice = device;
|
||||
} else {
|
||||
resolvedDevice = this->device;
|
||||
}
|
||||
// Using ADD_FAILURE + ASSERT instead of FAIL to prevent the current test from continuing with a
|
||||
// corrupt state.
|
||||
ADD_FAILURE() << "Device lost during test: " << message;
|
||||
ASSERT(false);
|
||||
EXPECT_CALL(mDeviceLostCallback,
|
||||
Call(WGPUDeviceLostReason_Undefined, testing::_, resolvedDevice.Get()))
|
||||
.Times(1);
|
||||
resolvedDevice.LoseForTesting();
|
||||
FlushWire();
|
||||
testing::Mock::VerifyAndClearExpectations(&mDeviceLostCallback);
|
||||
}
|
||||
|
||||
std::ostringstream& DawnTestBase::AddBufferExpectation(const char* file,
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "dawn/dawn_proc_table.h"
|
||||
#include "dawn/native/DawnNative.h"
|
||||
#include "dawn/platform/DawnPlatform.h"
|
||||
#include "dawn/tests/MockCallback.h"
|
||||
#include "dawn/tests/ParamGenerator.h"
|
||||
#include "dawn/tests/ToggleParser.h"
|
||||
#include "dawn/utils/ScopedAutoreleasePool.h"
|
||||
|
@ -100,16 +101,22 @@
|
|||
#define EXPECT_TEXTURE_FLOAT16_EQ(...) \
|
||||
AddTextureExpectation<float, uint16_t>(__FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
#define ASSERT_DEVICE_ERROR_MSG(statement, matcher) \
|
||||
StartExpectDeviceError(matcher); \
|
||||
statement; \
|
||||
FlushWire(); \
|
||||
if (!EndExpectDeviceError()) { \
|
||||
FAIL() << "Expected device error in:\n " << #statement; \
|
||||
} \
|
||||
do { \
|
||||
#define ASSERT_DEVICE_ERROR_MSG_ON(device, statement, matcher) \
|
||||
FlushWire(); \
|
||||
EXPECT_CALL(mDeviceErrorCallback, \
|
||||
Call(testing::Ne(WGPUErrorType_NoError), matcher, device.Get())); \
|
||||
statement; \
|
||||
FlushWire(); \
|
||||
testing::Mock::VerifyAndClearExpectations(&mDeviceErrorCallback); \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT_DEVICE_ERROR_MSG(statement, matcher) \
|
||||
ASSERT_DEVICE_ERROR_MSG_ON(this->device, statement, matcher)
|
||||
|
||||
#define ASSERT_DEVICE_ERROR_ON(device, statement) \
|
||||
ASSERT_DEVICE_ERROR_MSG_ON(device, statement, testing::_)
|
||||
|
||||
#define ASSERT_DEVICE_ERROR(statement) ASSERT_DEVICE_ERROR_MSG(statement, testing::_)
|
||||
|
||||
struct RGBA8 {
|
||||
|
@ -311,10 +318,8 @@ class DawnTestBase {
|
|||
|
||||
bool HasToggleEnabled(const char* workaround) const;
|
||||
|
||||
void StartExpectDeviceError(testing::Matcher<std::string> errorMatcher = testing::_);
|
||||
bool EndExpectDeviceError();
|
||||
|
||||
void ExpectDeviceDestruction();
|
||||
void DestroyDevice(wgpu::Device device = nullptr);
|
||||
void LoseDeviceForTesting(wgpu::Device device = nullptr);
|
||||
|
||||
bool HasVendorIdFilter() const;
|
||||
uint32_t GetVendorIdFilter() const;
|
||||
|
@ -348,6 +353,11 @@ class DawnTestBase {
|
|||
|
||||
size_t mLastWarningCount = 0;
|
||||
|
||||
// Mock callbacks tracking errors and destruction. Device lost is a nice mock since tests that
|
||||
// do not care about device destruction can ignore the callback entirely.
|
||||
testing::MockCallback<WGPUErrorCallback> mDeviceErrorCallback;
|
||||
testing::NiceMock<testing::MockCallback<WGPUDeviceLostCallback>> mDeviceLostCallback;
|
||||
|
||||
// Helper methods to implement the EXPECT_ macros
|
||||
std::ostringstream& AddBufferExpectation(const char* file,
|
||||
int line,
|
||||
|
@ -512,6 +522,9 @@ class DawnTestBase {
|
|||
|
||||
bool SupportsFeatures(const std::vector<wgpu::FeatureName>& features);
|
||||
|
||||
// Exposed device creation helper for tests to use when needing more than 1 device.
|
||||
wgpu::Device CreateDevice(std::string isolationKey = "");
|
||||
|
||||
// Called in SetUp() to get the features required to be enabled in the tests. The tests must
|
||||
// check if the required features are supported by the adapter in this function and guarantee
|
||||
// the returned features are all supported by the adapter. The tests may provide different
|
||||
|
@ -532,13 +545,8 @@ class DawnTestBase {
|
|||
AdapterTestParam mParam;
|
||||
std::unique_ptr<utils::WireHelper> mWireHelper;
|
||||
|
||||
// Tracking for validation errors
|
||||
static void OnDeviceError(WGPUErrorType type, const char* message, void* userdata);
|
||||
static void OnDeviceLost(WGPUDeviceLostReason reason, const char* message, void* userdata);
|
||||
bool mExpectError = false;
|
||||
bool mError = false;
|
||||
testing::Matcher<std::string> mErrorMatcher;
|
||||
bool mExpectDestruction = false;
|
||||
// Internal device creation function for default device creation with some optional overrides.
|
||||
std::pair<wgpu::Device, WGPUDevice> CreateDeviceImpl(std::string isolationKey = "");
|
||||
|
||||
std::ostringstream& AddTextureExpectationImpl(const char* file,
|
||||
int line,
|
||||
|
|
|
@ -440,8 +440,7 @@ TEST_P(CreatePipelineAsyncTest, DestroyDeviceBeforeCallbackOfCreateComputePipeli
|
|||
task->message = message;
|
||||
},
|
||||
&task);
|
||||
ExpectDeviceDestruction();
|
||||
device.Destroy();
|
||||
DestroyDevice();
|
||||
}
|
||||
|
||||
// Verify there is no error when the device is destroyed before the callback of
|
||||
|
@ -474,8 +473,7 @@ TEST_P(CreatePipelineAsyncTest, DestroyDeviceBeforeCallbackOfCreateRenderPipelin
|
|||
task->message = message;
|
||||
},
|
||||
&task);
|
||||
ExpectDeviceDestruction();
|
||||
device.Destroy();
|
||||
DestroyDevice();
|
||||
}
|
||||
|
||||
// Verify the code path of CreateComputePipelineAsync() to directly return the compute pipeline
|
||||
|
|
|
@ -173,10 +173,7 @@ TEST_P(DestroyTest, DestroyDeviceBeforeSubmit) {
|
|||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||
wgpu::CommandBuffer commands = CreateTriangleCommandBuffer();
|
||||
|
||||
// Tests normally don't expect a device lost error, but since we are destroying the device, we
|
||||
// actually do, so we need to override the default device lost callback.
|
||||
ExpectDeviceDestruction();
|
||||
device.Destroy();
|
||||
DestroyDevice();
|
||||
ASSERT_DEVICE_ERROR_MSG(queue.Submit(1, &commands), HasSubstr("[Device] is lost."));
|
||||
}
|
||||
|
||||
|
@ -190,10 +187,7 @@ TEST_P(DestroyTest, DestroyDeviceLingeringBGL) {
|
|||
device, {{0, wgpu::ShaderStage::Fragment, wgpu::SamplerBindingType::Filtering}});
|
||||
utils::MakeBindGroup(device, layout, {{0, device.CreateSampler()}});
|
||||
|
||||
// Tests normally don't expect a device lost error, but since we are destroying the device, we
|
||||
// actually do, so we need to override the default device lost callback.
|
||||
ExpectDeviceDestruction();
|
||||
device.Destroy();
|
||||
DestroyDevice();
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(DestroyTest,
|
||||
|
|
|
@ -26,20 +26,6 @@ using testing::_;
|
|||
using testing::Exactly;
|
||||
using testing::MockCallback;
|
||||
|
||||
class MockDeviceLostCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUDeviceLostReason reason, const char* message, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockDeviceLostCallback> mockDeviceLostCallback;
|
||||
static void ToMockDeviceLostCallback(WGPUDeviceLostReason reason,
|
||||
const char* message,
|
||||
void* userdata) {
|
||||
mockDeviceLostCallback->Call(reason, message, userdata);
|
||||
DawnTestBase* self = static_cast<DawnTestBase*>(userdata);
|
||||
self->StartExpectDeviceError();
|
||||
}
|
||||
|
||||
class MockQueueWorkDoneCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
||||
|
@ -57,26 +43,14 @@ class DeviceLostTest : public DawnTest {
|
|||
void SetUp() override {
|
||||
DawnTest::SetUp();
|
||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||
mockDeviceLostCallback = std::make_unique<MockDeviceLostCallback>();
|
||||
mockQueueWorkDoneCallback = std::make_unique<MockQueueWorkDoneCallback>();
|
||||
// SetDeviceLostCallback will trigger the callback task manager and clean all deferred
|
||||
// callback tasks, so it should be called at the beginning of each test to prevent
|
||||
// unexpectedly triggering callback tasks created during test
|
||||
device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
mockDeviceLostCallback = nullptr;
|
||||
mockQueueWorkDoneCallback = nullptr;
|
||||
DawnTest::TearDown();
|
||||
}
|
||||
|
||||
void LoseForTesting() {
|
||||
EXPECT_CALL(*mockDeviceLostCallback, Call(WGPUDeviceLostReason_Undefined, _, this))
|
||||
.Times(1);
|
||||
device.LoseForTesting();
|
||||
}
|
||||
|
||||
static void MapFailCallback(WGPUBufferMapAsyncStatus status, void* userdata) {
|
||||
EXPECT_EQ(WGPUBufferMapAsyncStatus_DeviceLost, status);
|
||||
EXPECT_EQ(&fakeUserData, userdata);
|
||||
|
@ -85,7 +59,7 @@ class DeviceLostTest : public DawnTest {
|
|||
|
||||
// Test that DeviceLostCallback is invoked when LostForTestimg is called
|
||||
TEST_P(DeviceLostTest, DeviceLostCallbackIsCalled) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
}
|
||||
|
||||
// Test that submit fails when device is lost
|
||||
|
@ -94,13 +68,13 @@ TEST_P(DeviceLostTest, SubmitFails) {
|
|||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
commands = encoder.Finish();
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(queue.Submit(0, &commands));
|
||||
}
|
||||
|
||||
// Test that CreateBindGroupLayout fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateBindGroupLayoutFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
wgpu::BindGroupLayoutEntry entry;
|
||||
entry.binding = 0;
|
||||
|
@ -129,13 +103,13 @@ TEST_P(DeviceLostTest, GetBindGroupLayoutFails) {
|
|||
|
||||
wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&descriptor);
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(pipeline.GetBindGroupLayout(0).Get());
|
||||
}
|
||||
|
||||
// Test that CreateBindGroup fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateBindGroupFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
wgpu::BindGroupEntry entry;
|
||||
entry.binding = 0;
|
||||
|
@ -154,7 +128,7 @@ TEST_P(DeviceLostTest, CreateBindGroupFails) {
|
|||
|
||||
// Test that CreatePipelineLayout fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreatePipelineLayoutFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
wgpu::PipelineLayoutDescriptor descriptor;
|
||||
descriptor.bindGroupLayoutCount = 0;
|
||||
|
@ -164,7 +138,7 @@ TEST_P(DeviceLostTest, CreatePipelineLayoutFails) {
|
|||
|
||||
// Tests that CreateRenderBundleEncoder fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateRenderBundleEncoderFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
wgpu::RenderBundleEncoderDescriptor descriptor;
|
||||
descriptor.colorFormatsCount = 0;
|
||||
|
@ -174,7 +148,7 @@ TEST_P(DeviceLostTest, CreateRenderBundleEncoderFails) {
|
|||
|
||||
// Tests that CreateComputePipeline fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateComputePipelineFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
wgpu::ComputePipelineDescriptor descriptor = {};
|
||||
descriptor.layout = nullptr;
|
||||
|
@ -184,7 +158,7 @@ TEST_P(DeviceLostTest, CreateComputePipelineFails) {
|
|||
|
||||
// Tests that CreateRenderPipeline fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateRenderPipelineFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
utils::ComboRenderPipelineDescriptor descriptor;
|
||||
ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
|
||||
|
@ -192,14 +166,14 @@ TEST_P(DeviceLostTest, CreateRenderPipelineFails) {
|
|||
|
||||
// Tests that CreateSampler fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateSamplerFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
ASSERT_DEVICE_ERROR(device.CreateSampler());
|
||||
}
|
||||
|
||||
// Tests that CreateShaderModule fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateShaderModuleFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, R"(
|
||||
@stage(fragment)
|
||||
|
@ -210,7 +184,7 @@ TEST_P(DeviceLostTest, CreateShaderModuleFails) {
|
|||
|
||||
// Tests that CreateSwapChain fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateSwapChainFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
wgpu::SwapChainDescriptor descriptor = {};
|
||||
ASSERT_DEVICE_ERROR(device.CreateSwapChain(nullptr, &descriptor));
|
||||
|
@ -218,7 +192,7 @@ TEST_P(DeviceLostTest, CreateSwapChainFails) {
|
|||
|
||||
// Tests that CreateTexture fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateTextureFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.size.width = 4;
|
||||
|
@ -233,7 +207,7 @@ TEST_P(DeviceLostTest, CreateTextureFails) {
|
|||
|
||||
// Test that CreateBuffer fails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateBufferFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
wgpu::BufferDescriptor bufferDescriptor;
|
||||
bufferDescriptor.size = sizeof(float);
|
||||
|
@ -248,7 +222,7 @@ TEST_P(DeviceLostTest, BufferMapAsyncFailsForWriting) {
|
|||
bufferDescriptor.usage = wgpu::BufferUsage::MapWrite;
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(buffer.MapAsync(wgpu::MapMode::Write, 0, 4, MapFailCallback,
|
||||
const_cast<int*>(&fakeUserData)));
|
||||
}
|
||||
|
@ -263,7 +237,7 @@ TEST_P(DeviceLostTest, BufferMapAsyncBeforeLossFailsForWriting) {
|
|||
|
||||
buffer.MapAsync(wgpu::MapMode::Write, 0, 4, MapFailCallback, const_cast<int*>(&fakeUserData));
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
}
|
||||
|
||||
// Test that buffer.Unmap fails after device is lost
|
||||
|
@ -274,7 +248,7 @@ TEST_P(DeviceLostTest, BufferUnmapFails) {
|
|||
bufferDescriptor.mappedAtCreation = true;
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(buffer.Unmap());
|
||||
}
|
||||
|
||||
|
@ -285,7 +259,7 @@ TEST_P(DeviceLostTest, CreateBufferMappedAtCreationFails) {
|
|||
bufferDescriptor.usage = wgpu::BufferUsage::MapWrite;
|
||||
bufferDescriptor.mappedAtCreation = true;
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(device.CreateBuffer(&bufferDescriptor));
|
||||
}
|
||||
|
||||
|
@ -297,7 +271,7 @@ TEST_P(DeviceLostTest, BufferMapAsyncFailsForReading) {
|
|||
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(buffer.MapAsync(wgpu::MapMode::Read, 0, 4, MapFailCallback,
|
||||
const_cast<int*>(&fakeUserData)));
|
||||
}
|
||||
|
@ -313,7 +287,7 @@ TEST_P(DeviceLostTest, BufferMapAsyncBeforeLossFailsForReading) {
|
|||
|
||||
buffer.MapAsync(wgpu::MapMode::Read, 0, 4, MapFailCallback, const_cast<int*>(&fakeUserData));
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
}
|
||||
|
||||
// Test that WriteBuffer fails after device is lost
|
||||
|
@ -324,14 +298,14 @@ TEST_P(DeviceLostTest, WriteBufferFails) {
|
|||
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
float data = 12.0f;
|
||||
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buffer, 0, &data, sizeof(data)));
|
||||
}
|
||||
|
||||
// Test it's possible to GetMappedRange on a buffer created mapped after device loss
|
||||
TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedAtCreationAfterLoss) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
wgpu::BufferDescriptor desc;
|
||||
desc.size = 4;
|
||||
|
@ -351,7 +325,7 @@ TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedAtCreationBeforeLoss) {
|
|||
wgpu::Buffer buffer = device.CreateBuffer(&desc);
|
||||
|
||||
void* rangeBeforeLoss = buffer.GetMappedRange();
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
ASSERT_NE(buffer.GetMappedRange(), nullptr);
|
||||
ASSERT_EQ(buffer.GetMappedRange(), rangeBeforeLoss);
|
||||
|
@ -368,7 +342,7 @@ TEST_P(DeviceLostTest, GetMappedRange_MapAsyncReading) {
|
|||
queue.Submit(0, nullptr);
|
||||
|
||||
const void* rangeBeforeLoss = buffer.GetConstMappedRange();
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
|
||||
ASSERT_EQ(buffer.GetConstMappedRange(), rangeBeforeLoss);
|
||||
|
@ -385,7 +359,7 @@ TEST_P(DeviceLostTest, GetMappedRange_MapAsyncWriting) {
|
|||
queue.Submit(0, nullptr);
|
||||
|
||||
const void* rangeBeforeLoss = buffer.GetConstMappedRange();
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
|
||||
ASSERT_EQ(buffer.GetConstMappedRange(), rangeBeforeLoss);
|
||||
|
@ -399,13 +373,13 @@ TEST_P(DeviceLostTest, CommandEncoderFinishFails) {
|
|||
wgpu::CommandBuffer commands;
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Test that QueueOnSubmittedWorkDone fails after device is lost.
|
||||
TEST_P(DeviceLostTest, QueueOnSubmittedWorkDoneFails) {
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
// callback should have device lost status
|
||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_DeviceLost, nullptr))
|
||||
|
@ -420,33 +394,29 @@ TEST_P(DeviceLostTest, QueueOnSubmittedWorkDoneBeforeLossFails) {
|
|||
.Times(1);
|
||||
queue.OnSubmittedWorkDone(0, ToMockQueueWorkDone, nullptr);
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
}
|
||||
|
||||
// Test that LostForTesting can only be called on one time
|
||||
TEST_P(DeviceLostTest, LoseForTestingOnce) {
|
||||
// First LoseForTesting call should occur normally. The callback is already set in SetUp.
|
||||
EXPECT_CALL(*mockDeviceLostCallback, Call(WGPUDeviceLostReason_Undefined, _, this)).Times(1);
|
||||
device.LoseForTesting();
|
||||
TEST_P(DeviceLostTest, LoseDeviceForTestingOnce) {
|
||||
// First LoseDeviceForTesting call should occur normally. The callback is already set in SetUp.
|
||||
LoseDeviceForTesting();
|
||||
|
||||
// Second LoseForTesting call should result in no callbacks. The LoseForTesting will return
|
||||
// without doing anything when it sees that device has already been lost.
|
||||
device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
|
||||
EXPECT_CALL(*mockDeviceLostCallback, Call(_, _, this)).Times(0);
|
||||
// Second LoseDeviceForTesting call should result in no callbacks. Note we also reset the
|
||||
// callback first since by default the device clears the callback after the device is lost.
|
||||
device.SetDeviceLostCallback(mDeviceLostCallback.Callback(),
|
||||
mDeviceLostCallback.MakeUserdata(device.Get()));
|
||||
EXPECT_CALL(mDeviceLostCallback, Call(WGPUDeviceLostReason_Undefined, testing::_, device.Get()))
|
||||
.Times(0);
|
||||
device.LoseForTesting();
|
||||
FlushWire();
|
||||
testing::Mock::VerifyAndClearExpectations(&mDeviceLostCallback);
|
||||
}
|
||||
|
||||
TEST_P(DeviceLostTest, DeviceLostDoesntCallUncapturedError) {
|
||||
// Set no callback.
|
||||
device.SetDeviceLostCallback(nullptr, nullptr);
|
||||
|
||||
// Set the uncaptured error callback which should not be called on
|
||||
// device lost.
|
||||
MockCallback<WGPUErrorCallback> mockErrorCallback;
|
||||
device.SetUncapturedErrorCallback(mockErrorCallback.Callback(),
|
||||
mockErrorCallback.MakeUserdata(nullptr));
|
||||
EXPECT_CALL(mockErrorCallback, Call(_, _, _)).Times(Exactly(0));
|
||||
device.LoseForTesting();
|
||||
// Since the device has a default error callback set that fails if it is called, we just need
|
||||
// to lose the device and verify no failures.
|
||||
LoseDeviceForTesting();
|
||||
}
|
||||
|
||||
// Test that WGPUCreatePipelineAsyncStatus_DeviceLost can be correctly returned when device is lost
|
||||
|
@ -466,7 +436,7 @@ TEST_P(DeviceLostTest, DeviceLostBeforeCreatePipelineAsyncCallback) {
|
|||
};
|
||||
|
||||
device.CreateComputePipelineAsync(&descriptor, callback, nullptr);
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
}
|
||||
|
||||
// This is a regression test for crbug.com/1212385 where Dawn didn't clean up all
|
||||
|
@ -493,7 +463,7 @@ TEST_P(DeviceLostTest, FreeBindGroupAfterDeviceLossWithPendingCommands) {
|
|||
queue.Submit(0, nullptr);
|
||||
queue.Submit(0, nullptr);
|
||||
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
|
||||
// Releasing the bing group places the bind group layout into a queue in the Vulkan backend
|
||||
// for recycling of descriptor sets. So, after these release calls there is still one last
|
||||
|
@ -513,7 +483,7 @@ TEST_P(DeviceLostTest, SetLabelAfterDeviceLoss) {
|
|||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::Uniform;
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
|
||||
LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
buffer.SetLabel(label.c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ TEST_P(SwapChainTests, SwitchingDevice) {
|
|||
// See https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/2256
|
||||
DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsBackendValidationEnabled());
|
||||
|
||||
wgpu::Device device2 = wgpu::Device::Acquire(GetAdapter().CreateDevice());
|
||||
wgpu::Device device2 = CreateDevice();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
wgpu::Device deviceToUse;
|
||||
|
|
|
@ -319,38 +319,26 @@ TEST_P(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_After
|
|||
ASSERT_DEVICE_ERROR(replacedSwapChain.Present());
|
||||
}
|
||||
|
||||
// Test that after Device is Lost, all swap chain operations fail
|
||||
static void ToMockDeviceLostCallback(WGPUDeviceLostReason reason,
|
||||
const char* message,
|
||||
void* userdata) {
|
||||
DawnTest* self = static_cast<DawnTest*>(userdata);
|
||||
self->StartExpectDeviceError();
|
||||
}
|
||||
|
||||
// Test that new swap chain present fails after device is lost
|
||||
TEST_P(SwapChainValidationTests, NewSwapChainPresentFailsAfterDeviceLost) {
|
||||
device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
wgpu::TextureView view = swapchain.GetCurrentTextureView();
|
||||
|
||||
device.LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(swapchain.Present());
|
||||
}
|
||||
|
||||
// Test that new swap chain get current texture view fails after device is lost
|
||||
TEST_P(SwapChainValidationTests, NewSwapChainGetCurrentTextureViewFailsAfterDevLost) {
|
||||
device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
|
||||
wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
|
||||
|
||||
device.LoseForTesting();
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(swapchain.GetCurrentTextureView());
|
||||
}
|
||||
|
||||
// Test that creation of a new swapchain fails after device is lost
|
||||
TEST_P(SwapChainValidationTests, CreateNewSwapChainFailsAfterDevLost) {
|
||||
device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
|
||||
device.LoseForTesting();
|
||||
|
||||
LoseDeviceForTesting();
|
||||
ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &goodDescriptor));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue