dawn_wire: Implement CreateBufferMapped on top of mappedAtCreation
Reland with a fix for narrowing of uint64_t to size_t of the buffer size in 32 bit mode. 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. TBR=senorblanco@chromium.org Bug: dawn:445 Change-Id: I89fe84b6e0b5d0d4a5c6a2db7b38cb7d6cd063f0 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/25981 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
ab04da48f4
commit
f93fa6acd9
|
@ -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 mapped": [
|
||||
"device create buffer": [
|
||||
{ "name": "device", "type": "device" },
|
||||
{ "name": "descriptor", "type": "buffer descriptor", "annotation": "const*" },
|
||||
{ "name": "result", "type": "ObjectHandle", "handle_type": "buffer" },
|
||||
|
@ -108,6 +108,8 @@
|
|||
"BufferSetSubData",
|
||||
"BufferGetConstMappedRange",
|
||||
"BufferGetMappedRange",
|
||||
"DeviceCreateBuffer",
|
||||
"DeviceCreateBufferMapped",
|
||||
"DevicePopErrorScope",
|
||||
"DeviceSetDeviceLostCallback",
|
||||
"DeviceSetUncapturedErrorCallback",
|
||||
|
@ -119,8 +121,6 @@
|
|||
"client_handwritten_commands": [
|
||||
"BufferDestroy",
|
||||
"BufferUnmap",
|
||||
"DeviceCreateBuffer",
|
||||
"DeviceCreateBufferMapped",
|
||||
"DeviceCreateErrorBuffer",
|
||||
"DeviceGetDefaultQueue",
|
||||
"DeviceInjectError",
|
||||
|
|
|
@ -23,95 +23,69 @@ namespace dawn_wire { namespace client {
|
|||
WGPUBuffer Buffer::Create(Device* device_, const WGPUBufferDescriptor* descriptor) {
|
||||
Client* wireClient = device_->GetClient();
|
||||
|
||||
if ((descriptor->usage & (WGPUBufferUsage_MapRead | WGPUBufferUsage_MapWrite)) != 0 &&
|
||||
descriptor->size > std::numeric_limits<size_t>::max()) {
|
||||
bool mappable =
|
||||
(descriptor->usage & (WGPUBufferUsage_MapRead | WGPUBufferUsage_MapWrite)) != 0 ||
|
||||
descriptor->mappedAtCreation;
|
||||
if (mappable && descriptor->size > std::numeric_limits<size_t>::max()) {
|
||||
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer is too large for map usage");
|
||||
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 = handleCreateInfoLength;
|
||||
cmd.handleCreateInfoLength = writeHandleCreateInfoLength;
|
||||
cmd.handleCreateInfo = nullptr;
|
||||
|
||||
char* writeHandleSpace =
|
||||
buffer->device->GetClient()->SerializeCommand(cmd, handleCreateInfoLength);
|
||||
char* writeHandleSpace = wireClient->SerializeCommand(cmd, writeHandleCreateInfoLength);
|
||||
|
||||
if (descriptor->mappedAtCreation) {
|
||||
// Serialize the WriteHandle into the space after the command.
|
||||
buffer->mWriteHandle->SerializeCreate(writeHandleSpace);
|
||||
writeHandle->SerializeCreate(writeHandleSpace);
|
||||
|
||||
return result;
|
||||
// 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);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -29,8 +29,6 @@ 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,16 +146,20 @@ 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) {
|
||||
return Buffer::CreateMapped(this, 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;
|
||||
}
|
||||
|
||||
WGPUBuffer Device::CreateErrorBuffer() {
|
||||
|
|
|
@ -118,50 +118,52 @@ namespace dawn_wire { namespace server {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Server::DoDeviceCreateBufferMapped(WGPUDevice device,
|
||||
bool Server::DoDeviceCreateBuffer(WGPUDevice device,
|
||||
const WGPUBufferDescriptor* descriptor,
|
||||
ObjectHandle bufferResult,
|
||||
uint64_t handleCreateInfoLength,
|
||||
const uint8_t* handleCreateInfo) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Create and register the buffer object.
|
||||
auto* resultData = BufferObjects().Allocate(bufferResult.id);
|
||||
if (resultData == nullptr) {
|
||||
return false;
|
||||
}
|
||||
resultData->generation = bufferResult.generation;
|
||||
resultData->handle = mProcs.deviceCreateBuffer(device, descriptor);
|
||||
|
||||
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.
|
||||
// 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.
|
||||
resultData->mapWriteState = BufferMapWriteState::MapError;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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);
|
||||
ASSERT(writeHandle != nullptr);
|
||||
writeHandle->SetTarget(mapping, descriptor->size);
|
||||
|
||||
// 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;
|
||||
resultData->writeHandle.reset(writeHandle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -477,84 +477,72 @@ TEST_F(WireBufferMappingTests, DestroyInsideMapWriteCallback) {
|
|||
FlushClient();
|
||||
}
|
||||
|
||||
// Test successful CreateBufferMapped
|
||||
TEST_F(WireBufferMappingTests, CreateBufferMappedSuccess) {
|
||||
// Test successful buffer creation with mappedAtCreation=true
|
||||
TEST_F(WireBufferMappingTests, MappedAtCreationSuccess) {
|
||||
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;
|
||||
|
||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
wgpuBufferUnmap(buffer);
|
||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
// Test that releasing after CreateBufferMapped does not call Unmap
|
||||
TEST_F(WireBufferMappingTests, ReleaseAfterCreateBufferMapped) {
|
||||
// Test that releasing a buffer mapped at creation does not call Unmap
|
||||
TEST_F(WireBufferMappingTests, MappedAtCreationReleaseBeforeUnmap) {
|
||||
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;
|
||||
|
||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferRelease(result.buffer);
|
||||
wgpuBufferRelease(buffer);
|
||||
EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
// Test that it is valid to map a buffer after CreateBufferMapped and Unmap
|
||||
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapSuccess) {
|
||||
// Test that it is valid to map a buffer after it is mapped at creation and unmapped
|
||||
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = 4;
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
uint32_t apiBufferData = 9863;
|
||||
apiResult.buffer = apiBuffer;
|
||||
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
|
||||
apiResult.dataLength = 4;
|
||||
uint32_t apiBufferData = 1234;
|
||||
|
||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
wgpuBufferUnmap(buffer);
|
||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||
wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||
|
||||
uint32_t zero = 0;
|
||||
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
|
@ -572,27 +560,23 @@ TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapSuccess) {
|
|||
FlushServer();
|
||||
}
|
||||
|
||||
// Test that it is invalid to map a buffer after CreateBufferMapped before Unmap
|
||||
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
|
||||
// Test that it is invalid to map a buffer after mappedAtCreation but before Unmap
|
||||
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = 4;
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
uint32_t apiBufferData = 9863;
|
||||
apiResult.buffer = apiBuffer;
|
||||
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
|
||||
apiResult.dataLength = 4;
|
||||
uint32_t apiBufferData = 1234;
|
||||
|
||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||
|
||||
FlushClient();
|
||||
|
||||
wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||
wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||
|
||||
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||
|
@ -605,7 +589,7 @@ TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
|
|||
|
||||
FlushServer();
|
||||
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
wgpuBufferUnmap(buffer);
|
||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
|
|
|
@ -155,24 +155,20 @@ class WireMemoryTransferServiceTests : public WireTest {
|
|||
return std::make_pair(apiBuffer, buffer);
|
||||
}
|
||||
|
||||
std::pair<WGPUCreateBufferMappedResult, WGPUCreateBufferMappedResult> CreateBufferMapped() {
|
||||
std::pair<WGPUBuffer, WGPUBuffer> CreateBufferMapped() {
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = sizeof(mBufferContent);
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
apiResult.buffer = apiBuffer;
|
||||
apiResult.data = reinterpret_cast<uint8_t*>(&mMappedBufferContent);
|
||||
apiResult.dataLength = sizeof(mMappedBufferContent);
|
||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||
|
||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, sizeof(mBufferContent)))
|
||||
.WillOnce(Return(&mMappedBufferContent));
|
||||
|
||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||
.WillOnce(Return(apiResult))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
return std::make_pair(apiResult, result);
|
||||
return std::make_pair(apiBuffer, buffer);
|
||||
}
|
||||
|
||||
ClientReadHandle* ExpectReadHandleCreation() {
|
||||
|
@ -891,8 +887,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test successful CreateBufferMapped.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedSuccess) {
|
||||
// Test successful buffer creation with mappedAtCreation = true.
|
||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||
|
||||
|
@ -904,9 +900,9 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedSuccess) {
|
|||
// The server should then deserialize the WriteHandle from the client.
|
||||
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
||||
|
||||
WGPUCreateBufferMappedResult result;
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
std::tie(apiResult, result) = CreateBufferMapped();
|
||||
WGPUBuffer buffer;
|
||||
WGPUBuffer apiBuffer;
|
||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||
FlushClient();
|
||||
|
||||
// Update the mapped contents.
|
||||
|
@ -916,35 +912,33 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedSuccess) {
|
|||
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
wgpuBufferUnmap(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(apiResult.buffer)).Times(1);
|
||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
// Test CreateBufferMapped WriteHandle creation failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedWriteHandleCreationFailure) {
|
||||
// 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;
|
||||
|
||||
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);
|
||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
|
||||
}
|
||||
|
||||
// Test CreateBufferMapped DeserializeWriteHandle failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeWriteHandleFailure) {
|
||||
// Test buffer creation with mappedAtCreation DeserializeWriteHandle failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFailure) {
|
||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||
|
||||
|
@ -956,16 +950,16 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeWriteHandleF
|
|||
// The server should then deserialize the WriteHandle from the client.
|
||||
MockServerWriteHandleDeserializeFailure();
|
||||
|
||||
WGPUCreateBufferMappedResult result;
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
std::tie(apiResult, result) = CreateBufferMapped();
|
||||
WGPUBuffer buffer;
|
||||
WGPUBuffer apiBuffer;
|
||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||
FlushClient(false);
|
||||
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||
}
|
||||
|
||||
// Test CreateBufferMapped handle Open failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedHandleOpenFailure) {
|
||||
// Test buffer creation with mappedAtCreation handle Open failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationHandleOpenFailure) {
|
||||
// The client should create a WriteHandle on createBufferMapped.
|
||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||
|
||||
|
@ -979,16 +973,14 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedHandleOpenFailure) {
|
|||
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = sizeof(mBufferContent);
|
||||
descriptor.mappedAtCreation = true;
|
||||
|
||||
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);
|
||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
|
||||
}
|
||||
|
||||
// Test CreateBufferMapped DeserializeFlush failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure) {
|
||||
// Test buffer creation with mappedAtCreation = true DeserializeFlush failure.
|
||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure) {
|
||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||
|
||||
|
@ -1000,9 +992,9 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure
|
|||
// The server should then deserialize the WriteHandle from the client.
|
||||
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
||||
|
||||
WGPUCreateBufferMappedResult result;
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
std::tie(apiResult, result) = CreateBufferMapped();
|
||||
WGPUBuffer buffer;
|
||||
WGPUBuffer apiBuffer;
|
||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||
FlushClient();
|
||||
|
||||
// Update the mapped contents.
|
||||
|
@ -1012,7 +1004,7 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure
|
|||
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||
|
||||
wgpuBufferUnmap(result.buffer);
|
||||
wgpuBufferUnmap(buffer);
|
||||
|
||||
// The server deserializes the Flush message. Mock a deserialization failure.
|
||||
MockServerWriteHandleDeserializeFlushFailure(serverHandle);
|
||||
|
@ -1022,8 +1014,8 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure
|
|||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||
}
|
||||
|
||||
// Test CreateBufferMapped destroying the buffer before unmapping on the client side.
|
||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDestroyBeforeUnmap) {
|
||||
// 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();
|
||||
|
||||
|
@ -1035,9 +1027,9 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDestroyBeforeUnmap) {
|
|||
// The server should then deserialize the WriteHandle from the client.
|
||||
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
||||
|
||||
WGPUCreateBufferMappedResult result;
|
||||
WGPUCreateBufferMappedResult apiResult;
|
||||
std::tie(apiResult, result) = CreateBufferMapped();
|
||||
WGPUBuffer buffer;
|
||||
WGPUBuffer apiBuffer;
|
||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||
FlushClient();
|
||||
|
||||
// Update the mapped contents.
|
||||
|
@ -1047,16 +1039,16 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDestroyBeforeUnmap) {
|
|||
// immediately, both in the client and server side.
|
||||
{
|
||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||
wgpuBufferDestroy(result.buffer);
|
||||
wgpuBufferDestroy(buffer);
|
||||
|
||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||
EXPECT_CALL(api, BufferDestroy(apiResult.buffer)).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(result.buffer);
|
||||
wgpuBufferUnmap(buffer);
|
||||
|
||||
EXPECT_CALL(api, BufferUnmap(apiResult.buffer)).Times(1);
|
||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||
FlushClient();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue