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>
This commit is contained in:
parent
b7ce8970d2
commit
0811ecc775
|
@ -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 mapped": [
|
"device create buffer": [
|
||||||
{ "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,6 +108,8 @@
|
||||||
"BufferSetSubData",
|
"BufferSetSubData",
|
||||||
"BufferGetConstMappedRange",
|
"BufferGetConstMappedRange",
|
||||||
"BufferGetMappedRange",
|
"BufferGetMappedRange",
|
||||||
|
"DeviceCreateBuffer",
|
||||||
|
"DeviceCreateBufferMapped",
|
||||||
"DevicePopErrorScope",
|
"DevicePopErrorScope",
|
||||||
"DeviceSetDeviceLostCallback",
|
"DeviceSetDeviceLostCallback",
|
||||||
"DeviceSetUncapturedErrorCallback",
|
"DeviceSetUncapturedErrorCallback",
|
||||||
|
@ -119,8 +121,6 @@
|
||||||
"client_handwritten_commands": [
|
"client_handwritten_commands": [
|
||||||
"BufferDestroy",
|
"BufferDestroy",
|
||||||
"BufferUnmap",
|
"BufferUnmap",
|
||||||
"DeviceCreateBuffer",
|
|
||||||
"DeviceCreateBufferMapped",
|
|
||||||
"DeviceCreateErrorBuffer",
|
"DeviceCreateErrorBuffer",
|
||||||
"DeviceGetDefaultQueue",
|
"DeviceGetDefaultQueue",
|
||||||
"DeviceInjectError",
|
"DeviceInjectError",
|
||||||
|
|
|
@ -29,89 +29,61 @@ 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 = handleCreateInfoLength;
|
cmd.handleCreateInfoLength = writeHandleCreateInfoLength;
|
||||||
cmd.handleCreateInfo = nullptr;
|
cmd.handleCreateInfo = nullptr;
|
||||||
|
|
||||||
char* writeHandleSpace =
|
char* writeHandleSpace = wireClient->SerializeCommand(cmd, writeHandleCreateInfoLength);
|
||||||
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);
|
||||||
|
|
||||||
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
|
// static
|
||||||
|
|
|
@ -29,8 +29,6 @@ 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();
|
||||||
|
|
|
@ -146,16 +146,20 @@ namespace dawn_wire { namespace client {
|
||||||
}
|
}
|
||||||
|
|
||||||
WGPUBuffer Device::CreateBuffer(const WGPUBufferDescriptor* descriptor) {
|
WGPUBuffer Device::CreateBuffer(const WGPUBufferDescriptor* descriptor) {
|
||||||
if (descriptor->mappedAtCreation) {
|
|
||||||
return CreateBufferMapped(descriptor).buffer;
|
|
||||||
} else {
|
|
||||||
return Buffer::Create(this, descriptor);
|
return Buffer::Create(this, descriptor);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult Device::CreateBufferMapped(
|
WGPUCreateBufferMappedResult Device::CreateBufferMapped(
|
||||||
const WGPUBufferDescriptor* descriptor) {
|
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() {
|
WGPUBuffer Device::CreateErrorBuffer() {
|
||||||
|
|
|
@ -118,50 +118,52 @@ namespace dawn_wire { namespace server {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Server::DoDeviceCreateBufferMapped(WGPUDevice device,
|
bool Server::DoDeviceCreateBuffer(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) {
|
||||||
if (handleCreateInfoLength > std::numeric_limits<size_t>::max()) {
|
// Create and register the buffer object.
|
||||||
// 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);
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result = mProcs.deviceCreateBufferMapped(device, descriptor);
|
// If the buffer isn't mapped at creation, we are done.
|
||||||
ASSERT(result.buffer != nullptr);
|
if (!descriptor->mappedAtCreation) {
|
||||||
if (result.data == nullptr && result.dataLength != 0) {
|
return handleCreateInfoLength == 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 is the size of data deserialized from the command stream to create the write handle,
|
||||||
// This should only happen when fuzzing with the Null backend.
|
// 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;
|
resultData->mapWriteState = BufferMapWriteState::MapError;
|
||||||
} else {
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Deserialize metadata produced from the client to create a companion server handle.
|
// Deserialize metadata produced from the client to create a companion server handle.
|
||||||
MemoryTransferService::WriteHandle* writeHandle = nullptr;
|
MemoryTransferService::WriteHandle* writeHandle = nullptr;
|
||||||
if (!mMemoryTransferService->DeserializeWriteHandle(
|
if (!mMemoryTransferService->DeserializeWriteHandle(
|
||||||
handleCreateInfo, static_cast<size_t>(handleCreateInfoLength), &writeHandle)) {
|
handleCreateInfo, static_cast<size_t>(handleCreateInfoLength), &writeHandle)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ASSERT(writeHandle != nullptr);
|
|
||||||
|
|
||||||
// Set the target of the WriteHandle to the mapped GPU memory.
|
// 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->mapWriteState = BufferMapWriteState::Mapped;
|
||||||
resultData->writeHandle =
|
resultData->writeHandle.reset(writeHandle);
|
||||||
std::unique_ptr<MemoryTransferService::WriteHandle>(writeHandle);
|
|
||||||
}
|
|
||||||
resultData->handle = result.buffer;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -477,84 +477,72 @@ TEST_F(WireBufferMappingTests, DestroyInsideMapWriteCallback) {
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test successful CreateBufferMapped
|
// Test successful buffer creation with mappedAtCreation=true
|
||||||
TEST_F(WireBufferMappingTests, CreateBufferMappedSuccess) {
|
TEST_F(WireBufferMappingTests, MappedAtCreationSuccess) {
|
||||||
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;
|
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||||
|
|
||||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
||||||
.WillOnce(Return(apiResult))
|
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||||
.RetiresOnSaturation();
|
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferUnmap(result.buffer);
|
wgpuBufferUnmap(buffer);
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that releasing after CreateBufferMapped does not call Unmap
|
// Test that releasing a buffer mapped at creation does not call Unmap
|
||||||
TEST_F(WireBufferMappingTests, ReleaseAfterCreateBufferMapped) {
|
TEST_F(WireBufferMappingTests, MappedAtCreationReleaseBeforeUnmap) {
|
||||||
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;
|
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||||
|
|
||||||
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
||||||
.WillOnce(Return(apiResult))
|
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||||
.RetiresOnSaturation();
|
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferRelease(result.buffer);
|
wgpuBufferRelease(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 CreateBufferMapped and Unmap
|
// Test that it is valid to map a buffer after it is mapped at creation and unmapped
|
||||||
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapSuccess) {
|
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
||||||
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 = 9863;
|
|
||||||
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, _))
|
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
||||||
.WillOnce(Return(apiResult))
|
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||||
.RetiresOnSaturation();
|
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferUnmap(result.buffer);
|
wgpuBufferUnmap(buffer);
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
|
wgpuBufferMapWriteAsync(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([&]() {
|
||||||
|
@ -572,27 +560,23 @@ TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapSuccess) {
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that it is invalid to map a buffer after CreateBufferMapped before Unmap
|
// Test that it is invalid to map a buffer after mappedAtCreation but before Unmap
|
||||||
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
|
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
||||||
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 = 9863;
|
|
||||||
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, _))
|
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
||||||
.WillOnce(Return(apiResult))
|
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
||||||
.RetiresOnSaturation();
|
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
|
wgpuBufferMapWriteAsync(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);
|
||||||
|
@ -605,7 +589,7 @@ TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
wgpuBufferUnmap(result.buffer);
|
wgpuBufferUnmap(buffer);
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
|
@ -155,24 +155,20 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||||
return std::make_pair(apiBuffer, buffer);
|
return std::make_pair(apiBuffer, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<WGPUCreateBufferMappedResult, WGPUCreateBufferMappedResult> CreateBufferMapped() {
|
std::pair<WGPUBuffer, WGPUBuffer> CreateBufferMapped() {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = sizeof(mBufferContent);
|
descriptor.size = sizeof(mBufferContent);
|
||||||
|
descriptor.mappedAtCreation = true;
|
||||||
|
|
||||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult apiResult;
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||||
apiResult.buffer = apiBuffer;
|
|
||||||
apiResult.data = reinterpret_cast<uint8_t*>(&mMappedBufferContent);
|
|
||||||
apiResult.dataLength = sizeof(mMappedBufferContent);
|
|
||||||
|
|
||||||
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, _))
|
return std::make_pair(apiBuffer, buffer);
|
||||||
.WillOnce(Return(apiResult))
|
|
||||||
.RetiresOnSaturation();
|
|
||||||
|
|
||||||
return std::make_pair(apiResult, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientReadHandle* ExpectReadHandleCreation() {
|
ClientReadHandle* ExpectReadHandleCreation() {
|
||||||
|
@ -891,8 +887,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test successful CreateBufferMapped.
|
// Test successful buffer creation with mappedAtCreation = true.
|
||||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedSuccess) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
||||||
// 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();
|
||||||
|
|
||||||
|
@ -904,9 +900,9 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedSuccess) {
|
||||||
// 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();
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result;
|
WGPUBuffer buffer;
|
||||||
WGPUCreateBufferMappedResult apiResult;
|
WGPUBuffer apiBuffer;
|
||||||
std::tie(apiResult, result) = CreateBufferMapped();
|
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// Update the mapped contents.
|
// Update the mapped contents.
|
||||||
|
@ -916,35 +912,33 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedSuccess) {
|
||||||
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
|
|
||||||
wgpuBufferUnmap(result.buffer);
|
wgpuBufferUnmap(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(apiResult.buffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test CreateBufferMapped WriteHandle creation failure.
|
// Test buffer creation with mappedAtCreation WriteHandle creation failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedWriteHandleCreationFailure) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationWriteHandleCreationFailure) {
|
||||||
// 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;
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(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 CreateBufferMapped DeserializeWriteHandle failure.
|
// Test buffer creation with mappedAtCreation DeserializeWriteHandle failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeWriteHandleFailure) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFailure) {
|
||||||
// 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();
|
||||||
|
|
||||||
|
@ -956,16 +950,16 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeWriteHandleF
|
||||||
// The server should then deserialize the WriteHandle from the client.
|
// The server should then deserialize the WriteHandle from the client.
|
||||||
MockServerWriteHandleDeserializeFailure();
|
MockServerWriteHandleDeserializeFailure();
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result;
|
WGPUBuffer buffer;
|
||||||
WGPUCreateBufferMappedResult apiResult;
|
WGPUBuffer apiBuffer;
|
||||||
std::tie(apiResult, result) = CreateBufferMapped();
|
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||||
FlushClient(false);
|
FlushClient(false);
|
||||||
|
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test CreateBufferMapped handle Open failure.
|
// Test buffer creation with mappedAtCreation handle Open failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedHandleOpenFailure) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationHandleOpenFailure) {
|
||||||
// The client should create a WriteHandle on createBufferMapped.
|
// The client should create a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||||
|
|
||||||
|
@ -979,16 +973,14 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedHandleOpenFailure) {
|
||||||
|
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = sizeof(mBufferContent);
|
descriptor.size = sizeof(mBufferContent);
|
||||||
|
descriptor.mappedAtCreation = true;
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
WGPUBuffer buffer = wgpuDeviceCreateBuffer(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 CreateBufferMapped DeserializeFlush failure.
|
// Test buffer creation with mappedAtCreation = true DeserializeFlush failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure) {
|
||||||
// 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();
|
||||||
|
|
||||||
|
@ -1000,9 +992,9 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure
|
||||||
// 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();
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result;
|
WGPUBuffer buffer;
|
||||||
WGPUCreateBufferMappedResult apiResult;
|
WGPUBuffer apiBuffer;
|
||||||
std::tie(apiResult, result) = CreateBufferMapped();
|
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// Update the mapped contents.
|
// Update the mapped contents.
|
||||||
|
@ -1012,7 +1004,7 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure
|
||||||
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
|
|
||||||
wgpuBufferUnmap(result.buffer);
|
wgpuBufferUnmap(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);
|
||||||
|
@ -1022,8 +1014,8 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test CreateBufferMapped destroying the buffer before unmapping on the client side.
|
// Test mappedAtCreation=true destroying the buffer before unmapping on the client side.
|
||||||
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDestroyBeforeUnmap) {
|
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
||||||
// 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();
|
||||||
|
|
||||||
|
@ -1035,9 +1027,9 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDestroyBeforeUnmap) {
|
||||||
// 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();
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result;
|
WGPUBuffer buffer;
|
||||||
WGPUCreateBufferMappedResult apiResult;
|
WGPUBuffer apiBuffer;
|
||||||
std::tie(apiResult, result) = CreateBufferMapped();
|
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// Update the mapped contents.
|
// Update the mapped contents.
|
||||||
|
@ -1047,16 +1039,16 @@ TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDestroyBeforeUnmap) {
|
||||||
// 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(result.buffer);
|
wgpuBufferDestroy(buffer);
|
||||||
|
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
EXPECT_CALL(api, BufferDestroy(apiResult.buffer)).Times(1);
|
EXPECT_CALL(api, BufferDestroy(apiBuffer)).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(result.buffer);
|
wgpuBufferUnmap(buffer);
|
||||||
|
|
||||||
EXPECT_CALL(api, BufferUnmap(apiResult.buffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue