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:
parent
225a2b46b0
commit
b88b1a15c7
|
@ -38,7 +38,7 @@
|
|||
{ "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}
|
||||
],
|
||||
"device create buffer": [
|
||||
"device create buffer mapped": [
|
||||
{ "name": "device", "type": "device" },
|
||||
{ "name": "descriptor", "type": "buffer descriptor", "annotation": "const*" },
|
||||
{ "name": "result", "type": "ObjectHandle", "handle_type": "buffer" },
|
||||
|
@ -108,8 +108,6 @@
|
|||
"BufferSetSubData",
|
||||
"BufferGetConstMappedRange",
|
||||
"BufferGetMappedRange",
|
||||
"DeviceCreateBuffer",
|
||||
"DeviceCreateBufferMapped",
|
||||
"DevicePopErrorScope",
|
||||
"DeviceSetDeviceLostCallback",
|
||||
"DeviceSetUncapturedErrorCallback",
|
||||
|
@ -121,6 +119,8 @@
|
|||
"client_handwritten_commands": [
|
||||
"BufferDestroy",
|
||||
"BufferUnmap",
|
||||
"DeviceCreateBuffer",
|
||||
"DeviceCreateBufferMapped",
|
||||
"DeviceCreateErrorBuffer",
|
||||
"DeviceGetDefaultQueue",
|
||||
"DeviceInjectError",
|
||||
|
|
|
@ -29,61 +29,89 @@ namespace dawn_wire { namespace client {
|
|||
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_);
|
||||
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;
|
||||
|
||||
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.descriptor = descriptor;
|
||||
cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
|
||||
cmd.handleCreateInfoLength = writeHandleCreateInfoLength;
|
||||
cmd.handleCreateInfoLength = handleCreateInfoLength;
|
||||
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.
|
||||
writeHandle->SerializeCreate(writeHandleSpace);
|
||||
buffer->mWriteHandle->SerializeCreate(writeHandleSpace);
|
||||
|
||||
// Set the buffer state for the mapping at creation. The buffer now owns the write
|
||||
// handle..
|
||||
buffer->mWriteHandle = std::move(writeHandle);
|
||||
buffer->mMappedData = writeData;
|
||||
buffer->mMapOffset = 0;
|
||||
buffer->mMapSize = buffer->mSize;
|
||||
}
|
||||
|
||||
return ToAPI(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace dawn_wire { namespace client {
|
|||
using ObjectBase::ObjectBase;
|
||||
|
||||
static WGPUBuffer Create(Device* device, const WGPUBufferDescriptor* descriptor);
|
||||
static WGPUCreateBufferMappedResult CreateMapped(Device* device,
|
||||
const WGPUBufferDescriptor* descriptor);
|
||||
static WGPUBuffer CreateError(Device* device);
|
||||
|
||||
~Buffer();
|
||||
|
|
|
@ -146,20 +146,16 @@ namespace dawn_wire { namespace client {
|
|||
}
|
||||
|
||||
WGPUBuffer Device::CreateBuffer(const WGPUBufferDescriptor* descriptor) {
|
||||
if (descriptor->mappedAtCreation) {
|
||||
return CreateBufferMapped(descriptor).buffer;
|
||||
} else {
|
||||
return Buffer::Create(this, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
WGPUCreateBufferMappedResult Device::CreateBufferMapped(
|
||||
const WGPUBufferDescriptor* descriptor) {
|
||||
WGPUBufferDescriptor descMappedAtCreation = *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;
|
||||
return Buffer::CreateMapped(this, descriptor);
|
||||
}
|
||||
|
||||
WGPUBuffer Device::CreateErrorBuffer() {
|
||||
|
|
|
@ -118,52 +118,50 @@ namespace dawn_wire { namespace server {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Server::DoDeviceCreateBuffer(WGPUDevice device,
|
||||
bool Server::DoDeviceCreateBufferMapped(WGPUDevice device,
|
||||
const WGPUBufferDescriptor* descriptor,
|
||||
ObjectHandle bufferResult,
|
||||
uint64_t handleCreateInfoLength,
|
||||
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);
|
||||
if (resultData == nullptr) {
|
||||
return false;
|
||||
}
|
||||
resultData->generation = bufferResult.generation;
|
||||
resultData->handle = mProcs.deviceCreateBuffer(device, descriptor);
|
||||
|
||||
// If the buffer isn't mapped at creation, we are done.
|
||||
if (!descriptor->mappedAtCreation) {
|
||||
return handleCreateInfoLength == 0;
|
||||
}
|
||||
|
||||
// This is the size of data deserialized from the command stream to create the write handle,
|
||||
// which must be CPU-addressable.
|
||||
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.
|
||||
WGPUCreateBufferMappedResult result = mProcs.deviceCreateBufferMapped(device, descriptor);
|
||||
ASSERT(result.buffer != nullptr);
|
||||
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
|
||||
// and subsequent operations will be errors.
|
||||
// This should only happen when fuzzing with the Null backend.
|
||||
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.
|
||||
ASSERT(writeHandle != nullptr);
|
||||
writeHandle->SetTarget(mapping, descriptor->size);
|
||||
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.reset(writeHandle);
|
||||
resultData->writeHandle =
|
||||
std::unique_ptr<MemoryTransferService::WriteHandle>(writeHandle);
|
||||
}
|
||||
resultData->handle = result.buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -477,72 +477,84 @@ TEST_F(WireBufferMappingTests, DestroyInsideMapWriteCallback) {
|
|||
FlushClient();
|
||||
}
|
||||
|
||||
// Test successful buffer creation with mappedAtCreation=true
|
||||
TEST_F(WireBufferMappingTests, MappedAtCreationSuccess) {
|
||||
// Test successful CreateBufferMapped
|
||||
TEST_F(WireBufferMappingTests, CreateBufferMappedSuccess) {
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = 4;
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
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, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferUnmap(buffer);
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
// Test that releasing a buffer mapped at creation does not call Unmap
|
||||
TEST_F(WireBufferMappingTests, MappedAtCreationReleaseBeforeUnmap) {
|
||||
// Test that releasing after CreateBufferMapped does not call Unmap
|
||||
TEST_F(WireBufferMappingTests, ReleaseAfterCreateBufferMapped) {
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = 4;
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
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, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferRelease(buffer);
|
||||
wgpuBufferRelease(result.buffer);
|
||||
EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
// Test that it is valid to map a buffer after it is mapped at creation and unmapped
|
||||
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
||||
// Test that it is valid to map a buffer after CreateBufferMapped and Unmap
|
||||
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapSuccess) {
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = 4;
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
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, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferUnmap(buffer);
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||
wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||
|
||||
uint32_t zero = 0;
|
||||
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
|
@ -560,23 +572,27 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
|||
FlushServer();
|
||||
}
|
||||
|
||||
// Test that it is invalid to map a buffer after mappedAtCreation but before Unmap
|
||||
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
||||
// Test that it is invalid to map a buffer after CreateBufferMapped before Unmap
|
||||
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = 4;
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
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, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||
wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||
|
||||
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||
|
@ -589,7 +605,7 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
|||
|
||||
FlushServer();
|
||||
|
||||
wgpuBufferUnmap(buffer);
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
|
|
|
@ -155,20 +155,24 @@ class WireMemoryTransferServiceTests : public WireTest {
|
|||
return std::make_pair(apiBuffer, buffer);
|
||||
}
|
||||
|
||||
std::pair<WGPUBuffer, WGPUBuffer> CreateBufferMapped() {
|
||||
std::pair<WGPUCreateBufferMappedResult, WGPUCreateBufferMappedResult> CreateBufferMapped() {
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = sizeof(mBufferContent);
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
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));
|
||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, sizeof(mBufferContent)))
|
||||
.WillOnce(Return(&mMappedBufferContent));
|
||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||
|
||||
return std::make_pair(apiBuffer, buffer);
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
return std::make_pair(apiResult, result);
|
||||
}
|
||||
|
||||
ClientReadHandle* ExpectReadHandleCreation() {
|
||||
|
@ -887,8 +891,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test successful buffer creation with mappedAtCreation = true.
|
||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
||||
// Test successful CreateBufferMapped.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedSuccess) {
|
||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||
|
||||
|
@ -900,9 +904,9 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
|||
// The server should then deserialize the WriteHandle from the client.
|
||||
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
||||
|
||||
WGPUBuffer buffer;
|
||||
WGPUBuffer apiBuffer;
|
||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||
WGPUCreateBufferMappedResult result;
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
std::tie(apiResult, result) = CreateBufferMapped();
|
||||
FlushClient();
|
||||
|
||||
// Update the mapped contents.
|
||||
|
@ -912,33 +916,35 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
|||
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||
|
||||
wgpuBufferUnmap(buffer);
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
|
||||
// The server deserializes the Flush message.
|
||||
ExpectServerWriteHandleDeserializeFlush(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);
|
||||
EXPECT_CALL(api, BufferUnmap(apiResult.buffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
// Test buffer creation with mappedAtCreation WriteHandle creation failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationWriteHandleCreationFailure) {
|
||||
// Test CreateBufferMapped WriteHandle creation failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedWriteHandleCreationFailure) {
|
||||
// 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)));
|
||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||
|
||||
// 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_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFailure) {
|
||||
// Test CreateBufferMapped DeserializeWriteHandle failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeWriteHandleFailure) {
|
||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||
|
||||
|
@ -950,16 +956,16 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFai
|
|||
// The server should then deserialize the WriteHandle from the client.
|
||||
MockServerWriteHandleDeserializeFailure();
|
||||
|
||||
WGPUBuffer buffer;
|
||||
WGPUBuffer apiBuffer;
|
||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||
WGPUCreateBufferMappedResult result;
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
std::tie(apiResult, result) = CreateBufferMapped();
|
||||
FlushClient(false);
|
||||
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||
}
|
||||
|
||||
// Test buffer creation with mappedAtCreation handle Open failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationHandleOpenFailure) {
|
||||
// Test CreateBufferMapped handle Open failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedHandleOpenFailure) {
|
||||
// The client should create a WriteHandle on createBufferMapped.
|
||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||
|
||||
|
@ -973,14 +979,16 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationHandleOpenFailure) {
|
|||
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = sizeof(mBufferContent);
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
|
||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||
|
||||
// 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_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure) {
|
||||
// Test CreateBufferMapped DeserializeFlush failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure) {
|
||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||
|
||||
|
@ -992,9 +1000,9 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure)
|
|||
// The server should then deserialize the WriteHandle from the client.
|
||||
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
||||
|
||||
WGPUBuffer buffer;
|
||||
WGPUBuffer apiBuffer;
|
||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||
WGPUCreateBufferMappedResult result;
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
std::tie(apiResult, result) = CreateBufferMapped();
|
||||
FlushClient();
|
||||
|
||||
// Update the mapped contents.
|
||||
|
@ -1004,7 +1012,7 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure)
|
|||
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||
|
||||
wgpuBufferUnmap(buffer);
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
|
||||
// The server deserializes the Flush message. Mock a deserialization failure.
|
||||
MockServerWriteHandleDeserializeFlushFailure(serverHandle);
|
||||
|
@ -1014,8 +1022,8 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure)
|
|||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||
}
|
||||
|
||||
// Test mappedAtCreation=true destroying the buffer before unmapping on the client side.
|
||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
||||
// Test CreateBufferMapped destroying the buffer before unmapping on the client side.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDestroyBeforeUnmap) {
|
||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||
|
||||
|
@ -1027,9 +1035,9 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
|||
// The server should then deserialize the WriteHandle from the client.
|
||||
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
||||
|
||||
WGPUBuffer buffer;
|
||||
WGPUBuffer apiBuffer;
|
||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||
WGPUCreateBufferMappedResult result;
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
std::tie(apiResult, result) = CreateBufferMapped();
|
||||
FlushClient();
|
||||
|
||||
// Update the mapped contents.
|
||||
|
@ -1039,16 +1047,16 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
|||
// immediately, both in the client and server side.
|
||||
{
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||
wgpuBufferDestroy(buffer);
|
||||
wgpuBufferDestroy(result.buffer);
|
||||
|
||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
||||
EXPECT_CALL(api, BufferDestroy(apiResult.buffer)).Times(1);
|
||||
FlushClient();
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue