[dawn][wire] Make FillReservation release WGPU objects if released.
- Refactors code a bit to use templating in some places so we can
use the types to choose accessors instead of via generator.
- Introduces WGPUTraits in server side to allow for any other future
traits we may find useful to include.
- Fixes failing fuzzer case where we allocate an object, then release
it before it is filled, causing a crash on FillReservation call.
Bug: b:334279466
Change-Id: Iaa26df7185cad27c214d5c1ff3e1b468f3c3fbdf
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/184460
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index d37e34f..e605181 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -1268,6 +1268,11 @@
'dawn/wire/server/ServerPrototypes.inc',
'src/dawn/wire/server/ServerPrototypes_autogen.inc',
wire_params))
+ renders.append(
+ FileRender('dawn/wire/server/WGPUTraits.h',
+ 'src/dawn/wire/server/WGPUTraits_autogen.h',
+ wire_params))
+
if 'dawn_lpmfuzz_proto' in targets:
params_dawn_wire = parse_json(loaded_json,
diff --git a/generator/templates/dawn/wire/ObjectType.h b/generator/templates/dawn/wire/ObjectType.h
index 5f53956..9eeab87 100644
--- a/generator/templates/dawn/wire/ObjectType.h
+++ b/generator/templates/dawn/wire/ObjectType.h
@@ -25,8 +25,8 @@
//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#ifndef DAWNWIRE_OBJECTTPYE_AUTOGEN_H_
-#define DAWNWIRE_OBJECTTPYE_AUTOGEN_H_
+#ifndef DAWNWIRE_OBJECTTYPE_AUTOGEN_H_
+#define DAWNWIRE_OBJECTTYPE_AUTOGEN_H_
#include "dawn/common/ityp_array.h"
@@ -46,4 +46,4 @@
} // namespace dawn::wire
-#endif // DAWNWIRE_OBJECTTPYE_AUTOGEN_H_
+#endif // DAWNWIRE_OBJECTTYPE_AUTOGEN_H_
diff --git a/generator/templates/dawn/wire/server/ServerBase.h b/generator/templates/dawn/wire/server/ServerBase.h
index 8ca45e0..54f2062 100644
--- a/generator/templates/dawn/wire/server/ServerBase.h
+++ b/generator/templates/dawn/wire/server/ServerBase.h
@@ -25,8 +25,10 @@
//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#ifndef DAWNWIRE_SERVER_SERVERBASE_H_
-#define DAWNWIRE_SERVER_SERVERBASE_H_
+#ifndef DAWNWIRE_SERVER_SERVERBASE_AUTOGEN_H_
+#define DAWNWIRE_SERVER_SERVERBASE_AUTOGEN_H_
+
+#include <tuple>
#include "dawn/dawn_proc_table.h"
#include "dawn/wire/ChunkedCommandHandler.h"
@@ -34,6 +36,7 @@
#include "dawn/wire/WireCmd_autogen.h"
#include "dawn/wire/WireDeserializeAllocator.h"
#include "dawn/wire/server/ObjectStorage.h"
+#include "dawn/wire/server/WGPUTraits_autogen.h"
namespace dawn::wire::server {
@@ -43,57 +46,65 @@
~ServerBase() override = default;
protected:
+ template <typename T>
+ const KnownObjects<T>& Objects() const {
+ return std::get<KnownObjects<T>>(mKnown);
+ }
+ template <typename T>
+ KnownObjects<T>& Objects() {
+ return std::get<KnownObjects<T>>(mKnown);
+ }
+
+ template <typename T>
+ void Release(const DawnProcTable& procs, T handle) {
+ (procs.*WGPUTraits<T>::Release)(handle);
+ }
+
void DestroyAllObjects(const DawnProcTable& procs) {
//* Release devices first to force completion of any async work.
{
- std::vector<WGPUDevice> handles = mKnownDevice.AcquireAllHandles();
+ std::vector<WGPUDevice> handles = Objects<WGPUDevice>().AcquireAllHandles();
for (WGPUDevice handle : handles) {
- procs.deviceRelease(handle);
+ Release(procs, handle);
}
}
//* Free all objects when the server is destroyed
{% for type in by_category["object"] if type.name.get() != "device" %}
+ {% set cType = as_cType(type.name) %}
{
- std::vector<{{as_cType(type.name)}}> handles = mKnown{{type.name.CamelCase()}}.AcquireAllHandles();
- for ({{as_cType(type.name)}} handle : handles) {
- procs.{{as_varName(type.name, Name("release"))}}(handle);
+ std::vector<{{cType}}> handles = Objects<{{cType}}>().AcquireAllHandles();
+ for ({{cType}} handle : handles) {
+ Release(procs, handle);
}
}
{% endfor %}
}
- {% for type in by_category["object"] %}
- const KnownObjects<{{as_cType(type.name)}}>& {{type.name.CamelCase()}}Objects() const {
- return mKnown{{type.name.CamelCase()}};
- }
- KnownObjects<{{as_cType(type.name)}}>& {{type.name.CamelCase()}}Objects() {
- return mKnown{{type.name.CamelCase()}};
- }
- {% endfor %}
-
private:
// Implementation of the ObjectIdResolver interface
{% for type in by_category["object"] %}
- WireResult GetFromId(ObjectId id, {{as_cType(type.name)}}* out) const final {
- return mKnown{{type.name.CamelCase()}}.GetNativeHandle(id, out);
+ {% set cType = as_cType(type.name) %}
+ WireResult GetFromId(ObjectId id, {{cType}}* out) const final {
+ return Objects<{{cType}}>().GetNativeHandle(id, out);
}
- WireResult GetOptionalFromId(ObjectId id, {{as_cType(type.name)}}* out) const final {
+ WireResult GetOptionalFromId(ObjectId id, {{cType}}* out) const final {
if (id == 0) {
*out = nullptr;
return WireResult::Success;
}
-
return GetFromId(id, out);
}
{% endfor %}
//* The list of known IDs for each object type.
- {% for type in by_category["object"] %}
- KnownObjects<{{as_cType(type.name)}}> mKnown{{type.name.CamelCase()}};
- {% endfor %}
+ std::tuple<
+ {% for type in by_category["object"] %}
+ KnownObjects<{{as_cType(type.name)}}>{{ ", " if not loop.last else "" }}
+ {% endfor %}
+ > mKnown;
};
} // namespace dawn::wire::server
-#endif // DAWNWIRE_SERVER_SERVERBASE_H_
+#endif // DAWNWIRE_SERVER_SERVERBASE_AUTOGEN_H_
diff --git a/generator/templates/dawn/wire/server/ServerDoers.cpp b/generator/templates/dawn/wire/server/ServerDoers.cpp
index 8f05ea4..d67795b 100644
--- a/generator/templates/dawn/wire/server/ServerDoers.cpp
+++ b/generator/templates/dawn/wire/server/ServerDoers.cpp
@@ -80,9 +80,10 @@
WireResult Server::DoDestroyObject(ObjectType objectType, ObjectId objectId) {
switch(objectType) {
{% for type in by_category["object"] %}
+ {% set cType = as_cType(type.name) %}
case ObjectType::{{type.name.CamelCase()}}: {
- Reserved<WGPU{{type.name.CamelCase()}}> obj;
- WIRE_TRY({{type.name.CamelCase()}}Objects().Get(objectId, &obj));
+ Reserved<{{cType}}> obj;
+ WIRE_TRY(Objects<{{cType}}>().Get(objectId, &obj));
if (obj->state == AllocationState::Allocated) {
DAWN_ASSERT(obj->handle != nullptr);
@@ -91,9 +92,9 @@
//* they should not be forwarded if the device no longer exists on the wire.
ClearDeviceCallbacks(obj->handle);
{% endif %}
- mProcs.{{as_varName(type.name, Name("release"))}}(obj->handle);
+ Release(mProcs, obj->handle);
}
- {{type.name.CamelCase()}}Objects().Free(objectId);
+ Objects<{{cType}}>().Free(objectId);
return WireResult::Success;
}
{% endfor %}
diff --git a/generator/templates/dawn/wire/server/ServerHandlers.cpp b/generator/templates/dawn/wire/server/ServerHandlers.cpp
index 7b8110b..0b788f7 100644
--- a/generator/templates/dawn/wire/server/ServerHandlers.cpp
+++ b/generator/templates/dawn/wire/server/ServerHandlers.cpp
@@ -50,18 +50,19 @@
//* Allocate any result objects
{% for member in command.members if member.is_return_value -%}
{{ assert(member.handle_type) }}
- {% set Type = member.handle_type.name.CamelCase() %}
+ {% set cType = as_cType(member.handle_type.name) %}
{% set name = as_varName(member.name) %}
- Reserved<WGPU{{Type}}> {{name}}Data;
- WIRE_TRY({{Type}}Objects().Allocate(&{{name}}Data, cmd.{{name}}));
+ Reserved<{{cType}}> {{name}}Data;
+ WIRE_TRY(Objects<{{cType}}>().Allocate(&{{name}}Data, cmd.{{name}}));
{{name}}Data->generation = cmd.{{name}}.generation;
{%- endfor %}
//* Get any input objects
{% for member in command.members if member.id_type != None -%}
+ {% set cType = as_cType(member.id_type.name) %}
{% set name = as_varName(member.name) %}
- Known<WGPU{{member.id_type.name.CamelCase()}}> {{name}}Handle;
- WIRE_TRY({{member.id_type.name.CamelCase()}}Objects().Get(cmd.{{name}}, &{{name}}Handle));
+ Known<{{cType}}> {{name}}Handle;
+ WIRE_TRY(Objects<{{cType}}>().Get(cmd.{{name}}, &{{name}}Handle));
{% endfor %}
//* Do command
@@ -123,7 +124,7 @@
// After the server handles all the commands from the stream, we additionally run
// ProcessEvents on all known Instances so that any work done on the server side can be
// forwarded through to the client.
- for (auto instance : InstanceObjects().GetAllHandles()) {
+ for (auto instance : Objects<WGPUInstance>().GetAllHandles()) {
if (DoInstanceProcessEvents(instance) != WireResult::Success) {
return nullptr;
}
diff --git a/generator/templates/dawn/wire/server/WGPUTraits.h b/generator/templates/dawn/wire/server/WGPUTraits.h
new file mode 100644
index 0000000..c404caf
--- /dev/null
+++ b/generator/templates/dawn/wire/server/WGPUTraits.h
@@ -0,0 +1,48 @@
+//* Copyright 2024 The Dawn & Tint Authors
+//*
+//* Redistribution and use in source and binary forms, with or without
+//* modification, are permitted provided that the following conditions are met:
+//*
+//* 1. Redistributions of source code must retain the above copyright notice, this
+//* list of conditions and the following disclaimer.
+//*
+//* 2. Redistributions in binary form must reproduce the above copyright notice,
+//* this list of conditions and the following disclaimer in the documentation
+//* and/or other materials provided with the distribution.
+//*
+//* 3. Neither the name of the copyright holder nor the names of its
+//* contributors may be used to endorse or promote products derived from
+//* this software without specific prior written permission.
+//*
+//* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+//* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+//* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+//* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+//* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+//* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef DAWNWIRE_SERVER_WGPUTRAITS_AUTOGEN_H_
+#define DAWNWIRE_SERVER_WGPUTRAITS_AUTOGEN_H_
+
+#include "dawn/dawn_proc_table.h"
+
+namespace dawn::wire::server {
+
+template <typename T>
+struct WGPUTraits;
+
+{% for type in by_category["object"] %}
+ {% set cType = as_cType(type.name) %}
+ template <>
+ struct WGPUTraits<{{cType}}> {
+ static constexpr auto Release = &DawnProcTable::{{as_varName(type.name, Name("release"))}};
+ };
+{% endfor %}
+
+} // namespace dawn::wire::server
+
+#endif // DAWNWIRE_SERVER_WGPUTRAITS_AUTOGEN_H_
diff --git a/src/dawn/wire/BUILD.gn b/src/dawn/wire/BUILD.gn
index b46b246..a915ec9 100644
--- a/src/dawn/wire/BUILD.gn
+++ b/src/dawn/wire/BUILD.gn
@@ -58,6 +58,7 @@
"src/dawn/wire/server/ServerDoers_autogen.cpp",
"src/dawn/wire/server/ServerHandlers_autogen.cpp",
"src/dawn/wire/server/ServerPrototypes_autogen.inc",
+ "src/dawn/wire/server/WGPUTraits_autogen.h",
]
}
diff --git a/src/dawn/wire/client/Adapter.cpp b/src/dawn/wire/client/Adapter.cpp
index fffeaf4..846fc86 100644
--- a/src/dawn/wire/client/Adapter.cpp
+++ b/src/dawn/wire/client/Adapter.cpp
@@ -69,23 +69,21 @@
private:
void CompleteImpl(FutureID futureID, EventCompletionType completionType) override {
- Device* device = mDevice.ExtractAsDangling();
if (completionType == EventCompletionType::Shutdown) {
mStatus = WGPURequestDeviceStatus_InstanceDropped;
mMessage = "A valid external Instance reference no longer exists.";
}
+
+ Device* device = mDevice.ExtractAsDangling();
if (mCallback) {
- Device* outputDevice = device;
- if (mStatus != WGPURequestDeviceStatus_Success) {
- outputDevice = nullptr;
- }
- mCallback(mStatus, ToAPI(outputDevice), mMessage ? mMessage->c_str() : nullptr,
- mUserdata.ExtractAsDangling());
+ // Callback needs to happen before device lost handling to ensure resolution order.
+ mCallback(mStatus, ToAPI(mStatus == WGPURequestDeviceStatus_Success ? device : nullptr),
+ mMessage ? mMessage->c_str() : nullptr, mUserdata.ExtractAsDangling());
}
if (mStatus != WGPURequestDeviceStatus_Success) {
- // If there was an error, we may need to call the device lost callback and reclaim the
- // device allocation, otherwise the device is returned to the user who owns it.
+ // If there was an error and we didn't return a device, we need to call the device lost
+ // callback and reclaim the device allocation.
if (mStatus == WGPURequestDeviceStatus_InstanceDropped) {
device->HandleDeviceLost(WGPUDeviceLostReason_InstanceDropped,
"A valid external Instance reference no longer exists.");
@@ -93,9 +91,12 @@
device->HandleDeviceLost(WGPUDeviceLostReason_FailedCreation,
"Device failed at creation.");
}
+ }
+
+ if (mCallback == nullptr) {
+ // If there's no callback, clean up the resources.
device->Release();
- } else if (!mCallback) {
- device->Release();
+ mUserdata.ExtractAsDangling();
}
}
diff --git a/src/dawn/wire/client/Client.h b/src/dawn/wire/client/Client.h
index 0d57c02..0140680 100644
--- a/src/dawn/wire/client/Client.h
+++ b/src/dawn/wire/client/Client.h
@@ -71,10 +71,6 @@
return object;
}
- template <typename T>
- void Free(T* obj) {
- Free(obj, ObjectTypeToTypeEnum<T>);
- }
void Free(ObjectBase* obj, ObjectType type);
template <typename T>
@@ -115,6 +111,11 @@
private:
void DestroyAllObjects();
+ template <typename T>
+ void Free(T* obj) {
+ Free(obj, ObjectTypeToTypeEnum<T>);
+ }
+
#include "dawn/wire/client/ClientPrototypes_autogen.inc"
ChunkedCommandSerializer mSerializer;
diff --git a/src/dawn/wire/client/Device.cpp b/src/dawn/wire/client/Device.cpp
index 47b909c..459d7a2 100644
--- a/src/dawn/wire/client/Device.cpp
+++ b/src/dawn/wire/client/Device.cpp
@@ -122,25 +122,22 @@
private:
void CompleteImpl(FutureID futureID, EventCompletionType completionType) override {
+ if (mCallback == nullptr) {
+ // If there's no callback, just clean up the resources.
+ mPipeline.ExtractAsDangling()->Release();
+ mUserdata.ExtractAsDangling();
+ return;
+ }
+
if (completionType == EventCompletionType::Shutdown) {
mStatus = WGPUCreatePipelineAsyncStatus_InstanceDropped;
mMessage = "A valid external Instance reference no longer exists.";
}
- // By default, we are initialized to a success state, and on shutdown we just return success
- // so we don't need to handle it specifically.
Pipeline* pipeline = mPipeline.ExtractAsDangling();
- if (mStatus != WGPUCreatePipelineAsyncStatus_Success) {
- // If there was an error we need to reclaim the pipeline allocation.
- pipeline->GetClient()->Free(pipeline);
- pipeline = nullptr;
- }
- if (mCallback) {
- mCallback(mStatus, ToAPI(pipeline), mMessage ? mMessage->c_str() : nullptr,
- mUserdata.ExtractAsDangling());
- } else if (pipeline != nullptr) {
- pipeline->Release();
- }
+ mCallback(mStatus,
+ ToAPI(mStatus == WGPUCreatePipelineAsyncStatus_Success ? pipeline : nullptr),
+ mMessage ? mMessage->c_str() : nullptr, mUserdata.ExtractAsDangling());
}
using Callback = decltype(std::declval<CallbackInfo>().callback);
diff --git a/src/dawn/wire/client/Instance.cpp b/src/dawn/wire/client/Instance.cpp
index 7b5b05a..19bdf82 100644
--- a/src/dawn/wire/client/Instance.cpp
+++ b/src/dawn/wire/client/Instance.cpp
@@ -76,23 +76,21 @@
private:
void CompleteImpl(FutureID futureID, EventCompletionType completionType) override {
+ if (mCallback == nullptr) {
+ // If there's no callback, just clean up the resources.
+ mAdapter.ExtractAsDangling()->Release();
+ mUserdata.ExtractAsDangling();
+ return;
+ }
+
if (completionType == EventCompletionType::Shutdown) {
mStatus = WGPURequestAdapterStatus_InstanceDropped;
mMessage = "A valid external Instance reference no longer exists.";
}
+
Adapter* adapter = mAdapter.ExtractAsDangling();
- if (mStatus != WGPURequestAdapterStatus_Success && adapter != nullptr) {
- // If there was an error, we may need to reclaim the adapter allocation, otherwise the
- // adapter is returned to the user who owns it.
- adapter->GetClient()->Free(adapter);
- adapter = nullptr;
- }
- if (mCallback) {
- mCallback(mStatus, ToAPI(adapter), mMessage ? mMessage->c_str() : nullptr,
- mUserdata.ExtractAsDangling());
- } else if (adapter != nullptr) {
- adapter->Release();
- }
+ mCallback(mStatus, ToAPI(mStatus == WGPURequestAdapterStatus_Success ? adapter : nullptr),
+ mMessage ? mMessage->c_str() : nullptr, mUserdata.ExtractAsDangling());
}
WGPURequestAdapterCallback mCallback;
diff --git a/src/dawn/wire/server/ObjectStorage.h b/src/dawn/wire/server/ObjectStorage.h
index 5ad842a..9074dc1 100644
--- a/src/dawn/wire/server/ObjectStorage.h
+++ b/src/dawn/wire/server/ObjectStorage.h
@@ -194,13 +194,19 @@
return WireResult::Success;
}
- Known<T> FillReservation(ObjectId id, T handle) {
+ WireResult FillReservation(ObjectId id, T handle, Known<T>* known = nullptr) {
DAWN_ASSERT(id < mKnown.size());
Data* data = &mKnown[id];
- DAWN_ASSERT(data->state == AllocationState::Reserved);
+
+ if (data->state != AllocationState::Reserved) {
+ return WireResult::FatalError;
+ }
data->handle = handle;
data->state = AllocationState::Allocated;
- return {id, data};
+ if (known != nullptr) {
+ *known = {id, data};
+ }
+ return WireResult::Success;
}
// Allocates the data for a given ID and returns it in result.
@@ -292,9 +298,11 @@
return WireResult::Success;
}
- Known<WGPUDevice> FillReservation(ObjectId id, WGPUDevice handle) {
- Known<WGPUDevice> result = KnownObjectsBase<WGPUDevice>::FillReservation(id, handle);
- mKnownSet.insert(result->handle);
+ WireResult FillReservation(ObjectId id, WGPUDevice handle, Known<WGPUDevice>* known = nullptr) {
+ auto result = KnownObjectsBase<WGPUDevice>::FillReservation(id, handle, known);
+ if (result == WireResult::Success) {
+ mKnownSet.insert((*known)->handle);
+ }
return result;
}
diff --git a/src/dawn/wire/server/Server.cpp b/src/dawn/wire/server/Server.cpp
index f7c0a26..c835a3f 100644
--- a/src/dawn/wire/server/Server.cpp
+++ b/src/dawn/wire/server/Server.cpp
@@ -55,7 +55,7 @@
Server::~Server() {
// Un-set the error and lost callbacks since we cannot forward them
// after the server has been destroyed.
- for (WGPUDevice device : DeviceObjects().GetAllHandles()) {
+ for (WGPUDevice device : Objects<WGPUDevice>().GetAllHandles()) {
ClearDeviceCallbacks(device);
}
DestroyAllObjects(mProcs);
@@ -66,13 +66,13 @@
const Handle& deviceHandle) {
DAWN_ASSERT(texture != nullptr);
Known<WGPUDevice> device;
- WIRE_TRY(DeviceObjects().Get(deviceHandle.id, &device));
+ WIRE_TRY(Objects<WGPUDevice>().Get(deviceHandle.id, &device));
if (device->generation != deviceHandle.generation) {
return WireResult::FatalError;
}
Reserved<WGPUTexture> data;
- WIRE_TRY(TextureObjects().Allocate(&data, handle));
+ WIRE_TRY(Objects<WGPUTexture>().Allocate(&data, handle));
data->handle = texture;
data->generation = handle.generation;
@@ -90,13 +90,13 @@
const Handle& deviceHandle) {
DAWN_ASSERT(swapchain != nullptr);
Known<WGPUDevice> device;
- WIRE_TRY(DeviceObjects().Get(deviceHandle.id, &device));
+ WIRE_TRY(Objects<WGPUDevice>().Get(deviceHandle.id, &device));
if (device->generation != deviceHandle.generation) {
return WireResult::FatalError;
}
Reserved<WGPUSwapChain> data;
- WIRE_TRY(SwapChainObjects().Allocate(&data, handle));
+ WIRE_TRY(Objects<WGPUSwapChain>().Allocate(&data, handle));
data->handle = swapchain;
data->generation = handle.generation;
@@ -112,7 +112,7 @@
WireResult Server::InjectInstance(WGPUInstance instance, const Handle& handle) {
DAWN_ASSERT(instance != nullptr);
Reserved<WGPUInstance> data;
- WIRE_TRY(InstanceObjects().Allocate(&data, handle));
+ WIRE_TRY(Objects<WGPUInstance>().Allocate(&data, handle));
data->handle = instance;
data->generation = handle.generation;
@@ -127,7 +127,7 @@
WGPUDevice Server::GetDevice(uint32_t id, uint32_t generation) {
Known<WGPUDevice> device;
- if (DeviceObjects().Get(id, &device) != WireResult::Success ||
+ if (Objects<WGPUDevice>().Get(id, &device) != WireResult::Success ||
device->generation != generation) {
return nullptr;
}
@@ -135,7 +135,7 @@
}
bool Server::IsDeviceKnown(WGPUDevice device) const {
- return DeviceObjects().IsKnown(device);
+ return Objects<WGPUDevice>().IsKnown(device);
}
void Server::SetForwardingDeviceCallbacks(Known<WGPUDevice> device) {
diff --git a/src/dawn/wire/server/Server.h b/src/dawn/wire/server/Server.h
index f908b3d..ba1b07f 100644
--- a/src/dawn/wire/server/Server.h
+++ b/src/dawn/wire/server/Server.h
@@ -210,6 +210,15 @@
mSerializer->SerializeCommand(cmd, std::forward<Extensions>(es)...);
}
+ template <typename T>
+ WireResult FillReservation(ObjectId id, T handle, Known<T>* known = nullptr) {
+ auto result = Objects<T>().FillReservation(id, handle, known);
+ if (result == WireResult::FatalError) {
+ Release(mProcs, handle);
+ }
+ return result;
+ }
+
void SetForwardingDeviceCallbacks(Known<WGPUDevice> device);
void ClearDeviceCallbacks(WGPUDevice device);
diff --git a/src/dawn/wire/server/ServerAdapter.cpp b/src/dawn/wire/server/ServerAdapter.cpp
index 4eb4c93..7bd5c53 100644
--- a/src/dawn/wire/server/ServerAdapter.cpp
+++ b/src/dawn/wire/server/ServerAdapter.cpp
@@ -39,7 +39,7 @@
WGPUFuture deviceLostFuture,
const WGPUDeviceDescriptor* descriptor) {
Reserved<WGPUDevice> device;
- WIRE_TRY(DeviceObjects().Allocate(&device, deviceHandle, AllocationState::Reserved));
+ WIRE_TRY(Objects<WGPUDevice>().Allocate(&device, deviceHandle, AllocationState::Reserved));
auto userdata = MakeUserdata<RequestDeviceUserdata>();
userdata->eventManager = eventManager;
@@ -114,7 +114,12 @@
cmd.limits = &limits;
// Assign the handle and allocated status if the device is created successfully.
- Known<WGPUDevice> reservation = DeviceObjects().FillReservation(data->deviceObjectId, device);
+ Known<WGPUDevice> reservation;
+ if (FillReservation(data->deviceObjectId, device, &reservation) == WireResult::FatalError) {
+ cmd.status = WGPURequestDeviceStatus_Unknown;
+ cmd.message = "Destroyed before request was fulfilled.";
+ SerializeCommand(cmd);
+ }
DAWN_ASSERT(reservation.data != nullptr);
reservation->info->server = this;
reservation->info->self = reservation.AsHandle();
diff --git a/src/dawn/wire/server/ServerBuffer.cpp b/src/dawn/wire/server/ServerBuffer.cpp
index 56be933..5f4b6ff 100644
--- a/src/dawn/wire/server/ServerBuffer.cpp
+++ b/src/dawn/wire/server/ServerBuffer.cpp
@@ -37,7 +37,7 @@
WireResult Server::PreHandleBufferUnmap(const BufferUnmapCmd& cmd) {
Known<WGPUBuffer> buffer;
- WIRE_TRY(BufferObjects().Get(cmd.selfId, &buffer));
+ WIRE_TRY(Objects<WGPUBuffer>().Get(cmd.selfId, &buffer));
if (buffer->mappedAtCreation && !(buffer->usage & WGPUMapMode_Write)) {
// This indicates the writeHandle is for mappedAtCreation only. Destroy on unmap
@@ -54,7 +54,7 @@
WireResult Server::PreHandleBufferDestroy(const BufferDestroyCmd& cmd) {
// Destroying a buffer does an implicit unmapping.
Known<WGPUBuffer> buffer;
- WIRE_TRY(BufferObjects().Get(cmd.selfId, &buffer));
+ WIRE_TRY(Objects<WGPUBuffer>().Get(cmd.selfId, &buffer));
// The buffer was destroyed. Clear the Read/WriteHandle.
buffer->readHandle = nullptr;
@@ -114,7 +114,7 @@
const uint8_t* writeHandleCreateInfo) {
// Create and register the buffer object.
Reserved<WGPUBuffer> buffer;
- WIRE_TRY(BufferObjects().Allocate(&buffer, bufferHandle));
+ WIRE_TRY(Objects<WGPUBuffer>().Allocate(&buffer, bufferHandle));
buffer->handle = mProcs.deviceCreateBuffer(device->handle, descriptor);
buffer->usage = descriptor->usage;
buffer->mappedAtCreation = descriptor->mappedAtCreation;
@@ -216,7 +216,7 @@
void Server::OnBufferMapAsyncCallback(MapUserdata* data, WGPUBufferMapAsyncStatus status) {
// Skip sending the callback if the buffer has already been destroyed.
Known<WGPUBuffer> buffer;
- if (BufferObjects().Get(data->buffer.id, &buffer) != WireResult::Success ||
+ if (Objects<WGPUBuffer>().Get(data->buffer.id, &buffer) != WireResult::Success ||
buffer->generation != data->buffer.generation) {
return;
}
diff --git a/src/dawn/wire/server/ServerDevice.cpp b/src/dawn/wire/server/ServerDevice.cpp
index 8c20356..f481838 100644
--- a/src/dawn/wire/server/ServerDevice.cpp
+++ b/src/dawn/wire/server/ServerDevice.cpp
@@ -29,24 +29,6 @@
namespace dawn::wire::server {
-namespace {
-
-template <ObjectType objectType, typename Pipeline>
-void HandleCreatePipelineAsyncCallback(KnownObjects<Pipeline>* knownObjects,
- WGPUCreatePipelineAsyncStatus status,
- Pipeline pipeline,
- CreatePipelineAsyncUserData* data) {
- if (status == WGPUCreatePipelineAsyncStatus_Success) {
- knownObjects->FillReservation(data->pipelineObjectID, pipeline);
- } else {
- // Otherwise, free the ObjectId which will make it unusable.
- knownObjects->Free(data->pipelineObjectID);
- DAWN_ASSERT(pipeline == nullptr);
- }
-}
-
-} // anonymous namespace
-
void Server::OnUncapturedError(ObjectHandle device, WGPUErrorType type, const char* message) {
ReturnDeviceUncapturedErrorCallbackCmd cmd;
cmd.device = device;
@@ -110,8 +92,8 @@
ObjectHandle pipelineObjectHandle,
const WGPUComputePipelineDescriptor* descriptor) {
Reserved<WGPUComputePipeline> pipeline;
- WIRE_TRY(ComputePipelineObjects().Allocate(&pipeline, pipelineObjectHandle,
- AllocationState::Reserved));
+ WIRE_TRY(Objects<WGPUComputePipeline>().Allocate(&pipeline, pipelineObjectHandle,
+ AllocationState::Reserved));
auto userdata = MakeUserdata<CreatePipelineAsyncUserData>();
userdata->device = device.AsHandle();
@@ -129,15 +111,16 @@
WGPUCreatePipelineAsyncStatus status,
WGPUComputePipeline pipeline,
const char* message) {
- HandleCreatePipelineAsyncCallback<ObjectType::ComputePipeline>(&ComputePipelineObjects(),
- status, pipeline, data);
-
ReturnDeviceCreateComputePipelineAsyncCallbackCmd cmd;
cmd.eventManager = data->eventManager;
cmd.future = data->future;
cmd.status = status;
cmd.message = message;
+ if (FillReservation(data->pipelineObjectID, pipeline) == WireResult::FatalError) {
+ cmd.status = WGPUCreatePipelineAsyncStatus_Unknown;
+ cmd.message = "Destroyed before request was fulfilled.";
+ }
SerializeCommand(cmd);
}
@@ -148,8 +131,8 @@
ObjectHandle pipelineObjectHandle,
const WGPURenderPipelineDescriptor* descriptor) {
Reserved<WGPURenderPipeline> pipeline;
- WIRE_TRY(RenderPipelineObjects().Allocate(&pipeline, pipelineObjectHandle,
- AllocationState::Reserved));
+ WIRE_TRY(Objects<WGPURenderPipeline>().Allocate(&pipeline, pipelineObjectHandle,
+ AllocationState::Reserved));
auto userdata = MakeUserdata<CreatePipelineAsyncUserData>();
userdata->device = device.AsHandle();
@@ -167,15 +150,16 @@
WGPUCreatePipelineAsyncStatus status,
WGPURenderPipeline pipeline,
const char* message) {
- HandleCreatePipelineAsyncCallback<ObjectType::RenderPipeline>(&RenderPipelineObjects(), status,
- pipeline, data);
-
ReturnDeviceCreateRenderPipelineAsyncCallbackCmd cmd;
cmd.eventManager = data->eventManager;
cmd.future = data->future;
cmd.status = status;
cmd.message = message;
+ if (FillReservation(data->pipelineObjectID, pipeline) == WireResult::FatalError) {
+ cmd.status = WGPUCreatePipelineAsyncStatus_Unknown;
+ cmd.message = "Destroyed before request was fulfilled.";
+ }
SerializeCommand(cmd);
}
diff --git a/src/dawn/wire/server/ServerInstance.cpp b/src/dawn/wire/server/ServerInstance.cpp
index 255ab3f..ca939c7 100644
--- a/src/dawn/wire/server/ServerInstance.cpp
+++ b/src/dawn/wire/server/ServerInstance.cpp
@@ -39,7 +39,7 @@
ObjectHandle adapterHandle,
const WGPURequestAdapterOptions* options) {
Reserved<WGPUAdapter> adapter;
- WIRE_TRY(AdapterObjects().Allocate(&adapter, adapterHandle, AllocationState::Reserved));
+ WIRE_TRY(Objects<WGPUAdapter>().Allocate(&adapter, adapterHandle, AllocationState::Reserved));
auto userdata = MakeUserdata<RequestAdapterUserdata>();
userdata->eventManager = eventManager;
@@ -63,15 +63,18 @@
cmd.message = message;
if (status != WGPURequestAdapterStatus_Success) {
- // Free the ObjectId which will make it unusable.
- AdapterObjects().Free(data->adapterObjectId);
DAWN_ASSERT(adapter == nullptr);
SerializeCommand(cmd);
return;
}
// Assign the handle and allocated status if the adapter is created successfully.
- AdapterObjects().FillReservation(data->adapterObjectId, adapter);
+ if (FillReservation(data->adapterObjectId, adapter) == WireResult::FatalError) {
+ cmd.status = WGPURequestAdapterStatus_Unknown;
+ cmd.message = "Destroyed before request was fulfilled.";
+ SerializeCommand(cmd);
+ return;
+ }
// Query and report the adapter supported features.
std::vector<WGPUFeatureName> features;