Remove MapRead/WriteAsync and CreateBufferMapped

Bug: dawn:445

Change-Id: I0b0755b6bb754d1fff99aa59b08362f89950e300
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/26301
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Corentin Wallez 2020-08-20 14:22:29 +00:00 committed by Commit Bot service account
parent d720785616
commit f7123d7463
31 changed files with 41 additions and 1822 deletions

View File

@ -175,20 +175,6 @@
"buffer": { "buffer": {
"category": "object", "category": "object",
"methods": [ "methods": [
{
"name": "map read async",
"args": [
{"name": "callback", "type": "buffer map read callback"},
{"name": "userdata", "type": "void", "annotation": "*"}
]
},
{
"name": "map write async",
"args": [
{"name": "callback", "type": "buffer map write callback"},
{"name": "userdata", "type": "void", "annotation": "*"}
]
},
{ {
"name": "map async", "name": "map async",
"args": [ "args": [
@ -248,24 +234,6 @@
{"name": "userdata", "type": "void", "annotation": "*"} {"name": "userdata", "type": "void", "annotation": "*"}
] ]
}, },
"buffer map read callback": {
"category": "callback",
"args": [
{"name": "status", "type": "buffer map async status"},
{"name": "data", "type": "void", "annotation": "const*"},
{"name": "data length", "type": "uint64_t"},
{"name": "userdata", "type": "void", "annotation": "*"}
]
},
"buffer map write callback": {
"category": "callback",
"args": [
{"name": "status", "type": "buffer map async status"},
{"name": "data", "type": "void", "annotation": "*"},
{"name": "data length", "type": "uint64_t"},
{"name": "userdata", "type": "void", "annotation": "*"}
]
},
"buffer map async status": { "buffer map async status": {
"category": "enum", "category": "enum",
"values": [ "values": [
@ -294,14 +262,6 @@
"char": { "char": {
"category": "native" "category": "native"
}, },
"create buffer mapped result": {
"category": "structure",
"members": [
{"name": "buffer", "type": "buffer"},
{"name": "data length", "type": "uint64_t"},
{"name": "data", "type": "void", "annotation": "*", "length": "data length"}
]
},
"color": { "color": {
"category": "structure", "category": "structure",
"members": [ "members": [
@ -575,13 +535,6 @@
"returns": "buffer", "returns": "buffer",
"TODO": "enga@: Make this part of a dawn_wire extension" "TODO": "enga@: Make this part of a dawn_wire extension"
}, },
{
"name": "create buffer mapped",
"returns": "create buffer mapped result",
"args": [
{"name": "descriptor", "type": "buffer descriptor", "annotation": "const*"}
]
},
{ {
"name": "create command encoder", "name": "create command encoder",
"returns": "command encoder", "returns": "command encoder",

View File

@ -90,19 +90,15 @@
}, },
"special items": { "special items": {
"client_side_structures": [ "client_side_structures": [
"CreateBufferMappedResult",
"SurfaceDescriptorFromMetalLayer", "SurfaceDescriptorFromMetalLayer",
"SurfaceDescriptorFromWindowsHWND", "SurfaceDescriptorFromWindowsHWND",
"SurfaceDescriptorFromXlib" "SurfaceDescriptorFromXlib"
], ],
"client_side_commands": [ "client_side_commands": [
"BufferMapAsync", "BufferMapAsync",
"BufferMapReadAsync",
"BufferMapWriteAsync",
"BufferGetConstMappedRange", "BufferGetConstMappedRange",
"BufferGetMappedRange", "BufferGetMappedRange",
"DeviceCreateBuffer", "DeviceCreateBuffer",
"DeviceCreateBufferMapped",
"DevicePopErrorScope", "DevicePopErrorScope",
"DeviceSetDeviceLostCallback", "DeviceSetDeviceLostCallback",
"DeviceSetUncapturedErrorCallback", "DeviceSetUncapturedErrorCallback",

View File

@ -52,7 +52,7 @@ scripts/perf_test_runner.py DrawCallPerf.Run/Vulkan__e_skip_validation
**BufferUploadPerf** **BufferUploadPerf**
Tests repetitively uploading data to the GPU using either `WriteBuffer` or `CreateBufferMapped`. Tests repetitively uploading data to the GPU using either `WriteBuffer` or `CreateBuffer` with `mappedAtCreation = true`.
**DrawCallPerf** **DrawCallPerf**

View File

@ -76,26 +76,6 @@ bool ProcTableAsClass::DevicePopErrorScope(WGPUDevice self,
return OnDevicePopErrorScopeCallback(self, callback, userdata); return OnDevicePopErrorScopeCallback(self, callback, userdata);
} }
void ProcTableAsClass::BufferMapReadAsync(WGPUBuffer self,
WGPUBufferMapReadCallback callback,
void* userdata) {
auto object = reinterpret_cast<ProcTableAsClass::Object*>(self);
object->mapReadCallback = callback;
object->userdata = userdata;
OnBufferMapReadAsyncCallback(self, callback, userdata);
}
void ProcTableAsClass::BufferMapWriteAsync(WGPUBuffer self,
WGPUBufferMapWriteCallback callback,
void* userdata) {
auto object = reinterpret_cast<ProcTableAsClass::Object*>(self);
object->mapWriteCallback = callback;
object->userdata = userdata;
OnBufferMapWriteAsyncCallback(self, callback, userdata);
}
void ProcTableAsClass::BufferMapAsync(WGPUBuffer self, void ProcTableAsClass::BufferMapAsync(WGPUBuffer self,
WGPUMapModeFlags mode, WGPUMapModeFlags mode,
size_t offset, size_t offset,
@ -132,22 +112,6 @@ void ProcTableAsClass::CallDeviceLostCallback(WGPUDevice device, const char* mes
object->deviceLostCallback(message, object->userdata); object->deviceLostCallback(message, object->userdata);
} }
void ProcTableAsClass::CallMapReadCallback(WGPUBuffer buffer,
WGPUBufferMapAsyncStatus status,
const void* data,
uint64_t dataLength) {
auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer);
object->mapReadCallback(status, data, dataLength, object->userdata);
}
void ProcTableAsClass::CallMapWriteCallback(WGPUBuffer buffer,
WGPUBufferMapAsyncStatus status,
void* data,
uint64_t dataLength) {
auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer);
object->mapWriteCallback(status, data, dataLength, object->userdata);
}
void ProcTableAsClass::CallMapAsyncCallback(WGPUBuffer buffer, WGPUBufferMapAsyncStatus status) { void ProcTableAsClass::CallMapAsyncCallback(WGPUBuffer buffer, WGPUBufferMapAsyncStatus status) {
auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer); auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer);
object->mapAsyncCallback(status, object->userdata); object->mapAsyncCallback(status, object->userdata);

View File

@ -59,12 +59,6 @@ class ProcTableAsClass {
WGPUDeviceLostCallback callback, WGPUDeviceLostCallback callback,
void* userdata); void* userdata);
bool DevicePopErrorScope(WGPUDevice self, WGPUErrorCallback callback, void* userdata); bool DevicePopErrorScope(WGPUDevice self, WGPUErrorCallback callback, void* userdata);
void BufferMapReadAsync(WGPUBuffer self,
WGPUBufferMapReadCallback callback,
void* userdata);
void BufferMapWriteAsync(WGPUBuffer self,
WGPUBufferMapWriteCallback callback,
void* userdata);
void BufferMapAsync(WGPUBuffer self, void BufferMapAsync(WGPUBuffer self,
WGPUMapModeFlags mode, WGPUMapModeFlags mode,
size_t offset, size_t offset,
@ -86,12 +80,6 @@ class ProcTableAsClass {
virtual bool OnDevicePopErrorScopeCallback(WGPUDevice device, virtual bool OnDevicePopErrorScopeCallback(WGPUDevice device,
WGPUErrorCallback callback, WGPUErrorCallback callback,
void* userdata) = 0; void* userdata) = 0;
virtual void OnBufferMapReadAsyncCallback(WGPUBuffer buffer,
WGPUBufferMapReadCallback callback,
void* userdata) = 0;
virtual void OnBufferMapWriteAsyncCallback(WGPUBuffer buffer,
WGPUBufferMapWriteCallback callback,
void* userdata) = 0;
virtual void OnBufferMapAsyncCallback(WGPUBuffer buffer, virtual void OnBufferMapAsyncCallback(WGPUBuffer buffer,
WGPUBufferMapCallback callback, WGPUBufferMapCallback callback,
void* userdata) = 0; void* userdata) = 0;
@ -103,8 +91,6 @@ class ProcTableAsClass {
// Calls the stored callbacks // Calls the stored callbacks
void CallDeviceErrorCallback(WGPUDevice device, WGPUErrorType type, const char* message); void CallDeviceErrorCallback(WGPUDevice device, WGPUErrorType type, const char* message);
void CallDeviceLostCallback(WGPUDevice device, const char* message); void CallDeviceLostCallback(WGPUDevice device, const char* message);
void CallMapReadCallback(WGPUBuffer buffer, WGPUBufferMapAsyncStatus status, const void* data, uint64_t dataLength);
void CallMapWriteCallback(WGPUBuffer buffer, WGPUBufferMapAsyncStatus status, void* data, uint64_t dataLength);
void CallMapAsyncCallback(WGPUBuffer buffer, WGPUBufferMapAsyncStatus status); void CallMapAsyncCallback(WGPUBuffer buffer, WGPUBufferMapAsyncStatus status);
void CallFenceOnCompletionCallback(WGPUFence fence, WGPUFenceCompletionStatus status); void CallFenceOnCompletionCallback(WGPUFence fence, WGPUFenceCompletionStatus status);
@ -112,8 +98,6 @@ class ProcTableAsClass {
ProcTableAsClass* procs = nullptr; ProcTableAsClass* procs = nullptr;
WGPUErrorCallback deviceErrorCallback = nullptr; WGPUErrorCallback deviceErrorCallback = nullptr;
WGPUDeviceLostCallback deviceLostCallback = nullptr; WGPUDeviceLostCallback deviceLostCallback = nullptr;
WGPUBufferMapReadCallback mapReadCallback = nullptr;
WGPUBufferMapWriteCallback mapWriteCallback = nullptr;
WGPUBufferMapCallback mapAsyncCallback = nullptr; WGPUBufferMapCallback mapAsyncCallback = nullptr;
WGPUFenceOnCompletionCallback fenceOnCompletionCallback = nullptr; WGPUFenceOnCompletionCallback fenceOnCompletionCallback = nullptr;
void* userdata = 0; void* userdata = 0;
@ -149,8 +133,6 @@ class MockProcTable : public ProcTableAsClass {
MOCK_METHOD(void, OnDeviceSetUncapturedErrorCallback, (WGPUDevice device, WGPUErrorCallback callback, void* userdata), (override)); MOCK_METHOD(void, OnDeviceSetUncapturedErrorCallback, (WGPUDevice device, WGPUErrorCallback callback, void* userdata), (override));
MOCK_METHOD(void, OnDeviceSetDeviceLostCallback, (WGPUDevice device, WGPUDeviceLostCallback callback, void* userdata), (override)); MOCK_METHOD(void, OnDeviceSetDeviceLostCallback, (WGPUDevice device, WGPUDeviceLostCallback callback, void* userdata), (override));
MOCK_METHOD(bool, OnDevicePopErrorScopeCallback, (WGPUDevice device, WGPUErrorCallback callback, void* userdata), (override)); MOCK_METHOD(bool, OnDevicePopErrorScopeCallback, (WGPUDevice device, WGPUErrorCallback callback, void* userdata), (override));
MOCK_METHOD(void, OnBufferMapReadAsyncCallback, (WGPUBuffer buffer, WGPUBufferMapReadCallback callback, void* userdata), (override));
MOCK_METHOD(void, OnBufferMapWriteAsyncCallback, (WGPUBuffer buffer, WGPUBufferMapWriteCallback callback, void* userdata), (override));
MOCK_METHOD(void, MOCK_METHOD(void,
OnBufferMapAsyncCallback, OnBufferMapAsyncCallback,
(WGPUBuffer buffer, WGPUBufferMapCallback callback, void* userdata), (WGPUBuffer buffer, WGPUBufferMapCallback callback, void* userdata),

View File

@ -65,14 +65,6 @@ namespace dawn_native {
return {}; return {};
} }
MaybeError MapReadAsyncImpl() override {
UNREACHABLE();
return {};
}
MaybeError MapWriteAsyncImpl() override {
UNREACHABLE();
return {};
}
MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override { MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override {
UNREACHABLE(); UNREACHABLE();
return {}; return {};
@ -149,8 +141,6 @@ namespace dawn_native {
BufferBase::~BufferBase() { BufferBase::~BufferBase() {
if (mState == BufferState::Mapped) { if (mState == BufferState::Mapped) {
ASSERT(!IsError()); ASSERT(!IsError());
CallMapReadCallback(mMapSerial, WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u);
CallMapWriteCallback(mMapSerial, WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u);
CallMapCallback(mMapSerial, WGPUBufferMapAsyncStatus_Unknown); CallMapCallback(mMapSerial, WGPUBufferMapAsyncStatus_Unknown);
} }
} }
@ -213,48 +203,6 @@ namespace dawn_native {
} }
} }
void BufferBase::CallMapReadCallback(uint32_t serial,
WGPUBufferMapAsyncStatus status,
const void* pointer,
uint64_t dataLength) {
ASSERT(!IsError());
if (mMapReadCallback != nullptr && serial == mMapSerial) {
ASSERT(mMapWriteCallback == nullptr);
// Tag the callback as fired before firing it, otherwise it could fire a second time if
// for example buffer.Unmap() is called inside the application-provided callback.
WGPUBufferMapReadCallback callback = mMapReadCallback;
mMapReadCallback = nullptr;
if (GetDevice()->IsLost()) {
callback(WGPUBufferMapAsyncStatus_DeviceLost, nullptr, 0, mMapUserdata);
} else {
callback(status, pointer, dataLength, mMapUserdata);
}
}
}
void BufferBase::CallMapWriteCallback(uint32_t serial,
WGPUBufferMapAsyncStatus status,
void* pointer,
uint64_t dataLength) {
ASSERT(!IsError());
if (mMapWriteCallback != nullptr && serial == mMapSerial) {
ASSERT(mMapReadCallback == nullptr);
// Tag the callback as fired before firing it, otherwise it could fire a second time if
// for example buffer.Unmap() is called inside the application-provided callback.
WGPUBufferMapWriteCallback callback = mMapWriteCallback;
mMapWriteCallback = nullptr;
if (GetDevice()->IsLost()) {
callback(WGPUBufferMapAsyncStatus_DeviceLost, nullptr, 0, mMapUserdata);
} else {
callback(status, pointer, dataLength, mMapUserdata);
}
}
}
void BufferBase::CallMapCallback(uint32_t serial, WGPUBufferMapAsyncStatus status) { void BufferBase::CallMapCallback(uint32_t serial, WGPUBufferMapAsyncStatus status) {
ASSERT(!IsError()); ASSERT(!IsError());
if (mMapCallback != nullptr && serial == mMapSerial) { if (mMapCallback != nullptr && serial == mMapSerial) {
@ -271,66 +219,6 @@ namespace dawn_native {
} }
} }
void BufferBase::MapReadAsync(WGPUBufferMapReadCallback callback, void* userdata) {
GetDevice()->EmitDeprecationWarning(
"Buffer::MapReadAsync is deprecated. Use Buffer::MapAsync instead");
WGPUBufferMapAsyncStatus status;
if (GetDevice()->ConsumedError(ValidateMap(wgpu::BufferUsage::MapRead, &status))) {
callback(status, nullptr, 0, userdata);
return;
}
ASSERT(!IsError());
ASSERT(mMapWriteCallback == nullptr);
// TODO(cwallez@chromium.org): what to do on wraparound? Could cause crashes.
mMapSerial++;
mMapReadCallback = callback;
mMapUserdata = userdata;
mMapOffset = 0;
mMapSize = mSize;
mState = BufferState::Mapped;
if (GetDevice()->ConsumedError(MapReadAsyncImpl())) {
CallMapReadCallback(mMapSerial, WGPUBufferMapAsyncStatus_DeviceLost, nullptr, 0);
return;
}
MapRequestTracker* tracker = GetDevice()->GetMapRequestTracker();
tracker->Track(this, mMapSerial, MapType::Read);
}
void BufferBase::MapWriteAsync(WGPUBufferMapWriteCallback callback, void* userdata) {
GetDevice()->EmitDeprecationWarning(
"Buffer::MapReadAsync is deprecated. Use Buffer::MapAsync instead");
WGPUBufferMapAsyncStatus status;
if (GetDevice()->ConsumedError(ValidateMap(wgpu::BufferUsage::MapWrite, &status))) {
callback(status, nullptr, 0, userdata);
return;
}
ASSERT(!IsError());
ASSERT(mMapReadCallback == nullptr);
// TODO(cwallez@chromium.org): what to do on wraparound? Could cause crashes.
mMapSerial++;
mMapWriteCallback = callback;
mMapUserdata = userdata;
mMapOffset = 0;
mMapSize = mSize;
mState = BufferState::Mapped;
if (GetDevice()->ConsumedError(MapWriteAsyncImpl())) {
CallMapWriteCallback(mMapSerial, WGPUBufferMapAsyncStatus_DeviceLost, nullptr, 0);
return;
}
MapRequestTracker* tracker = GetDevice()->GetMapRequestTracker();
tracker->Track(this, mMapSerial, MapType::Write);
}
void BufferBase::MapAsync(wgpu::MapMode mode, void BufferBase::MapAsync(wgpu::MapMode mode,
size_t offset, size_t offset,
size_t size, size_t size,
@ -367,7 +255,7 @@ namespace dawn_native {
} }
MapRequestTracker* tracker = GetDevice()->GetMapRequestTracker(); MapRequestTracker* tracker = GetDevice()->GetMapRequestTracker();
tracker->Track(this, mMapSerial, MapType::Async); tracker->Track(this, mMapSerial);
} }
void* BufferBase::GetMappedRange(size_t offset, size_t size) { void* BufferBase::GetMappedRange(size_t offset, size_t size) {
@ -450,14 +338,10 @@ namespace dawn_native {
// A map request can only be called once, so this will fire only if the request wasn't // A map request can only be called once, so this will fire only if the request wasn't
// completed before the Unmap. // completed before the Unmap.
// Callbacks are not fired if there is no callback registered, so this is correct for // Callbacks are not fired if there is no callback registered, so this is correct for
// CreateBufferMapped. // mappedAtCreation = true.
CallMapReadCallback(mMapSerial, WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u);
CallMapWriteCallback(mMapSerial, WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u);
CallMapCallback(mMapSerial, WGPUBufferMapAsyncStatus_Unknown); CallMapCallback(mMapSerial, WGPUBufferMapAsyncStatus_Unknown);
UnmapImpl(); UnmapImpl();
mMapReadCallback = nullptr;
mMapWriteCallback = nullptr;
mMapCallback = nullptr; mMapCallback = nullptr;
mMapUserdata = 0; mMapUserdata = 0;
@ -599,7 +483,7 @@ namespace dawn_native {
switch (mState) { switch (mState) {
case BufferState::Mapped: case BufferState::Mapped:
case BufferState::MappedAtCreation: case BufferState::MappedAtCreation:
// A buffer may be in the Mapped state if it was created with CreateBufferMapped // A buffer may be in the Mapped state if it was created with mappedAtCreation
// even if it did not have a mappable usage. // even if it did not have a mappable usage.
return {}; return {};
case BufferState::Unmapped: case BufferState::Unmapped:
@ -626,20 +510,8 @@ namespace dawn_native {
mState = BufferState::Destroyed; mState = BufferState::Destroyed;
} }
void BufferBase::OnMapCommandSerialFinished(uint32_t mapSerial, MapType type) { void BufferBase::OnMapCommandSerialFinished(uint32_t mapSerial) {
switch (type) {
case MapType::Read:
CallMapReadCallback(mapSerial, WGPUBufferMapAsyncStatus_Success,
GetMappedRangeInternal(false, 0, mSize), GetSize());
break;
case MapType::Write:
CallMapWriteCallback(mapSerial, WGPUBufferMapAsyncStatus_Success,
GetMappedRangeInternal(true, 0, mSize), GetSize());
break;
case MapType::Async:
CallMapCallback(mapSerial, WGPUBufferMapAsyncStatus_Success); CallMapCallback(mapSerial, WGPUBufferMapAsyncStatus_Success);
break;
}
} }
bool BufferBase::IsDataInitialized() const { bool BufferBase::IsDataInitialized() const {

View File

@ -52,7 +52,7 @@ namespace dawn_native {
wgpu::BufferUsage GetUsage() const; wgpu::BufferUsage GetUsage() const;
MaybeError MapAtCreation(); MaybeError MapAtCreation();
void OnMapCommandSerialFinished(uint32_t mapSerial, MapType type); void OnMapCommandSerialFinished(uint32_t mapSerial);
MaybeError ValidateCanUseOnQueueNow() const; MaybeError ValidateCanUseOnQueueNow() const;
@ -61,8 +61,6 @@ namespace dawn_native {
void SetIsDataInitialized(); void SetIsDataInitialized();
// Dawn API // Dawn API
void MapReadAsync(WGPUBufferMapReadCallback callback, void* userdata);
void MapWriteAsync(WGPUBufferMapWriteCallback callback, void* userdata);
void MapAsync(wgpu::MapMode mode, void MapAsync(wgpu::MapMode mode,
size_t offset, size_t offset,
size_t size, size_t size,
@ -85,8 +83,6 @@ namespace dawn_native {
private: private:
virtual MaybeError MapAtCreationImpl() = 0; virtual MaybeError MapAtCreationImpl() = 0;
virtual MaybeError MapReadAsyncImpl() = 0;
virtual MaybeError MapWriteAsyncImpl() = 0;
virtual MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) = 0; virtual MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) = 0;
virtual void UnmapImpl() = 0; virtual void UnmapImpl() = 0;
virtual void DestroyImpl() = 0; virtual void DestroyImpl() = 0;
@ -95,14 +91,6 @@ namespace dawn_native {
virtual bool IsMappableAtCreation() const = 0; virtual bool IsMappableAtCreation() const = 0;
MaybeError CopyFromStagingBuffer(); MaybeError CopyFromStagingBuffer();
void* GetMappedRangeInternal(bool writable, size_t offset, size_t size); void* GetMappedRangeInternal(bool writable, size_t offset, size_t size);
void CallMapReadCallback(uint32_t serial,
WGPUBufferMapAsyncStatus status,
const void* pointer,
uint64_t dataLength);
void CallMapWriteCallback(uint32_t serial,
WGPUBufferMapAsyncStatus status,
void* pointer,
uint64_t dataLength);
void CallMapCallback(uint32_t serial, WGPUBufferMapAsyncStatus status); void CallMapCallback(uint32_t serial, WGPUBufferMapAsyncStatus status);
MaybeError ValidateMap(wgpu::BufferUsage requiredUsage, MaybeError ValidateMap(wgpu::BufferUsage requiredUsage,
@ -122,8 +110,6 @@ namespace dawn_native {
std::unique_ptr<StagingBufferBase> mStagingBuffer; std::unique_ptr<StagingBufferBase> mStagingBuffer;
WGPUBufferMapReadCallback mMapReadCallback = nullptr;
WGPUBufferMapWriteCallback mMapWriteCallback = nullptr;
WGPUBufferMapCallback mMapCallback = nullptr; WGPUBufferMapCallback mMapCallback = nullptr;
void* mMapUserdata = 0; void* mMapUserdata = 0;
uint32_t mMapSerial = 0; uint32_t mMapSerial = 0;

View File

@ -612,27 +612,6 @@ namespace dawn_native {
return result.Detach(); return result.Detach();
} }
WGPUCreateBufferMappedResult DeviceBase::CreateBufferMapped(
const BufferDescriptor* descriptor) {
EmitDeprecationWarning(
"CreateBufferMapped is deprecated, use wgpu::BufferDescriptor::mappedAtCreation and "
"wgpu::Buffer::GetMappedRange instead");
BufferDescriptor fixedDesc = *descriptor;
fixedDesc.mappedAtCreation = true;
BufferBase* buffer = CreateBuffer(&fixedDesc);
WGPUCreateBufferMappedResult result = {};
result.buffer = reinterpret_cast<WGPUBuffer>(buffer);
result.data = buffer->GetMappedRange(0, descriptor->size);
result.dataLength = descriptor->size;
if (result.data != nullptr) {
memset(result.data, 0, result.dataLength);
}
return result;
}
CommandEncoder* DeviceBase::CreateCommandEncoder(const CommandEncoderDescriptor* descriptor) { CommandEncoder* DeviceBase::CreateCommandEncoder(const CommandEncoderDescriptor* descriptor) {
return new CommandEncoder(this, descriptor); return new CommandEncoder(this, descriptor);
} }

View File

@ -145,7 +145,6 @@ namespace dawn_native {
BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor); BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor);
BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor); BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
BufferBase* CreateBuffer(const BufferDescriptor* descriptor); BufferBase* CreateBuffer(const BufferDescriptor* descriptor);
WGPUCreateBufferMappedResult CreateBufferMapped(const BufferDescriptor* descriptor);
CommandEncoder* CreateCommandEncoder(const CommandEncoderDescriptor* descriptor); CommandEncoder* CreateCommandEncoder(const CommandEncoderDescriptor* descriptor);
ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor); ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor);
PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor); PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);

View File

@ -27,11 +27,10 @@ namespace dawn_native {
ASSERT(mInflightRequests.Empty()); ASSERT(mInflightRequests.Empty());
} }
void MapRequestTracker::Track(BufferBase* buffer, uint32_t mapSerial, MapType type) { void MapRequestTracker::Track(BufferBase* buffer, uint32_t mapSerial) {
Request request; Request request;
request.buffer = buffer; request.buffer = buffer;
request.mapSerial = mapSerial; request.mapSerial = mapSerial;
request.type = type;
mInflightRequests.Enqueue(std::move(request), mDevice->GetPendingCommandSerial()); mInflightRequests.Enqueue(std::move(request), mDevice->GetPendingCommandSerial());
mDevice->AddFutureCallbackSerial(mDevice->GetPendingCommandSerial()); mDevice->AddFutureCallbackSerial(mDevice->GetPendingCommandSerial());
@ -39,7 +38,7 @@ namespace dawn_native {
void MapRequestTracker::Tick(Serial finishedSerial) { void MapRequestTracker::Tick(Serial finishedSerial) {
for (auto& request : mInflightRequests.IterateUpTo(finishedSerial)) { for (auto& request : mInflightRequests.IterateUpTo(finishedSerial)) {
request.buffer->OnMapCommandSerialFinished(request.mapSerial, request.type); request.buffer->OnMapCommandSerialFinished(request.mapSerial);
} }
mInflightRequests.ClearUpTo(finishedSerial); mInflightRequests.ClearUpTo(finishedSerial);
} }

View File

@ -20,15 +20,12 @@
namespace dawn_native { namespace dawn_native {
// TODO(dawn:22) remove this enum once MapReadAsync/MapWriteAsync are removed.
enum class MapType : uint32_t { Read, Write, Async };
class MapRequestTracker { class MapRequestTracker {
public: public:
MapRequestTracker(DeviceBase* device); MapRequestTracker(DeviceBase* device);
~MapRequestTracker(); ~MapRequestTracker();
void Track(BufferBase* buffer, uint32_t mapSerial, MapType type); void Track(BufferBase* buffer, uint32_t mapSerial);
void Tick(Serial finishedSerial); void Tick(Serial finishedSerial);
private: private:
@ -37,7 +34,6 @@ namespace dawn_native {
struct Request { struct Request {
Ref<BufferBase> buffer; Ref<BufferBase> buffer;
uint32_t mapSerial; uint32_t mapSerial;
MapType type;
}; };
SerialQueue<Request> mInflightRequests; SerialQueue<Request> mInflightRequests;
}; };

View File

@ -103,7 +103,7 @@ namespace dawn_native { namespace d3d12 {
resourceDescriptor.SampleDesc.Count = 1; resourceDescriptor.SampleDesc.Count = 1;
resourceDescriptor.SampleDesc.Quality = 0; resourceDescriptor.SampleDesc.Quality = 0;
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
// Add CopyDst for non-mappable buffer initialization in CreateBufferMapped // Add CopyDst for non-mappable buffer initialization with mappedAtCreation
// and robust resource initialization. // and robust resource initialization.
resourceDescriptor.Flags = D3D12ResourceFlags(GetUsage() | wgpu::BufferUsage::CopyDst); resourceDescriptor.Flags = D3D12ResourceFlags(GetUsage() | wgpu::BufferUsage::CopyDst);
@ -293,14 +293,6 @@ namespace dawn_native { namespace d3d12 {
return {}; return {};
} }
MaybeError Buffer::MapReadAsyncImpl() {
return MapInternal(false, 0, size_t(GetSize()), "D3D12 map read async");
}
MaybeError Buffer::MapWriteAsyncImpl() {
return MapInternal(true, 0, size_t(GetSize()), "D3D12 map write async");
}
MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) { MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) {
CommandRecordingContext* commandContext; CommandRecordingContext* commandContext;
DAWN_TRY_ASSIGN(commandContext, ToBackend(GetDevice())->GetPendingCommandContext()); DAWN_TRY_ASSIGN(commandContext, ToBackend(GetDevice())->GetPendingCommandContext());

View File

@ -53,16 +53,13 @@ namespace dawn_native { namespace d3d12 {
private: private:
~Buffer() override; ~Buffer() override;
// Dawn API
MaybeError MapReadAsyncImpl() override;
MaybeError MapWriteAsyncImpl() override;
MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override; MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
bool IsMappableAtCreation() const override; bool IsMappableAtCreation() const override;
virtual MaybeError MapAtCreationImpl() override; virtual MaybeError MapAtCreationImpl() override;
void* GetMappedPointerImpl() override; void* GetMappedPointerImpl() override;
MaybeError MapInternal(bool isWrite, size_t start, size_t end, const char* contextInfo); MaybeError MapInternal(bool isWrite, size_t start, size_t end, const char* contextInfo);
bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext, bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,

View File

@ -41,15 +41,12 @@ namespace dawn_native { namespace metal {
private: private:
using BufferBase::BufferBase; using BufferBase::BufferBase;
MaybeError Initialize(); MaybeError Initialize();
~Buffer() override; ~Buffer() override;
// Dawn API
MaybeError MapReadAsyncImpl() override;
MaybeError MapWriteAsyncImpl() override;
MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override; MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
void* GetMappedPointerImpl() override; void* GetMappedPointerImpl() override;
bool IsMappableAtCreation() const override; bool IsMappableAtCreation() const override;
MaybeError MapAtCreationImpl() override; MaybeError MapAtCreationImpl() override;

View File

@ -120,14 +120,6 @@ namespace dawn_native { namespace metal {
return {}; return {};
} }
MaybeError Buffer::MapReadAsyncImpl() {
return {};
}
MaybeError Buffer::MapWriteAsyncImpl() {
return {};
}
MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) { MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) {
CommandRecordingContext* commandContext = CommandRecordingContext* commandContext =
ToBackend(GetDevice())->GetPendingCommandContext(); ToBackend(GetDevice())->GetPendingCommandContext();

View File

@ -311,14 +311,6 @@ namespace dawn_native { namespace null {
memcpy(mBackingData.get() + bufferOffset, data, size); memcpy(mBackingData.get() + bufferOffset, data, size);
} }
MaybeError Buffer::MapReadAsyncImpl() {
return {};
}
MaybeError Buffer::MapWriteAsyncImpl() {
return {};
}
MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) { MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) {
return {}; return {};
} }

View File

@ -204,14 +204,9 @@ namespace dawn_native { namespace null {
private: private:
~Buffer() override; ~Buffer() override;
// Dawn API
MaybeError MapReadAsyncImpl() override;
MaybeError MapWriteAsyncImpl() override;
MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override; MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
bool IsMappableAtCreation() const override; bool IsMappableAtCreation() const override;
MaybeError MapAtCreationImpl() override; MaybeError MapAtCreationImpl() override;
void* GetMappedPointerImpl() override; void* GetMappedPointerImpl() override;

View File

@ -123,26 +123,6 @@ namespace dawn_native { namespace opengl {
return {}; return {};
} }
MaybeError Buffer::MapReadAsyncImpl() {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
// TODO(cwallez@chromium.org): this does GPU->CPU synchronization, we could require a high
// version of OpenGL that would let us map the buffer unsynchronized.
gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
mMappedData = gl.MapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
return {};
}
MaybeError Buffer::MapWriteAsyncImpl() {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
// TODO(cwallez@chromium.org): this does GPU->CPU synchronization, we could require a high
// version of OpenGL that would let us map the buffer unsynchronized.
gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
mMappedData = gl.MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
return {};
}
MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) { MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl; const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;

View File

@ -35,16 +35,13 @@ namespace dawn_native { namespace opengl {
private: private:
~Buffer() override; ~Buffer() override;
// Dawn API
MaybeError MapReadAsyncImpl() override;
MaybeError MapWriteAsyncImpl() override;
MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override; MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
bool IsMappableAtCreation() const override; bool IsMappableAtCreation() const override;
MaybeError MapAtCreationImpl() override; MaybeError MapAtCreationImpl() override;
void* GetMappedPointerImpl() override; void* GetMappedPointerImpl() override;
uint64_t GetAppliedSize() const; uint64_t GetAppliedSize() const;
void InitializeToZero(); void InitializeToZero();

View File

@ -141,7 +141,7 @@ namespace dawn_native { namespace vulkan {
// TODO(cwallez@chromium.org): Have a global "zero" buffer that can do everything instead // TODO(cwallez@chromium.org): Have a global "zero" buffer that can do everything instead
// of creating a new 4-byte buffer? // of creating a new 4-byte buffer?
createInfo.size = std::max(GetSize(), uint64_t(4u)); createInfo.size = std::max(GetSize(), uint64_t(4u));
// Add CopyDst for non-mappable buffer initialization in CreateBufferMapped // Add CopyDst for non-mappable buffer initialization with mappedAtCreation
// and robust resource initialization. // and robust resource initialization.
createInfo.usage = VulkanBufferUsage(GetUsage() | wgpu::BufferUsage::CopyDst); createInfo.usage = VulkanBufferUsage(GetUsage() | wgpu::BufferUsage::CopyDst);
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
@ -250,22 +250,6 @@ namespace dawn_native { namespace vulkan {
return {}; return {};
} }
MaybeError Buffer::MapReadAsyncImpl() {
Device* device = ToBackend(GetDevice());
CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
TransitionUsageNow(recordingContext, wgpu::BufferUsage::MapRead);
return {};
}
MaybeError Buffer::MapWriteAsyncImpl() {
Device* device = ToBackend(GetDevice());
CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
TransitionUsageNow(recordingContext, wgpu::BufferUsage::MapWrite);
return {};
}
MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) { MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());

View File

@ -57,13 +57,9 @@ namespace dawn_native { namespace vulkan {
void InitializeToZero(CommandRecordingContext* recordingContext); void InitializeToZero(CommandRecordingContext* recordingContext);
void ClearBuffer(CommandRecordingContext* recordingContext, uint32_t clearValue); void ClearBuffer(CommandRecordingContext* recordingContext, uint32_t clearValue);
// Dawn API
MaybeError MapReadAsyncImpl() override;
MaybeError MapWriteAsyncImpl() override;
MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override; MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
void UnmapImpl() override; void UnmapImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
bool IsMappableAtCreation() const override; bool IsMappableAtCreation() const override;
MaybeError MapAtCreationImpl() override; MaybeError MapAtCreationImpl() override;
void* GetMappedPointerImpl() override; void* GetMappedPointerImpl() override;

View File

@ -115,78 +115,6 @@ namespace dawn_wire { namespace client {
mRequests.clear(); mRequests.clear();
} }
void Buffer::MapReadAsync(WGPUBufferMapReadCallback callback, void* userdata) {
struct ProxyData {
WGPUBufferMapReadCallback callback;
void* userdata;
Buffer* self;
};
ProxyData* proxy = new ProxyData;
proxy->callback = callback;
proxy->userdata = userdata;
proxy->self = this;
MapAsync(
WGPUMapMode_Read, 0, mSize,
[](WGPUBufferMapAsyncStatus status, void* userdata) {
ProxyData* proxy = static_cast<ProxyData*>(userdata);
Buffer* self = proxy->self;
if (status == WGPUBufferMapAsyncStatus_Success) {
// On buffer creation we assert that a mappable buffer cannot be bigger than
// MAX_SIZE_T so we should never have a successful mapping in this case.
ASSERT(self->mSize <= std::numeric_limits<size_t>::max());
self->mMapOffset = 0;
self->mMapSize = self->mSize;
}
if (proxy->callback) {
const void* data = self->GetConstMappedRange(0, self->mSize);
uint64_t dataLength = data == nullptr ? 0 : self->mSize;
proxy->callback(status, data, dataLength, proxy->userdata);
}
delete proxy;
},
proxy);
}
void Buffer::MapWriteAsync(WGPUBufferMapWriteCallback callback, void* userdata) {
struct ProxyData {
WGPUBufferMapWriteCallback callback;
void* userdata;
Buffer* self;
};
ProxyData* proxy = new ProxyData;
proxy->callback = callback;
proxy->userdata = userdata;
proxy->self = this;
MapAsync(
WGPUMapMode_Write, 0, mSize,
[](WGPUBufferMapAsyncStatus status, void* userdata) {
ProxyData* proxy = static_cast<ProxyData*>(userdata);
Buffer* self = proxy->self;
if (status == WGPUBufferMapAsyncStatus_Success) {
// On buffer creation we assert that a mappable buffer cannot be bigger than
// MAX_SIZE_T so we should never have a successful mapping in this case.
ASSERT(self->mSize <= std::numeric_limits<size_t>::max());
self->mMapOffset = 0;
self->mMapSize = self->mSize;
}
if (proxy->callback) {
void* data = self->GetMappedRange(0, self->mSize);
uint64_t dataLength = data == nullptr ? 0 : self->mSize;
proxy->callback(status, data, dataLength, proxy->userdata);
}
delete proxy;
},
proxy);
}
void Buffer::MapAsync(WGPUMapModeFlags mode, void Buffer::MapAsync(WGPUMapModeFlags mode,
size_t offset, size_t offset,
size_t size, size_t size,

View File

@ -34,8 +34,6 @@ namespace dawn_wire { namespace client {
~Buffer(); ~Buffer();
void ClearMapRequests(WGPUBufferMapAsyncStatus status); void ClearMapRequests(WGPUBufferMapAsyncStatus status);
void MapReadAsync(WGPUBufferMapReadCallback callback, void* userdata);
void MapWriteAsync(WGPUBufferMapWriteCallback callback, void* userdata);
bool OnMapAsyncCallback(uint32_t requestSerial, bool OnMapAsyncCallback(uint32_t requestSerial,
uint32_t status, uint32_t status,
uint64_t readInitialDataInfoLength, uint64_t readInitialDataInfoLength,

View File

@ -149,19 +149,6 @@ namespace dawn_wire { namespace client {
return Buffer::Create(this, descriptor); return Buffer::Create(this, descriptor);
} }
WGPUCreateBufferMappedResult Device::CreateBufferMapped(
const WGPUBufferDescriptor* descriptor) {
WGPUBufferDescriptor descMappedAtCreation = *descriptor;
descMappedAtCreation.mappedAtCreation = true;
WGPUCreateBufferMappedResult result;
result.buffer = CreateBuffer(&descMappedAtCreation);
result.data = FromAPI(result.buffer)->GetMappedRange(0, descriptor->size);
result.dataLength = result.data == nullptr ? 0 : descriptor->size;
return result;
}
WGPUBuffer Device::CreateErrorBuffer() { WGPUBuffer Device::CreateErrorBuffer() {
return Buffer::CreateError(this); return Buffer::CreateError(this);
} }

View File

@ -38,7 +38,6 @@ namespace dawn_wire { namespace client {
void PushErrorScope(WGPUErrorFilter filter); void PushErrorScope(WGPUErrorFilter filter);
bool PopErrorScope(WGPUErrorCallback callback, void* userdata); bool PopErrorScope(WGPUErrorCallback callback, void* userdata);
WGPUBuffer CreateBuffer(const WGPUBufferDescriptor* descriptor); WGPUBuffer CreateBuffer(const WGPUBufferDescriptor* descriptor);
WGPUCreateBufferMappedResult CreateBufferMapped(const WGPUBufferDescriptor* descriptor);
WGPUBuffer CreateErrorBuffer(); WGPUBuffer CreateErrorBuffer();
void HandleError(WGPUErrorType errorType, const char* message); void HandleError(WGPUErrorType errorType, const char* message);

View File

@ -17,307 +17,6 @@
#include <array> #include <array>
#include <cstring> #include <cstring>
class BufferMapReadTests : public DawnTest {
protected:
static void MapReadCallback(WGPUBufferMapAsyncStatus status,
const void* data,
uint64_t,
void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
ASSERT_NE(nullptr, data);
static_cast<BufferMapReadTests*>(userdata)->mappedData = data;
}
const void* MapReadAsyncAndWait(const wgpu::Buffer& buffer) {
buffer.MapReadAsync(MapReadCallback, this);
while (mappedData == nullptr) {
WaitABit();
}
return mappedData;
}
void UnmapBuffer(const wgpu::Buffer& buffer) {
buffer.Unmap();
mappedData = nullptr;
}
private:
const void* mappedData = nullptr;
};
// Test that the simplest map read works.
TEST_P(BufferMapReadTests, SmallReadAtZero) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
uint32_t myData = 0x01020304;
queue.WriteBuffer(buffer, 0, &myData, sizeof(myData));
const void* mappedData = MapReadAsyncAndWait(buffer);
ASSERT_EQ(myData, *reinterpret_cast<const uint32_t*>(mappedData));
UnmapBuffer(buffer);
}
// Map, read and unmap twice. Test that both of these two iterations work.
TEST_P(BufferMapReadTests, MapTwice) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
uint32_t myData = 0x01020304;
queue.WriteBuffer(buffer, 0, &myData, sizeof(myData));
const void* mappedData = MapReadAsyncAndWait(buffer);
EXPECT_EQ(myData, *reinterpret_cast<const uint32_t*>(mappedData));
UnmapBuffer(buffer);
myData = 0x05060708;
queue.WriteBuffer(buffer, 0, &myData, sizeof(myData));
const void* mappedData1 = MapReadAsyncAndWait(buffer);
EXPECT_EQ(myData, *reinterpret_cast<const uint32_t*>(mappedData1));
UnmapBuffer(buffer);
}
// Test mapping a large buffer.
TEST_P(BufferMapReadTests, LargeRead) {
constexpr uint32_t kDataSize = 1000 * 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
wgpu::BufferDescriptor descriptor;
descriptor.size = static_cast<uint32_t>(kDataSize * sizeof(uint32_t));
descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
queue.WriteBuffer(buffer, 0, myData.data(), kDataSize * sizeof(uint32_t));
const void* mappedData = MapReadAsyncAndWait(buffer);
ASSERT_EQ(0, memcmp(mappedData, myData.data(), kDataSize * sizeof(uint32_t)));
UnmapBuffer(buffer);
}
// Test mapping a zero-sized buffer.
TEST_P(BufferMapReadTests, ZeroSized) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
MapReadAsyncAndWait(buffer);
UnmapBuffer(buffer);
}
// Test the result of GetMappedRange when mapped for reading.
TEST_P(BufferMapReadTests, GetMappedRange) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
const void* mappedData = MapReadAsyncAndWait(buffer);
ASSERT_EQ(buffer.GetConstMappedRange(), mappedData);
ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
UnmapBuffer(buffer);
}
// Test the result of GetMappedRange when mapped for reading for a zero-sized buffer.
TEST_P(BufferMapReadTests, GetMappedRangeZeroSized) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
const void* mappedData = MapReadAsyncAndWait(buffer);
ASSERT_EQ(buffer.GetConstMappedRange(), mappedData);
ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
UnmapBuffer(buffer);
}
DAWN_INSTANTIATE_TEST(BufferMapReadTests,
D3D12Backend(),
MetalBackend(),
OpenGLBackend(),
VulkanBackend());
class BufferMapWriteTests : public DawnTest {
protected:
static void MapWriteCallback(WGPUBufferMapAsyncStatus status,
void* data,
uint64_t,
void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
ASSERT_NE(nullptr, data);
static_cast<BufferMapWriteTests*>(userdata)->mappedData = data;
}
void* MapWriteAsyncAndWait(const wgpu::Buffer& buffer) {
buffer.MapWriteAsync(MapWriteCallback, this);
while (mappedData == nullptr) {
WaitABit();
}
// Ensure the prior write's status is updated.
void* resultPointer = mappedData;
mappedData = nullptr;
return resultPointer;
}
void UnmapBuffer(const wgpu::Buffer& buffer) {
buffer.Unmap();
mappedData = nullptr;
}
private:
void* mappedData = nullptr;
};
// Test that the simplest map write works.
TEST_P(BufferMapWriteTests, SmallWriteAtZero) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
uint32_t myData = 2934875;
void* mappedData = MapWriteAsyncAndWait(buffer);
memcpy(mappedData, &myData, sizeof(myData));
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}
// Map, write and unmap twice. Test that both of these two iterations work.
TEST_P(BufferMapWriteTests, MapTwice) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
uint32_t myData = 2934875;
void* mappedData = MapWriteAsyncAndWait(buffer);
memcpy(mappedData, &myData, sizeof(myData));
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
myData = 9999999;
void* mappedData1 = MapWriteAsyncAndWait(buffer);
memcpy(mappedData1, &myData, sizeof(myData));
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}
// Test mapping a large buffer.
TEST_P(BufferMapWriteTests, LargeWrite) {
constexpr uint32_t kDataSize = 1000 * 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
wgpu::BufferDescriptor descriptor;
descriptor.size = static_cast<uint32_t>(kDataSize * sizeof(uint32_t));
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
void* mappedData = MapWriteAsyncAndWait(buffer);
memcpy(mappedData, myData.data(), kDataSize * sizeof(uint32_t));
UnmapBuffer(buffer);
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), buffer, 0, kDataSize);
}
// Test mapping a zero-sized buffer.
TEST_P(BufferMapWriteTests, ZeroSized) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
MapWriteAsyncAndWait(buffer);
UnmapBuffer(buffer);
}
// Stress test mapping many buffers.
TEST_P(BufferMapWriteTests, ManyWrites) {
constexpr uint32_t kDataSize = 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
std::vector<wgpu::Buffer> buffers;
constexpr uint32_t kBuffers = 100;
for (uint32_t i = 0; i < kBuffers; ++i) {
wgpu::BufferDescriptor descriptor;
descriptor.size = static_cast<uint32_t>(kDataSize * sizeof(uint32_t));
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
void* mappedData = MapWriteAsyncAndWait(buffer);
memcpy(mappedData, myData.data(), kDataSize * sizeof(uint32_t));
UnmapBuffer(buffer);
buffers.push_back(buffer); // Destroy buffers upon return.
}
for (uint32_t i = 0; i < kBuffers; ++i) {
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), buffers[i], 0, kDataSize);
}
}
// Test the result of GetMappedRange when mapped for writing.
TEST_P(BufferMapWriteTests, GetMappedRange) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
void* mappedData = MapWriteAsyncAndWait(buffer);
ASSERT_EQ(buffer.GetMappedRange(), mappedData);
ASSERT_EQ(buffer.GetMappedRange(), buffer.GetConstMappedRange());
ASSERT_NE(buffer.GetMappedRange(), nullptr);
UnmapBuffer(buffer);
}
// Test the result of GetMappedRange when mapped for writing for a zero-sized buffer.
TEST_P(BufferMapWriteTests, GetMappedRangeZeroSized) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
void* mappedData = MapWriteAsyncAndWait(buffer);
ASSERT_EQ(buffer.GetMappedRange(), mappedData);
ASSERT_EQ(buffer.GetMappedRange(), buffer.GetConstMappedRange());
ASSERT_NE(buffer.GetMappedRange(), nullptr);
UnmapBuffer(buffer);
}
DAWN_INSTANTIATE_TEST(BufferMapWriteTests,
D3D12Backend(),
MetalBackend(),
OpenGLBackend(),
VulkanBackend());
class BufferMappingTests : public DawnTest { class BufferMappingTests : public DawnTest {
protected: protected:
void MapAsyncAndWait(const wgpu::Buffer& buffer, void MapAsyncAndWait(const wgpu::Buffer& buffer,
@ -737,290 +436,6 @@ DAWN_INSTANTIATE_TEST(BufferMappingTests,
OpenGLBackend(), OpenGLBackend(),
VulkanBackend()); VulkanBackend());
class CreateBufferMappedTests : public DawnTest {
protected:
static void MapReadCallback(WGPUBufferMapAsyncStatus status,
const void* data,
uint64_t,
void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
ASSERT_NE(nullptr, data);
static_cast<CreateBufferMappedTests*>(userdata)->mappedData = data;
}
const void* MapReadAsyncAndWait(const wgpu::Buffer& buffer) {
buffer.MapReadAsync(MapReadCallback, this);
while (mappedData == nullptr) {
WaitABit();
}
return mappedData;
}
void UnmapBuffer(const wgpu::Buffer& buffer) {
buffer.Unmap();
mappedData = nullptr;
}
void CheckResultStartsZeroed(const wgpu::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);
}
}
wgpu::CreateBufferMappedResult CreateBufferMapped(wgpu::BufferUsage usage, uint64_t size) {
wgpu::BufferDescriptor descriptor = {};
descriptor.size = size;
descriptor.usage = usage;
wgpu::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
CheckResultStartsZeroed(result, size);
return result;
}
wgpu::CreateBufferMappedResult CreateBufferMappedWithData(wgpu::BufferUsage usage,
const std::vector<uint32_t>& data) {
size_t byteLength = data.size() * sizeof(uint32_t);
wgpu::CreateBufferMappedResult result = CreateBufferMapped(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) {
uint32_t myData = 230502;
wgpu::CreateBufferMappedResult result = CreateBufferMappedWithData(
wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(result.buffer);
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
}
// Test that the simplest CreateBufferMapped works for MapRead buffers.
TEST_P(CreateBufferMappedTests, MapReadUsageSmall) {
uint32_t myData = 230502;
wgpu::CreateBufferMappedResult result =
CreateBufferMappedWithData(wgpu::BufferUsage::MapRead, {myData});
UnmapBuffer(result.buffer);
const void* mappedData = MapReadAsyncAndWait(result.buffer);
ASSERT_EQ(myData, *reinterpret_cast<const uint32_t*>(mappedData));
UnmapBuffer(result.buffer);
}
// Test that the simplest CreateBufferMapped works for non-mappable buffers.
TEST_P(CreateBufferMappedTests, NonMappableUsageSmall) {
uint32_t myData = 4239;
wgpu::CreateBufferMappedResult result =
CreateBufferMappedWithData(wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(result.buffer);
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
}
// Test CreateBufferMapped for a large MapWrite buffer
TEST_P(CreateBufferMappedTests, MapWriteUsageLarge) {
constexpr uint64_t kDataSize = 1000 * 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
wgpu::CreateBufferMappedResult result = CreateBufferMappedWithData(
wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(result.buffer);
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
}
// Test CreateBufferMapped for a large MapRead buffer
TEST_P(CreateBufferMappedTests, MapReadUsageLarge) {
constexpr uint64_t kDataSize = 1000 * 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
wgpu::CreateBufferMappedResult result =
CreateBufferMappedWithData(wgpu::BufferUsage::MapRead, myData);
UnmapBuffer(result.buffer);
const void* mappedData = MapReadAsyncAndWait(result.buffer);
ASSERT_EQ(0, memcmp(mappedData, myData.data(), kDataSize * sizeof(uint32_t)));
UnmapBuffer(result.buffer);
}
// Test CreateBufferMapped for a large non-mappable buffer
TEST_P(CreateBufferMappedTests, NonMappableUsageLarge) {
constexpr uint64_t kDataSize = 1000 * 1000;
std::vector<uint32_t> myData;
for (uint32_t i = 0; i < kDataSize; ++i) {
myData.push_back(i);
}
wgpu::CreateBufferMappedResult result =
CreateBufferMappedWithData(wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(result.buffer);
EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), result.buffer, 0, kDataSize);
}
// Test destroying a non-mappable buffer mapped at creation.
// This is a regression test for an issue where the D3D12 backend thought the buffer was actually
// mapped and tried to unlock the heap residency (when actually the buffer was using a staging
// buffer)
TEST_P(CreateBufferMappedTests, DestroyNonMappableWhileMappedForCreation) {
wgpu::CreateBufferMappedResult result = CreateBufferMapped(wgpu::BufferUsage::CopySrc, 4);
result.buffer.Destroy();
}
// Test destroying a mappable buffer mapped at creation.
TEST_P(CreateBufferMappedTests, DestroyMappableWhileMappedForCreation) {
wgpu::CreateBufferMappedResult result = CreateBufferMapped(wgpu::BufferUsage::MapRead, 4);
result.buffer.Destroy();
}
// Test that mapping a buffer is valid after CreateBufferMapped and Unmap
TEST_P(CreateBufferMappedTests, CreateThenMapSuccess) {
static uint32_t myData = 230502;
static uint32_t myData2 = 1337;
wgpu::CreateBufferMappedResult result = CreateBufferMappedWithData(
wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
UnmapBuffer(result.buffer);
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
bool done = false;
result.buffer.MapWriteAsync(
[](WGPUBufferMapAsyncStatus status, void* data, uint64_t, void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
ASSERT_NE(nullptr, data);
*static_cast<uint32_t*>(data) = myData2;
*static_cast<bool*>(userdata) = true;
},
&done);
while (!done) {
WaitABit();
}
UnmapBuffer(result.buffer);
EXPECT_BUFFER_U32_EQ(myData2, result.buffer, 0);
}
// Test that is is invalid to map a buffer twice when using CreateBufferMapped
TEST_P(CreateBufferMappedTests, CreateThenMapBeforeUnmapFailure) {
uint32_t myData = 230502;
wgpu::CreateBufferMappedResult result = CreateBufferMappedWithData(
wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
ASSERT_DEVICE_ERROR([&]() {
bool done = false;
result.buffer.MapWriteAsync(
[](WGPUBufferMapAsyncStatus status, void* data, uint64_t, void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Error, status);
ASSERT_EQ(nullptr, data);
*static_cast<bool*>(userdata) = true;
},
&done);
while (!done) {
WaitABit();
}
}());
// CreateBufferMapped is unaffected by the MapWrite error.
UnmapBuffer(result.buffer);
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
}
// Test that creating a zero-sized buffer mapped is allowed.
TEST_P(CreateBufferMappedTests, ZeroSized) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::Vertex;
wgpu::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
ASSERT_EQ(0u, result.dataLength);
ASSERT_NE(nullptr, result.data);
// Check that unmapping the buffer works too.
UnmapBuffer(result.buffer);
}
// Test that creating a zero-sized mapppable buffer mapped. (it is a different code path)
TEST_P(CreateBufferMappedTests, ZeroSizedMappableBuffer) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::MapWrite;
wgpu::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
ASSERT_EQ(0u, result.dataLength);
ASSERT_NE(nullptr, result.data);
// Check that unmapping the buffer works too.
UnmapBuffer(result.buffer);
}
// Test that creating a zero-sized error buffer mapped. (it is a different code path)
TEST_P(CreateBufferMappedTests, ZeroSizedErrorBuffer) {
DAWN_SKIP_TEST_IF(IsDawnValidationSkipped());
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Storage;
wgpu::CreateBufferMappedResult result;
ASSERT_DEVICE_ERROR(result = device.CreateBufferMapped(&descriptor));
ASSERT_EQ(0u, result.dataLength);
ASSERT_NE(nullptr, result.data);
}
// Test the result of GetMappedRange when mapped at creation.
TEST_P(CreateBufferMappedTests, GetMappedRange) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopyDst;
wgpu::CreateBufferMappedResult result;
result = device.CreateBufferMapped(&descriptor);
ASSERT_EQ(result.buffer.GetMappedRange(), result.data);
ASSERT_EQ(result.buffer.GetMappedRange(), result.buffer.GetConstMappedRange());
ASSERT_NE(result.buffer.GetMappedRange(), nullptr);
result.buffer.Unmap();
}
// Test the result of GetMappedRange when mapped at creation for a zero-sized buffer.
TEST_P(CreateBufferMappedTests, GetMappedRangeZeroSized) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 0;
descriptor.usage = wgpu::BufferUsage::CopyDst;
wgpu::CreateBufferMappedResult result;
result = device.CreateBufferMapped(&descriptor);
ASSERT_EQ(result.buffer.GetMappedRange(), result.data);
ASSERT_EQ(result.buffer.GetMappedRange(), result.buffer.GetConstMappedRange());
ASSERT_NE(result.buffer.GetMappedRange(), nullptr);
result.buffer.Unmap();
}
DAWN_INSTANTIATE_TEST(CreateBufferMappedTests,
D3D12Backend(),
D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}),
MetalBackend(),
OpenGLBackend(),
VulkanBackend());
class BufferMappedAtCreationTests : public DawnTest { class BufferMappedAtCreationTests : public DawnTest {
protected: protected:
static void MapCallback(WGPUBufferMapAsyncStatus status, void* userdata) { static void MapCallback(WGPUBufferMapAsyncStatus status, void* userdata) {
@ -1302,49 +717,6 @@ TEST_P(BufferTests, CreateBufferOOM) {
ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor)); ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
} }
// Test that a very large CreateBufferMapped fails gracefully.
TEST_P(BufferTests, CreateBufferMappedOOM) {
// TODO(http://crbug.com/dawn/27): Missing support.
DAWN_SKIP_TEST_IF(IsOpenGL());
DAWN_SKIP_TEST_IF(IsAsan());
// Test non-mappable buffer
{
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopyDst;
// Control: test a small buffer works.
device.CreateBufferMapped(&descriptor);
// Test an enormous buffer fails
descriptor.size = std::numeric_limits<uint64_t>::max();
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&descriptor));
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
descriptor.size = 1ull << 50;
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&descriptor));
}
// Test mappable buffer
{
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
// Control: test a small buffer works.
device.CreateBufferMapped(&descriptor);
// Test an enormous buffer fails
descriptor.size = std::numeric_limits<uint64_t>::max();
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&descriptor));
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
descriptor.size = 1ull << 50;
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&descriptor));
}
}
// Test that a very large buffer mappedAtCreation fails gracefully. // Test that a very large buffer mappedAtCreation fails gracefully.
TEST_P(BufferTests, BufferMappedAtCreationOOM) { TEST_P(BufferTests, BufferMappedAtCreationOOM) {
// TODO(http://crbug.com/dawn/27): Missing support. // TODO(http://crbug.com/dawn/27): Missing support.
@ -1390,81 +762,6 @@ TEST_P(BufferTests, BufferMappedAtCreationOOM) {
} }
} }
// Test that mapping an OOM buffer for reading fails gracefully
TEST_P(BufferTests, CreateBufferOOMMapReadAsync) {
// TODO(http://crbug.com/dawn/27): Missing support.
DAWN_SKIP_TEST_IF(IsOpenGL());
DAWN_SKIP_TEST_IF(IsAsan());
auto RunTest = [this](const wgpu::BufferDescriptor& descriptor) {
wgpu::Buffer buffer;
ASSERT_DEVICE_ERROR(buffer = device.CreateBuffer(&descriptor));
bool done = false;
ASSERT_DEVICE_ERROR(buffer.MapReadAsync(
[](WGPUBufferMapAsyncStatus status, const void* ptr, uint64_t dataLength,
void* userdata) {
EXPECT_EQ(status, WGPUBufferMapAsyncStatus_Error);
EXPECT_EQ(ptr, nullptr);
EXPECT_EQ(dataLength, 0u);
*static_cast<bool*>(userdata) = true;
},
&done));
while (!done) {
WaitABit();
}
};
// Test an enormous buffer
wgpu::BufferDescriptor descriptor;
descriptor.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
descriptor.size = std::numeric_limits<uint64_t>::max();
RunTest(descriptor);
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
descriptor.size = 1ull << 50;
RunTest(descriptor);
}
// Test that mapping an OOM buffer for reading fails gracefully
TEST_P(BufferTests, CreateBufferOOMMapWriteAsync) {
// TODO(http://crbug.com/dawn/27): Missing support.
DAWN_SKIP_TEST_IF(IsOpenGL());
DAWN_SKIP_TEST_IF(IsAsan());
auto RunTest = [this](const wgpu::BufferDescriptor& descriptor) {
wgpu::Buffer buffer;
ASSERT_DEVICE_ERROR(buffer = device.CreateBuffer(&descriptor));
bool done = false;
ASSERT_DEVICE_ERROR(buffer.MapWriteAsync(
[](WGPUBufferMapAsyncStatus status, void* ptr, uint64_t dataLength, void* userdata) {
EXPECT_EQ(status, WGPUBufferMapAsyncStatus_Error);
EXPECT_EQ(ptr, nullptr);
EXPECT_EQ(dataLength, 0u);
*static_cast<bool*>(userdata) = true;
},
&done));
while (!done) {
WaitABit();
}
};
wgpu::BufferDescriptor descriptor;
descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
// Test an enormous buffer
descriptor.size = std::numeric_limits<uint64_t>::max();
RunTest(descriptor);
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
descriptor.size = 1ull << 50;
RunTest(descriptor);
}
// Test that mapping an OOM buffer fails gracefully // Test that mapping an OOM buffer fails gracefully
TEST_P(BufferTests, CreateBufferOOMMapAsync) { TEST_P(BufferTests, CreateBufferOOMMapAsync) {
// TODO(http://crbug.com/dawn/27): Missing support. // TODO(http://crbug.com/dawn/27): Missing support.

View File

@ -679,7 +679,7 @@ TEST_P(BufferZeroInitTest, CopyBufferToBufferDestination) {
// Test that the code path of readable buffer mapping clears the buffer correctly when it is the // Test that the code path of readable buffer mapping clears the buffer correctly when it is the
// first use of the buffer. // first use of the buffer.
TEST_P(BufferZeroInitTest, MapReadAsync) { TEST_P(BufferZeroInitTest, MapAsync_Read) {
constexpr uint32_t kBufferSize = 16u; constexpr uint32_t kBufferSize = 16u;
constexpr wgpu::BufferUsage kBufferUsage = constexpr wgpu::BufferUsage kBufferUsage =
wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst; wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
@ -724,7 +724,7 @@ TEST_P(BufferZeroInitTest, MapReadAsync) {
// Test that the code path of writable buffer mapping clears the buffer correctly when it is the // Test that the code path of writable buffer mapping clears the buffer correctly when it is the
// first use of the buffer. // first use of the buffer.
TEST_P(BufferZeroInitTest, MapWriteAsync) { TEST_P(BufferZeroInitTest, MapAsync_Write) {
constexpr uint32_t kBufferSize = 16u; constexpr uint32_t kBufferSize = 16u;
constexpr wgpu::BufferUsage kBufferUsage = constexpr wgpu::BufferUsage kBufferUsage =
wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc; wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;

View File

@ -332,34 +332,6 @@ TEST_P(DeviceLostTest, WriteBufferFails) {
ASSERT_DEVICE_ERROR(queue.WriteBuffer(buffer, 0, &data, sizeof(data))); ASSERT_DEVICE_ERROR(queue.WriteBuffer(buffer, 0, &data, sizeof(data)));
} }
// Test it's possible to GetMappedRange on a buffer created mapped after device loss
TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedAfterLoss) {
SetCallbackAndLoseForTesting();
wgpu::BufferDescriptor desc;
desc.size = 4;
desc.usage = wgpu::BufferUsage::CopySrc;
ASSERT_DEVICE_ERROR(wgpu::CreateBufferMappedResult result = device.CreateBufferMapped(&desc));
ASSERT_NE(result.buffer.GetMappedRange(), nullptr);
ASSERT_EQ(result.buffer.GetMappedRange(), result.data);
}
// Test that device loss doesn't change the result of GetMappedRange, createBufferMapped version.
TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedBeforeLoss) {
wgpu::BufferDescriptor desc;
desc.size = 4;
desc.usage = wgpu::BufferUsage::CopySrc;
wgpu::CreateBufferMappedResult result = device.CreateBufferMapped(&desc);
void* rangeBeforeLoss = result.buffer.GetMappedRange();
SetCallbackAndLoseForTesting();
ASSERT_NE(result.buffer.GetMappedRange(), nullptr);
ASSERT_EQ(result.buffer.GetMappedRange(), rangeBeforeLoss);
ASSERT_EQ(result.buffer.GetMappedRange(), result.data);
}
// Test it's possible to GetMappedRange on a buffer created mapped after device loss // Test it's possible to GetMappedRange on a buffer created mapped after device loss
TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedAtCreationAfterLoss) { TEST_P(DeviceLostTest, GetMappedRange_CreateBufferMappedAtCreationAfterLoss) {
SetCallbackAndLoseForTesting(); SetCallbackAndLoseForTesting();
@ -422,8 +394,8 @@ TEST_P(DeviceLostTest, GetMappedRange_MapAsyncWriting) {
ASSERT_EQ(buffer.GetConstMappedRange(), rangeBeforeLoss); ASSERT_EQ(buffer.GetConstMappedRange(), rangeBeforeLoss);
} }
// mapreadasync + resolve + loss getmappedrange != nullptr. // TODO mapasync read + resolve + loss getmappedrange != nullptr.
// mapwriteasync + resolve + loss getmappedrange != nullptr. // TODO mapasync write + resolve + loss getmappedrange != nullptr.
// Test that Command Encoder Finish fails when device lost // Test that Command Encoder Finish fails when device lost
TEST_P(DeviceLostTest, CommandEncoderFinishFails) { TEST_P(DeviceLostTest, CommandEncoderFinishFails) {

View File

@ -20,44 +20,6 @@
using namespace testing; using namespace testing;
class MockBufferMapReadCallback {
public:
MOCK_METHOD(void,
Call,
(WGPUBufferMapAsyncStatus status,
const uint32_t* ptr,
uint64_t dataLength,
void* userdata));
};
static std::unique_ptr<MockBufferMapReadCallback> mockBufferMapReadCallback;
static void ToMockBufferMapReadCallback(WGPUBufferMapAsyncStatus status,
const void* ptr,
uint64_t dataLength,
void* userdata) {
// Assume the data is uint32_t to make writing matchers easier
mockBufferMapReadCallback->Call(status, reinterpret_cast<const uint32_t*>(ptr), dataLength,
userdata);
}
class MockBufferMapWriteCallback {
public:
MOCK_METHOD(
void,
Call,
(WGPUBufferMapAsyncStatus status, uint32_t* ptr, uint64_t dataLength, void* userdata));
};
static std::unique_ptr<MockBufferMapWriteCallback> mockBufferMapWriteCallback;
static void ToMockBufferMapWriteCallback(WGPUBufferMapAsyncStatus status,
void* ptr,
uint64_t dataLength,
void* userdata) {
// Assume the data is uint32_t to make writing matchers easier
mockBufferMapWriteCallback->Call(status, reinterpret_cast<uint32_t*>(ptr), dataLength,
userdata);
}
class MockBufferMapAsyncCallback { class MockBufferMapAsyncCallback {
public: public:
MOCK_METHOD(void, Call, (WGPUBufferMapAsyncStatus status, void* userdata)); MOCK_METHOD(void, Call, (WGPUBufferMapAsyncStatus status, void* userdata));
@ -86,14 +48,6 @@ class BufferValidationTest : public ValidationTest {
return device.CreateBuffer(&descriptor); return device.CreateBuffer(&descriptor);
} }
wgpu::CreateBufferMappedResult CreateBufferMapped(uint64_t size, wgpu::BufferUsage usage) {
wgpu::BufferDescriptor descriptor;
descriptor.size = size;
descriptor.usage = usage;
return device.CreateBufferMapped(&descriptor);
}
wgpu::Buffer BufferMappedAtCreation(uint64_t size, wgpu::BufferUsage usage) { wgpu::Buffer BufferMappedAtCreation(uint64_t size, wgpu::BufferUsage usage) {
wgpu::BufferDescriptor descriptor; wgpu::BufferDescriptor descriptor;
descriptor.size = size; descriptor.size = size;
@ -116,16 +70,12 @@ class BufferValidationTest : public ValidationTest {
void SetUp() override { void SetUp() override {
ValidationTest::SetUp(); ValidationTest::SetUp();
mockBufferMapReadCallback = std::make_unique<MockBufferMapReadCallback>();
mockBufferMapWriteCallback = std::make_unique<MockBufferMapWriteCallback>();
mockBufferMapAsyncCallback = std::make_unique<MockBufferMapAsyncCallback>(); mockBufferMapAsyncCallback = std::make_unique<MockBufferMapAsyncCallback>();
queue = device.GetDefaultQueue(); queue = device.GetDefaultQueue();
} }
void TearDown() override { void TearDown() override {
// Delete mocks so that expectations are checked // Delete mocks so that expectations are checked
mockBufferMapReadCallback = nullptr;
mockBufferMapWriteCallback = nullptr;
mockBufferMapAsyncCallback = nullptr; mockBufferMapAsyncCallback = nullptr;
ValidationTest::TearDown(); ValidationTest::TearDown();
@ -488,50 +438,6 @@ TEST_F(BufferValidationTest, MapAsync_DestroyCalledInCallback) {
} }
} }
// Test the success case for mapping buffer for reading
TEST_F(BufferValidationTest, MapReadAsyncSuccess) {
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.Times(1);
WaitForAllOperations(device);
buf.Unmap();
}
// Test the success case for mapping buffer for writing
TEST_F(BufferValidationTest, MapWriteAsyncSuccess) {
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.Times(1);
WaitForAllOperations(device);
buf.Unmap();
}
// Test the success case for CreateBufferMapped
TEST_F(BufferValidationTest, CreateBufferMappedSuccess) {
wgpu::CreateBufferMappedResult result = CreateBufferMapped(4, wgpu::BufferUsage::MapWrite);
ASSERT_NE(result.data, nullptr);
ASSERT_EQ(result.dataLength, 4u);
result.buffer.Unmap();
}
// Test the success case for non-mappable CreateBufferMapped
TEST_F(BufferValidationTest, NonMappableCreateBufferMappedSuccess) {
wgpu::CreateBufferMappedResult result = CreateBufferMapped(4, wgpu::BufferUsage::CopySrc);
ASSERT_NE(result.data, nullptr);
ASSERT_EQ(result.dataLength, 4u);
result.buffer.Unmap();
}
// Test the success case for mappedAtCreation // Test the success case for mappedAtCreation
TEST_F(BufferValidationTest, MappedAtCreationSuccess) { TEST_F(BufferValidationTest, MappedAtCreationSuccess) {
BufferMappedAtCreation(4, wgpu::BufferUsage::MapWrite); BufferMappedAtCreation(4, wgpu::BufferUsage::MapWrite);
@ -547,228 +453,6 @@ TEST_F(BufferValidationTest, MappedAtCreationSizeAlignment) {
ASSERT_DEVICE_ERROR(BufferMappedAtCreation(2, wgpu::BufferUsage::MapWrite)); ASSERT_DEVICE_ERROR(BufferMappedAtCreation(2, wgpu::BufferUsage::MapWrite));
} }
// Test map reading a buffer with wrong current usage
TEST_F(BufferValidationTest, MapReadWrongUsage) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopyDst;
wgpu::Buffer buf = device.CreateBuffer(&descriptor);
EXPECT_CALL(*mockBufferMapReadCallback, Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0u, _))
.Times(1);
ASSERT_DEVICE_ERROR(buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr));
}
// Test map writing a buffer with wrong current usage
TEST_F(BufferValidationTest, MapWriteWrongUsage) {
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopySrc;
wgpu::Buffer buf = device.CreateBuffer(&descriptor);
EXPECT_CALL(*mockBufferMapWriteCallback, Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0u, _))
.Times(1);
ASSERT_DEVICE_ERROR(buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr));
}
// Test map reading a buffer that is already mapped
TEST_F(BufferValidationTest, MapReadAlreadyMapped) {
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, this + 0);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, this + 0))
.Times(1);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0u, this + 1))
.Times(1);
ASSERT_DEVICE_ERROR(buf.MapReadAsync(ToMockBufferMapReadCallback, this + 1));
WaitForAllOperations(device);
}
// Test map writing a buffer that is already mapped
TEST_F(BufferValidationTest, MapWriteAlreadyMapped) {
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, this + 0);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, this + 0))
.Times(1);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0u, this + 1))
.Times(1);
ASSERT_DEVICE_ERROR(buf.MapWriteAsync(ToMockBufferMapWriteCallback, this + 1));
WaitForAllOperations(device);
}
// TODO(cwallez@chromium.org) Test a MapWrite and already MapRead and vice-versa
// Test unmapping before having the result gives UNKNOWN - for reading
TEST_F(BufferValidationTest, MapReadUnmapBeforeResult) {
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
EXPECT_CALL(*mockBufferMapReadCallback, Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u, _))
.Times(1);
buf.Unmap();
// The callback shouldn't be called again.
WaitForAllOperations(device);
}
// Test unmapping before having the result gives UNKNOWN - for writing
TEST_F(BufferValidationTest, MapWriteUnmapBeforeResult) {
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
EXPECT_CALL(*mockBufferMapWriteCallback, Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u, _))
.Times(1);
buf.Unmap();
// The callback shouldn't be called again.
WaitForAllOperations(device);
}
// Test destroying the buffer before having the result gives UNKNOWN - for reading
// TODO(cwallez@chromium.org) currently this doesn't work because the buffer doesn't know
// when its external ref count reaches 0.
TEST_F(BufferValidationTest, DISABLED_MapReadDestroyBeforeResult) {
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u, _))
.Times(1);
}
// The callback shouldn't be called again.
WaitForAllOperations(device);
}
// Test destroying the buffer before having the result gives UNKNOWN - for writing
// TODO(cwallez@chromium.org) currently this doesn't work because the buffer doesn't know
// when its external ref count reaches 0.
TEST_F(BufferValidationTest, DISABLED_MapWriteDestroyBeforeResult) {
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u, _))
.Times(1);
}
// The callback shouldn't be called again.
WaitForAllOperations(device);
}
// When a MapRead is cancelled with Unmap it might still be in flight, test doing a new request
// works as expected and we don't get the cancelled request's data.
TEST_F(BufferValidationTest, MapReadUnmapBeforeResultThenMapAgain) {
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, this + 0);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u, this + 0))
.Times(1);
buf.Unmap();
buf.MapReadAsync(ToMockBufferMapReadCallback, this + 1);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, this + 1))
.Times(1);
WaitForAllOperations(device);
}
// TODO(cwallez@chromium.org) Test a MapWrite and already MapRead and vice-versa
// When a MapWrite is cancelled with Unmap it might still be in flight, test doing a new request
// works as expected and we don't get the cancelled request's data.
TEST_F(BufferValidationTest, MapWriteUnmapBeforeResultThenMapAgain) {
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, this + 0);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0u, this + 0))
.Times(1);
buf.Unmap();
buf.MapWriteAsync(ToMockBufferMapWriteCallback, this + 1);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, this + 1))
.Times(1);
WaitForAllOperations(device);
}
// Test that the MapReadCallback isn't fired twice when unmap() is called inside the callback
TEST_F(BufferValidationTest, UnmapInsideMapReadCallback) {
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.WillOnce(InvokeWithoutArgs([&]() { buf.Unmap(); }));
WaitForAllOperations(device);
}
// Test that the MapWriteCallback isn't fired twice when unmap() is called inside the callback
TEST_F(BufferValidationTest, UnmapInsideMapWriteCallback) {
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.WillOnce(InvokeWithoutArgs([&]() { buf.Unmap(); }));
WaitForAllOperations(device);
}
// Test that the MapReadCallback isn't fired twice the buffer external refcount reaches 0 in the
// callback
TEST_F(BufferValidationTest, DestroyInsideMapReadCallback) {
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.WillOnce(InvokeWithoutArgs([&]() { buf = wgpu::Buffer(); }));
WaitForAllOperations(device);
}
// Test that the MapWriteCallback isn't fired twice the buffer external refcount reaches 0 in the
// callback
TEST_F(BufferValidationTest, DestroyInsideMapWriteCallback) {
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.WillOnce(InvokeWithoutArgs([&]() { buf = wgpu::Buffer(); }));
WaitForAllOperations(device);
}
// Test that it is valid to destroy an unmapped buffer // Test that it is valid to destroy an unmapped buffer
TEST_F(BufferValidationTest, DestroyUnmappedBuffer) { TEST_F(BufferValidationTest, DestroyUnmappedBuffer) {
{ {
@ -781,44 +465,6 @@ TEST_F(BufferValidationTest, DestroyUnmappedBuffer) {
} }
} }
// Test that it is valid to destroy a mapped buffer
TEST_F(BufferValidationTest, DestroyMappedBuffer) {
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
buf.Destroy();
}
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
buf.Destroy();
}
}
// Test that destroying a buffer implicitly unmaps it
TEST_F(BufferValidationTest, DestroyMappedBufferCausesImplicitUnmap) {
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, this + 0);
// Buffer is destroyed. Callback should be called with UNKNOWN status
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0, this + 0))
.Times(1);
buf.Destroy();
WaitForAllOperations(device);
}
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, this + 1);
// Buffer is destroyed. Callback should be called with UNKNOWN status
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0, this + 1))
.Times(1);
buf.Destroy();
WaitForAllOperations(device);
}
}
// Test that it is valid to Destroy a destroyed buffer // Test that it is valid to Destroy a destroyed buffer
TEST_F(BufferValidationTest, DestroyDestroyedBuffer) { TEST_F(BufferValidationTest, DestroyDestroyedBuffer) {
wgpu::Buffer buf = CreateMapWriteBuffer(4); wgpu::Buffer buf = CreateMapWriteBuffer(4);
@ -840,64 +486,6 @@ TEST_F(BufferValidationTest, UnmapDestroyedBuffer) {
} }
} }
// Test that it is invalid to map a destroyed buffer
TEST_F(BufferValidationTest, MapDestroyedBuffer) {
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.Destroy();
ASSERT_DEVICE_ERROR(buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr));
}
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.Destroy();
ASSERT_DEVICE_ERROR(buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr));
}
}
// Test that is is invalid to Map a mapped buffer
TEST_F(BufferValidationTest, MapMappedBuffer) {
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
ASSERT_DEVICE_ERROR(buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr));
WaitForAllOperations(device);
}
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
ASSERT_DEVICE_ERROR(buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr));
WaitForAllOperations(device);
}
}
// Test that is is invalid to Map a CreateBufferMapped buffer
TEST_F(BufferValidationTest, MapCreateBufferMappedBuffer) {
{
wgpu::Buffer buf = CreateBufferMapped(4, wgpu::BufferUsage::MapRead).buffer;
ASSERT_DEVICE_ERROR(buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr));
WaitForAllOperations(device);
}
{
wgpu::Buffer buf = CreateBufferMapped(4, wgpu::BufferUsage::MapWrite).buffer;
ASSERT_DEVICE_ERROR(buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr));
WaitForAllOperations(device);
}
}
// Test that is is invalid to Map a buffer mapped at creation.
TEST_F(BufferValidationTest, MapBufferMappedAtCreation) {
{
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::MapRead);
ASSERT_DEVICE_ERROR(buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr));
WaitForAllOperations(device);
}
{
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::MapWrite);
ASSERT_DEVICE_ERROR(buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr));
WaitForAllOperations(device);
}
}
// Test that it is valid to submit a buffer in a queue with a map usage if it is unmapped // Test that it is valid to submit a buffer in a queue with a map usage if it is unmapped
TEST_F(BufferValidationTest, SubmitBufferWithMapUsage) { TEST_F(BufferValidationTest, SubmitBufferWithMapUsage) {
wgpu::BufferDescriptor descriptorA; wgpu::BufferDescriptor descriptorA;
@ -950,50 +538,6 @@ TEST_F(BufferValidationTest, SubmitMappedBuffer) {
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands)); ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
WaitForAllOperations(device); WaitForAllOperations(device);
} }
{
wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
wgpu::Buffer bufB = device.CreateBuffer(&descriptorB);
bufA.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
WaitForAllOperations(device);
}
{
wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
wgpu::Buffer bufB = device.CreateBuffer(&descriptorB);
bufB.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
WaitForAllOperations(device);
}
{
wgpu::Buffer bufA = device.CreateBufferMapped(&descriptorA).buffer;
wgpu::Buffer bufB = device.CreateBuffer(&descriptorB);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
WaitForAllOperations(device);
}
{
wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
wgpu::Buffer bufB = device.CreateBufferMapped(&descriptorB).buffer;
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
WaitForAllOperations(device);
}
{ {
wgpu::BufferDescriptor mappedBufferDesc = descriptorA; wgpu::BufferDescriptor mappedBufferDesc = descriptorA;
mappedBufferDesc.mappedAtCreation = true; mappedBufferDesc.mappedAtCreation = true;
@ -1052,24 +596,6 @@ TEST_F(BufferValidationTest, UnmapWithoutMapUsage) {
// Test that it is valid to call Unmap on a buffer that is not mapped // Test that it is valid to call Unmap on a buffer that is not mapped
TEST_F(BufferValidationTest, UnmapUnmappedBuffer) { TEST_F(BufferValidationTest, UnmapUnmappedBuffer) {
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
// Buffer starts unmapped. Unmap should succeed.
buf.Unmap();
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
buf.Unmap();
// Unmapping twice should succeed
buf.Unmap();
}
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
// Buffer starts unmapped. Unmap should succeed.
buf.Unmap();
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
// Unmapping twice should succeed
buf.Unmap();
buf.Unmap();
}
{ {
wgpu::Buffer buf = CreateMapReadBuffer(4); wgpu::Buffer buf = CreateMapReadBuffer(4);
// Buffer starts unmapped. Unmap should succeed. // Buffer starts unmapped. Unmap should succeed.
@ -1103,15 +629,6 @@ TEST_F(BufferValidationTest, GetMappedRange_OnUnmappedBuffer) {
ASSERT_EQ(nullptr, buf.GetConstMappedRange()); ASSERT_EQ(nullptr, buf.GetConstMappedRange());
} }
// Unmapped after CreateBufferMapped case.
{
wgpu::Buffer buf = CreateBufferMapped(4, wgpu::BufferUsage::CopySrc).buffer;
buf.Unmap();
ASSERT_EQ(nullptr, buf.GetMappedRange());
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Unmapped after mappedAtCreation case. // Unmapped after mappedAtCreation case.
{ {
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc); wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
@ -1121,34 +638,6 @@ TEST_F(BufferValidationTest, GetMappedRange_OnUnmappedBuffer) {
ASSERT_EQ(nullptr, buf.GetConstMappedRange()); ASSERT_EQ(nullptr, buf.GetConstMappedRange());
} }
// Unmapped after MapReadAsync case.
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.Times(1);
WaitForAllOperations(device);
buf.Unmap();
ASSERT_EQ(nullptr, buf.GetMappedRange());
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Unmapped after MapWriteAsync case.
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.Times(1);
WaitForAllOperations(device);
buf.Unmap();
ASSERT_EQ(nullptr, buf.GetMappedRange());
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Unmapped after MapAsync read case. // Unmapped after MapAsync read case.
{ {
wgpu::Buffer buf = CreateMapReadBuffer(4); wgpu::Buffer buf = CreateMapReadBuffer(4);
@ -1191,15 +680,6 @@ TEST_F(BufferValidationTest, GetMappedRange_OnDestroyedBuffer) {
ASSERT_EQ(nullptr, buf.GetConstMappedRange()); ASSERT_EQ(nullptr, buf.GetConstMappedRange());
} }
// Destroyed after CreateBufferMapped case.
{
wgpu::Buffer buf = CreateBufferMapped(4, wgpu::BufferUsage::CopySrc).buffer;
buf.Destroy();
ASSERT_EQ(nullptr, buf.GetMappedRange());
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Destroyed after mappedAtCreation case. // Destroyed after mappedAtCreation case.
{ {
wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc); wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
@ -1209,34 +689,6 @@ TEST_F(BufferValidationTest, GetMappedRange_OnDestroyedBuffer) {
ASSERT_EQ(nullptr, buf.GetConstMappedRange()); ASSERT_EQ(nullptr, buf.GetConstMappedRange());
} }
// Destroyed after MapReadAsync case.
{
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapReadAsync(ToMockBufferMapReadCallback, nullptr);
EXPECT_CALL(*mockBufferMapReadCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.Times(1);
WaitForAllOperations(device);
buf.Destroy();
ASSERT_EQ(nullptr, buf.GetMappedRange());
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Destroyed after MapWriteAsync case.
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapWriteAsync(ToMockBufferMapWriteCallback, nullptr);
EXPECT_CALL(*mockBufferMapWriteCallback,
Call(WGPUBufferMapAsyncStatus_Success, Ne(nullptr), 4u, _))
.Times(1);
WaitForAllOperations(device);
buf.Destroy();
ASSERT_EQ(nullptr, buf.GetMappedRange());
ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}
// Destroyed after MapAsync read case. // Destroyed after MapAsync read case.
{ {
wgpu::Buffer buf = CreateMapReadBuffer(4); wgpu::Buffer buf = CreateMapReadBuffer(4);
@ -1278,14 +730,6 @@ TEST_F(BufferValidationTest, GetMappedRange_NonConstOnMappedForReading) {
// Test valid cases to call GetMappedRange on a buffer. // Test valid cases to call GetMappedRange on a buffer.
TEST_F(BufferValidationTest, GetMappedRange_ValidBufferStateCases) { TEST_F(BufferValidationTest, GetMappedRange_ValidBufferStateCases) {
// GetMappedRange after CreateBufferMapped case.
{
wgpu::CreateBufferMappedResult result = CreateBufferMapped(4, wgpu::BufferUsage::CopySrc);
ASSERT_NE(result.buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.buffer.GetMappedRange());
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.data);
}
// GetMappedRange after mappedAtCreation case. // GetMappedRange after mappedAtCreation case.
{ {
wgpu::Buffer buffer = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc); wgpu::Buffer buffer = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
@ -1323,41 +767,6 @@ TEST_F(BufferValidationTest, GetMappedRange_OnErrorBuffer) {
uint64_t kStupidLarge = uint64_t(1) << uint64_t(63); uint64_t kStupidLarge = uint64_t(1) << uint64_t(63);
// GetMappedRange after CreateBufferMapped a zero-sized buffer returns a non-nullptr.
// This is to check we don't do a malloc(0).
{
wgpu::CreateBufferMappedResult result;
ASSERT_DEVICE_ERROR(result = CreateBufferMapped(
0, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead));
ASSERT_NE(result.buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.buffer.GetMappedRange());
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.data);
}
// GetMappedRange after CreateBufferMapped non-OOM returns a non-nullptr.
{
wgpu::CreateBufferMappedResult result;
ASSERT_DEVICE_ERROR(result = CreateBufferMapped(
4, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead));
ASSERT_NE(result.buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.buffer.GetMappedRange());
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.data);
}
// GetMappedRange after CreateBufferMapped OOM case returns nullptr.
{
wgpu::CreateBufferMappedResult result;
ASSERT_DEVICE_ERROR(result =
CreateBufferMapped(kStupidLarge, wgpu::BufferUsage::Storage |
wgpu::BufferUsage::MapRead));
ASSERT_EQ(result.buffer.GetConstMappedRange(), nullptr);
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.buffer.GetMappedRange());
ASSERT_EQ(result.buffer.GetConstMappedRange(), result.data);
}
// GetMappedRange after mappedAtCreation a zero-sized buffer returns a non-nullptr. // GetMappedRange after mappedAtCreation a zero-sized buffer returns a non-nullptr.
// This is to check we don't do a malloc(0). // This is to check we don't do a malloc(0).
{ {

View File

@ -165,17 +165,6 @@ namespace {
// Test WriteBuffer with mapped buffer // Test WriteBuffer with mapped buffer
TEST_F(QueueWriteBufferValidationTest, MappedBuffer) { TEST_F(QueueWriteBufferValidationTest, MappedBuffer) {
// CreateBufferMapped
{
wgpu::BufferDescriptor descriptor;
descriptor.size = 4;
descriptor.usage = wgpu::BufferUsage::CopyDst;
wgpu::CreateBufferMappedResult result = device.CreateBufferMapped(&descriptor);
uint32_t value = 0;
ASSERT_DEVICE_ERROR(queue.WriteBuffer(result.buffer, 0, &value, sizeof(value)));
}
// mappedAtCreation // mappedAtCreation
{ {
wgpu::BufferDescriptor descriptor; wgpu::BufferDescriptor descriptor;

View File

@ -87,8 +87,6 @@ class D3D12ResidencyTestBase : public DawnTest {
} }
wgpu::Buffer mSourceBuffer; wgpu::Buffer mSourceBuffer;
void* mMappedWriteData = nullptr;
const void* mMappedReadData = nullptr;
}; };
class D3D12ResourceResidencyTests : public D3D12ResidencyTestBase { class D3D12ResourceResidencyTests : public D3D12ResidencyTestBase {
@ -109,26 +107,6 @@ class D3D12ResourceResidencyTests : public D3D12ResidencyTestBase {
bool IsUMA() const { bool IsUMA() const {
return reinterpret_cast<dawn_native::d3d12::Device*>(device.Get())->GetDeviceInfo().isUMA; return reinterpret_cast<dawn_native::d3d12::Device*>(device.Get())->GetDeviceInfo().isUMA;
} }
static void MapReadCallback(WGPUBufferMapAsyncStatus status,
const void* data,
uint64_t,
void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
ASSERT_NE(nullptr, data);
static_cast<D3D12ResourceResidencyTests*>(userdata)->mMappedReadData = data;
}
static void MapWriteCallback(WGPUBufferMapAsyncStatus status,
void* data,
uint64_t,
void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
ASSERT_NE(nullptr, data);
static_cast<D3D12ResourceResidencyTests*>(userdata)->mMappedWriteData = data;
}
}; };
class D3D12DescriptorResidencyTests : public D3D12ResidencyTestBase {}; class D3D12DescriptorResidencyTests : public D3D12ResidencyTestBase {};
@ -211,7 +189,7 @@ TEST_P(D3D12ResourceResidencyTests, OvercommitLargeResources) {
EXPECT_FALSE(CheckIfBufferIsResident(bufferSet1[indexOfBufferInSet1])); EXPECT_FALSE(CheckIfBufferIsResident(bufferSet1[indexOfBufferInSet1]));
} }
// Check that calling MapReadAsync makes the buffer resident and keeps it locked resident. // Check that calling MapAsync for reading makes the buffer resident and keeps it locked resident.
TEST_P(D3D12ResourceResidencyTests, AsyncMappedBufferRead) { TEST_P(D3D12ResourceResidencyTests, AsyncMappedBufferRead) {
// Create a mappable buffer. // Create a mappable buffer.
wgpu::Buffer buffer = CreateBuffer(4, kMapReadBufferUsage); wgpu::Buffer buffer = CreateBuffer(4, kMapReadBufferUsage);
@ -231,11 +209,18 @@ TEST_P(D3D12ResourceResidencyTests, AsyncMappedBufferRead) {
// The mappable buffer should have been evicted. // The mappable buffer should have been evicted.
EXPECT_FALSE(CheckIfBufferIsResident(buffer)); EXPECT_FALSE(CheckIfBufferIsResident(buffer));
// Calling MapReadAsync should make the buffer resident. // Calling MapAsync for reading should make the buffer resident.
buffer.MapReadAsync(MapReadCallback, this); bool done = false;
buffer.MapAsync(
wgpu::MapMode::Read, 0, sizeof(uint32_t),
[](WGPUBufferMapAsyncStatus status, void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
*static_cast<bool*>(userdata) = true;
},
&done);
EXPECT_TRUE(CheckIfBufferIsResident(buffer)); EXPECT_TRUE(CheckIfBufferIsResident(buffer));
while (mMappedReadData == nullptr) { while (!done) {
WaitABit(); WaitABit();
} }
@ -254,7 +239,7 @@ TEST_P(D3D12ResourceResidencyTests, AsyncMappedBufferRead) {
EXPECT_FALSE(CheckIfBufferIsResident(buffer)); EXPECT_FALSE(CheckIfBufferIsResident(buffer));
} }
// Check that calling MapWriteAsync makes the buffer resident and keeps it locked resident. // Check that calling MapAsync for writing makes the buffer resident and keeps it locked resident.
TEST_P(D3D12ResourceResidencyTests, AsyncMappedBufferWrite) { TEST_P(D3D12ResourceResidencyTests, AsyncMappedBufferWrite) {
// Create a mappable buffer. // Create a mappable buffer.
wgpu::Buffer buffer = CreateBuffer(4, kMapWriteBufferUsage); wgpu::Buffer buffer = CreateBuffer(4, kMapWriteBufferUsage);
@ -270,11 +255,18 @@ TEST_P(D3D12ResourceResidencyTests, AsyncMappedBufferWrite) {
// The mappable buffer should have been evicted. // The mappable buffer should have been evicted.
EXPECT_FALSE(CheckIfBufferIsResident(buffer)); EXPECT_FALSE(CheckIfBufferIsResident(buffer));
// Calling MapWriteAsync should make the buffer resident. // Calling MapAsync for writing should make the buffer resident.
buffer.MapWriteAsync(MapWriteCallback, this); bool done = false;
buffer.MapAsync(
wgpu::MapMode::Write, 0, sizeof(uint32_t),
[](WGPUBufferMapAsyncStatus status, void* userdata) {
ASSERT_EQ(WGPUBufferMapAsyncStatus_Success, status);
*static_cast<bool*>(userdata) = true;
},
&done);
EXPECT_TRUE(CheckIfBufferIsResident(buffer)); EXPECT_TRUE(CheckIfBufferIsResident(buffer));
while (mMappedWriteData == nullptr) { while (!done) {
WaitABit(); WaitABit();
} }