blob: ccc5bdbd4756a09fc47da664d0bc82c142a359fd [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/client/webgpu_implementation.h"
#include "gpu/command_buffer/tests/webgpu_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class MockFenceOnCompletionCallback {
public:
MOCK_METHOD2(Call, void(WGPUFenceCompletionStatus status, void* userdata));
};
std::unique_ptr<MockFenceOnCompletionCallback> mockFenceOnCompletionCallback;
void ToMockFenceOnCompletionCallback(WGPUFenceCompletionStatus status,
void* userdata) {
mockFenceOnCompletionCallback->Call(status, userdata);
}
} // namespace
namespace gpu {
class WebGPUFenceTest : public WebGPUTest {
protected:
void SetUp() override {
WebGPUTest::SetUp();
Initialize(WebGPUTest::Options());
mockFenceOnCompletionCallback =
std::make_unique<MockFenceOnCompletionCallback>();
}
void TearDown() override {
mockFenceOnCompletionCallback = nullptr;
WebGPUTest::TearDown();
}
void WaitForFence(wgpu::Device device, wgpu::Fence fence, uint64_t value) {
while (fence.GetCompletedValue() < value) {
device.Tick();
webgpu()->FlushCommands();
RunPendingTasks();
}
}
};
// Test that getting the value of the fence is the initial value.
TEST_F(WebGPUFenceTest, InitialValue) {
if (!WebGPUSupported()) {
LOG(ERROR) << "Test skipped";
return;
}
DeviceAndClientID device_and_id = GetNewDeviceAndClientID();
wgpu::Device device = device_and_id.device;
wgpu::Queue queue = device.GetDefaultQueue();
{
wgpu::FenceDescriptor fence_desc{nullptr, nullptr, 0};
wgpu::Fence fence = queue.CreateFence(&fence_desc);
EXPECT_EQ(fence.GetCompletedValue(), 0u);
}
{
wgpu::FenceDescriptor fence_desc{nullptr, nullptr, 2};
wgpu::Fence fence = queue.CreateFence(&fence_desc);
EXPECT_EQ(fence.GetCompletedValue(), 2u);
}
}
// Test that after signaling a fence, its completed value gets updated.
TEST_F(WebGPUFenceTest, GetCompletedValue) {
if (!WebGPUSupported()) {
LOG(ERROR) << "Test skipped";
return;
}
DeviceAndClientID device_and_id = GetNewDeviceAndClientID();
wgpu::Device device = device_and_id.device;
wgpu::Queue queue = device.GetDefaultQueue();
wgpu::FenceDescriptor fence_desc{nullptr, nullptr, 0};
wgpu::Fence fence = queue.CreateFence(&fence_desc);
queue.Signal(fence, 2u);
WaitForFence(device, fence, 2u);
EXPECT_EQ(fence.GetCompletedValue(), 2u);
}
// Test that a fence's OnCompletion handler is called after the signal value
// is completed.
TEST_F(WebGPUFenceTest, OnCompletion) {
if (!WebGPUSupported()) {
LOG(ERROR) << "Test skipped";
return;
}
DeviceAndClientID device_and_id = GetNewDeviceAndClientID();
wgpu::Device device = device_and_id.device;
wgpu::Queue queue = device.GetDefaultQueue();
wgpu::FenceDescriptor fence_desc{nullptr, nullptr, 0};
wgpu::Fence fence = queue.CreateFence(&fence_desc);
queue.Signal(fence, 2u);
EXPECT_CALL(*mockFenceOnCompletionCallback,
Call(WGPUFenceCompletionStatus_Success, this))
.Times(1);
fence.OnCompletion(2u, ToMockFenceOnCompletionCallback, this);
WaitForFence(device, fence, 2u);
}
// Test signaling a fence a million times.
TEST_F(WebGPUFenceTest, SignalManyTimes) {
if (!WebGPUSupported()) {
LOG(ERROR) << "Test skipped";
return;
}
DeviceAndClientID device_and_id = GetNewDeviceAndClientID();
wgpu::Device device = device_and_id.device;
wgpu::Queue queue = device.GetDefaultQueue();
wgpu::FenceDescriptor fence_desc{nullptr, nullptr, 0};
wgpu::Fence fence = queue.CreateFence(&fence_desc);
uint64_t max_value = 1000000u;
for (uint64_t i = 1; i <= max_value; ++i) {
queue.Signal(fence, i);
}
WaitForFence(device, fence, max_value);
EXPECT_EQ(fence.GetCompletedValue(), max_value);
}
} // namespace gpu