mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-04 04:06:01 +00:00
Implement CreateBufferMappedAsync in dawn_wire and dawn_native
Bug: dawn:7 Change-Id: I1a4e5eece53d83a4c5395ba6b41df2e20668c5bb Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8120 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
d1b4b5cba5
commit
21eba761b5
11
dawn.json
11
dawn.json
@ -160,6 +160,9 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"buffer create mapped callback": {
|
||||||
|
"category": "natively defined"
|
||||||
|
},
|
||||||
"buffer copy view": {
|
"buffer copy view": {
|
||||||
"category": "structure",
|
"category": "structure",
|
||||||
"extensible": true,
|
"extensible": true,
|
||||||
@ -417,6 +420,14 @@
|
|||||||
{"name": "descriptor", "type": "buffer descriptor", "annotation": "const*"}
|
{"name": "descriptor", "type": "buffer descriptor", "annotation": "const*"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "create buffer mapped async",
|
||||||
|
"args": [
|
||||||
|
{"name": "descriptor", "type": "buffer descriptor", "annotation": "const*"},
|
||||||
|
{"name": "callback", "type": "buffer create mapped callback"},
|
||||||
|
{"name": "userdata", "type": "void", "annotation": "*"}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "create command encoder",
|
"name": "create command encoder",
|
||||||
"returns": "command encoder"
|
"returns": "command encoder"
|
||||||
|
@ -36,6 +36,12 @@
|
|||||||
{ "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" }
|
||||||
],
|
],
|
||||||
|
"device create buffer mapped async": [
|
||||||
|
{ "name": "device", "type": "device" },
|
||||||
|
{ "name": "descriptor", "type": "buffer descriptor", "annotation": "const*" },
|
||||||
|
{ "name": "request serial", "type": "uint32_t" },
|
||||||
|
{ "name": "result", "type": "ObjectHandle", "handle_type": "buffer" }
|
||||||
|
],
|
||||||
"destroy object": [
|
"destroy object": [
|
||||||
{ "name": "object type", "type": "ObjectType" },
|
{ "name": "object type", "type": "ObjectType" },
|
||||||
{ "name": "object id", "type": "ObjectId" }
|
{ "name": "object id", "type": "ObjectId" }
|
||||||
@ -75,6 +81,7 @@
|
|||||||
"BufferSetSubData",
|
"BufferSetSubData",
|
||||||
"BufferUnmap",
|
"BufferUnmap",
|
||||||
"DeviceCreateBufferMapped",
|
"DeviceCreateBufferMapped",
|
||||||
|
"DeviceCreateBufferMappedAsync",
|
||||||
"QueueCreateFence",
|
"QueueCreateFence",
|
||||||
"FenceGetCompletedValue",
|
"FenceGetCompletedValue",
|
||||||
"QueueSignal"
|
"QueueSignal"
|
||||||
|
@ -49,6 +49,9 @@
|
|||||||
|
|
||||||
// Custom types depending on the target language
|
// Custom types depending on the target language
|
||||||
typedef void (*DawnDeviceErrorCallback)(const char* message, void* userdata);
|
typedef void (*DawnDeviceErrorCallback)(const char* message, void* userdata);
|
||||||
|
typedef void (*DawnBufferCreateMappedCallback)(DawnBufferMapAsyncStatus status,
|
||||||
|
DawnCreateBufferMappedResult result,
|
||||||
|
void* userdata);
|
||||||
typedef void (*DawnBufferMapReadCallback)(DawnBufferMapAsyncStatus status,
|
typedef void (*DawnBufferMapReadCallback)(DawnBufferMapAsyncStatus status,
|
||||||
const void* data,
|
const void* data,
|
||||||
uint64_t dataLength,
|
uint64_t dataLength,
|
||||||
|
@ -60,6 +60,17 @@ void ProcTableAsClass::DeviceSetErrorCallback(DawnDevice self,
|
|||||||
OnDeviceSetErrorCallback(self, callback, userdata);
|
OnDeviceSetErrorCallback(self, callback, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProcTableAsClass::DeviceCreateBufferMappedAsync(DawnDevice self,
|
||||||
|
const DawnBufferDescriptor* descriptor,
|
||||||
|
DawnBufferCreateMappedCallback callback,
|
||||||
|
void* userdata) {
|
||||||
|
auto object = reinterpret_cast<ProcTableAsClass::Object*>(self);
|
||||||
|
object->createBufferMappedCallback = callback;
|
||||||
|
object->userdata1 = userdata;
|
||||||
|
|
||||||
|
OnDeviceCreateBufferMappedAsyncCallback(self, descriptor, callback, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
void ProcTableAsClass::BufferMapReadAsync(DawnBuffer self,
|
void ProcTableAsClass::BufferMapReadAsync(DawnBuffer self,
|
||||||
DawnBufferMapReadCallback callback,
|
DawnBufferMapReadCallback callback,
|
||||||
void* userdata) {
|
void* userdata) {
|
||||||
@ -95,12 +106,16 @@ void ProcTableAsClass::CallDeviceErrorCallback(DawnDevice device, const char* me
|
|||||||
auto object = reinterpret_cast<ProcTableAsClass::Object*>(device);
|
auto object = reinterpret_cast<ProcTableAsClass::Object*>(device);
|
||||||
object->deviceErrorCallback(message, object->userdata1);
|
object->deviceErrorCallback(message, object->userdata1);
|
||||||
}
|
}
|
||||||
void ProcTableAsClass::CallMapReadCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, const void* data, uint32_t dataLength) {
|
void ProcTableAsClass::CallCreateBufferMappedCallback(DawnDevice device, DawnBufferMapAsyncStatus status, DawnCreateBufferMappedResult result) {
|
||||||
|
auto object = reinterpret_cast<ProcTableAsClass::Object*>(device);
|
||||||
|
object->createBufferMappedCallback(status, result, object->userdata1);
|
||||||
|
}
|
||||||
|
void ProcTableAsClass::CallMapReadCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, const void* data, uint64_t dataLength) {
|
||||||
auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer);
|
auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer);
|
||||||
object->mapReadCallback(status, data, dataLength, object->userdata1);
|
object->mapReadCallback(status, data, dataLength, object->userdata1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcTableAsClass::CallMapWriteCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, void* data, uint32_t dataLength) {
|
void ProcTableAsClass::CallMapWriteCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, void* data, uint64_t dataLength) {
|
||||||
auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer);
|
auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer);
|
||||||
object->mapWriteCallback(status, data, dataLength, object->userdata1);
|
object->mapWriteCallback(status, data, dataLength, object->userdata1);
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,10 @@ class ProcTableAsClass {
|
|||||||
void DeviceSetErrorCallback(DawnDevice self,
|
void DeviceSetErrorCallback(DawnDevice self,
|
||||||
DawnDeviceErrorCallback callback,
|
DawnDeviceErrorCallback callback,
|
||||||
void* userdata);
|
void* userdata);
|
||||||
|
void DeviceCreateBufferMappedAsync(DawnDevice self,
|
||||||
|
const DawnBufferDescriptor* descriptor,
|
||||||
|
DawnBufferCreateMappedCallback callback,
|
||||||
|
void* userdata);
|
||||||
void BufferMapReadAsync(DawnBuffer self,
|
void BufferMapReadAsync(DawnBuffer self,
|
||||||
DawnBufferMapReadCallback callback,
|
DawnBufferMapReadCallback callback,
|
||||||
void* userdata);
|
void* userdata);
|
||||||
@ -69,6 +73,10 @@ class ProcTableAsClass {
|
|||||||
virtual void OnDeviceSetErrorCallback(DawnDevice device,
|
virtual void OnDeviceSetErrorCallback(DawnDevice device,
|
||||||
DawnDeviceErrorCallback callback,
|
DawnDeviceErrorCallback callback,
|
||||||
void* userdata) = 0;
|
void* userdata) = 0;
|
||||||
|
virtual void OnDeviceCreateBufferMappedAsyncCallback(DawnDevice self,
|
||||||
|
const DawnBufferDescriptor* descriptor,
|
||||||
|
DawnBufferCreateMappedCallback callback,
|
||||||
|
void* userdata) = 0;
|
||||||
virtual void OnBufferMapReadAsyncCallback(DawnBuffer buffer,
|
virtual void OnBufferMapReadAsyncCallback(DawnBuffer buffer,
|
||||||
DawnBufferMapReadCallback callback,
|
DawnBufferMapReadCallback callback,
|
||||||
void* userdata) = 0;
|
void* userdata) = 0;
|
||||||
@ -82,13 +90,15 @@ class ProcTableAsClass {
|
|||||||
|
|
||||||
// Calls the stored callbacks
|
// Calls the stored callbacks
|
||||||
void CallDeviceErrorCallback(DawnDevice device, const char* message);
|
void CallDeviceErrorCallback(DawnDevice device, const char* message);
|
||||||
void CallMapReadCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, const void* data, uint32_t dataLength);
|
void CallCreateBufferMappedCallback(DawnDevice device, DawnBufferMapAsyncStatus status, DawnCreateBufferMappedResult result);
|
||||||
void CallMapWriteCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, void* data, uint32_t dataLength);
|
void CallMapReadCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, const void* data, uint64_t dataLength);
|
||||||
|
void CallMapWriteCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, void* data, uint64_t dataLength);
|
||||||
void CallFenceOnCompletionCallback(DawnFence fence, DawnFenceCompletionStatus status);
|
void CallFenceOnCompletionCallback(DawnFence fence, DawnFenceCompletionStatus status);
|
||||||
|
|
||||||
struct Object {
|
struct Object {
|
||||||
ProcTableAsClass* procs = nullptr;
|
ProcTableAsClass* procs = nullptr;
|
||||||
DawnDeviceErrorCallback deviceErrorCallback = nullptr;
|
DawnDeviceErrorCallback deviceErrorCallback = nullptr;
|
||||||
|
DawnBufferCreateMappedCallback createBufferMappedCallback = nullptr;
|
||||||
DawnBufferMapReadCallback mapReadCallback = nullptr;
|
DawnBufferMapReadCallback mapReadCallback = nullptr;
|
||||||
DawnBufferMapWriteCallback mapWriteCallback = nullptr;
|
DawnBufferMapWriteCallback mapWriteCallback = nullptr;
|
||||||
DawnFenceOnCompletionCallback fenceOnCompletionCallback = nullptr;
|
DawnFenceOnCompletionCallback fenceOnCompletionCallback = nullptr;
|
||||||
@ -124,6 +134,7 @@ class MockProcTable : public ProcTableAsClass {
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
MOCK_METHOD3(OnDeviceSetErrorCallback, void(DawnDevice device, DawnDeviceErrorCallback callback, void* userdata));
|
MOCK_METHOD3(OnDeviceSetErrorCallback, void(DawnDevice device, DawnDeviceErrorCallback callback, void* userdata));
|
||||||
|
MOCK_METHOD4(OnDeviceCreateBufferMappedAsyncCallback, void(DawnDevice device, const DawnBufferDescriptor* descriptor, DawnBufferCreateMappedCallback callback, void* userdata));
|
||||||
MOCK_METHOD3(OnBufferMapReadAsyncCallback, void(DawnBuffer buffer, DawnBufferMapReadCallback callback, void* userdata));
|
MOCK_METHOD3(OnBufferMapReadAsyncCallback, void(DawnBuffer buffer, DawnBufferMapReadCallback callback, void* userdata));
|
||||||
MOCK_METHOD3(OnBufferMapWriteAsyncCallback, void(DawnBuffer buffer, DawnBufferMapWriteCallback callback, void* userdata));
|
MOCK_METHOD3(OnBufferMapWriteAsyncCallback, void(DawnBuffer buffer, DawnBufferMapWriteCallback callback, void* userdata));
|
||||||
MOCK_METHOD4(OnFenceOnCompletionCallback,
|
MOCK_METHOD4(OnFenceOnCompletionCallback,
|
||||||
|
@ -68,6 +68,7 @@ namespace dawn_native {
|
|||||||
DeviceBase::~DeviceBase() {
|
DeviceBase::~DeviceBase() {
|
||||||
// Devices must explicitly free the uploader
|
// Devices must explicitly free the uploader
|
||||||
ASSERT(mDynamicUploader == nullptr);
|
ASSERT(mDynamicUploader == nullptr);
|
||||||
|
ASSERT(mDeferredCreateBufferMappedAsyncResults.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::HandleError(const char* message) {
|
void DeviceBase::HandleError(const char* message) {
|
||||||
@ -291,6 +292,25 @@ namespace dawn_native {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
void DeviceBase::CreateBufferMappedAsync(const BufferDescriptor* descriptor,
|
||||||
|
dawn::BufferCreateMappedCallback callback,
|
||||||
|
void* userdata) {
|
||||||
|
DawnCreateBufferMappedResult result = CreateBufferMapped(descriptor);
|
||||||
|
|
||||||
|
DawnBufferMapAsyncStatus status = DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS;
|
||||||
|
if (result.data == nullptr || result.dataLength != descriptor->size) {
|
||||||
|
status = DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeferredCreateBufferMappedAsync deferred_info;
|
||||||
|
deferred_info.callback = callback;
|
||||||
|
deferred_info.status = status;
|
||||||
|
deferred_info.result = result;
|
||||||
|
deferred_info.userdata = userdata;
|
||||||
|
|
||||||
|
// The callback is deferred so it matches the async behavior of WebGPU.
|
||||||
|
mDeferredCreateBufferMappedAsyncResults.push_back(deferred_info);
|
||||||
|
}
|
||||||
CommandEncoderBase* DeviceBase::CreateCommandEncoder() {
|
CommandEncoderBase* DeviceBase::CreateCommandEncoder() {
|
||||||
return new CommandEncoderBase(this);
|
return new CommandEncoderBase(this);
|
||||||
}
|
}
|
||||||
@ -387,6 +407,12 @@ namespace dawn_native {
|
|||||||
|
|
||||||
void DeviceBase::Tick() {
|
void DeviceBase::Tick() {
|
||||||
TickImpl();
|
TickImpl();
|
||||||
|
{
|
||||||
|
auto deferredResults = std::move(mDeferredCreateBufferMappedAsyncResults);
|
||||||
|
for (const auto& deferred : deferredResults) {
|
||||||
|
deferred.callback(deferred.status, deferred.result, deferred.userdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
mFenceSignalTracker->Tick(GetCompletedCommandSerial());
|
mFenceSignalTracker->Tick(GetCompletedCommandSerial());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +108,9 @@ namespace dawn_native {
|
|||||||
BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
|
BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
|
||||||
BufferBase* CreateBuffer(const BufferDescriptor* descriptor);
|
BufferBase* CreateBuffer(const BufferDescriptor* descriptor);
|
||||||
DawnCreateBufferMappedResult CreateBufferMapped(const BufferDescriptor* descriptor);
|
DawnCreateBufferMappedResult CreateBufferMapped(const BufferDescriptor* descriptor);
|
||||||
|
void CreateBufferMappedAsync(const BufferDescriptor* descriptor,
|
||||||
|
dawn::BufferCreateMappedCallback callback,
|
||||||
|
void* userdata);
|
||||||
CommandEncoderBase* CreateCommandEncoder();
|
CommandEncoderBase* CreateCommandEncoder();
|
||||||
ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor);
|
ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor);
|
||||||
PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);
|
PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);
|
||||||
@ -202,7 +205,15 @@ namespace dawn_native {
|
|||||||
struct Caches;
|
struct Caches;
|
||||||
std::unique_ptr<Caches> mCaches;
|
std::unique_ptr<Caches> mCaches;
|
||||||
|
|
||||||
|
struct DeferredCreateBufferMappedAsync {
|
||||||
|
dawn::BufferCreateMappedCallback callback;
|
||||||
|
DawnBufferMapAsyncStatus status;
|
||||||
|
DawnCreateBufferMappedResult result;
|
||||||
|
void* userdata;
|
||||||
|
};
|
||||||
|
|
||||||
std::unique_ptr<FenceSignalTracker> mFenceSignalTracker;
|
std::unique_ptr<FenceSignalTracker> mFenceSignalTracker;
|
||||||
|
std::vector<DeferredCreateBufferMappedAsync> mDeferredCreateBufferMappedAsyncResults;
|
||||||
|
|
||||||
dawn::DeviceErrorCallback mErrorCallback = nullptr;
|
dawn::DeviceErrorCallback mErrorCallback = nullptr;
|
||||||
void* mErrorUserdata = 0;
|
void* mErrorUserdata = 0;
|
||||||
|
@ -101,6 +101,57 @@ namespace dawn_wire { namespace client {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientDeviceCreateBufferMappedAsync(DawnDevice cDevice,
|
||||||
|
const DawnBufferDescriptor* descriptor,
|
||||||
|
DawnBufferCreateMappedCallback callback,
|
||||||
|
void* userdata) {
|
||||||
|
Device* device = reinterpret_cast<Device*>(cDevice);
|
||||||
|
Client* wireClient = device->GetClient();
|
||||||
|
|
||||||
|
auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(device);
|
||||||
|
Buffer* buffer = bufferObjectAndSerial->object.get();
|
||||||
|
|
||||||
|
uint32_t serial = buffer->requestSerial++;
|
||||||
|
|
||||||
|
struct CreateBufferMappedInfo {
|
||||||
|
DawnBuffer buffer;
|
||||||
|
DawnBufferCreateMappedCallback callback;
|
||||||
|
void* userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateBufferMappedInfo* info = new CreateBufferMappedInfo;
|
||||||
|
info->buffer = reinterpret_cast<DawnBuffer>(buffer);
|
||||||
|
info->callback = callback;
|
||||||
|
info->userdata = userdata;
|
||||||
|
|
||||||
|
Buffer::MapRequestData request;
|
||||||
|
request.writeCallback = [](DawnBufferMapAsyncStatus status, void* data, uint64_t dataLength,
|
||||||
|
void* userdata) {
|
||||||
|
auto info = std::unique_ptr<CreateBufferMappedInfo>(
|
||||||
|
static_cast<CreateBufferMappedInfo*>(userdata));
|
||||||
|
|
||||||
|
DawnCreateBufferMappedResult result;
|
||||||
|
result.buffer = info->buffer;
|
||||||
|
result.data = data;
|
||||||
|
result.dataLength = dataLength;
|
||||||
|
|
||||||
|
info->callback(status, result, info->userdata);
|
||||||
|
};
|
||||||
|
request.userdata = info;
|
||||||
|
request.isWrite = true;
|
||||||
|
buffer->requests[serial] = request;
|
||||||
|
|
||||||
|
DeviceCreateBufferMappedAsyncCmd cmd;
|
||||||
|
cmd.device = cDevice;
|
||||||
|
cmd.descriptor = descriptor;
|
||||||
|
cmd.requestSerial = serial;
|
||||||
|
cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->serial};
|
||||||
|
|
||||||
|
size_t requiredSize = cmd.GetRequiredSize();
|
||||||
|
char* allocatedBuffer = static_cast<char*>(wireClient->GetCmdSpace(requiredSize));
|
||||||
|
cmd.Serialize(allocatedBuffer, *wireClient);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t ClientFenceGetCompletedValue(DawnFence cSelf) {
|
uint64_t ClientFenceGetCompletedValue(DawnFence cSelf) {
|
||||||
auto fence = reinterpret_cast<Fence*>(cSelf);
|
auto fence = reinterpret_cast<Fence*>(cSelf);
|
||||||
return fence->completedValue;
|
return fence->completedValue;
|
||||||
|
@ -86,6 +86,32 @@ namespace dawn_wire { namespace server {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Server::DoDeviceCreateBufferMappedAsync(DawnDevice device,
|
||||||
|
const DawnBufferDescriptor* descriptor,
|
||||||
|
uint32_t requestSerial,
|
||||||
|
ObjectHandle bufferResult) {
|
||||||
|
if (!DoDeviceCreateBufferMapped(device, descriptor, bufferResult)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* bufferData = BufferObjects().Get(bufferResult.id);
|
||||||
|
ASSERT(bufferData != nullptr);
|
||||||
|
|
||||||
|
ReturnBufferMapWriteAsyncCallbackCmd cmd;
|
||||||
|
cmd.buffer = ObjectHandle{bufferResult.id, bufferResult.serial};
|
||||||
|
cmd.requestSerial = requestSerial;
|
||||||
|
cmd.status = bufferData->mapWriteState == BufferMapWriteState::Mapped
|
||||||
|
? DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS
|
||||||
|
: DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR;
|
||||||
|
cmd.dataLength = bufferData->mappedDataSize;
|
||||||
|
|
||||||
|
size_t requiredSize = cmd.GetRequiredSize();
|
||||||
|
char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize));
|
||||||
|
cmd.Serialize(allocatedBuffer);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Server::DoBufferSetSubDataInternal(ObjectId bufferId,
|
bool Server::DoBufferSetSubDataInternal(ObjectId bufferId,
|
||||||
uint64_t start,
|
uint64_t start,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
|
@ -226,6 +226,7 @@ DAWN_INSTANTIATE_TEST(BufferSetSubDataTests,
|
|||||||
OpenGLBackend,
|
OpenGLBackend,
|
||||||
VulkanBackend);
|
VulkanBackend);
|
||||||
|
|
||||||
|
// TODO(enga): These tests should use the testing toggle to initialize resources to 1.
|
||||||
class CreateBufferMappedTests : public DawnTest {
|
class CreateBufferMappedTests : public DawnTest {
|
||||||
protected:
|
protected:
|
||||||
static void MapReadCallback(DawnBufferMapAsyncStatus status,
|
static void MapReadCallback(DawnBufferMapAsyncStatus status,
|
||||||
@ -248,37 +249,97 @@ class CreateBufferMappedTests : public DawnTest {
|
|||||||
return mappedData;
|
return mappedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckResultStartsZeroed(const dawn::CreateBufferMappedResult& result, uint64_t size) {
|
||||||
|
ASSERT_EQ(result.dataLength, size);
|
||||||
|
for (uint64_t i = 0; i < result.dataLength; ++i) {
|
||||||
|
uint8_t value = *(reinterpret_cast<uint8_t*>(result.data) + i);
|
||||||
|
ASSERT_EQ(value, 0u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dawn::CreateBufferMappedResult CreateBufferMapped(dawn::BufferUsageBit usage, uint64_t size) {
|
||||||
|
dawn::BufferDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = nullptr;
|
||||||
|
descriptor.size = size;
|
||||||
|
descriptor.usage = usage;
|
||||||
|
|
||||||
|
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
||||||
|
CheckResultStartsZeroed(result, size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
dawn::CreateBufferMappedResult CreateBufferMappedWithData(dawn::BufferUsageBit usage,
|
||||||
|
const std::vector<uint32_t>& data) {
|
||||||
|
size_t byteLength = data.size() * sizeof(uint32_t);
|
||||||
|
dawn::CreateBufferMappedResult result = CreateBufferMapped(usage, byteLength);
|
||||||
|
memcpy(result.data, data.data(), byteLength);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <DawnBufferMapAsyncStatus expectedStatus = DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS>
|
||||||
|
dawn::CreateBufferMappedResult CreateBufferMappedAsyncAndWait(dawn::BufferUsageBit usage,
|
||||||
|
uint64_t size) {
|
||||||
|
dawn::BufferDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = nullptr;
|
||||||
|
descriptor.size = size;
|
||||||
|
descriptor.usage = usage;
|
||||||
|
|
||||||
|
struct ResultInfo {
|
||||||
|
dawn::CreateBufferMappedResult result;
|
||||||
|
bool done = false;
|
||||||
|
} resultInfo;
|
||||||
|
|
||||||
|
device.CreateBufferMappedAsync(
|
||||||
|
&descriptor,
|
||||||
|
[](DawnBufferMapAsyncStatus status, DawnCreateBufferMappedResult result,
|
||||||
|
void* userdata) {
|
||||||
|
ASSERT_EQ(status, expectedStatus);
|
||||||
|
auto* resultInfo = reinterpret_cast<ResultInfo*>(userdata);
|
||||||
|
resultInfo->result.buffer = dawn::Buffer::Acquire(result.buffer);
|
||||||
|
resultInfo->result.data = result.data;
|
||||||
|
resultInfo->result.dataLength = result.dataLength;
|
||||||
|
resultInfo->done = true;
|
||||||
|
},
|
||||||
|
&resultInfo);
|
||||||
|
|
||||||
|
while (!resultInfo.done) {
|
||||||
|
WaitABit();
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckResultStartsZeroed(resultInfo.result, size);
|
||||||
|
|
||||||
|
return resultInfo.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
dawn::CreateBufferMappedResult CreateBufferMappedAsyncWithDataAndWait(
|
||||||
|
dawn::BufferUsageBit usage,
|
||||||
|
const std::vector<uint32_t>& data) {
|
||||||
|
size_t byteLength = data.size() * sizeof(uint32_t);
|
||||||
|
dawn::CreateBufferMappedResult result = CreateBufferMappedAsyncAndWait(usage, byteLength);
|
||||||
|
memcpy(result.data, data.data(), byteLength);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const void* mappedData = nullptr;
|
const void* mappedData = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test that the simplest CreateBufferMapped works for MapWrite buffers.
|
// Test that the simplest CreateBufferMapped works for MapWrite buffers.
|
||||||
TEST_P(CreateBufferMappedTests, MapWriteUsageSmall) {
|
TEST_P(CreateBufferMappedTests, MapWriteUsageSmall) {
|
||||||
dawn::BufferDescriptor descriptor;
|
|
||||||
descriptor.nextInChain = nullptr;
|
|
||||||
descriptor.size = 4;
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
|
|
||||||
|
|
||||||
uint32_t myData = 230502;
|
uint32_t myData = 230502;
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
dawn::CreateBufferMappedResult result = CreateBufferMappedWithData(
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
memcpy(result.data, &myData, sizeof(myData));
|
|
||||||
result.buffer.Unmap();
|
result.buffer.Unmap();
|
||||||
|
|
||||||
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the simplest CreateBufferMapped works for MapRead buffers.
|
// Test that the simplest CreateBufferMapped works for MapRead buffers.
|
||||||
TEST_P(CreateBufferMappedTests, MapReadUsageSmall) {
|
TEST_P(CreateBufferMappedTests, MapReadUsageSmall) {
|
||||||
dawn::BufferDescriptor descriptor;
|
|
||||||
descriptor.nextInChain = nullptr;
|
|
||||||
descriptor.size = 4;
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::MapRead;
|
|
||||||
|
|
||||||
uint32_t myData = 230502;
|
uint32_t myData = 230502;
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
dawn::CreateBufferMappedResult result =
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
CreateBufferMappedWithData(dawn::BufferUsageBit::MapRead, {myData});
|
||||||
memcpy(result.data, &myData, sizeof(myData));
|
|
||||||
result.buffer.Unmap();
|
result.buffer.Unmap();
|
||||||
|
|
||||||
const void* mappedData = MapReadAsyncAndWait(result.buffer);
|
const void* mappedData = MapReadAsyncAndWait(result.buffer);
|
||||||
@ -288,15 +349,9 @@ TEST_P(CreateBufferMappedTests, MapReadUsageSmall) {
|
|||||||
|
|
||||||
// Test that the simplest CreateBufferMapped works for non-mappable buffers.
|
// Test that the simplest CreateBufferMapped works for non-mappable buffers.
|
||||||
TEST_P(CreateBufferMappedTests, NonMappableUsageSmall) {
|
TEST_P(CreateBufferMappedTests, NonMappableUsageSmall) {
|
||||||
dawn::BufferDescriptor descriptor;
|
|
||||||
descriptor.nextInChain = nullptr;
|
|
||||||
descriptor.size = 4;
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::TransferSrc;
|
|
||||||
|
|
||||||
uint32_t myData = 4239;
|
uint32_t myData = 4239;
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
dawn::CreateBufferMappedResult result =
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
CreateBufferMappedWithData(dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
memcpy(result.data, &myData, sizeof(myData));
|
|
||||||
result.buffer.Unmap();
|
result.buffer.Unmap();
|
||||||
|
|
||||||
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||||
@ -310,14 +365,8 @@ TEST_P(CreateBufferMappedTests, MapWriteUsageLarge) {
|
|||||||
myData.push_back(i);
|
myData.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
dawn::BufferDescriptor descriptor;
|
dawn::CreateBufferMappedResult result = CreateBufferMappedWithData(
|
||||||
descriptor.nextInChain = nullptr;
|
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
descriptor.size = static_cast<uint64_t>(kDataSize * sizeof(uint32_t));
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
|
|
||||||
|
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
|
||||||
memcpy(result.data, myData.data(), kDataSize * sizeof(uint32_t));
|
|
||||||
result.buffer.Unmap();
|
result.buffer.Unmap();
|
||||||
|
|
||||||
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
|
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
|
||||||
@ -331,14 +380,8 @@ TEST_P(CreateBufferMappedTests, MapReadUsageLarge) {
|
|||||||
myData.push_back(i);
|
myData.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
dawn::BufferDescriptor descriptor;
|
dawn::CreateBufferMappedResult result =
|
||||||
descriptor.nextInChain = nullptr;
|
CreateBufferMappedWithData(dawn::BufferUsageBit::MapRead, myData);
|
||||||
descriptor.size = static_cast<uint64_t>(kDataSize * sizeof(uint32_t));
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::MapRead;
|
|
||||||
|
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
|
||||||
memcpy(result.data, myData.data(), kDataSize * sizeof(uint32_t));
|
|
||||||
result.buffer.Unmap();
|
result.buffer.Unmap();
|
||||||
|
|
||||||
const void* mappedData = MapReadAsyncAndWait(result.buffer);
|
const void* mappedData = MapReadAsyncAndWait(result.buffer);
|
||||||
@ -354,59 +397,19 @@ TEST_P(CreateBufferMappedTests, NonMappableUsageLarge) {
|
|||||||
myData.push_back(i);
|
myData.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
dawn::BufferDescriptor descriptor;
|
dawn::CreateBufferMappedResult result =
|
||||||
descriptor.nextInChain = nullptr;
|
CreateBufferMappedWithData(dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
descriptor.size = static_cast<uint64_t>(kDataSize * sizeof(uint32_t));
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::TransferSrc;
|
|
||||||
|
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
|
||||||
memcpy(result.data, myData.data(), kDataSize * sizeof(uint32_t));
|
|
||||||
result.buffer.Unmap();
|
result.buffer.Unmap();
|
||||||
|
|
||||||
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
|
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that CreateBufferMapped returns zero-initialized data
|
|
||||||
// TODO(enga): This should use the testing toggle to initialize resources to 1.
|
|
||||||
TEST_P(CreateBufferMappedTests, MappableZeroInitialized) {
|
|
||||||
dawn::BufferDescriptor descriptor;
|
|
||||||
descriptor.nextInChain = nullptr;
|
|
||||||
descriptor.size = 4;
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
|
|
||||||
|
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
|
||||||
ASSERT_EQ(*reinterpret_cast<uint8_t*>(result.data), 0);
|
|
||||||
result.buffer.Unmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that CreateBufferMapped returns zero-initialized data
|
|
||||||
// TODO(enga): This should use the testing toggle to initialize resources to 1.
|
|
||||||
TEST_P(CreateBufferMappedTests, NonMappableZeroInitialized) {
|
|
||||||
dawn::BufferDescriptor descriptor;
|
|
||||||
descriptor.nextInChain = nullptr;
|
|
||||||
descriptor.size = 4;
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::TransferSrc;
|
|
||||||
|
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
|
||||||
ASSERT_EQ(*reinterpret_cast<uint8_t*>(result.data), 0);
|
|
||||||
result.buffer.Unmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that mapping a buffer is valid after CreateBufferMapped and Unmap
|
// Test that mapping a buffer is valid after CreateBufferMapped and Unmap
|
||||||
TEST_P(CreateBufferMappedTests, CreateThenMapSuccess) {
|
TEST_P(CreateBufferMappedTests, CreateThenMapSuccess) {
|
||||||
dawn::BufferDescriptor descriptor;
|
|
||||||
descriptor.nextInChain = nullptr;
|
|
||||||
descriptor.size = 4;
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
|
|
||||||
|
|
||||||
static uint32_t myData = 230502;
|
static uint32_t myData = 230502;
|
||||||
static uint32_t myData2 = 1337;
|
static uint32_t myData2 = 1337;
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
dawn::CreateBufferMappedResult result = CreateBufferMappedWithData(
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
memcpy(result.data, &myData, sizeof(myData));
|
|
||||||
result.buffer.Unmap();
|
result.buffer.Unmap();
|
||||||
|
|
||||||
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||||
@ -432,15 +435,9 @@ TEST_P(CreateBufferMappedTests, CreateThenMapSuccess) {
|
|||||||
|
|
||||||
// Test that is is invalid to map a buffer twice when using CreateBufferMapped
|
// Test that is is invalid to map a buffer twice when using CreateBufferMapped
|
||||||
TEST_P(CreateBufferMappedTests, CreateThenMapBeforeUnmapFailure) {
|
TEST_P(CreateBufferMappedTests, CreateThenMapBeforeUnmapFailure) {
|
||||||
dawn::BufferDescriptor descriptor;
|
|
||||||
descriptor.nextInChain = nullptr;
|
|
||||||
descriptor.size = 4;
|
|
||||||
descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
|
|
||||||
|
|
||||||
uint32_t myData = 230502;
|
uint32_t myData = 230502;
|
||||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
dawn::CreateBufferMappedResult result = CreateBufferMappedWithData(
|
||||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
memcpy(result.data, &myData, sizeof(myData));
|
|
||||||
|
|
||||||
ASSERT_DEVICE_ERROR([&]() {
|
ASSERT_DEVICE_ERROR([&]() {
|
||||||
bool done = false;
|
bool done = false;
|
||||||
@ -463,6 +460,140 @@ TEST_P(CreateBufferMappedTests, CreateThenMapBeforeUnmapFailure) {
|
|||||||
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that the simplest CreateBufferMappedAsync works for MapWrite buffers.
|
||||||
|
TEST_P(CreateBufferMappedTests, MapWriteUsageSmallAsync) {
|
||||||
|
uint32_t myData = 230502;
|
||||||
|
dawn::CreateBufferMappedResult result = CreateBufferMappedAsyncWithDataAndWait(
|
||||||
|
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
|
result.buffer.Unmap();
|
||||||
|
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the simplest CreateBufferMappedAsync works for MapRead buffers.
|
||||||
|
TEST_P(CreateBufferMappedTests, MapReadUsageSmallAsync) {
|
||||||
|
uint32_t myData = 230502;
|
||||||
|
dawn::CreateBufferMappedResult result =
|
||||||
|
CreateBufferMappedAsyncWithDataAndWait(dawn::BufferUsageBit::MapRead, {myData});
|
||||||
|
result.buffer.Unmap();
|
||||||
|
|
||||||
|
const void* mappedData = MapReadAsyncAndWait(result.buffer);
|
||||||
|
ASSERT_EQ(myData, *reinterpret_cast<const uint32_t*>(mappedData));
|
||||||
|
result.buffer.Unmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the simplest CreateBufferMappedAsync works for non-mappable buffers.
|
||||||
|
TEST_P(CreateBufferMappedTests, NonMappableUsageSmallAsync) {
|
||||||
|
uint32_t myData = 4239;
|
||||||
|
dawn::CreateBufferMappedResult result =
|
||||||
|
CreateBufferMappedAsyncWithDataAndWait(dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
|
result.buffer.Unmap();
|
||||||
|
|
||||||
|
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test CreateBufferMappedAsync for a large MapWrite buffer
|
||||||
|
TEST_P(CreateBufferMappedTests, MapWriteUsageLargeAsync) {
|
||||||
|
constexpr uint64_t kDataSize = 1000 * 1000;
|
||||||
|
std::vector<uint32_t> myData;
|
||||||
|
for (uint32_t i = 0; i < kDataSize; ++i) {
|
||||||
|
myData.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
dawn::CreateBufferMappedResult result = CreateBufferMappedAsyncWithDataAndWait(
|
||||||
|
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
|
result.buffer.Unmap();
|
||||||
|
|
||||||
|
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test CreateBufferMappedAsync for a large MapRead buffer
|
||||||
|
TEST_P(CreateBufferMappedTests, MapReadUsageLargeAsync) {
|
||||||
|
constexpr uint64_t kDataSize = 1000 * 1000;
|
||||||
|
std::vector<uint32_t> myData;
|
||||||
|
for (uint32_t i = 0; i < kDataSize; ++i) {
|
||||||
|
myData.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
dawn::CreateBufferMappedResult result =
|
||||||
|
CreateBufferMappedAsyncWithDataAndWait(dawn::BufferUsageBit::MapRead, {myData});
|
||||||
|
result.buffer.Unmap();
|
||||||
|
|
||||||
|
const void* mappedData = MapReadAsyncAndWait(result.buffer);
|
||||||
|
ASSERT_EQ(0, memcmp(mappedData, myData.data(), kDataSize * sizeof(uint32_t)));
|
||||||
|
result.buffer.Unmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test CreateBufferMappedAsync for a large non-mappable buffer
|
||||||
|
TEST_P(CreateBufferMappedTests, NonMappableUsageLargeAsync) {
|
||||||
|
constexpr uint64_t kDataSize = 1000 * 1000;
|
||||||
|
std::vector<uint32_t> myData;
|
||||||
|
for (uint32_t i = 0; i < kDataSize; ++i) {
|
||||||
|
myData.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
dawn::CreateBufferMappedResult result =
|
||||||
|
CreateBufferMappedAsyncWithDataAndWait(dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
|
result.buffer.Unmap();
|
||||||
|
|
||||||
|
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that mapping a buffer is valid after CreateBufferMappedAsync and Unmap
|
||||||
|
TEST_P(CreateBufferMappedTests, CreateThenMapSuccessAsync) {
|
||||||
|
static uint32_t myData = 230502;
|
||||||
|
static uint32_t myData2 = 1337;
|
||||||
|
dawn::CreateBufferMappedResult result = CreateBufferMappedAsyncWithDataAndWait(
|
||||||
|
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
|
result.buffer.Unmap();
|
||||||
|
|
||||||
|
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
result.buffer.MapWriteAsync(
|
||||||
|
[](DawnBufferMapAsyncStatus status, void* data, uint64_t, void* userdata) {
|
||||||
|
ASSERT_EQ(DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, status);
|
||||||
|
ASSERT_NE(nullptr, data);
|
||||||
|
|
||||||
|
*static_cast<uint32_t*>(data) = myData2;
|
||||||
|
*static_cast<bool*>(userdata) = true;
|
||||||
|
},
|
||||||
|
&done);
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
WaitABit();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.buffer.Unmap();
|
||||||
|
EXPECT_BUFFER_U32_EQ(myData2, result.buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that is is invalid to map a buffer twice when using CreateBufferMappedAsync
|
||||||
|
TEST_P(CreateBufferMappedTests, CreateThenMapBeforeUnmapFailureAsync) {
|
||||||
|
uint32_t myData = 230502;
|
||||||
|
dawn::CreateBufferMappedResult result = CreateBufferMappedAsyncWithDataAndWait(
|
||||||
|
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||||
|
|
||||||
|
ASSERT_DEVICE_ERROR([&]() {
|
||||||
|
bool done = false;
|
||||||
|
result.buffer.MapWriteAsync(
|
||||||
|
[](DawnBufferMapAsyncStatus status, void* data, uint64_t, void* userdata) {
|
||||||
|
ASSERT_EQ(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, status);
|
||||||
|
ASSERT_EQ(nullptr, data);
|
||||||
|
|
||||||
|
*static_cast<bool*>(userdata) = true;
|
||||||
|
},
|
||||||
|
&done);
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
WaitABit();
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
|
// CreateBufferMappedAsync is unaffected by the MapWrite error.
|
||||||
|
result.buffer.Unmap();
|
||||||
|
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(CreateBufferMappedTests,
|
DAWN_INSTANTIATE_TEST(CreateBufferMappedTests,
|
||||||
D3D12Backend,
|
D3D12Backend,
|
||||||
MetalBackend,
|
MetalBackend,
|
||||||
|
@ -59,6 +59,28 @@ namespace {
|
|||||||
mockBufferMapWriteCallback->Call(status, lastMapWritePointer, dataLength, userdata);
|
mockBufferMapWriteCallback->Call(status, lastMapWritePointer, dataLength, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MockBufferCreateMappedCallback {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD5(Call,
|
||||||
|
void(DawnBufferMapAsyncStatus status,
|
||||||
|
DawnBuffer buffer,
|
||||||
|
uint32_t* ptr,
|
||||||
|
uint64_t dataLength,
|
||||||
|
void* userdata));
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<StrictMock<MockBufferCreateMappedCallback>> mockCreateBufferMappedCallback;
|
||||||
|
uint32_t* lastCreateMappedPointer = nullptr;
|
||||||
|
void ToMockCreateBufferMappedCallback(DawnBufferMapAsyncStatus status,
|
||||||
|
DawnCreateBufferMappedResult result,
|
||||||
|
void* userdata) {
|
||||||
|
// Assume the data is uint32_t to make writing matchers easier
|
||||||
|
lastCreateMappedPointer = static_cast<uint32_t*>(result.data);
|
||||||
|
// Unpack DawnCreateBufferMappedResult to make writing matchers easier
|
||||||
|
mockCreateBufferMappedCallback->Call(status, result.buffer, lastCreateMappedPointer,
|
||||||
|
result.dataLength, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
class WireBufferMappingTests : public WireTest {
|
class WireBufferMappingTests : public WireTest {
|
||||||
@ -72,6 +94,8 @@ class WireBufferMappingTests : public WireTest {
|
|||||||
|
|
||||||
mockBufferMapReadCallback = std::make_unique<StrictMock<MockBufferMapReadCallback>>();
|
mockBufferMapReadCallback = std::make_unique<StrictMock<MockBufferMapReadCallback>>();
|
||||||
mockBufferMapWriteCallback = std::make_unique<StrictMock<MockBufferMapWriteCallback>>();
|
mockBufferMapWriteCallback = std::make_unique<StrictMock<MockBufferMapWriteCallback>>();
|
||||||
|
mockCreateBufferMappedCallback =
|
||||||
|
std::make_unique<StrictMock<MockBufferCreateMappedCallback>>();
|
||||||
|
|
||||||
DawnBufferDescriptor descriptor;
|
DawnBufferDescriptor descriptor;
|
||||||
descriptor.nextInChain = nullptr;
|
descriptor.nextInChain = nullptr;
|
||||||
@ -91,6 +115,7 @@ class WireBufferMappingTests : public WireTest {
|
|||||||
// Delete mocks so that expectations are checked
|
// Delete mocks so that expectations are checked
|
||||||
mockBufferMapReadCallback = nullptr;
|
mockBufferMapReadCallback = nullptr;
|
||||||
mockBufferMapWriteCallback = nullptr;
|
mockBufferMapWriteCallback = nullptr;
|
||||||
|
mockCreateBufferMappedCallback = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlushServer() {
|
void FlushServer() {
|
||||||
@ -98,6 +123,7 @@ class WireBufferMappingTests : public WireTest {
|
|||||||
|
|
||||||
Mock::VerifyAndClearExpectations(&mockBufferMapReadCallback);
|
Mock::VerifyAndClearExpectations(&mockBufferMapReadCallback);
|
||||||
Mock::VerifyAndClearExpectations(&mockBufferMapWriteCallback);
|
Mock::VerifyAndClearExpectations(&mockBufferMapWriteCallback);
|
||||||
|
Mock::VerifyAndClearExpectations(&mockCreateBufferMappedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -612,3 +638,184 @@ TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
|
|||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test successful CreateBufferMappedAsync
|
||||||
|
TEST_F(WireBufferMappingTests, CreateBufferMappedAsyncSuccess) {
|
||||||
|
DawnBufferDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = nullptr;
|
||||||
|
|
||||||
|
DawnCreateBufferMappedResult apiResult;
|
||||||
|
uint32_t serverBufferContent = 31337;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = reinterpret_cast<uint8_t*>(&serverBufferContent);
|
||||||
|
apiResult.dataLength = 4;
|
||||||
|
|
||||||
|
uint32_t updatedContent = 4242;
|
||||||
|
uint32_t zero = 0;
|
||||||
|
|
||||||
|
dawnDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback, nullptr);
|
||||||
|
|
||||||
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
DawnBuffer buffer;
|
||||||
|
// The callback always gets a buffer full of zeroes.
|
||||||
|
EXPECT_CALL(*mockCreateBufferMappedCallback, Call(DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, _,
|
||||||
|
Pointee(Eq(zero)), sizeof(uint32_t), _))
|
||||||
|
.WillOnce(::testing::SaveArg<1>(&buffer));
|
||||||
|
|
||||||
|
FlushServer();
|
||||||
|
|
||||||
|
// Write something to the mapped pointer
|
||||||
|
*lastCreateMappedPointer = updatedContent;
|
||||||
|
|
||||||
|
dawnBufferUnmap(buffer);
|
||||||
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
// After the buffer is unmapped, the content of the buffer is updated on the server
|
||||||
|
ASSERT_EQ(serverBufferContent, updatedContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test CreateBufferMappedAsync with map error
|
||||||
|
TEST_F(WireBufferMappingTests, CreateBufferMappedAsyncMapError) {
|
||||||
|
DawnBufferDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = nullptr;
|
||||||
|
|
||||||
|
DawnCreateBufferMappedResult apiResult;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = nullptr; // error mapping
|
||||||
|
apiResult.dataLength = 4;
|
||||||
|
|
||||||
|
dawnDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback, nullptr);
|
||||||
|
|
||||||
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
DawnBuffer buffer;
|
||||||
|
EXPECT_CALL(*mockCreateBufferMappedCallback,
|
||||||
|
Call(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, _, nullptr, 0, _))
|
||||||
|
.WillOnce(::testing::SaveArg<1>(&buffer));
|
||||||
|
|
||||||
|
FlushServer();
|
||||||
|
|
||||||
|
dawnBufferUnmap(buffer);
|
||||||
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the CreateBufferMappedCallback isn't fired twice when unmap() is called inside the
|
||||||
|
// callback
|
||||||
|
TEST_F(WireBufferMappingTests, UnmapInsideCreateBufferMappedAsyncCallback) {
|
||||||
|
DawnBufferDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = nullptr;
|
||||||
|
|
||||||
|
DawnCreateBufferMappedResult apiResult;
|
||||||
|
uint32_t serverBufferContent = 31337;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = reinterpret_cast<uint8_t*>(&serverBufferContent);
|
||||||
|
apiResult.dataLength = 4;
|
||||||
|
|
||||||
|
uint32_t zero = 0;
|
||||||
|
|
||||||
|
dawnDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback, nullptr);
|
||||||
|
|
||||||
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
DawnBuffer buffer;
|
||||||
|
// The callback always gets a buffer full of zeroes.
|
||||||
|
EXPECT_CALL(*mockCreateBufferMappedCallback, Call(DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, _,
|
||||||
|
Pointee(Eq(zero)), sizeof(uint32_t), _))
|
||||||
|
.WillOnce(DoAll(::testing::SaveArg<1>(&buffer),
|
||||||
|
InvokeWithoutArgs([&]() { dawnBufferUnmap(buffer); })));
|
||||||
|
|
||||||
|
FlushServer();
|
||||||
|
|
||||||
|
EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the CreateBufferMappedCallback isn't fired twice when the buffer is deleted inside
|
||||||
|
// the callback
|
||||||
|
TEST_F(WireBufferMappingTests, ReleaseInsideCreateBufferMappedAsyncCallback) {
|
||||||
|
DawnBufferDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = nullptr;
|
||||||
|
|
||||||
|
DawnCreateBufferMappedResult apiResult;
|
||||||
|
uint32_t serverBufferContent = 31337;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = reinterpret_cast<uint8_t*>(&serverBufferContent);
|
||||||
|
apiResult.dataLength = 4;
|
||||||
|
|
||||||
|
uint32_t zero = 0;
|
||||||
|
|
||||||
|
dawnDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback, nullptr);
|
||||||
|
|
||||||
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
DawnBuffer buffer;
|
||||||
|
// The callback always gets a buffer full of zeroes.
|
||||||
|
EXPECT_CALL(*mockCreateBufferMappedCallback, Call(DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, _,
|
||||||
|
Pointee(Eq(zero)), sizeof(uint32_t), _))
|
||||||
|
.WillOnce(DoAll(::testing::SaveArg<1>(&buffer),
|
||||||
|
InvokeWithoutArgs([&]() { dawnBufferRelease(buffer); })));
|
||||||
|
|
||||||
|
FlushServer();
|
||||||
|
|
||||||
|
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the CreateBufferMappedCallback isn't fired twice when the buffer is destroyed inside
|
||||||
|
// the callback
|
||||||
|
TEST_F(WireBufferMappingTests, DestroyInsideCreateBufferMappedAsyncCallback) {
|
||||||
|
DawnBufferDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = nullptr;
|
||||||
|
|
||||||
|
DawnCreateBufferMappedResult apiResult;
|
||||||
|
uint32_t serverBufferContent = 31337;
|
||||||
|
apiResult.buffer = apiBuffer;
|
||||||
|
apiResult.data = reinterpret_cast<uint8_t*>(&serverBufferContent);
|
||||||
|
apiResult.dataLength = 4;
|
||||||
|
|
||||||
|
uint32_t zero = 0;
|
||||||
|
|
||||||
|
dawnDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback, nullptr);
|
||||||
|
|
||||||
|
EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
|
||||||
|
.WillOnce(Return(apiResult))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
DawnBuffer buffer;
|
||||||
|
// The callback always gets a buffer full of zeroes.
|
||||||
|
EXPECT_CALL(*mockCreateBufferMappedCallback, Call(DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, _,
|
||||||
|
Pointee(Eq(zero)), sizeof(uint32_t), _))
|
||||||
|
.WillOnce(DoAll(::testing::SaveArg<1>(&buffer),
|
||||||
|
InvokeWithoutArgs([&]() { dawnBufferDestroy(buffer); })));
|
||||||
|
|
||||||
|
FlushServer();
|
||||||
|
|
||||||
|
EXPECT_CALL(api, BufferDestroy(apiBuffer));
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user