mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-03 11:46:09 +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": {
|
||||
"category": "structure",
|
||||
"extensible": true,
|
||||
@ -417,6 +420,14 @@
|
||||
{"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",
|
||||
"returns": "command encoder"
|
||||
|
@ -36,6 +36,12 @@
|
||||
{ "name": "descriptor", "type": "buffer descriptor", "annotation": "const*" },
|
||||
{ "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": [
|
||||
{ "name": "object type", "type": "ObjectType" },
|
||||
{ "name": "object id", "type": "ObjectId" }
|
||||
@ -75,6 +81,7 @@
|
||||
"BufferSetSubData",
|
||||
"BufferUnmap",
|
||||
"DeviceCreateBufferMapped",
|
||||
"DeviceCreateBufferMappedAsync",
|
||||
"QueueCreateFence",
|
||||
"FenceGetCompletedValue",
|
||||
"QueueSignal"
|
||||
|
@ -49,6 +49,9 @@
|
||||
|
||||
// Custom types depending on the target language
|
||||
typedef void (*DawnDeviceErrorCallback)(const char* message, void* userdata);
|
||||
typedef void (*DawnBufferCreateMappedCallback)(DawnBufferMapAsyncStatus status,
|
||||
DawnCreateBufferMappedResult result,
|
||||
void* userdata);
|
||||
typedef void (*DawnBufferMapReadCallback)(DawnBufferMapAsyncStatus status,
|
||||
const void* data,
|
||||
uint64_t dataLength,
|
||||
|
@ -60,6 +60,17 @@ void ProcTableAsClass::DeviceSetErrorCallback(DawnDevice self,
|
||||
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,
|
||||
DawnBufferMapReadCallback callback,
|
||||
void* userdata) {
|
||||
@ -95,12 +106,16 @@ void ProcTableAsClass::CallDeviceErrorCallback(DawnDevice device, const char* me
|
||||
auto object = reinterpret_cast<ProcTableAsClass::Object*>(device);
|
||||
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);
|
||||
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);
|
||||
object->mapWriteCallback(status, data, dataLength, object->userdata1);
|
||||
}
|
||||
|
@ -54,6 +54,10 @@ class ProcTableAsClass {
|
||||
void DeviceSetErrorCallback(DawnDevice self,
|
||||
DawnDeviceErrorCallback callback,
|
||||
void* userdata);
|
||||
void DeviceCreateBufferMappedAsync(DawnDevice self,
|
||||
const DawnBufferDescriptor* descriptor,
|
||||
DawnBufferCreateMappedCallback callback,
|
||||
void* userdata);
|
||||
void BufferMapReadAsync(DawnBuffer self,
|
||||
DawnBufferMapReadCallback callback,
|
||||
void* userdata);
|
||||
@ -69,6 +73,10 @@ class ProcTableAsClass {
|
||||
virtual void OnDeviceSetErrorCallback(DawnDevice device,
|
||||
DawnDeviceErrorCallback callback,
|
||||
void* userdata) = 0;
|
||||
virtual void OnDeviceCreateBufferMappedAsyncCallback(DawnDevice self,
|
||||
const DawnBufferDescriptor* descriptor,
|
||||
DawnBufferCreateMappedCallback callback,
|
||||
void* userdata) = 0;
|
||||
virtual void OnBufferMapReadAsyncCallback(DawnBuffer buffer,
|
||||
DawnBufferMapReadCallback callback,
|
||||
void* userdata) = 0;
|
||||
@ -82,13 +90,15 @@ class ProcTableAsClass {
|
||||
|
||||
// Calls the stored callbacks
|
||||
void CallDeviceErrorCallback(DawnDevice device, const char* message);
|
||||
void CallMapReadCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, const void* data, uint32_t dataLength);
|
||||
void CallMapWriteCallback(DawnBuffer buffer, DawnBufferMapAsyncStatus status, void* data, uint32_t dataLength);
|
||||
void CallCreateBufferMappedCallback(DawnDevice device, DawnBufferMapAsyncStatus status, DawnCreateBufferMappedResult result);
|
||||
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);
|
||||
|
||||
struct Object {
|
||||
ProcTableAsClass* procs = nullptr;
|
||||
DawnDeviceErrorCallback deviceErrorCallback = nullptr;
|
||||
DawnBufferCreateMappedCallback createBufferMappedCallback = nullptr;
|
||||
DawnBufferMapReadCallback mapReadCallback = nullptr;
|
||||
DawnBufferMapWriteCallback mapWriteCallback = nullptr;
|
||||
DawnFenceOnCompletionCallback fenceOnCompletionCallback = nullptr;
|
||||
@ -124,6 +134,7 @@ class MockProcTable : public ProcTableAsClass {
|
||||
{% endfor %}
|
||||
|
||||
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(OnBufferMapWriteAsyncCallback, void(DawnBuffer buffer, DawnBufferMapWriteCallback callback, void* userdata));
|
||||
MOCK_METHOD4(OnFenceOnCompletionCallback,
|
||||
|
@ -68,6 +68,7 @@ namespace dawn_native {
|
||||
DeviceBase::~DeviceBase() {
|
||||
// Devices must explicitly free the uploader
|
||||
ASSERT(mDynamicUploader == nullptr);
|
||||
ASSERT(mDeferredCreateBufferMappedAsyncResults.empty());
|
||||
}
|
||||
|
||||
void DeviceBase::HandleError(const char* message) {
|
||||
@ -291,6 +292,25 @@ namespace dawn_native {
|
||||
|
||||
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() {
|
||||
return new CommandEncoderBase(this);
|
||||
}
|
||||
@ -387,6 +407,12 @@ namespace dawn_native {
|
||||
|
||||
void DeviceBase::Tick() {
|
||||
TickImpl();
|
||||
{
|
||||
auto deferredResults = std::move(mDeferredCreateBufferMappedAsyncResults);
|
||||
for (const auto& deferred : deferredResults) {
|
||||
deferred.callback(deferred.status, deferred.result, deferred.userdata);
|
||||
}
|
||||
}
|
||||
mFenceSignalTracker->Tick(GetCompletedCommandSerial());
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,9 @@ namespace dawn_native {
|
||||
BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
|
||||
BufferBase* CreateBuffer(const BufferDescriptor* descriptor);
|
||||
DawnCreateBufferMappedResult CreateBufferMapped(const BufferDescriptor* descriptor);
|
||||
void CreateBufferMappedAsync(const BufferDescriptor* descriptor,
|
||||
dawn::BufferCreateMappedCallback callback,
|
||||
void* userdata);
|
||||
CommandEncoderBase* CreateCommandEncoder();
|
||||
ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor);
|
||||
PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);
|
||||
@ -202,7 +205,15 @@ namespace dawn_native {
|
||||
struct Caches;
|
||||
std::unique_ptr<Caches> mCaches;
|
||||
|
||||
struct DeferredCreateBufferMappedAsync {
|
||||
dawn::BufferCreateMappedCallback callback;
|
||||
DawnBufferMapAsyncStatus status;
|
||||
DawnCreateBufferMappedResult result;
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
std::unique_ptr<FenceSignalTracker> mFenceSignalTracker;
|
||||
std::vector<DeferredCreateBufferMappedAsync> mDeferredCreateBufferMappedAsyncResults;
|
||||
|
||||
dawn::DeviceErrorCallback mErrorCallback = nullptr;
|
||||
void* mErrorUserdata = 0;
|
||||
|
@ -101,6 +101,57 @@ namespace dawn_wire { namespace client {
|
||||
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) {
|
||||
auto fence = reinterpret_cast<Fence*>(cSelf);
|
||||
return fence->completedValue;
|
||||
|
@ -86,6 +86,32 @@ namespace dawn_wire { namespace server {
|
||||
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,
|
||||
uint64_t start,
|
||||
uint64_t offset,
|
||||
|
@ -226,6 +226,7 @@ DAWN_INSTANTIATE_TEST(BufferSetSubDataTests,
|
||||
OpenGLBackend,
|
||||
VulkanBackend);
|
||||
|
||||
// TODO(enga): These tests should use the testing toggle to initialize resources to 1.
|
||||
class CreateBufferMappedTests : public DawnTest {
|
||||
protected:
|
||||
static void MapReadCallback(DawnBufferMapAsyncStatus status,
|
||||
@ -248,37 +249,97 @@ class CreateBufferMappedTests : public DawnTest {
|
||||
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:
|
||||
const void* mappedData = nullptr;
|
||||
};
|
||||
|
||||
// Test that the simplest CreateBufferMapped works for MapWrite buffers.
|
||||
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;
|
||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
||||
memcpy(result.data, &myData, sizeof(myData));
|
||||
dawn::CreateBufferMappedResult result = CreateBufferMappedWithData(
|
||||
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||
result.buffer.Unmap();
|
||||
|
||||
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||
}
|
||||
|
||||
// Test that the simplest CreateBufferMapped works for MapRead buffers.
|
||||
TEST_P(CreateBufferMappedTests, MapReadUsageSmall) {
|
||||
dawn::BufferDescriptor descriptor;
|
||||
descriptor.nextInChain = nullptr;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = dawn::BufferUsageBit::MapRead;
|
||||
|
||||
uint32_t myData = 230502;
|
||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
||||
memcpy(result.data, &myData, sizeof(myData));
|
||||
dawn::CreateBufferMappedResult result =
|
||||
CreateBufferMappedWithData(dawn::BufferUsageBit::MapRead, {myData});
|
||||
result.buffer.Unmap();
|
||||
|
||||
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_P(CreateBufferMappedTests, NonMappableUsageSmall) {
|
||||
dawn::BufferDescriptor descriptor;
|
||||
descriptor.nextInChain = nullptr;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = dawn::BufferUsageBit::TransferSrc;
|
||||
|
||||
uint32_t myData = 4239;
|
||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
||||
memcpy(result.data, &myData, sizeof(myData));
|
||||
dawn::CreateBufferMappedResult result =
|
||||
CreateBufferMappedWithData(dawn::BufferUsageBit::TransferSrc, {myData});
|
||||
result.buffer.Unmap();
|
||||
|
||||
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||
@ -310,14 +365,8 @@ TEST_P(CreateBufferMappedTests, MapWriteUsageLarge) {
|
||||
myData.push_back(i);
|
||||
}
|
||||
|
||||
dawn::BufferDescriptor descriptor;
|
||||
descriptor.nextInChain = nullptr;
|
||||
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));
|
||||
dawn::CreateBufferMappedResult result = CreateBufferMappedWithData(
|
||||
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||
result.buffer.Unmap();
|
||||
|
||||
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
|
||||
@ -331,14 +380,8 @@ TEST_P(CreateBufferMappedTests, MapReadUsageLarge) {
|
||||
myData.push_back(i);
|
||||
}
|
||||
|
||||
dawn::BufferDescriptor descriptor;
|
||||
descriptor.nextInChain = nullptr;
|
||||
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));
|
||||
dawn::CreateBufferMappedResult result =
|
||||
CreateBufferMappedWithData(dawn::BufferUsageBit::MapRead, myData);
|
||||
result.buffer.Unmap();
|
||||
|
||||
const void* mappedData = MapReadAsyncAndWait(result.buffer);
|
||||
@ -354,59 +397,19 @@ TEST_P(CreateBufferMappedTests, NonMappableUsageLarge) {
|
||||
myData.push_back(i);
|
||||
}
|
||||
|
||||
dawn::BufferDescriptor descriptor;
|
||||
descriptor.nextInChain = nullptr;
|
||||
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));
|
||||
dawn::CreateBufferMappedResult result =
|
||||
CreateBufferMappedWithData(dawn::BufferUsageBit::TransferSrc, {myData});
|
||||
result.buffer.Unmap();
|
||||
|
||||
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_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 myData2 = 1337;
|
||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
||||
memcpy(result.data, &myData, sizeof(myData));
|
||||
dawn::CreateBufferMappedResult result = CreateBufferMappedWithData(
|
||||
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||
result.buffer.Unmap();
|
||||
|
||||
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_P(CreateBufferMappedTests, CreateThenMapBeforeUnmapFailure) {
|
||||
dawn::BufferDescriptor descriptor;
|
||||
descriptor.nextInChain = nullptr;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
|
||||
|
||||
uint32_t myData = 230502;
|
||||
dawn::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
|
||||
ASSERT_EQ(result.dataLength, descriptor.size);
|
||||
memcpy(result.data, &myData, sizeof(myData));
|
||||
dawn::CreateBufferMappedResult result = CreateBufferMappedWithData(
|
||||
dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc, {myData});
|
||||
|
||||
ASSERT_DEVICE_ERROR([&]() {
|
||||
bool done = false;
|
||||
@ -463,6 +460,140 @@ TEST_P(CreateBufferMappedTests, CreateThenMapBeforeUnmapFailure) {
|
||||
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,
|
||||
D3D12Backend,
|
||||
MetalBackend,
|
||||
|
@ -59,6 +59,28 @@ namespace {
|
||||
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
|
||||
|
||||
class WireBufferMappingTests : public WireTest {
|
||||
@ -72,6 +94,8 @@ class WireBufferMappingTests : public WireTest {
|
||||
|
||||
mockBufferMapReadCallback = std::make_unique<StrictMock<MockBufferMapReadCallback>>();
|
||||
mockBufferMapWriteCallback = std::make_unique<StrictMock<MockBufferMapWriteCallback>>();
|
||||
mockCreateBufferMappedCallback =
|
||||
std::make_unique<StrictMock<MockBufferCreateMappedCallback>>();
|
||||
|
||||
DawnBufferDescriptor descriptor;
|
||||
descriptor.nextInChain = nullptr;
|
||||
@ -91,6 +115,7 @@ class WireBufferMappingTests : public WireTest {
|
||||
// Delete mocks so that expectations are checked
|
||||
mockBufferMapReadCallback = nullptr;
|
||||
mockBufferMapWriteCallback = nullptr;
|
||||
mockCreateBufferMappedCallback = nullptr;
|
||||
}
|
||||
|
||||
void FlushServer() {
|
||||
@ -98,6 +123,7 @@ class WireBufferMappingTests : public WireTest {
|
||||
|
||||
Mock::VerifyAndClearExpectations(&mockBufferMapReadCallback);
|
||||
Mock::VerifyAndClearExpectations(&mockBufferMapWriteCallback);
|
||||
Mock::VerifyAndClearExpectations(&mockCreateBufferMappedCallback);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -612,3 +638,184 @@ TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
|
||||
|
||||
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