mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-07 20:49:25 +00:00
Change dawn read/write handle for buffer mapping to be created at buffer creation time instead of at mapAsync time. Update related buffer mapping tests and wire tests. Bug: dawn:773 Change-Id: I7dd423c94e1bc15cfe561ea33ec9e348ddf2bfe0 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/51164 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Shrek Shao <shrekshao@google.com>
1056 lines
42 KiB
C++
1056 lines
42 KiB
C++
// Copyright 2019 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/unittests/wire/WireTest.h"
|
|
|
|
#include "dawn_wire/client/ClientMemoryTransferService_mock.h"
|
|
#include "dawn_wire/server/ServerMemoryTransferService_mock.h"
|
|
|
|
using namespace testing;
|
|
using namespace dawn_wire;
|
|
|
|
namespace {
|
|
|
|
// Mock class to add expectations on the wire calling callbacks
|
|
class MockBufferMapCallback {
|
|
public:
|
|
MOCK_METHOD(void,
|
|
Call,
|
|
(WGPUBufferMapAsyncStatus status,
|
|
void* userdata));
|
|
};
|
|
|
|
std::unique_ptr<StrictMock<MockBufferMapCallback>> mockBufferMapCallback;
|
|
void ToMockBufferMapCallback(WGPUBufferMapAsyncStatus status, void* userdata) {
|
|
mockBufferMapCallback->Call(status, userdata);
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
// WireMemoryTransferServiceTests test the MemoryTransferService with buffer mapping.
|
|
// They test the basic success and error cases for buffer mapping, and they test
|
|
// mocked failures of each fallible MemoryTransferService method that an embedder
|
|
// could implement.
|
|
// The test harness defines multiple helpers for expecting operations on Read/Write handles
|
|
// and for mocking failures. The helpers are designed such that for a given run of a test,
|
|
// a Serialization expection has a corresponding Deserialization expectation for which the
|
|
// serialized data must match.
|
|
// There are tests which check for Success for every mapping operation which mock an entire mapping
|
|
// operation from map to unmap, and add all MemoryTransferService expectations.
|
|
// Tests which check for errors perform the same mapping operations but insert mocked failures for
|
|
// various mapping or MemoryTransferService operations.
|
|
class WireMemoryTransferServiceTests : public WireTest {
|
|
public:
|
|
WireMemoryTransferServiceTests() {
|
|
}
|
|
~WireMemoryTransferServiceTests() override = default;
|
|
|
|
client::MemoryTransferService* GetClientMemoryTransferService() override {
|
|
return &clientMemoryTransferService;
|
|
}
|
|
|
|
server::MemoryTransferService* GetServerMemoryTransferService() override {
|
|
return &serverMemoryTransferService;
|
|
}
|
|
|
|
void SetUp() override {
|
|
WireTest::SetUp();
|
|
|
|
mockBufferMapCallback = std::make_unique<StrictMock<MockBufferMapCallback>>();
|
|
|
|
// TODO(enga): Make this thread-safe.
|
|
mBufferContent++;
|
|
mMappedBufferContent = 0;
|
|
mUpdatedBufferContent++;
|
|
mSerializeCreateInfo++;
|
|
mReadHandleSerializeDataInfo++;
|
|
mWriteHandleSerializeDataInfo++;
|
|
}
|
|
|
|
void TearDown() override {
|
|
WireTest::TearDown();
|
|
|
|
// Delete mock so that expectations are checked
|
|
mockBufferMapCallback = nullptr;
|
|
}
|
|
|
|
void FlushClient(bool success = true) {
|
|
WireTest::FlushClient(success);
|
|
Mock::VerifyAndClearExpectations(&serverMemoryTransferService);
|
|
}
|
|
|
|
void FlushServer(bool success = true) {
|
|
WireTest::FlushServer(success);
|
|
|
|
Mock::VerifyAndClearExpectations(&mockBufferMapCallback);
|
|
Mock::VerifyAndClearExpectations(&clientMemoryTransferService);
|
|
}
|
|
|
|
protected:
|
|
using ClientReadHandle = client::MockMemoryTransferService::MockReadHandle;
|
|
using ServerReadHandle = server::MockMemoryTransferService::MockReadHandle;
|
|
using ClientWriteHandle = client::MockMemoryTransferService::MockWriteHandle;
|
|
using ServerWriteHandle = server::MockMemoryTransferService::MockWriteHandle;
|
|
|
|
std::pair<WGPUBuffer, WGPUBuffer> CreateBuffer(WGPUBufferUsage usage = WGPUBufferUsage_None) {
|
|
WGPUBufferDescriptor descriptor = {};
|
|
descriptor.size = kBufferSize;
|
|
descriptor.usage = usage;
|
|
|
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
|
|
|
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _))
|
|
.WillOnce(Return(apiBuffer))
|
|
.RetiresOnSaturation();
|
|
|
|
return std::make_pair(apiBuffer, buffer);
|
|
}
|
|
|
|
std::pair<WGPUBuffer, WGPUBuffer> CreateBufferMapped(
|
|
WGPUBufferUsage usage = WGPUBufferUsage_None) {
|
|
WGPUBufferDescriptor descriptor = {};
|
|
descriptor.size = sizeof(mBufferContent);
|
|
descriptor.mappedAtCreation = true;
|
|
descriptor.usage = usage;
|
|
|
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
|
|
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
|
|
|
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
|
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, sizeof(mBufferContent)))
|
|
.WillOnce(Return(&mMappedBufferContent));
|
|
|
|
return std::make_pair(apiBuffer, buffer);
|
|
}
|
|
|
|
ClientReadHandle* ExpectReadHandleCreation() {
|
|
// Create the handle first so we can use it in later expectations.
|
|
ClientReadHandle* handle = clientMemoryTransferService.NewReadHandle();
|
|
|
|
EXPECT_CALL(clientMemoryTransferService, OnCreateReadHandle(sizeof(mBufferContent)))
|
|
.WillOnce(InvokeWithoutArgs([=]() { return handle; }));
|
|
|
|
return handle;
|
|
}
|
|
|
|
void MockReadHandleCreationFailure() {
|
|
EXPECT_CALL(clientMemoryTransferService, OnCreateReadHandle(sizeof(mBufferContent)))
|
|
.WillOnce(InvokeWithoutArgs([=]() { return nullptr; }));
|
|
}
|
|
|
|
void ExpectReadHandleSerialization(ClientReadHandle* handle) {
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleSerializeCreateSize(handle))
|
|
.WillOnce(InvokeWithoutArgs([&]() { return sizeof(mSerializeCreateInfo); }));
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleSerializeCreate(handle, _))
|
|
.WillOnce(WithArg<1>([&](void* serializePointer) {
|
|
memcpy(serializePointer, &mSerializeCreateInfo, sizeof(mSerializeCreateInfo));
|
|
return sizeof(mSerializeCreateInfo);
|
|
}));
|
|
}
|
|
|
|
ServerReadHandle* ExpectServerReadHandleDeserialize() {
|
|
// Create the handle first so we can use it in later expectations.
|
|
ServerReadHandle* handle = serverMemoryTransferService.NewReadHandle();
|
|
|
|
EXPECT_CALL(serverMemoryTransferService,
|
|
OnDeserializeReadHandle(Pointee(Eq(mSerializeCreateInfo)),
|
|
sizeof(mSerializeCreateInfo), _))
|
|
.WillOnce(WithArg<2>([=](server::MemoryTransferService::ReadHandle** readHandle) {
|
|
*readHandle = handle;
|
|
return true;
|
|
}));
|
|
|
|
return handle;
|
|
}
|
|
|
|
void MockServerReadHandleDeserializeFailure() {
|
|
EXPECT_CALL(serverMemoryTransferService,
|
|
OnDeserializeReadHandle(Pointee(Eq(mSerializeCreateInfo)),
|
|
sizeof(mSerializeCreateInfo), _))
|
|
.WillOnce(InvokeWithoutArgs([&]() { return false; }));
|
|
}
|
|
|
|
void ExpectServerReadHandleSerializeDataUpdate(ServerReadHandle* handle) {
|
|
EXPECT_CALL(serverMemoryTransferService,
|
|
OnReadHandleSizeOfSerializeDataUpdate(handle, _, _))
|
|
.WillOnce(InvokeWithoutArgs([&]() { return sizeof(mReadHandleSerializeDataInfo); }));
|
|
EXPECT_CALL(serverMemoryTransferService,
|
|
OnReadHandleSerializeDataUpdate(handle, _, _, _, _))
|
|
.WillOnce(WithArg<4>([&](void* serializePointer) {
|
|
memcpy(serializePointer, &mReadHandleSerializeDataInfo,
|
|
sizeof(mReadHandleSerializeDataInfo));
|
|
return sizeof(mReadHandleSerializeDataInfo);
|
|
}));
|
|
}
|
|
|
|
void ExpectClientReadHandleDeserializeDataUpdate(ClientReadHandle* handle,
|
|
uint32_t* mappedData) {
|
|
EXPECT_CALL(
|
|
clientMemoryTransferService,
|
|
OnReadHandleDeserializeDataUpdate(handle, Pointee(Eq(mReadHandleSerializeDataInfo)),
|
|
sizeof(mReadHandleSerializeDataInfo), _, _))
|
|
.WillOnce(Return(true));
|
|
}
|
|
|
|
void MockClientReadHandleDeserializeDataUpdateFailure(ClientReadHandle* handle) {
|
|
EXPECT_CALL(
|
|
clientMemoryTransferService,
|
|
OnReadHandleDeserializeDataUpdate(handle, Pointee(Eq(mReadHandleSerializeDataInfo)),
|
|
sizeof(mReadHandleSerializeDataInfo), _, _))
|
|
.WillOnce(Return(false));
|
|
}
|
|
|
|
ClientWriteHandle* ExpectWriteHandleCreation(bool mappedAtCreation) {
|
|
// Create the handle first so we can use it in later expectations.
|
|
ClientWriteHandle* handle = clientMemoryTransferService.NewWriteHandle();
|
|
|
|
EXPECT_CALL(clientMemoryTransferService, OnCreateWriteHandle(sizeof(mBufferContent)))
|
|
.WillOnce(InvokeWithoutArgs([=]() { return handle; }));
|
|
if (mappedAtCreation) {
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleGetData(handle))
|
|
.WillOnce(Return(&mBufferContent));
|
|
}
|
|
|
|
return handle;
|
|
}
|
|
|
|
void MockWriteHandleCreationFailure() {
|
|
EXPECT_CALL(clientMemoryTransferService, OnCreateWriteHandle(sizeof(mBufferContent)))
|
|
.WillOnce(InvokeWithoutArgs([=]() { return nullptr; }));
|
|
}
|
|
|
|
void ExpectWriteHandleSerialization(ClientWriteHandle* handle) {
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleSerializeCreateSize(handle))
|
|
.WillOnce(InvokeWithoutArgs([&]() { return sizeof(mSerializeCreateInfo); }));
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleSerializeCreate(handle, _))
|
|
.WillOnce(WithArg<1>([&](void* serializePointer) {
|
|
memcpy(serializePointer, &mSerializeCreateInfo, sizeof(mSerializeCreateInfo));
|
|
return sizeof(mSerializeCreateInfo);
|
|
}));
|
|
}
|
|
|
|
ServerWriteHandle* ExpectServerWriteHandleDeserialization() {
|
|
// Create the handle first so it can be used in later expectations.
|
|
ServerWriteHandle* handle = serverMemoryTransferService.NewWriteHandle();
|
|
|
|
EXPECT_CALL(serverMemoryTransferService,
|
|
OnDeserializeWriteHandle(Pointee(Eq(mSerializeCreateInfo)),
|
|
sizeof(mSerializeCreateInfo), _))
|
|
.WillOnce(WithArg<2>([=](server::MemoryTransferService::WriteHandle** writeHandle) {
|
|
*writeHandle = handle;
|
|
return true;
|
|
}));
|
|
|
|
return handle;
|
|
}
|
|
|
|
void MockServerWriteHandleDeserializeFailure() {
|
|
EXPECT_CALL(serverMemoryTransferService,
|
|
OnDeserializeWriteHandle(Pointee(Eq(mSerializeCreateInfo)),
|
|
sizeof(mSerializeCreateInfo), _))
|
|
.WillOnce(Return(false));
|
|
}
|
|
|
|
void ExpectClientWriteHandleSerializeDataUpdate(ClientWriteHandle* handle) {
|
|
EXPECT_CALL(clientMemoryTransferService,
|
|
OnWriteHandleSizeOfSerializeDataUpdate(handle, _, _))
|
|
.WillOnce(InvokeWithoutArgs([&]() { return sizeof(mWriteHandleSerializeDataInfo); }));
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleSerializeDataUpdate(handle, _, _, _))
|
|
.WillOnce(WithArg<1>([&](void* serializePointer) {
|
|
memcpy(serializePointer, &mWriteHandleSerializeDataInfo,
|
|
sizeof(mWriteHandleSerializeDataInfo));
|
|
return sizeof(mWriteHandleSerializeDataInfo);
|
|
}));
|
|
}
|
|
|
|
void ExpectServerWriteHandleDeserializeDataUpdate(ServerWriteHandle* handle,
|
|
uint32_t expectedData) {
|
|
EXPECT_CALL(
|
|
serverMemoryTransferService,
|
|
OnWriteHandleDeserializeDataUpdate(handle, Pointee(Eq(mWriteHandleSerializeDataInfo)),
|
|
sizeof(mWriteHandleSerializeDataInfo), _, _))
|
|
.WillOnce(Return(true));
|
|
}
|
|
|
|
void MockServerWriteHandleDeserializeDataUpdateFailure(ServerWriteHandle* handle) {
|
|
EXPECT_CALL(
|
|
serverMemoryTransferService,
|
|
OnWriteHandleDeserializeDataUpdate(handle, Pointee(Eq(mWriteHandleSerializeDataInfo)),
|
|
sizeof(mWriteHandleSerializeDataInfo), _, _))
|
|
.WillOnce(Return(false));
|
|
}
|
|
|
|
// Arbitrary values used within tests to check if serialized data is correctly passed
|
|
// between the client and server. The static data changes between runs of the tests and
|
|
// test expectations will check that serialized values are passed to the respective
|
|
// deserialization function.
|
|
static uint32_t mSerializeCreateInfo;
|
|
static uint32_t mReadHandleSerializeDataInfo;
|
|
static uint32_t mWriteHandleSerializeDataInfo;
|
|
|
|
// Represents the buffer contents for the test.
|
|
static uint32_t mBufferContent;
|
|
|
|
static constexpr size_t kBufferSize = sizeof(mBufferContent);
|
|
|
|
// The client's zero-initialized buffer for writing.
|
|
uint32_t mMappedBufferContent = 0;
|
|
|
|
// |mMappedBufferContent| should be set equal to |mUpdatedBufferContent| when the client
|
|
// performs a write. Test expectations should check that |mBufferContent ==
|
|
// mUpdatedBufferContent| after all writes are flushed.
|
|
static uint32_t mUpdatedBufferContent;
|
|
|
|
testing::StrictMock<dawn_wire::server::MockMemoryTransferService> serverMemoryTransferService;
|
|
testing::StrictMock<dawn_wire::client::MockMemoryTransferService> clientMemoryTransferService;
|
|
};
|
|
|
|
uint32_t WireMemoryTransferServiceTests::mBufferContent = 1337;
|
|
uint32_t WireMemoryTransferServiceTests::mUpdatedBufferContent = 2349;
|
|
uint32_t WireMemoryTransferServiceTests::mSerializeCreateInfo = 4242;
|
|
uint32_t WireMemoryTransferServiceTests::mReadHandleSerializeDataInfo = 1394;
|
|
uint32_t WireMemoryTransferServiceTests::mWriteHandleSerializeDataInfo = 1235;
|
|
|
|
// Test successful mapping for reading.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadSuccess) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
// The client should create and serialize a ReadHandle on creation.
|
|
ClientReadHandle* clientHandle = ExpectReadHandleCreation();
|
|
ExpectReadHandleSerialization(clientHandle);
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
|
|
|
// The server should deserialize the read handle from the client and then serialize
|
|
// an initialization message.
|
|
ServerReadHandle* serverHandle = ExpectServerReadHandleDeserialize();
|
|
|
|
FlushClient();
|
|
|
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
|
|
|
// The handle serialize data update on mapAsync cmd
|
|
ExpectServerReadHandleSerializeDataUpdate(serverHandle);
|
|
|
|
// Mock a successful callback
|
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
|
.WillOnce(InvokeWithoutArgs([&]() {
|
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
|
|
}));
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleGetData(clientHandle))
|
|
.WillOnce(Return(&mBufferContent));
|
|
EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
|
|
.WillOnce(Return(&mBufferContent));
|
|
|
|
FlushClient();
|
|
|
|
// The client receives a successful callback.
|
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
|
|
|
|
// The client should receive the handle data update message from the server.
|
|
ExpectClientReadHandleDeserializeDataUpdate(clientHandle, &mBufferContent);
|
|
|
|
FlushServer();
|
|
|
|
wgpuBufferUnmap(buffer);
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
|
|
FlushClient();
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
|
}
|
|
|
|
// Test ReadHandle destroy behavior
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDestroy) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
// The client should create and serialize a ReadHandle on creation.
|
|
ClientReadHandle* clientHandle = ExpectReadHandleCreation();
|
|
ExpectReadHandleSerialization(clientHandle);
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
|
|
|
// The server should deserialize the read handle from the client and then serialize
|
|
// an initialization message.
|
|
ServerReadHandle* serverHandle = ExpectServerReadHandleDeserialize();
|
|
|
|
FlushClient();
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
|
wgpuBufferDestroy(buffer);
|
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
|
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test unsuccessful mapping for reading.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadError) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
// The client should create and serialize a ReadHandle on creation.
|
|
ClientReadHandle* clientHandle = ExpectReadHandleCreation();
|
|
ExpectReadHandleSerialization(clientHandle);
|
|
|
|
// The server should deserialize the ReadHandle from the client.
|
|
ServerReadHandle* serverHandle = ExpectServerReadHandleDeserialize();
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
|
FlushClient();
|
|
|
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
|
|
|
// Mock a failed callback.
|
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
|
.WillOnce(InvokeWithoutArgs(
|
|
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
|
|
|
FlushClient();
|
|
|
|
// The client receives an error callback.
|
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
|
|
|
|
FlushServer();
|
|
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
|
|
FlushClient();
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
|
}
|
|
|
|
// Test ReadHandle creation failure.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadHandleCreationFailure) {
|
|
// Mock a ReadHandle creation failure
|
|
MockReadHandleCreationFailure();
|
|
|
|
WGPUBufferDescriptor descriptor = {};
|
|
descriptor.size = kBufferSize;
|
|
descriptor.usage = WGPUBufferUsage_MapRead;
|
|
|
|
wgpuDeviceCreateBuffer(device, &descriptor);
|
|
}
|
|
|
|
// Test MapRead DeserializeReadHandle failure.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDeserializeReadHandleFailure) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
// The client should create and serialize a ReadHandle on mapping for reading..
|
|
ClientReadHandle* clientHandle = ExpectReadHandleCreation();
|
|
ExpectReadHandleSerialization(clientHandle);
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
|
|
|
// Mock a Deserialization failure.
|
|
MockServerReadHandleDeserializeFailure();
|
|
|
|
FlushClient(false);
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
|
}
|
|
|
|
// Test read handle DeserializeDataUpdate failure.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDeserializeDataUpdateFailure) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
// The client should create and serialize a ReadHandle on mapping for reading.
|
|
ClientReadHandle* clientHandle = ExpectReadHandleCreation();
|
|
ExpectReadHandleSerialization(clientHandle);
|
|
|
|
// The server should deserialize the read handle from the client and then serialize
|
|
// an initialization message.
|
|
ServerReadHandle* serverHandle = ExpectServerReadHandleDeserialize();
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
|
FlushClient();
|
|
|
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
|
|
|
// The handle serialize data update on mapAsync cmd
|
|
ExpectServerReadHandleSerializeDataUpdate(serverHandle);
|
|
|
|
// Mock a successful callback
|
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
|
.WillOnce(InvokeWithoutArgs([&]() {
|
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
|
|
}));
|
|
EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
|
|
.WillOnce(Return(&mBufferContent));
|
|
|
|
FlushClient();
|
|
|
|
// The client should receive the handle data update message from the server.
|
|
// Mock a deserialization failure.
|
|
MockClientReadHandleDeserializeDataUpdateFailure(clientHandle);
|
|
|
|
// Failed deserialization is a fatal failure and the client synchronously receives a
|
|
// DEVICE_LOST callback.
|
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, _)).Times(1);
|
|
|
|
FlushServer(false);
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
|
}
|
|
|
|
// Test mapping for reading destroying the buffer before unmapping on the client side.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapReadDestroyBeforeUnmap) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
// The client should create and serialize a ReadHandle on mapping for reading..
|
|
ClientReadHandle* clientHandle = ExpectReadHandleCreation();
|
|
ExpectReadHandleSerialization(clientHandle);
|
|
|
|
// The server should deserialize the read handle from the client and then serialize
|
|
// an initialization message.
|
|
ServerReadHandle* serverHandle = ExpectServerReadHandleDeserialize();
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapRead);
|
|
FlushClient();
|
|
|
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
|
|
|
// The handle serialize data update on mapAsync cmd
|
|
ExpectServerReadHandleSerializeDataUpdate(serverHandle);
|
|
|
|
// Mock a successful callback
|
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
|
|
.WillOnce(InvokeWithoutArgs([&]() {
|
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
|
|
}));
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleGetData(clientHandle))
|
|
.WillOnce(Return(&mBufferContent));
|
|
EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
|
|
.WillOnce(Return(&mBufferContent));
|
|
|
|
FlushClient();
|
|
|
|
// The client receives a successful callback.
|
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
|
|
|
|
// The client should receive the handle data update message from the server.
|
|
ExpectClientReadHandleDeserializeDataUpdate(clientHandle, &mBufferContent);
|
|
|
|
FlushServer();
|
|
|
|
// THIS IS THE TEST: destroy the buffer before unmapping and check it destroyed the mapping
|
|
// immediately, both in the client and server side.
|
|
{
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientHandle)).Times(1);
|
|
wgpuBufferDestroy(buffer);
|
|
|
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverHandle)).Times(1);
|
|
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
|
FlushClient();
|
|
|
|
// The handle is already destroyed so unmap only results in a server unmap call.
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
FlushClient();
|
|
}
|
|
}
|
|
|
|
// Test successful mapping for writing.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteSuccess) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapWrite);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
FlushClient();
|
|
|
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
|
|
|
// Mock a successful callback.
|
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
|
.WillOnce(InvokeWithoutArgs([&]() {
|
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
|
|
}));
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleGetData(clientHandle))
|
|
.WillOnce(Return(&mBufferContent));
|
|
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
|
|
.WillOnce(Return(&mMappedBufferContent));
|
|
|
|
FlushClient();
|
|
|
|
// The client receives a successful callback.
|
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
|
|
|
|
FlushServer();
|
|
|
|
// The client writes to the handle contents.
|
|
mMappedBufferContent = mUpdatedBufferContent;
|
|
|
|
// The client will then serialize data update and destroy the handle on Unmap()
|
|
ExpectClientWriteHandleSerializeDataUpdate(clientHandle);
|
|
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
// The server deserializes the data update message.
|
|
ExpectServerWriteHandleDeserializeDataUpdate(serverHandle, mUpdatedBufferContent);
|
|
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
|
|
FlushClient();
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
|
}
|
|
|
|
// Test WriteHandle destroy behavior
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroy) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapWrite);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
FlushClient();
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
wgpuBufferDestroy(buffer);
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
|
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test unsuccessful MapWrite.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteError) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
// The client should create and serialize a WriteHandle on buffer creation with MapWrite usage.
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapWrite);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
FlushClient();
|
|
|
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
|
|
|
// Mock an error callback.
|
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
|
.WillOnce(InvokeWithoutArgs(
|
|
[&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
|
|
|
|
|
|
FlushClient();
|
|
|
|
// The client receives an error callback.
|
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
|
|
|
|
FlushServer();
|
|
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
|
|
FlushClient();
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
|
}
|
|
|
|
// Test WriteHandle creation failure.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteHandleCreationFailure) {
|
|
// Mock a WriteHandle creation failure
|
|
MockWriteHandleCreationFailure();
|
|
|
|
WGPUBufferDescriptor descriptor = {};
|
|
descriptor.size = kBufferSize;
|
|
descriptor.usage = WGPUBufferUsage_MapWrite;
|
|
|
|
wgpuDeviceCreateBuffer(device, &descriptor);
|
|
}
|
|
|
|
// Test MapWrite DeserializeWriteHandle failure.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDeserializeWriteHandleFailure) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
// The client should create and serialize a WriteHandle on buffer creation with MapWrite usage.
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapWrite);
|
|
|
|
// Mock a deserialization failure.
|
|
MockServerWriteHandleDeserializeFailure();
|
|
|
|
FlushClient(false);
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
}
|
|
|
|
// Test MapWrite DeserializeDataUpdate failure.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDeserializeDataUpdateFailure) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapWrite);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
FlushClient();
|
|
|
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
|
|
|
// Mock a successful callback.
|
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
|
.WillOnce(InvokeWithoutArgs([&]() {
|
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
|
|
}));
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleGetData(clientHandle))
|
|
.WillOnce(Return(&mBufferContent));
|
|
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
|
|
.WillOnce(Return(&mMappedBufferContent));
|
|
|
|
FlushClient();
|
|
|
|
// The client receives a success callback.
|
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
|
|
|
|
FlushServer();
|
|
|
|
// The client writes to the handle contents.
|
|
mMappedBufferContent = mUpdatedBufferContent;
|
|
|
|
// The client will then serialize data update
|
|
ExpectClientWriteHandleSerializeDataUpdate(clientHandle);
|
|
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
// The server deserializes the data update message. Mock a deserialization failure.
|
|
MockServerWriteHandleDeserializeDataUpdateFailure(serverHandle);
|
|
|
|
FlushClient(false);
|
|
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
|
}
|
|
|
|
// Test MapWrite destroying the buffer before unmapping on the client side.
|
|
TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(false);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
std::tie(apiBuffer, buffer) = CreateBuffer(WGPUBufferUsage_MapWrite);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
FlushClient();
|
|
|
|
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
|
|
|
|
// Mock a successful callback.
|
|
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
|
|
.WillOnce(InvokeWithoutArgs([&]() {
|
|
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
|
|
}));
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleGetData(clientHandle))
|
|
.WillOnce(Return(&mBufferContent));
|
|
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
|
|
.WillOnce(Return(&mMappedBufferContent));
|
|
|
|
FlushClient();
|
|
|
|
// The client receives a successful callback.
|
|
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
|
|
|
|
FlushServer();
|
|
|
|
// The client writes to the handle contents.
|
|
mMappedBufferContent = mUpdatedBufferContent;
|
|
|
|
// THIS IS THE TEST: destroy the buffer before unmapping and check it destroyed the mapping
|
|
// immediately, both in the client and server side.
|
|
{
|
|
// The handle is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
|
|
wgpuBufferDestroy(buffer);
|
|
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
|
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
|
FlushClient();
|
|
|
|
// The handle is already destroyed so unmap only results in a server unmap call.
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
FlushClient();
|
|
}
|
|
}
|
|
|
|
// Test successful buffer creation with mappedAtCreation = true.
|
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
|
FlushClient();
|
|
|
|
// Update the mapped contents.
|
|
mMappedBufferContent = mUpdatedBufferContent;
|
|
|
|
// When the client Unmaps the buffer, it will serialize data update writes to the handle and
|
|
// destroy it.
|
|
ExpectClientWriteHandleSerializeDataUpdate(clientHandle);
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
// The server deserializes the data update message.
|
|
ExpectServerWriteHandleDeserializeDataUpdate(serverHandle, mUpdatedBufferContent);
|
|
|
|
// After the handle is updated it can be destroyed.
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
|
|
FlushClient();
|
|
}
|
|
|
|
// Test buffer creation with mappedAtCreation WriteHandle creation failure.
|
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationWriteHandleCreationFailure) {
|
|
// Mock a WriteHandle creation failure
|
|
MockWriteHandleCreationFailure();
|
|
|
|
WGPUBufferDescriptor descriptor = {};
|
|
descriptor.size = sizeof(mBufferContent);
|
|
descriptor.mappedAtCreation = true;
|
|
|
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
|
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
|
|
}
|
|
|
|
// Test buffer creation with mappedAtCreation DeserializeWriteHandle failure.
|
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFailure) {
|
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
MockServerWriteHandleDeserializeFailure();
|
|
|
|
WGPUBufferDescriptor descriptor = {};
|
|
descriptor.size = sizeof(mBufferContent);
|
|
descriptor.mappedAtCreation = true;
|
|
|
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
|
|
|
wgpuDeviceCreateBuffer(device, &descriptor);
|
|
|
|
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
|
// Now bufferGetMappedRange won't be called if deserialize writeHandle fails
|
|
|
|
FlushClient(false);
|
|
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
}
|
|
|
|
// Test buffer creation with mappedAtCreation = true DeserializeDataUpdate failure.
|
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeDataUpdateFailure) {
|
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
|
FlushClient();
|
|
|
|
// Update the mapped contents.
|
|
mMappedBufferContent = mUpdatedBufferContent;
|
|
|
|
// When the client Unmaps the buffer, it will serialize data update writes to the handle and
|
|
// destroy it.
|
|
ExpectClientWriteHandleSerializeDataUpdate(clientHandle);
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
// The server deserializes the data update message. Mock a deserialization failure.
|
|
MockServerWriteHandleDeserializeDataUpdateFailure(serverHandle);
|
|
|
|
FlushClient(false);
|
|
|
|
// Failed BufferUpdateMappedData cmd will early return so BufferUnmap is not processed.
|
|
// The server side writeHandle is destructed at buffer destruction.
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
|
}
|
|
|
|
// Test mappedAtCreation=true destroying the buffer before unmapping on the client side.
|
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
|
FlushClient();
|
|
|
|
// Update the mapped contents.
|
|
mMappedBufferContent = mUpdatedBufferContent;
|
|
|
|
// THIS IS THE TEST: destroy the buffer before unmapping and check it destroyed the mapping
|
|
// immediately, both in the client and server side.
|
|
{
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
wgpuBufferDestroy(buffer);
|
|
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
|
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
|
FlushClient();
|
|
|
|
// The handle is already destroyed so unmap only results in a server unmap call.
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
FlushClient();
|
|
}
|
|
}
|
|
|
|
// Test a buffer with mappedAtCreation and MapRead usage destroy WriteHandle on unmap and switch
|
|
// data pointer to ReadHandle
|
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationAndMapReadSuccess) {
|
|
// The client should create and serialize a ReadHandle and a WriteHandle on createBufferMapped.
|
|
ClientReadHandle* clientReadHandle = ExpectReadHandleCreation();
|
|
ExpectReadHandleSerialization(clientReadHandle);
|
|
ClientWriteHandle* clientWriteHandle = ExpectWriteHandleCreation(true);
|
|
ExpectWriteHandleSerialization(clientWriteHandle);
|
|
|
|
// The server should then deserialize a ReadHandle and a WriteHandle from the client.
|
|
ServerReadHandle* serverReadHandle = ExpectServerReadHandleDeserialize();
|
|
ServerWriteHandle* serverWriteHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
std::tie(apiBuffer, buffer) = CreateBufferMapped(WGPUBufferUsage_MapRead);
|
|
FlushClient();
|
|
|
|
// Update the mapped contents.
|
|
mMappedBufferContent = mUpdatedBufferContent;
|
|
|
|
// When the client Unmaps the buffer, it will serialize data update writes to the handle and
|
|
// destroy it.
|
|
ExpectClientWriteHandleSerializeDataUpdate(clientWriteHandle);
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientWriteHandle)).Times(1);
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleGetData(clientReadHandle))
|
|
.WillOnce(Return(&mBufferContent));
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
// The server deserializes the data update message.
|
|
ExpectServerWriteHandleDeserializeDataUpdate(serverWriteHandle, mUpdatedBufferContent);
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverWriteHandle)).Times(1);
|
|
FlushClient();
|
|
|
|
// The ReadHandle will be destoryed on buffer destroy.
|
|
EXPECT_CALL(clientMemoryTransferService, OnReadHandleDestroy(clientReadHandle)).Times(1);
|
|
EXPECT_CALL(serverMemoryTransferService, OnReadHandleDestroy(serverReadHandle)).Times(1);
|
|
}
|
|
|
|
// Test WriteHandle preserves after unmap for a buffer with mappedAtCreation and MapWrite usage
|
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationAndMapWriteSuccess) {
|
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(true);
|
|
|
|
ExpectWriteHandleSerialization(clientHandle);
|
|
|
|
// The server should then deserialize the WriteHandle from the client.
|
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
|
|
|
WGPUBuffer buffer;
|
|
WGPUBuffer apiBuffer;
|
|
std::tie(apiBuffer, buffer) = CreateBufferMapped(WGPUBufferUsage_MapWrite);
|
|
FlushClient();
|
|
|
|
// Update the mapped contents.
|
|
mMappedBufferContent = mUpdatedBufferContent;
|
|
|
|
// When the client Unmaps the buffer, it will serialize data update writes to the handle.
|
|
ExpectClientWriteHandleSerializeDataUpdate(clientHandle);
|
|
|
|
wgpuBufferUnmap(buffer);
|
|
|
|
// The server deserializes the data update message.
|
|
ExpectServerWriteHandleDeserializeDataUpdate(serverHandle, mUpdatedBufferContent);
|
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
|
|
|
FlushClient();
|
|
|
|
// The writeHandle is preserved after unmap and is destroyed once the buffer is destroyed.
|
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
|
} |