Special-case GetDefaultQueue in the wire
Reland with a fix where commands only start being serialized by the device after the first GetDevice() is called, not in the constructor. This makes it so calling GetDefaultQueue always returns the same object. It required updating various WireTests to account for the additional wire calls. Bug: dawn:22 Change-Id: Ibe43d84b25100f58a9ec5029a9341e400aec97f6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/19982 Commit-Queue: Kai Ninomiya <kainino@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
parent
b46d002057
commit
409cf67207
|
@ -101,6 +101,7 @@
|
||||||
"BufferUnmap",
|
"BufferUnmap",
|
||||||
"DeviceCreateBuffer",
|
"DeviceCreateBuffer",
|
||||||
"DeviceCreateBufferMapped",
|
"DeviceCreateBufferMapped",
|
||||||
|
"DeviceGetDefaultQueue",
|
||||||
"DevicePushErrorScope",
|
"DevicePushErrorScope",
|
||||||
"QueueCreateFence",
|
"QueueCreateFence",
|
||||||
"QueueSignal"
|
"QueueSignal"
|
||||||
|
|
|
@ -370,6 +370,11 @@ namespace dawn_wire { namespace client {
|
||||||
void ClientDeviceRelease(WGPUDevice) {
|
void ClientDeviceRelease(WGPUDevice) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WGPUQueue ClientHandwrittenDeviceGetDefaultQueue(WGPUDevice cSelf) {
|
||||||
|
Device* device = reinterpret_cast<Device*>(cSelf);
|
||||||
|
return device->GetDefaultQueue();
|
||||||
|
}
|
||||||
|
|
||||||
void ClientHandwrittenDeviceSetUncapturedErrorCallback(WGPUDevice cSelf,
|
void ClientHandwrittenDeviceSetUncapturedErrorCallback(WGPUDevice cSelf,
|
||||||
WGPUErrorCallback callback,
|
WGPUErrorCallback callback,
|
||||||
void* userdata) {
|
void* userdata) {
|
||||||
|
|
|
@ -21,7 +21,6 @@ namespace dawn_wire { namespace client {
|
||||||
|
|
||||||
Client::Client(CommandSerializer* serializer, MemoryTransferService* memoryTransferService)
|
Client::Client(CommandSerializer* serializer, MemoryTransferService* memoryTransferService)
|
||||||
: ClientBase(),
|
: ClientBase(),
|
||||||
mDevice(DeviceAllocator().New(this)->object.get()),
|
|
||||||
mSerializer(serializer),
|
mSerializer(serializer),
|
||||||
mMemoryTransferService(memoryTransferService) {
|
mMemoryTransferService(memoryTransferService) {
|
||||||
if (mMemoryTransferService == nullptr) {
|
if (mMemoryTransferService == nullptr) {
|
||||||
|
@ -32,7 +31,16 @@ namespace dawn_wire { namespace client {
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client() {
|
Client::~Client() {
|
||||||
DeviceAllocator().Free(mDevice);
|
if (mDevice != nullptr) {
|
||||||
|
DeviceAllocator().Free(mDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUDevice Client::GetDevice() {
|
||||||
|
if (mDevice == nullptr) {
|
||||||
|
mDevice = DeviceAllocator().New(this)->object.get();
|
||||||
|
}
|
||||||
|
return reinterpret_cast<WGPUDeviceImpl*>(mDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservedTexture Client::ReserveTexture(WGPUDevice cDevice) {
|
ReservedTexture Client::ReserveTexture(WGPUDevice cDevice) {
|
||||||
|
@ -57,8 +65,12 @@ namespace dawn_wire { namespace client {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::Disconnect() {
|
void Client::Disconnect() {
|
||||||
if (!mIsDisconnected) {
|
if (mIsDisconnected) {
|
||||||
mIsDisconnected = true;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsDisconnected = true;
|
||||||
|
if (mDevice != nullptr) {
|
||||||
mDevice->HandleDeviceLost("GPU connection lost");
|
mDevice->HandleDeviceLost("GPU connection lost");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,7 @@ namespace dawn_wire { namespace client {
|
||||||
Client(CommandSerializer* serializer, MemoryTransferService* memoryTransferService);
|
Client(CommandSerializer* serializer, MemoryTransferService* memoryTransferService);
|
||||||
~Client();
|
~Client();
|
||||||
|
|
||||||
WGPUDevice GetDevice() const {
|
WGPUDevice GetDevice();
|
||||||
return reinterpret_cast<WGPUDeviceImpl*>(mDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryTransferService* GetMemoryTransferService() const {
|
MemoryTransferService* GetMemoryTransferService() const {
|
||||||
return mMemoryTransferService;
|
return mMemoryTransferService;
|
||||||
|
|
|
@ -16,20 +16,46 @@
|
||||||
|
|
||||||
#include "common/Assert.h"
|
#include "common/Assert.h"
|
||||||
#include "dawn_wire/WireCmd_autogen.h"
|
#include "dawn_wire/WireCmd_autogen.h"
|
||||||
|
#include "dawn_wire/client/ApiObjects_autogen.h"
|
||||||
#include "dawn_wire/client/Client.h"
|
#include "dawn_wire/client/Client.h"
|
||||||
|
#include "dawn_wire/client/ObjectAllocator.h"
|
||||||
|
|
||||||
namespace dawn_wire { namespace client {
|
namespace dawn_wire { namespace client {
|
||||||
|
|
||||||
Device::Device(Client* client, uint32_t initialRefcount, uint32_t initialId)
|
Device::Device(Client* client, uint32_t initialRefcount, uint32_t initialId)
|
||||||
: ObjectBase(this, initialRefcount, initialId), mClient(client) {
|
: ObjectBase(this, initialRefcount, initialId), mClient(client) {
|
||||||
this->device = this;
|
this->device = this;
|
||||||
|
|
||||||
|
// Get the default queue for this device.
|
||||||
|
ObjectAllocator<Queue>::ObjectAndSerial* allocation = mClient->QueueAllocator().New(this);
|
||||||
|
mDefaultQueue = allocation->object.get();
|
||||||
|
|
||||||
|
DeviceGetDefaultQueueCmd cmd;
|
||||||
|
cmd.self = reinterpret_cast<WGPUDevice>(this);
|
||||||
|
cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
|
||||||
|
|
||||||
|
size_t requiredSize = cmd.GetRequiredSize();
|
||||||
|
char* allocatedBuffer = static_cast<char*>(mClient->GetCmdSpace(requiredSize));
|
||||||
|
cmd.Serialize(allocatedBuffer, *mClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
|
// Fire pending error scopes
|
||||||
auto errorScopes = std::move(mErrorScopes);
|
auto errorScopes = std::move(mErrorScopes);
|
||||||
for (const auto& it : errorScopes) {
|
for (const auto& it : errorScopes) {
|
||||||
it.second.callback(WGPUErrorType_Unknown, "Device destroyed", it.second.userdata);
|
it.second.callback(WGPUErrorType_Unknown, "Device destroyed", it.second.userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy the default queue
|
||||||
|
DestroyObjectCmd cmd;
|
||||||
|
cmd.objectType = ObjectType::Queue;
|
||||||
|
cmd.objectId = mDefaultQueue->id;
|
||||||
|
|
||||||
|
size_t requiredSize = cmd.GetRequiredSize();
|
||||||
|
char* allocatedBuffer = static_cast<char*>(mClient->GetCmdSpace(requiredSize));
|
||||||
|
cmd.Serialize(allocatedBuffer);
|
||||||
|
|
||||||
|
mClient->QueueAllocator().Free(mDefaultQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
Client* Device::GetClient() {
|
Client* Device::GetClient() {
|
||||||
|
@ -119,4 +145,9 @@ namespace dawn_wire { namespace client {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WGPUQueue Device::GetDefaultQueue() {
|
||||||
|
mDefaultQueue->refcount++;
|
||||||
|
return reinterpret_cast<WGPUQueue>(mDefaultQueue);
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace dawn_wire::client
|
}} // namespace dawn_wire::client
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
namespace dawn_wire { namespace client {
|
namespace dawn_wire { namespace client {
|
||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
|
struct Queue;
|
||||||
|
|
||||||
class Device : public ObjectBase {
|
class Device : public ObjectBase {
|
||||||
public:
|
public:
|
||||||
|
@ -40,6 +41,8 @@ namespace dawn_wire { namespace client {
|
||||||
bool RequestPopErrorScope(WGPUErrorCallback callback, void* userdata);
|
bool RequestPopErrorScope(WGPUErrorCallback callback, void* userdata);
|
||||||
bool PopErrorScope(uint64_t requestSerial, WGPUErrorType type, const char* message);
|
bool PopErrorScope(uint64_t requestSerial, WGPUErrorType type, const char* message);
|
||||||
|
|
||||||
|
WGPUQueue GetDefaultQueue();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ErrorScopeData {
|
struct ErrorScopeData {
|
||||||
WGPUErrorCallback callback = nullptr;
|
WGPUErrorCallback callback = nullptr;
|
||||||
|
@ -53,8 +56,10 @@ namespace dawn_wire { namespace client {
|
||||||
WGPUErrorCallback mErrorCallback = nullptr;
|
WGPUErrorCallback mErrorCallback = nullptr;
|
||||||
WGPUDeviceLostCallback mDeviceLostCallback = nullptr;
|
WGPUDeviceLostCallback mDeviceLostCallback = nullptr;
|
||||||
bool mDidRunLostCallback = false;
|
bool mDidRunLostCallback = false;
|
||||||
void* mErrorUserdata;
|
void* mErrorUserdata = nullptr;
|
||||||
void* mDeviceLostUserdata;
|
void* mDeviceLostUserdata = nullptr;
|
||||||
|
|
||||||
|
Queue* mDefaultQueue = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace dawn_wire::client
|
}} // namespace dawn_wire::client
|
||||||
|
|
|
@ -25,7 +25,7 @@ class QueueTests : public DawnTest {};
|
||||||
TEST_P(QueueTests, GetDefaultQueueSameObject) {
|
TEST_P(QueueTests, GetDefaultQueueSameObject) {
|
||||||
wgpu::Queue q1 = device.GetDefaultQueue();
|
wgpu::Queue q1 = device.GetDefaultQueue();
|
||||||
wgpu::Queue q2 = device.GetDefaultQueue();
|
wgpu::Queue q2 = device.GetDefaultQueue();
|
||||||
EXPECT_EQ(q1.Get() == q2.Get(), !UsesWire());
|
EXPECT_EQ(q1.Get(), q2.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(QueueTests,
|
DAWN_INSTANTIATE_TEST(QueueTests,
|
||||||
|
|
|
@ -231,11 +231,6 @@ TEST_F(WireArgumentTests, ObjectsAsPointerArgument) {
|
||||||
.WillOnce(Return(apiCmdBufs[i]));
|
.WillOnce(Return(apiCmdBufs[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create queue
|
|
||||||
WGPUQueue queue = wgpuDeviceGetDefaultQueue(device);
|
|
||||||
WGPUQueue apiQueue = api.GetNewQueue();
|
|
||||||
EXPECT_CALL(api, DeviceGetDefaultQueue(apiDevice)).WillOnce(Return(apiQueue));
|
|
||||||
|
|
||||||
// Submit command buffer and check we got a call with both API-side command buffers
|
// Submit command buffer and check we got a call with both API-side command buffers
|
||||||
wgpuQueueSubmit(queue, 2, cmdBufs);
|
wgpuQueueSubmit(queue, 2, cmdBufs);
|
||||||
|
|
||||||
|
|
|
@ -43,12 +43,6 @@ class WireFenceTests : public WireTest {
|
||||||
mockFenceOnCompletionCallback =
|
mockFenceOnCompletionCallback =
|
||||||
std::make_unique<StrictMock<MockFenceOnCompletionCallback>>();
|
std::make_unique<StrictMock<MockFenceOnCompletionCallback>>();
|
||||||
|
|
||||||
{
|
|
||||||
queue = wgpuDeviceGetDefaultQueue(device);
|
|
||||||
apiQueue = api.GetNewQueue();
|
|
||||||
EXPECT_CALL(api, DeviceGetDefaultQueue(apiDevice)).WillOnce(Return(apiQueue));
|
|
||||||
FlushClient();
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
WGPUFenceDescriptor descriptor = {};
|
WGPUFenceDescriptor descriptor = {};
|
||||||
descriptor.initialValue = 1;
|
descriptor.initialValue = 1;
|
||||||
|
@ -89,9 +83,6 @@ class WireFenceTests : public WireTest {
|
||||||
// A successfully created fence
|
// A successfully created fence
|
||||||
WGPUFence fence;
|
WGPUFence fence;
|
||||||
WGPUFence apiFence;
|
WGPUFence apiFence;
|
||||||
|
|
||||||
WGPUQueue queue;
|
|
||||||
WGPUQueue apiQueue;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check that signaling a fence succeeds
|
// Check that signaling a fence succeeds
|
||||||
|
@ -227,7 +218,8 @@ TEST_F(WireFenceTests, DestroyBeforeOnCompletionEnd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that signaling a fence on a wrong queue is invalid
|
// Test that signaling a fence on a wrong queue is invalid
|
||||||
TEST_F(WireFenceTests, SignalWrongQueue) {
|
// DISABLED until we have support for multiple queues.
|
||||||
|
TEST_F(WireFenceTests, DISABLED_SignalWrongQueue) {
|
||||||
WGPUQueue queue2 = wgpuDeviceGetDefaultQueue(device);
|
WGPUQueue queue2 = wgpuDeviceGetDefaultQueue(device);
|
||||||
WGPUQueue apiQueue2 = api.GetNewQueue();
|
WGPUQueue apiQueue2 = api.GetNewQueue();
|
||||||
EXPECT_CALL(api, DeviceGetDefaultQueue(apiDevice)).WillOnce(Return(apiQueue2));
|
EXPECT_CALL(api, DeviceGetDefaultQueue(apiDevice)).WillOnce(Return(apiQueue2));
|
||||||
|
@ -240,7 +232,8 @@ TEST_F(WireFenceTests, SignalWrongQueue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that signaling a fence on a wrong queue does not update fence signaled value
|
// Test that signaling a fence on a wrong queue does not update fence signaled value
|
||||||
TEST_F(WireFenceTests, SignalWrongQueueDoesNotUpdateValue) {
|
// DISABLED until we have support for multiple queues.
|
||||||
|
TEST_F(WireFenceTests, DISABLED_SignalWrongQueueDoesNotUpdateValue) {
|
||||||
WGPUQueue queue2 = wgpuDeviceGetDefaultQueue(device);
|
WGPUQueue queue2 = wgpuDeviceGetDefaultQueue(device);
|
||||||
WGPUQueue apiQueue2 = api.GetNewQueue();
|
WGPUQueue apiQueue2 = api.GetNewQueue();
|
||||||
EXPECT_CALL(api, DeviceGetDefaultQueue(apiDevice)).WillOnce(Return(apiQueue2));
|
EXPECT_CALL(api, DeviceGetDefaultQueue(apiDevice)).WillOnce(Return(apiQueue2));
|
||||||
|
|
|
@ -69,6 +69,12 @@ class WireMultipleDeviceTests : public testing::Test {
|
||||||
mS2cBuf->SetHandler(mWireClient.get());
|
mS2cBuf->SetHandler(mWireClient.get());
|
||||||
|
|
||||||
mClientDevice = mWireClient->GetDevice();
|
mClientDevice = mWireClient->GetDevice();
|
||||||
|
|
||||||
|
// The GetDefaultQueue is done on WireClient startup so we expect it now.
|
||||||
|
mClientQueue = wgpuDeviceGetDefaultQueue(mClientDevice);
|
||||||
|
mServerQueue = mApi.GetNewQueue();
|
||||||
|
EXPECT_CALL(mApi, DeviceGetDefaultQueue(mServerDevice)).WillOnce(Return(mServerQueue));
|
||||||
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
~WireHolder() {
|
~WireHolder() {
|
||||||
|
@ -97,6 +103,14 @@ class WireMultipleDeviceTests : public testing::Test {
|
||||||
return mServerDevice;
|
return mServerDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WGPUQueue ClientQueue() {
|
||||||
|
return mClientQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUQueue ServerQueue() {
|
||||||
|
return mServerQueue;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
testing::StrictMock<MockProcTable> mApi;
|
testing::StrictMock<MockProcTable> mApi;
|
||||||
std::unique_ptr<dawn_wire::WireServer> mWireServer;
|
std::unique_ptr<dawn_wire::WireServer> mWireServer;
|
||||||
|
@ -105,6 +119,8 @@ class WireMultipleDeviceTests : public testing::Test {
|
||||||
std::unique_ptr<utils::TerribleCommandBuffer> mC2sBuf;
|
std::unique_ptr<utils::TerribleCommandBuffer> mC2sBuf;
|
||||||
WGPUDevice mServerDevice;
|
WGPUDevice mServerDevice;
|
||||||
WGPUDevice mClientDevice;
|
WGPUDevice mClientDevice;
|
||||||
|
WGPUQueue mServerQueue;
|
||||||
|
WGPUQueue mClientQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ExpectInjectedError(WireHolder* wire) {
|
void ExpectInjectedError(WireHolder* wire) {
|
||||||
|
@ -134,20 +150,12 @@ TEST_F(WireMultipleDeviceTests, ValidatesSameDevice) {
|
||||||
WireHolder wireA;
|
WireHolder wireA;
|
||||||
WireHolder wireB;
|
WireHolder wireB;
|
||||||
|
|
||||||
// Create the objects
|
// Create the fence
|
||||||
WGPUQueue queueA = wgpuDeviceGetDefaultQueue(wireA.ClientDevice());
|
|
||||||
WGPUQueue queueB = wgpuDeviceGetDefaultQueue(wireB.ClientDevice());
|
|
||||||
|
|
||||||
WGPUFenceDescriptor desc = {};
|
WGPUFenceDescriptor desc = {};
|
||||||
WGPUFence fenceA = wgpuQueueCreateFence(queueA, &desc);
|
WGPUFence fenceA = wgpuQueueCreateFence(wireA.ClientQueue(), &desc);
|
||||||
|
|
||||||
// Flush on wire B. We should see the queue created.
|
|
||||||
EXPECT_CALL(*wireB.Api(), DeviceGetDefaultQueue(wireB.ServerDevice()))
|
|
||||||
.WillOnce(Return(wireB.Api()->GetNewQueue()));
|
|
||||||
wireB.FlushClient();
|
|
||||||
|
|
||||||
// Signal with a fence from a different wire.
|
// Signal with a fence from a different wire.
|
||||||
wgpuQueueSignal(queueB, fenceA, 1u);
|
wgpuQueueSignal(wireB.ClientQueue(), fenceA, 1u);
|
||||||
|
|
||||||
// We should inject an error into the server.
|
// We should inject an error into the server.
|
||||||
ExpectInjectedError(&wireB);
|
ExpectInjectedError(&wireB);
|
||||||
|
|
|
@ -70,6 +70,12 @@ void WireTest::SetUp() {
|
||||||
dawnProcSetProcs(&clientProcs);
|
dawnProcSetProcs(&clientProcs);
|
||||||
|
|
||||||
apiDevice = mockDevice;
|
apiDevice = mockDevice;
|
||||||
|
|
||||||
|
// The GetDefaultQueue is done on WireClient startup so we expect it now.
|
||||||
|
queue = wgpuDeviceGetDefaultQueue(device);
|
||||||
|
apiQueue = api.GetNewQueue();
|
||||||
|
EXPECT_CALL(api, DeviceGetDefaultQueue(apiDevice)).WillOnce(Return(apiQueue));
|
||||||
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WireTest::TearDown() {
|
void WireTest::TearDown() {
|
||||||
|
@ -104,6 +110,7 @@ dawn_wire::WireClient* WireTest::GetWireClient() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WireTest::DeleteServer() {
|
void WireTest::DeleteServer() {
|
||||||
|
EXPECT_CALL(api, QueueRelease(apiQueue)).Times(1);
|
||||||
mWireServer = nullptr;
|
mWireServer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,9 @@ class WireTest : public testing::Test {
|
||||||
|
|
||||||
testing::StrictMock<MockProcTable> api;
|
testing::StrictMock<MockProcTable> api;
|
||||||
WGPUDevice apiDevice;
|
WGPUDevice apiDevice;
|
||||||
|
WGPUQueue apiQueue;
|
||||||
WGPUDevice device;
|
WGPUDevice device;
|
||||||
|
WGPUQueue queue;
|
||||||
|
|
||||||
dawn_wire::WireServer* GetWireServer();
|
dawn_wire::WireServer* GetWireServer();
|
||||||
dawn_wire::WireClient* GetWireClient();
|
dawn_wire::WireClient* GetWireClient();
|
||||||
|
|
Loading…
Reference in New Issue