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:
parent
d720785616
commit
f7123d7463
47
dawn.json
47
dawn.json
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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**
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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).
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue