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 length", "type": "uint64_t" },
|
||||||
{ "name": "write flush info", "type": "uint8_t", "annotation": "const*", "length": "write flush info length", "skip_serialize": true}
|
{ "name": "write flush info", "type": "uint8_t", "annotation": "const*", "length": "write flush info length", "skip_serialize": true}
|
||||||
],
|
],
|
||||||
"device create buffer": [
|
"device create buffer mapped": [
|
||||||
{ "name": "device", "type": "device" },
|
{ "name": "device", "type": "device" },
|
||||||
{ "name": "descriptor", "type": "buffer descriptor", "annotation": "const*" },
|
{ "name": "descriptor", "type": "buffer descriptor", "annotation": "const*" },
|
||||||
{ "name": "result", "type": "ObjectHandle", "handle_type": "buffer" },
|
{ "name": "result", "type": "ObjectHandle", "handle_type": "buffer" },
|
||||||
|
@ -108,8 +108,6 @@
|
||||||
"BufferSetSubData",
|
"BufferSetSubData",
|
||||||
"BufferGetConstMappedRange",
|
"BufferGetConstMappedRange",
|
||||||
"BufferGetMappedRange",
|
"BufferGetMappedRange",
|
||||||
"DeviceCreateBuffer",
|
|
||||||
"DeviceCreateBufferMapped",
|
|
||||||
"DevicePopErrorScope",
|
"DevicePopErrorScope",
|
||||||
"DeviceSetDeviceLostCallback",
|
"DeviceSetDeviceLostCallback",
|
||||||
"DeviceSetUncapturedErrorCallback",
|
"DeviceSetUncapturedErrorCallback",
|
||||||
|
@ -121,6 +119,8 @@
|
||||||
"client_handwritten_commands": [
|
"client_handwritten_commands": [
|
||||||
"BufferDestroy",
|
"BufferDestroy",
|
||||||
"BufferUnmap",
|
"BufferUnmap",
|
||||||
|
"DeviceCreateBuffer",
|
||||||
|
"DeviceCreateBufferMapped",
|
||||||
"DeviceCreateErrorBuffer",
|
"DeviceCreateErrorBuffer",
|
||||||
"DeviceGetDefaultQueue",
|
"DeviceGetDefaultQueue",
|
||||||
"DeviceInjectError",
|
"DeviceInjectError",
|
||||||
|
|
|
@ -29,61 +29,89 @@ namespace dawn_wire { namespace client {
|
||||||
return device_->CreateErrorBuffer();
|
return device_->CreateErrorBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle = nullptr;
|
|
||||||
void* writeData = nullptr;
|
|
||||||
size_t writeHandleCreateInfoLength = 0;
|
|
||||||
|
|
||||||
// If the buffer is mapped at creation, create a write handle that will represent the
|
|
||||||
// mapping of the whole buffer.
|
|
||||||
if (descriptor->mappedAtCreation) {
|
|
||||||
// Create the handle.
|
|
||||||
writeHandle.reset(
|
|
||||||
wireClient->GetMemoryTransferService()->CreateWriteHandle(descriptor->size));
|
|
||||||
if (writeHandle == nullptr) {
|
|
||||||
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer mapping allocation failed");
|
|
||||||
return device_->CreateErrorBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the handle, it may fail by returning a nullptr in writeData.
|
|
||||||
size_t writeDataLength = 0;
|
|
||||||
std::tie(writeData, writeDataLength) = writeHandle->Open();
|
|
||||||
if (writeData == nullptr) {
|
|
||||||
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer mapping allocation failed");
|
|
||||||
return device_->CreateErrorBuffer();
|
|
||||||
}
|
|
||||||
ASSERT(writeDataLength == descriptor->size);
|
|
||||||
|
|
||||||
// Get the serialization size of the write handle.
|
|
||||||
writeHandleCreateInfoLength = writeHandle->SerializeCreateSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the buffer and send the creation command.
|
|
||||||
auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(device_);
|
auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(device_);
|
||||||
Buffer* buffer = bufferObjectAndSerial->object.get();
|
Buffer* buffer = bufferObjectAndSerial->object.get();
|
||||||
|
// Store the size of the buffer so that mapping operations can allocate a
|
||||||
|
// MemoryTransfer handle of the proper size.
|
||||||
buffer->mSize = descriptor->size;
|
buffer->mSize = descriptor->size;
|
||||||
|
|
||||||
DeviceCreateBufferCmd cmd;
|
DeviceCreateBufferCmd cmd;
|
||||||
|
cmd.self = ToAPI(device_);
|
||||||
|
cmd.descriptor = descriptor;
|
||||||
|
cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
|
||||||
|
|
||||||
|
wireClient->SerializeCommand(cmd);
|
||||||
|
|
||||||
|
return ToAPI(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
WGPUCreateBufferMappedResult Buffer::CreateMapped(Device* device_,
|
||||||
|
const WGPUBufferDescriptor* descriptor) {
|
||||||
|
Client* wireClient = device_->GetClient();
|
||||||
|
|
||||||
|
WGPUCreateBufferMappedResult result;
|
||||||
|
result.data = nullptr;
|
||||||
|
result.dataLength = 0;
|
||||||
|
|
||||||
|
// This buffer is too large to be mapped and to make a WriteHandle for.
|
||||||
|
if (descriptor->size > std::numeric_limits<size_t>::max()) {
|
||||||
|
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer is too large for mapping");
|
||||||
|
result.buffer = device_->CreateErrorBuffer();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a WriteHandle for the map request. This is the client's intent to write GPU
|
||||||
|
// memory.
|
||||||
|
std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle =
|
||||||
|
std::unique_ptr<MemoryTransferService::WriteHandle>(
|
||||||
|
wireClient->GetMemoryTransferService()->CreateWriteHandle(descriptor->size));
|
||||||
|
|
||||||
|
if (writeHandle == nullptr) {
|
||||||
|
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer mapping allocation failed");
|
||||||
|
result.buffer = device_->CreateErrorBuffer();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBufferMapped is synchronous and the staging buffer for upload should be immediately
|
||||||
|
// available.
|
||||||
|
// Open the WriteHandle. This returns a pointer and size of mapped memory.
|
||||||
|
// |result.data| may be null on error.
|
||||||
|
std::tie(result.data, result.dataLength) = writeHandle->Open();
|
||||||
|
if (result.data == nullptr) {
|
||||||
|
device_->InjectError(WGPUErrorType_OutOfMemory, "Buffer mapping allocation failed");
|
||||||
|
result.buffer = device_->CreateErrorBuffer();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(device_);
|
||||||
|
Buffer* buffer = bufferObjectAndSerial->object.get();
|
||||||
|
buffer->mSize = descriptor->size;
|
||||||
|
// Successfully created staging memory. The buffer now owns the WriteHandle.
|
||||||
|
buffer->mWriteHandle = std::move(writeHandle);
|
||||||
|
buffer->mMappedData = result.data;
|
||||||
|
buffer->mMapOffset = 0;
|
||||||
|
buffer->mMapSize = descriptor->size;
|
||||||
|
|
||||||
|
result.buffer = ToAPI(buffer);
|
||||||
|
|
||||||
|
// Get the serialization size of the WriteHandle.
|
||||||
|
size_t handleCreateInfoLength = buffer->mWriteHandle->SerializeCreateSize();
|
||||||
|
|
||||||
|
DeviceCreateBufferMappedCmd cmd;
|
||||||
cmd.device = ToAPI(device_);
|
cmd.device = ToAPI(device_);
|
||||||
cmd.descriptor = descriptor;
|
cmd.descriptor = descriptor;
|
||||||
cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
|
cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
|
||||||
cmd.handleCreateInfoLength = writeHandleCreateInfoLength;
|
cmd.handleCreateInfoLength = handleCreateInfoLength;
|
||||||
cmd.handleCreateInfo = nullptr;
|
cmd.handleCreateInfo = nullptr;
|
||||||
|
|
||||||
char* writeHandleSpace = wireClient->SerializeCommand(cmd, writeHandleCreateInfoLength);
|
char* writeHandleSpace =
|
||||||
|
buffer->device->GetClient()->SerializeCommand(cmd, handleCreateInfoLength);
|
||||||
|
|
||||||
if (descriptor->mappedAtCreation) {
|
|
||||||
// Serialize the WriteHandle into the space after the command.
|
// Serialize the WriteHandle into the space after the command.
|
||||||
writeHandle->SerializeCreate(writeHandleSpace);
|
buffer->mWriteHandle->SerializeCreate(writeHandleSpace);
|
||||||
|
|
||||||
// Set the buffer state for the mapping at creation. The buffer now owns the write
|
return result;
|
||||||
// handle..
|
|
||||||
buffer->mWriteHandle = std::move(writeHandle);
|
|
||||||
buffer->mMappedData = writeData;
|
|
||||||
buffer->mMapOffset = 0;
|
|
||||||
buffer->mMapSize = buffer->mSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ToAPI(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -29,6 +29,8 @@ namespace dawn_wire { namespace client {
|
||||||
using ObjectBase::ObjectBase;
|
using ObjectBase::ObjectBase;
|
||||||
|
|
||||||
static WGPUBuffer Create(Device* device, const WGPUBufferDescriptor* descriptor);
|
static WGPUBuffer Create(Device* device, const WGPUBufferDescriptor* descriptor);
|
||||||
|
static WGPUCreateBufferMappedResult CreateMapped(Device* device,
|
||||||
|
const WGPUBufferDescriptor* descriptor);
|
||||||
static WGPUBuffer CreateError(Device* device);
|
static WGPUBuffer CreateError(Device* device);
|
||||||
|
|
||||||
~Buffer();
|
~Buffer();
|
||||||
|
|
|
@ -146,20 +146,16 @@ 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) {
|
||||||
WGPUBufferDescriptor descMappedAtCreation = *descriptor;
|
return Buffer::CreateMapped(this, descriptor);
|
||||||
descMappedAtCreation.mappedAtCreation = true;
|
|
||||||
|
|
||||||
WGPUCreateBufferMappedResult result;
|
|
||||||
result.buffer = CreateBuffer(&descMappedAtCreation);
|
|
||||||
result.data = FromAPI(result.buffer)->GetMappedRange(0, descriptor->size);
|
|
||||||
result.dataLength = result.data == nullptr ? 0 : descriptor->size;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WGPUBuffer Device::CreateErrorBuffer() {
|
WGPUBuffer Device::CreateErrorBuffer() {
|
||||||
|
|
|
@ -118,52 +118,50 @@ namespace dawn_wire { namespace server {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Server::DoDeviceCreateBuffer(WGPUDevice device,
|
bool Server::DoDeviceCreateBufferMapped(WGPUDevice device,
|
||||||
const WGPUBufferDescriptor* descriptor,
|
const WGPUBufferDescriptor* descriptor,
|
||||||
ObjectHandle bufferResult,
|
ObjectHandle bufferResult,
|
||||||
uint64_t handleCreateInfoLength,
|
uint64_t handleCreateInfoLength,
|
||||||
const uint8_t* handleCreateInfo) {
|
const uint8_t* handleCreateInfo) {
|
||||||
// Create and register the buffer object.
|
if (handleCreateInfoLength > std::numeric_limits<size_t>::max()) {
|
||||||
|
// This is the size of data deserialized from the command stream, which must be
|
||||||
|
// CPU-addressable.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto* resultData = BufferObjects().Allocate(bufferResult.id);
|
auto* resultData = BufferObjects().Allocate(bufferResult.id);
|
||||||
if (resultData == nullptr) {
|
if (resultData == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
resultData->generation = bufferResult.generation;
|
resultData->generation = bufferResult.generation;
|
||||||
resultData->handle = mProcs.deviceCreateBuffer(device, descriptor);
|
|
||||||
|
|
||||||
// If the buffer isn't mapped at creation, we are done.
|
WGPUCreateBufferMappedResult result = mProcs.deviceCreateBufferMapped(device, descriptor);
|
||||||
if (!descriptor->mappedAtCreation) {
|
ASSERT(result.buffer != nullptr);
|
||||||
return handleCreateInfoLength == 0;
|
if (result.data == nullptr && result.dataLength != 0) {
|
||||||
}
|
// Non-zero dataLength but null data is used to indicate an allocation error.
|
||||||
|
// Don't return false because this is not fatal. result.buffer is an ErrorBuffer
|
||||||
// This is the size of data deserialized from the command stream to create the write handle,
|
// and subsequent operations will be errors.
|
||||||
// which must be CPU-addressable.
|
// This should only happen when fuzzing with the Null backend.
|
||||||
if (handleCreateInfoLength > std::numeric_limits<size_t>::max()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* mapping = mProcs.bufferGetMappedRange(resultData->handle, 0, descriptor->size);
|
|
||||||
if (mapping == nullptr) {
|
|
||||||
// A zero mapping is used to indicate an allocation error of an error buffer. This is a
|
|
||||||
// valid case and isn't fatal. Remember the buffer is an error so as to skip subsequent
|
|
||||||
// mapping operations.
|
|
||||||
resultData->mapWriteState = BufferMapWriteState::MapError;
|
resultData->mapWriteState = BufferMapWriteState::MapError;
|
||||||
return true;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize metadata produced from the client to create a companion server handle.
|
// 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.
|
||||||
ASSERT(writeHandle != nullptr);
|
writeHandle->SetTarget(result.data, result.dataLength);
|
||||||
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.reset(writeHandle);
|
resultData->writeHandle =
|
||||||
|
std::unique_ptr<MemoryTransferService::WriteHandle>(writeHandle);
|
||||||
|
}
|
||||||
|
resultData->handle = result.buffer;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -477,72 +477,84 @@ TEST_F(WireBufferMappingTests, DestroyInsideMapWriteCallback) {
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test successful buffer creation with mappedAtCreation=true
|
// Test successful CreateBufferMapped
|
||||||
TEST_F(WireBufferMappingTests, MappedAtCreationSuccess) {
|
TEST_F(WireBufferMappingTests, CreateBufferMappedSuccess) {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = 4;
|
descriptor.size = 4;
|
||||||
descriptor.mappedAtCreation = true;
|
|
||||||
|
|
||||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||||
|
WGPUCreateBufferMappedResult apiResult;
|
||||||
uint32_t apiBufferData = 1234;
|
uint32_t apiBufferData = 1234;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
|
||||||
|
apiResult.dataLength = 4;
|
||||||
|
|
||||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||||
|
|
||||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferUnmap(buffer);
|
wgpuBufferUnmap(result.buffer);
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that releasing a buffer mapped at creation does not call Unmap
|
// Test that releasing after CreateBufferMapped does not call Unmap
|
||||||
TEST_F(WireBufferMappingTests, MappedAtCreationReleaseBeforeUnmap) {
|
TEST_F(WireBufferMappingTests, ReleaseAfterCreateBufferMapped) {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = 4;
|
descriptor.size = 4;
|
||||||
descriptor.mappedAtCreation = true;
|
|
||||||
|
|
||||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||||
|
WGPUCreateBufferMappedResult apiResult;
|
||||||
uint32_t apiBufferData = 1234;
|
uint32_t apiBufferData = 1234;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
|
||||||
|
apiResult.dataLength = 4;
|
||||||
|
|
||||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||||
|
|
||||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferRelease(buffer);
|
wgpuBufferRelease(result.buffer);
|
||||||
EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that it is valid to map a buffer after it is mapped at creation and unmapped
|
// Test that it is valid to map a buffer after CreateBufferMapped and Unmap
|
||||||
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapSuccess) {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = 4;
|
descriptor.size = 4;
|
||||||
descriptor.mappedAtCreation = true;
|
|
||||||
|
|
||||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||||
uint32_t apiBufferData = 1234;
|
WGPUCreateBufferMappedResult apiResult;
|
||||||
|
uint32_t apiBufferData = 9863;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
|
||||||
|
apiResult.dataLength = 4;
|
||||||
|
|
||||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||||
|
|
||||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferUnmap(buffer);
|
wgpuBufferUnmap(result.buffer);
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);
|
wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||||
|
|
||||||
uint32_t zero = 0;
|
uint32_t zero = 0;
|
||||||
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||||
|
@ -560,23 +572,27 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that it is invalid to map a buffer after mappedAtCreation but before Unmap
|
// Test that it is invalid to map a buffer after CreateBufferMapped before Unmap
|
||||||
TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = 4;
|
descriptor.size = 4;
|
||||||
descriptor.mappedAtCreation = true;
|
|
||||||
|
|
||||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||||
uint32_t apiBufferData = 1234;
|
WGPUCreateBufferMappedResult apiResult;
|
||||||
|
uint32_t apiBufferData = 9863;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
|
||||||
|
apiResult.dataLength = 4;
|
||||||
|
|
||||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||||
|
|
||||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);
|
wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||||
|
|
||||||
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
EXPECT_CALL(api, OnBufferMapAsyncCallback(apiBuffer, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||||
api.CallMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
api.CallMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error);
|
||||||
|
@ -589,7 +605,7 @@ TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
|
||||||
wgpuBufferUnmap(buffer);
|
wgpuBufferUnmap(result.buffer);
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
|
@ -155,20 +155,24 @@ class WireMemoryTransferServiceTests : public WireTest {
|
||||||
return std::make_pair(apiBuffer, buffer);
|
return std::make_pair(apiBuffer, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<WGPUBuffer, WGPUBuffer> CreateBufferMapped() {
|
std::pair<WGPUCreateBufferMappedResult, WGPUCreateBufferMappedResult> CreateBufferMapped() {
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = sizeof(mBufferContent);
|
descriptor.size = sizeof(mBufferContent);
|
||||||
descriptor.mappedAtCreation = true;
|
|
||||||
|
|
||||||
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
WGPUBuffer apiBuffer = api.GetNewBuffer();
|
||||||
|
|
||||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
WGPUCreateBufferMappedResult apiResult;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = reinterpret_cast<uint8_t*>(&mMappedBufferContent);
|
||||||
|
apiResult.dataLength = sizeof(mMappedBufferContent);
|
||||||
|
|
||||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
|
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||||
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, sizeof(mBufferContent)))
|
|
||||||
.WillOnce(Return(&mMappedBufferContent));
|
|
||||||
|
|
||||||
return std::make_pair(apiBuffer, buffer);
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
|
return std::make_pair(apiResult, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientReadHandle* ExpectReadHandleCreation() {
|
ClientReadHandle* ExpectReadHandleCreation() {
|
||||||
|
@ -887,8 +891,8 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteDestroyBeforeUnmap) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test successful buffer creation with mappedAtCreation = true.
|
// Test successful CreateBufferMapped.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedSuccess) {
|
||||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||||
|
|
||||||
|
@ -900,9 +904,9 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
||||||
// The server should then deserialize the WriteHandle from the client.
|
// The server should then deserialize the WriteHandle from the client.
|
||||||
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
||||||
|
|
||||||
WGPUBuffer buffer;
|
WGPUCreateBufferMappedResult result;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUCreateBufferMappedResult apiResult;
|
||||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
std::tie(apiResult, result) = CreateBufferMapped();
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// Update the mapped contents.
|
// Update the mapped contents.
|
||||||
|
@ -912,33 +916,35 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationSuccess) {
|
||||||
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
|
|
||||||
wgpuBufferUnmap(buffer);
|
wgpuBufferUnmap(result.buffer);
|
||||||
|
|
||||||
// The server deserializes the Flush message.
|
// The server deserializes the Flush message.
|
||||||
ExpectServerWriteHandleDeserializeFlush(serverHandle, mUpdatedBufferContent);
|
ExpectServerWriteHandleDeserializeFlush(serverHandle, mUpdatedBufferContent);
|
||||||
|
|
||||||
// After the handle is updated it can be destroyed.
|
// After the handle is updated it can be destroyed.
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiResult.buffer)).Times(1);
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test buffer creation with mappedAtCreation WriteHandle creation failure.
|
// Test CreateBufferMapped WriteHandle creation failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationWriteHandleCreationFailure) {
|
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedWriteHandleCreationFailure) {
|
||||||
// Mock a WriteHandle creation failure
|
// Mock a WriteHandle creation failure
|
||||||
MockWriteHandleCreationFailure();
|
MockWriteHandleCreationFailure();
|
||||||
|
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = sizeof(mBufferContent);
|
descriptor.size = sizeof(mBufferContent);
|
||||||
descriptor.mappedAtCreation = true;
|
|
||||||
|
|
||||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||||
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
|
|
||||||
|
// TODO(enga): Check that the client generated a context lost.
|
||||||
|
EXPECT_EQ(result.data, nullptr);
|
||||||
|
EXPECT_EQ(result.dataLength, 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test buffer creation with mappedAtCreation DeserializeWriteHandle failure.
|
// Test CreateBufferMapped DeserializeWriteHandle failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFailure) {
|
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeWriteHandleFailure) {
|
||||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||||
|
|
||||||
|
@ -950,16 +956,16 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeWriteHandleFai
|
||||||
// The server should then deserialize the WriteHandle from the client.
|
// The server should then deserialize the WriteHandle from the client.
|
||||||
MockServerWriteHandleDeserializeFailure();
|
MockServerWriteHandleDeserializeFailure();
|
||||||
|
|
||||||
WGPUBuffer buffer;
|
WGPUCreateBufferMappedResult result;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUCreateBufferMappedResult apiResult;
|
||||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
std::tie(apiResult, result) = CreateBufferMapped();
|
||||||
FlushClient(false);
|
FlushClient(false);
|
||||||
|
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test buffer creation with mappedAtCreation handle Open failure.
|
// Test CreateBufferMapped handle Open failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationHandleOpenFailure) {
|
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedHandleOpenFailure) {
|
||||||
// The client should create a WriteHandle on createBufferMapped.
|
// The client should create a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||||
|
|
||||||
|
@ -973,14 +979,16 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationHandleOpenFailure) {
|
||||||
|
|
||||||
WGPUBufferDescriptor descriptor = {};
|
WGPUBufferDescriptor descriptor = {};
|
||||||
descriptor.size = sizeof(mBufferContent);
|
descriptor.size = sizeof(mBufferContent);
|
||||||
descriptor.mappedAtCreation = true;
|
|
||||||
|
|
||||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);
|
||||||
EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, sizeof(mBufferContent)));
|
|
||||||
|
// TODO(enga): Check that the client generated a context lost.
|
||||||
|
EXPECT_EQ(result.data, nullptr);
|
||||||
|
EXPECT_EQ(result.dataLength, 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test buffer creation with mappedAtCreation = true DeserializeFlush failure.
|
// Test CreateBufferMapped DeserializeFlush failure.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure) {
|
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDeserializeFlushFailure) {
|
||||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||||
|
|
||||||
|
@ -992,9 +1000,9 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure)
|
||||||
// The server should then deserialize the WriteHandle from the client.
|
// The server should then deserialize the WriteHandle from the client.
|
||||||
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
||||||
|
|
||||||
WGPUBuffer buffer;
|
WGPUCreateBufferMappedResult result;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUCreateBufferMappedResult apiResult;
|
||||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
std::tie(apiResult, result) = CreateBufferMapped();
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// Update the mapped contents.
|
// Update the mapped contents.
|
||||||
|
@ -1004,7 +1012,7 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure)
|
||||||
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
ExpectClientWriteHandleSerializeFlush(clientHandle);
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
|
|
||||||
wgpuBufferUnmap(buffer);
|
wgpuBufferUnmap(result.buffer);
|
||||||
|
|
||||||
// The server deserializes the Flush message. Mock a deserialization failure.
|
// The server deserializes the Flush message. Mock a deserialization failure.
|
||||||
MockServerWriteHandleDeserializeFlushFailure(serverHandle);
|
MockServerWriteHandleDeserializeFlushFailure(serverHandle);
|
||||||
|
@ -1014,8 +1022,8 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDeserializeFlushFailure)
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test mappedAtCreation=true destroying the buffer before unmapping on the client side.
|
// Test CreateBufferMapped destroying the buffer before unmapping on the client side.
|
||||||
TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
TEST_F(WireMemoryTransferServiceTests, CreateBufferMappedDestroyBeforeUnmap) {
|
||||||
// The client should create and serialize a WriteHandle on createBufferMapped.
|
// The client should create and serialize a WriteHandle on createBufferMapped.
|
||||||
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
ClientWriteHandle* clientHandle = ExpectWriteHandleCreation();
|
||||||
|
|
||||||
|
@ -1027,9 +1035,9 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
||||||
// The server should then deserialize the WriteHandle from the client.
|
// The server should then deserialize the WriteHandle from the client.
|
||||||
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
ServerWriteHandle* serverHandle = ExpectServerWriteHandleDeserialization();
|
||||||
|
|
||||||
WGPUBuffer buffer;
|
WGPUCreateBufferMappedResult result;
|
||||||
WGPUBuffer apiBuffer;
|
WGPUCreateBufferMappedResult apiResult;
|
||||||
std::tie(apiBuffer, buffer) = CreateBufferMapped();
|
std::tie(apiResult, result) = CreateBufferMapped();
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// Update the mapped contents.
|
// Update the mapped contents.
|
||||||
|
@ -1039,16 +1047,16 @@ TEST_F(WireMemoryTransferServiceTests, MappedAtCreationDestroyBeforeUnmap) {
|
||||||
// immediately, both in the client and server side.
|
// immediately, both in the client and server side.
|
||||||
{
|
{
|
||||||
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
EXPECT_CALL(clientMemoryTransferService, OnWriteHandleDestroy(clientHandle)).Times(1);
|
||||||
wgpuBufferDestroy(buffer);
|
wgpuBufferDestroy(result.buffer);
|
||||||
|
|
||||||
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
EXPECT_CALL(serverMemoryTransferService, OnWriteHandleDestroy(serverHandle)).Times(1);
|
||||||
EXPECT_CALL(api, BufferDestroy(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferDestroy(apiResult.buffer)).Times(1);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
// The handle is already destroyed so unmap only results in a server unmap call.
|
// The handle is already destroyed so unmap only results in a server unmap call.
|
||||||
wgpuBufferUnmap(buffer);
|
wgpuBufferUnmap(result.buffer);
|
||||||
|
|
||||||
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
EXPECT_CALL(api, BufferUnmap(apiResult.buffer)).Times(1);
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue