Revert "dawn_wire: Implement CreateBufferMapped on top of mappedAtCreation"

This reverts commit 0811ecc775.

Reason for revert: Makes the Dawn roll fail.

Original change's description:
> dawn_wire: Implement CreateBufferMapped on top of mappedAtCreation
> 
> This inverts the shimming to have the old mapping at creation method
> be implemented on top of the new method..
> 
> Also updates Wire tests to use mappedAtCreation instead of
> CreateBufferMapped.
> 
> Bug: dawn:445
> 
> Change-Id: I77dcfe72040e5bf187c41fe99c8dd785d5156a07
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/25701
> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
> Reviewed-by: Austin Eng <enga@chromium.org>

TBR=cwallez@chromium.org,senorblanco@chromium.org,enga@chromium.org

Change-Id: Ied940d505fdf576860697dee8df2548c73581eba
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: dawn:445
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/25980
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2020-07-29 09:10:13 +00:00 committed by Commit Bot service account
parent 225a2b46b0
commit b88b1a15c7
7 changed files with 218 additions and 170 deletions

View File

@ -38,7 +38,7 @@
{ "name": "write flush info length", "type": "uint64_t" }, { "name": "write flush info length", "type": "uint64_t" },
{ "name": "write flush info", "type": "uint8_t", "annotation": "const*", "length": "write flush info length", "skip_serialize": true} { "name": "write flush info", "type": "uint8_t", "annotation": "const*", "length": "write flush info length", "skip_serialize": true}
], ],
"device create buffer": [ "device create buffer mapped": [
{ "name": "device", "type": "device" }, { "name": "device", "type": "device" },
{ "name": "descriptor", "type": "buffer descriptor", "annotation": "const*" }, { "name": "descriptor", "type": "buffer descriptor", "annotation": "const*" },
{ "name": "result", "type": "ObjectHandle", "handle_type": "buffer" }, { "name": "result", "type": "ObjectHandle", "handle_type": "buffer" },
@ -108,8 +108,6 @@
"BufferSetSubData", "BufferSetSubData",
"BufferGetConstMappedRange", "BufferGetConstMappedRange",
"BufferGetMappedRange", "BufferGetMappedRange",
"DeviceCreateBuffer",
"DeviceCreateBufferMapped",
"DevicePopErrorScope", "DevicePopErrorScope",
"DeviceSetDeviceLostCallback", "DeviceSetDeviceLostCallback",
"DeviceSetUncapturedErrorCallback", "DeviceSetUncapturedErrorCallback",
@ -121,6 +119,8 @@
"client_handwritten_commands": [ "client_handwritten_commands": [
"BufferDestroy", "BufferDestroy",
"BufferUnmap", "BufferUnmap",
"DeviceCreateBuffer",
"DeviceCreateBufferMapped",
"DeviceCreateErrorBuffer", "DeviceCreateErrorBuffer",
"DeviceGetDefaultQueue", "DeviceGetDefaultQueue",
"DeviceInjectError", "DeviceInjectError",

View File

@ -29,61 +29,89 @@ namespace dawn_wire { namespace client {
return device_->CreateErrorBuffer(); return device_->CreateErrorBuffer();
} }
std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle = nullptr;
void* writeData = nullptr;
size_t writeHandleCreateInfoLength = 0;
// If the buffer is mapped at creation, create a write handle that will represent the
// mapping of the whole buffer.
if (descriptor->mappedAtCreation) {
// Create the handle.
writeHandle.reset(
wireClient->GetMemoryTransferService()->CreateWriteHandle(descriptor->size));
if (writeHandle == nullptr) {
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer mapping allocation failed");
return device_->CreateErrorBuffer();
}
// Open the handle, it may fail by returning a nullptr in writeData.
size_t writeDataLength = 0;
std::tie(writeData, writeDataLength) = writeHandle->Open();
if (writeData == nullptr) {
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer mapping allocation failed");
return device_->CreateErrorBuffer();
}
ASSERT(writeDataLength == descriptor->size);
// Get the serialization size of the write handle.
writeHandleCreateInfoLength = writeHandle->SerializeCreateSize();
}
// Create the buffer and send the creation command.
auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(device_); auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(device_);
Buffer* buffer = bufferObjectAndSerial->object.get(); Buffer* buffer = bufferObjectAndSerial->object.get();
// Store the size of the buffer so that mapping operations can allocate a
// MemoryTransfer handle of the proper size.
buffer->mSize = descriptor->size; buffer->mSize = descriptor->size;
DeviceCreateBufferCmd cmd; DeviceCreateBufferCmd cmd;
cmd.self = ToAPI(device_);
cmd.descriptor = descriptor;
cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
wireClient->SerializeCommand(cmd);
return ToAPI(buffer);
}
// static
WGPUCreateBufferMappedResult Buffer::CreateMapped(Device* device_,
const WGPUBufferDescriptor* descriptor) {
Client* wireClient = device_->GetClient();
WGPUCreateBufferMappedResult result;
result.data = nullptr;
result.dataLength = 0;
// This buffer is too large to be mapped and to make a WriteHandle for.
if (descriptor->size > std::numeric_limits<size_t>::max()) {
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer is too large for mapping");
result.buffer = device_->CreateErrorBuffer();
return result;
}
// Create a WriteHandle for the map request. This is the client's intent to write GPU
// memory.
std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle =
std::unique_ptr<MemoryTransferService::WriteHandle>(
wireClient->GetMemoryTransferService()->CreateWriteHandle(descriptor->size));
if (writeHandle == nullptr) {
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer mapping allocation failed");
result.buffer = device_->CreateErrorBuffer();
return result;
}
// CreateBufferMapped is synchronous and the staging buffer for upload should be immediately
// available.
// Open the WriteHandle. This returns a pointer and size of mapped memory.
// |result.data| may be null on error.
std::tie(result.data, result.dataLength) = writeHandle->Open();
if (result.data == nullptr) {
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer mapping allocation failed");
result.buffer = device_->CreateErrorBuffer();
return result;
}
auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(device_);
Buffer* buffer = bufferObjectAndSerial->object.get();
buffer->mSize = descriptor->size;
// Successfully created staging memory. The buffer now owns the WriteHandle.
buffer->mWriteHandle = std::move(writeHandle);
buffer->mMappedData = result.data;
buffer->mMapOffset = 0;
buffer->mMapSize = descriptor->size;
result.buffer = ToAPI(buffer);
// Get the serialization size of the WriteHandle.
size_t handleCreateInfoLength = buffer->mWriteHandle->SerializeCreateSize();
DeviceCreateBufferMappedCmd cmd;
cmd.device = ToAPI(device_); cmd.device = ToAPI(device_);
cmd.descriptor = descriptor; cmd.descriptor = descriptor;
cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation}; cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
cmd.handleCreateInfoLength = writeHandleCreateInfoLength; cmd.handleCreateInfoLength = handleCreateInfoLength;
cmd.handleCreateInfo = nullptr; cmd.handleCreateInfo = nullptr;
char* writeHandleSpace = wireClient->SerializeCommand(cmd, writeHandleCreateInfoLength); char* writeHandleSpace =
buffer->device->GetClient()->SerializeCommand(cmd, handleCreateInfoLength);
if (descriptor->mappedAtCreation) { // Serialize the WriteHandle into the space after the command.
// Serialize the WriteHandle into the space after the command. buffer->mWriteHandle->SerializeCreate(writeHandleSpace);
writeHandle->SerializeCreate(writeHandleSpace);
// Set the buffer state for the mapping at creation. The buffer now owns the write return result;
// handle..
buffer->mWriteHandle = std::move(writeHandle);
buffer->mMappedData = writeData;
buffer->mMapOffset = 0;
buffer->mMapSize = buffer->mSize;
}
return ToAPI(buffer);
} }
// static // static

View File

@ -29,6 +29,8 @@ namespace dawn_wire { namespace client {
using ObjectBase::ObjectBase; using ObjectBase::ObjectBase;
static WGPUBuffer Create(Device* device, const WGPUBufferDescriptor* descriptor); static WGPUBuffer Create(Device* device, const WGPUBufferDescriptor* descriptor);
static WGPUCreateBufferMappedResult CreateMapped(Device* device,
const WGPUBufferDescriptor* descriptor);
static WGPUBuffer CreateError(Device* device); static WGPUBuffer CreateError(Device* device);
~Buffer(); ~Buffer();

View File

@ -146,20 +146,16 @@ namespace dawn_wire { namespace client {
} }
WGPUBuffer Device::CreateBuffer(const WGPUBufferDescriptor* descriptor) { WGPUBuffer Device::CreateBuffer(const WGPUBufferDescriptor* descriptor) {
return Buffer::Create(this, descriptor); if (descriptor->mappedAtCreation) {
return CreateBufferMapped(descriptor).buffer;
} else {
return Buffer::Create(this, descriptor);
}
} }
WGPUCreateBufferMappedResult Device::CreateBufferMapped( WGPUCreateBufferMappedResult Device::CreateBufferMapped(
const WGPUBufferDescriptor* descriptor) { const WGPUBufferDescriptor* descriptor) {
WGPUBufferDescriptor descMappedAtCreation = *descriptor; return Buffer::CreateMapped(this, descriptor);
descMappedAtCreation.mappedAtCreation = true;
WGPUCreateBufferMappedResult result;
result.buffer = CreateBuffer(&descMappedAtCreation);
result.data = FromAPI(result.buffer)->GetMappedRange(0, descriptor->size);
result.dataLength = result.data == nullptr ? 0 : descriptor->size;
return result;
} }
WGPUBuffer Device::CreateErrorBuffer() { WGPUBuffer Device::CreateErrorBuffer() {

View File

@ -118,52 +118,50 @@ namespace dawn_wire { namespace server {
return true; return true;
} }
bool Server::DoDeviceCreateBuffer(WGPUDevice device, bool Server::DoDeviceCreateBufferMapped(WGPUDevice device,
const WGPUBufferDescriptor* descriptor, const WGPUBufferDescriptor* descriptor,
ObjectHandle bufferResult, ObjectHandle bufferResult,
uint64_t handleCreateInfoLength, uint64_t handleCreateInfoLength,
const uint8_t* handleCreateInfo) { const uint8_t* handleCreateInfo) {
// Create and register the buffer object. if (handleCreateInfoLength > std::numeric_limits<size_t>::max()) {
// This is the size of data deserialized from the command stream, which must be
// CPU-addressable.
return false;
}
auto* resultData = BufferObjects().Allocate(bufferResult.id); auto* resultData = BufferObjects().Allocate(bufferResult.id);
if (resultData == nullptr) { if (resultData == nullptr) {
return false; return false;
} }
resultData->generation = bufferResult.generation; resultData->generation = bufferResult.generation;
resultData->handle = mProcs.deviceCreateBuffer(device, descriptor);
// If the buffer isn't mapped at creation, we are done. WGPUCreateBufferMappedResult result = mProcs.deviceCreateBufferMapped(device, descriptor);
if (!descriptor->mappedAtCreation) { ASSERT(result.buffer != nullptr);
return handleCreateInfoLength == 0; if (result.data == nullptr && result.dataLength != 0) {
} // Non-zero dataLength but null data is used to indicate an allocation error.
// Don't return false because this is not fatal. result.buffer is an ErrorBuffer
// This is the size of data deserialized from the command stream to create the write handle, // and subsequent operations will be errors.
// which must be CPU-addressable. // This should only happen when fuzzing with the Null backend.
if (handleCreateInfoLength > std::numeric_limits<size_t>::max()) {
return false;
}
void* mapping = mProcs.bufferGetMappedRange(resultData->handle, 0, descriptor->size);
if (mapping == nullptr) {
// A zero mapping is used to indicate an allocation error of an error buffer. This is a
// valid case and isn't fatal. Remember the buffer is an error so as to skip subsequent
// mapping operations.
resultData->mapWriteState = BufferMapWriteState::MapError; resultData->mapWriteState = BufferMapWriteState::MapError;
return true; } else {
// Deserialize metadata produced from the client to create a companion server handle.
MemoryTransferService::WriteHandle* writeHandle = nullptr;
if (!mMemoryTransferService->DeserializeWriteHandle(
handleCreateInfo, static_cast<size_t>(handleCreateInfoLength), &writeHandle)) {
return false;
}
ASSERT(writeHandle != nullptr);
// Set the target of the WriteHandle to the mapped GPU memory.
writeHandle->SetTarget(result.data, result.dataLength);
// The buffer is mapped and has a valid mappedData pointer.
// The buffer may still be an error with fake staging data.
resultData->mapWriteState = BufferMapWriteState::Mapped;
resultData->writeHandle =
std::unique_ptr<MemoryTransferService::WriteHandle>(writeHandle);
} }
resultData->handle = result.buffer;
// Deserialize metadata produced from the client to create a companion server handle.
MemoryTransferService::WriteHandle* writeHandle = nullptr;
if (!mMemoryTransferService->DeserializeWriteHandle(
handleCreateInfo, static_cast<size_t>(handleCreateInfoLength), &writeHandle)) {
return false;
}
// Set the target of the WriteHandle to the mapped GPU memory.
ASSERT(writeHandle != nullptr);
writeHandle->SetTarget(mapping, descriptor->size);
resultData->mapWriteState = BufferMapWriteState::Mapped;
resultData->writeHandle.reset(writeHandle);
return true; return true;
} }

View File

@ -477,72 +477,84 @@ TEST_F(WireBufferMappingTests, DestroyInsideMapWriteCallback) {
FlushClient(); FlushClient();
} }
// Test successful buffer creation with mappedAtCreation=true // Test successful CreateBufferMapped
TEST_F(WireBufferMappingTests, MappedAtCreationSuccess) { TEST_F(WireBufferMappingTests, CreateBufferMappedSuccess) {
WGPUBufferDescriptor descriptor = {}; WGPUBufferDescriptor descriptor = {};
descriptor.size = 4; descriptor.size = 4;
descriptor.mappedAtCreation = true;
WGPUBuffer apiBuffer = api.GetNewBuffer(); WGPUBuffer apiBuffer = api.GetNewBuffer();
WGPUCreateBufferMappedResult apiResult;
uint32_t apiBufferData = 1234; uint32_t apiBufferData = 1234;
apiResult.buffer = apiBuffer;
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
apiResult.dataLength = 4;
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor); WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer)); EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData)); .WillOnce(Return(apiResult))
.RetiresOnSaturation();
FlushClient(); FlushClient();
wgpuBufferUnmap(buffer); wgpuBufferUnmap(result.buffer);
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1); EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
FlushClient(); FlushClient();
} }
// Test that releasing a buffer mapped at creation does not call Unmap // Test that releasing after CreateBufferMapped does not call Unmap
TEST_F(WireBufferMappingTests, MappedAtCreationReleaseBeforeUnmap) { TEST_F(WireBufferMappingTests, ReleaseAfterCreateBufferMapped) {
WGPUBufferDescriptor descriptor = {}; WGPUBufferDescriptor descriptor = {};
descriptor.size = 4; descriptor.size = 4;
descriptor.mappedAtCreation = true;
WGPUBuffer apiBuffer = api.GetNewBuffer(); WGPUBuffer apiBuffer = api.GetNewBuffer();
WGPUCreateBufferMappedResult apiResult;
uint32_t apiBufferData = 1234; uint32_t apiBufferData = 1234;
apiResult.buffer = apiBuffer;
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
apiResult.dataLength = 4;
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor); WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer)); EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData)); .WillOnce(Return(apiResult))
.RetiresOnSaturation();
FlushClient(); FlushClient();
wgpuBufferRelease(buffer); wgpuBufferRelease(result.buffer);
EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1); EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
FlushClient(); FlushClient();
} }
// Test that it is valid to map a buffer after it is mapped at creation and unmapped // Test that it is valid to map a buffer after CreateBufferMapped and Unmap
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) { TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapSuccess) {
WGPUBufferDescriptor descriptor = {}; WGPUBufferDescriptor descriptor = {};
descriptor.size = 4; descriptor.size = 4;
descriptor.mappedAtCreation = true;
WGPUBuffer apiBuffer = api.GetNewBuffer(); WGPUBuffer apiBuffer = api.GetNewBuffer();
uint32_t apiBufferData = 1234; WGPUCreateBufferMappedResult apiResult;
uint32_t apiBufferData = 9863;
apiResult.buffer = apiBuffer;
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
apiResult.dataLength = 4;
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor); WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer)); EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData)); .WillOnce(Return(apiResult))
.RetiresOnSaturation();
FlushClient(); FlushClient();
wgpuBufferUnmap(buffer); wgpuBufferUnmap(result.buffer);
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1); EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
FlushClient(); FlushClient();
wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr); wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
uint32_t zero = 0; uint32_t zero = 0;
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() { EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
@ -560,23 +572,27 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
FlushServer(); FlushServer();
} }
// Test that it is invalid to map a buffer after mappedAtCreation but before Unmap // Test that it is invalid to map a buffer after CreateBufferMapped before Unmap
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) { TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
WGPUBufferDescriptor descriptor = {}; WGPUBufferDescriptor descriptor = {};
descriptor.size = 4; descriptor.size = 4;
descriptor.mappedAtCreation = true;
WGPUBuffer apiBuffer = api.GetNewBuffer(); WGPUBuffer apiBuffer = api.GetNewBuffer();
uint32_t apiBufferData = 1234; WGPUCreateBufferMappedResult apiResult;
uint32_t apiBufferData = 9863;
apiResult.buffer = apiBuffer;
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
apiResult.dataLength = 4;
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor); WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer)); EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData)); .WillOnce(Return(apiResult))
.RetiresOnSaturation();
FlushClient(); FlushClient();
wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr); wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() { EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
api.CallMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); api.CallMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
@ -589,7 +605,7 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
FlushServer(); FlushServer();
wgpuBufferUnmap(buffer); wgpuBufferUnmap(result.buffer);
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1); EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
FlushClient(); FlushClient();

View File

@ -155,20 +155,24 @@ class WireMemoryTransferServiceTests : public WireTest {
return std::make_pair(apiBuffer, buffer); return std::make_pair(apiBuffer, buffer);
} }
std::pair<WGPUBuffer, WGPUBuffer> CreateBufferMapped() { std::pair<WGPUCreateBufferMappedResult, WGPUCreateBufferMappedResult> CreateBufferMapped() {
WGPUBufferDescriptor descriptor = {}; WGPUBufferDescriptor descriptor = {};
descriptor.size = sizeof(mBufferContent); descriptor.size = sizeof(mBufferContent);
descriptor.mappedAtCreation = true;
WGPUBuffer apiBuffer = api.GetNewBuffer(); WGPUBuffer apiBuffer = api.GetNewBuffer();
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor); WGPUCreateBufferMappedResult apiResult;
apiResult.buffer = apiBuffer;
apiResult.data = reinterpret_cast<uint8_t*>(&mMappedBufferContent);
apiResult.dataLength = sizeof(mMappedBufferContent);
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer)); WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, sizeof(mBufferContent)))
.WillOnce(Return(&mMappedBufferContent));
return std::make_pair(apiBuffer, buffer); EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
.WillOnce(Return(apiResult))
.RetiresOnSaturation();
return std::make_pair(apiResult, result);
} }
ClientReadHandle* ExpectReadHandleCreation() { ClientReadHandle* ExpectReadHandleCreation() {
@ -887,8 +891,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
} }
} }
// Test successful buffer creation with mappedAtCreation = true. // Test successful CreateBufferMapped.
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) { TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedSuccess) {
// The client should create and serialize a WriteHandle on createBufferMapped. // The client should create and serialize a WriteHandle on createBufferMapped.
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(); ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
@ -900,9 +904,9 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
// The server should then deserialize the WriteHandle from the client. // The server should then deserialize the WriteHandle from the client.
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization(); ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
WGPUBuffer buffer; WGPUCreateBufferMappedResult result;
WGPUBuffer apiBuffer; WGPUCreateBufferMappedResult apiResult;
std::tie(apiBuffer, buffer) = CreateBufferMapped(); std::tie(apiResult, result) = CreateBufferMapped();
FlushClient(); FlushClient();
// Update the mapped contents. // Update the mapped contents.
@ -912,33 +916,35 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
ExpectClientWriteHandleSerializeFlush(clientHandle); ExpectClientWriteHandleSerializeFlush(clientHandle);
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1); EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
wgpuBufferUnmap(buffer); wgpuBufferUnmap(result.buffer);
// The server deserializes the Flush message. // The server deserializes the Flush message.
ExpectServerWriteHandleDeserializeFlush(serverHandle, mUpdatedBufferContent); ExpectServerWriteHandleDeserializeFlush(serverHandle, mUpdatedBufferContent);
// After the handle is updated it can be destroyed. // After the handle is updated it can be destroyed.
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1); EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1); EXPECT_CALL(api, BufferUnmap(apiResult.buffer)).Times(1);
FlushClient(); FlushClient();
} }
// Test buffer creation with mappedAtCreation WriteHandle creation failure. // Test CreateBufferMapped WriteHandle creation failure.
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationWriteHandleCreationFailure) { TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedWriteHandleCreationFailure) {
// Mock a WriteHandle creation failure // Mock a WriteHandle creation failure
MockWriteHandleCreationFailure(); MockWriteHandleCreationFailure();
WGPUBufferDescriptor descriptor = {}; WGPUBufferDescriptor descriptor = {};
descriptor.size = sizeof(mBufferContent); descriptor.size = sizeof(mBufferContent);
descriptor.mappedAtCreation = true;
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor); WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
// TODO(enga): Check that the client generated a context lost.
EXPECT_EQ(result.data, nullptr);
EXPECT_EQ(result.dataLength, 0u);
} }
// Test buffer creation with mappedAtCreation DeserializeWriteHandle failure. // Test CreateBufferMapped DeserializeWriteHandle failure.
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFailure) { TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeWriteHandleFailure) {
// The client should create and serialize a WriteHandle on createBufferMapped. // The client should create and serialize a WriteHandle on createBufferMapped.
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(); ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
@ -950,16 +956,16 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFai
// The server should then deserialize the WriteHandle from the client. // The server should then deserialize the WriteHandle from the client.
MockServerWriteHandleDeserializeFailure(); MockServerWriteHandleDeserializeFailure();
WGPUBuffer buffer; WGPUCreateBufferMappedResult result;
WGPUBuffer apiBuffer; WGPUCreateBufferMappedResult apiResult;
std::tie(apiBuffer, buffer) = CreateBufferMapped(); std::tie(apiResult, result) = CreateBufferMapped();
FlushClient(false); FlushClient(false);
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1); EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
} }
// Test buffer creation with mappedAtCreation handle Open failure. // Test CreateBufferMapped handle Open failure.
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationHandleOpenFailure) { TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedHandleOpenFailure) {
// The client should create a WriteHandle on createBufferMapped. // The client should create a WriteHandle on createBufferMapped.
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(); ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
@ -973,14 +979,16 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationHandleOpenFailure) {
WGPUBufferDescriptor descriptor = {}; WGPUBufferDescriptor descriptor = {};
descriptor.size = sizeof(mBufferContent); descriptor.size = sizeof(mBufferContent);
descriptor.mappedAtCreation = true;
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor); WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
// TODO(enga): Check that the client generated a context lost.
EXPECT_EQ(result.data, nullptr);
EXPECT_EQ(result.dataLength, 0u);
} }
// Test buffer creation with mappedAtCreation = true DeserializeFlush failure. // Test CreateBufferMapped DeserializeFlush failure.
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure) { TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure) {
// The client should create and serialize a WriteHandle on createBufferMapped. // The client should create and serialize a WriteHandle on createBufferMapped.
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(); ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
@ -992,9 +1000,9 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure)
// The server should then deserialize the WriteHandle from the client. // The server should then deserialize the WriteHandle from the client.
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization(); ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
WGPUBuffer buffer; WGPUCreateBufferMappedResult result;
WGPUBuffer apiBuffer; WGPUCreateBufferMappedResult apiResult;
std::tie(apiBuffer, buffer) = CreateBufferMapped(); std::tie(apiResult, result) = CreateBufferMapped();
FlushClient(); FlushClient();
// Update the mapped contents. // Update the mapped contents.
@ -1004,7 +1012,7 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure)
ExpectClientWriteHandleSerializeFlush(clientHandle); ExpectClientWriteHandleSerializeFlush(clientHandle);
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1); EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
wgpuBufferUnmap(buffer); wgpuBufferUnmap(result.buffer);
// The server deserializes the Flush message. Mock a deserialization failure. // The server deserializes the Flush message. Mock a deserialization failure.
MockServerWriteHandleDeserializeFlushFailure(serverHandle); MockServerWriteHandleDeserializeFlushFailure(serverHandle);
@ -1014,8 +1022,8 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure)
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1); EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
} }
// Test mappedAtCreation=true destroying the buffer before unmapping on the client side. // Test CreateBufferMapped destroying the buffer before unmapping on the client side.
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) { TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDestroyBeforeUnmap) {
// The client should create and serialize a WriteHandle on createBufferMapped. // The client should create and serialize a WriteHandle on createBufferMapped.
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation(); ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
@ -1027,9 +1035,9 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
// The server should then deserialize the WriteHandle from the client. // The server should then deserialize the WriteHandle from the client.
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization(); ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
WGPUBuffer buffer; WGPUCreateBufferMappedResult result;
WGPUBuffer apiBuffer; WGPUCreateBufferMappedResult apiResult;
std::tie(apiBuffer, buffer) = CreateBufferMapped(); std::tie(apiResult, result) = CreateBufferMapped();
FlushClient(); FlushClient();
// Update the mapped contents. // Update the mapped contents.
@ -1039,16 +1047,16 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
// immediately, both in the client and server side. // immediately, both in the client and server side.
{ {
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1); EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
wgpuBufferDestroy(buffer); wgpuBufferDestroy(result.buffer);
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1); EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1); EXPECT_CALL(api, BufferDestroy(apiResult.buffer)).Times(1);
FlushClient(); FlushClient();
// The handle is already destroyed so unmap only results in a server unmap call. // The handle is already destroyed so unmap only results in a server unmap call.
wgpuBufferUnmap(buffer); wgpuBufferUnmap(result.buffer);
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1); EXPECT_CALL(api, BufferUnmap(apiResult.buffer)).Times(1);
FlushClient(); FlushClient();
} }
} }