Nuke Builders Part 2: remove all builder code from wire
This removes blocks of code that were obviously builder-specific but also removes the ObjectStorage::valid member that was used to implement the maybe monad on the wire server side. This is no longer needed since dawn_native handles the maybe monad internally now. BUG=dawn:125 Change-Id: I8c30daae9fc70853bc1996d85a860b4877c5976c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/6161 Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
20b0c33913
commit
cb2c64f7d9
3
BUILD.gn
3
BUILD.gn
|
@ -396,18 +396,15 @@ dawn_component("libdawn_native") {
|
||||||
dawn_generator("libdawn_wire_gen") {
|
dawn_generator("libdawn_wire_gen") {
|
||||||
target = "dawn_wire"
|
target = "dawn_wire"
|
||||||
outputs = [
|
outputs = [
|
||||||
"dawn_wire/TypeTraits_autogen.h",
|
|
||||||
"dawn_wire/WireCmd_autogen.h",
|
"dawn_wire/WireCmd_autogen.h",
|
||||||
"dawn_wire/WireCmd_autogen.cpp",
|
"dawn_wire/WireCmd_autogen.cpp",
|
||||||
"dawn_wire/client/ApiObjects_autogen.h",
|
"dawn_wire/client/ApiObjects_autogen.h",
|
||||||
"dawn_wire/client/ApiProcs_autogen.cpp",
|
"dawn_wire/client/ApiProcs_autogen.cpp",
|
||||||
"dawn_wire/client/ApiProcs_autogen.h",
|
"dawn_wire/client/ApiProcs_autogen.h",
|
||||||
"dawn_wire/client/ClientBase_autogen.h",
|
"dawn_wire/client/ClientBase_autogen.h",
|
||||||
"dawn_wire/client/ClientDoers_autogen.cpp",
|
|
||||||
"dawn_wire/client/ClientHandlers_autogen.cpp",
|
"dawn_wire/client/ClientHandlers_autogen.cpp",
|
||||||
"dawn_wire/client/ClientPrototypes_autogen.inl",
|
"dawn_wire/client/ClientPrototypes_autogen.inl",
|
||||||
"dawn_wire/server/ServerBase_autogen.h",
|
"dawn_wire/server/ServerBase_autogen.h",
|
||||||
"dawn_wire/server/ServerCallbacks_autogen.cpp",
|
|
||||||
"dawn_wire/server/ServerDoers_autogen.cpp",
|
"dawn_wire/server/ServerDoers_autogen.cpp",
|
||||||
"dawn_wire/server/ServerHandlers_autogen.cpp",
|
"dawn_wire/server/ServerHandlers_autogen.cpp",
|
||||||
"dawn_wire/server/ServerPrototypes_autogen.inl",
|
"dawn_wire/server/ServerPrototypes_autogen.inl",
|
||||||
|
|
|
@ -386,18 +386,15 @@ def get_renders_for_targets(api_params, wire_json, targets):
|
||||||
},
|
},
|
||||||
additional_params
|
additional_params
|
||||||
]
|
]
|
||||||
renders.append(FileRender('dawn_wire/TypeTraits.h', 'dawn_wire/TypeTraits_autogen.h', wire_params))
|
|
||||||
renders.append(FileRender('dawn_wire/WireCmd.h', 'dawn_wire/WireCmd_autogen.h', wire_params))
|
renders.append(FileRender('dawn_wire/WireCmd.h', 'dawn_wire/WireCmd_autogen.h', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/WireCmd.cpp', 'dawn_wire/WireCmd_autogen.cpp', wire_params))
|
renders.append(FileRender('dawn_wire/WireCmd.cpp', 'dawn_wire/WireCmd_autogen.cpp', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/client/ApiObjects.h', 'dawn_wire/client/ApiObjects_autogen.h', wire_params))
|
renders.append(FileRender('dawn_wire/client/ApiObjects.h', 'dawn_wire/client/ApiObjects_autogen.h', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/client/ApiProcs.cpp', 'dawn_wire/client/ApiProcs_autogen.cpp', wire_params))
|
renders.append(FileRender('dawn_wire/client/ApiProcs.cpp', 'dawn_wire/client/ApiProcs_autogen.cpp', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/client/ApiProcs.h', 'dawn_wire/client/ApiProcs_autogen.h', wire_params))
|
renders.append(FileRender('dawn_wire/client/ApiProcs.h', 'dawn_wire/client/ApiProcs_autogen.h', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/client/ClientBase.h', 'dawn_wire/client/ClientBase_autogen.h', wire_params))
|
renders.append(FileRender('dawn_wire/client/ClientBase.h', 'dawn_wire/client/ClientBase_autogen.h', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/client/ClientDoers.cpp', 'dawn_wire/client/ClientDoers_autogen.cpp', wire_params))
|
|
||||||
renders.append(FileRender('dawn_wire/client/ClientHandlers.cpp', 'dawn_wire/client/ClientHandlers_autogen.cpp', wire_params))
|
renders.append(FileRender('dawn_wire/client/ClientHandlers.cpp', 'dawn_wire/client/ClientHandlers_autogen.cpp', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/client/ClientPrototypes.inl', 'dawn_wire/client/ClientPrototypes_autogen.inl', wire_params))
|
renders.append(FileRender('dawn_wire/client/ClientPrototypes.inl', 'dawn_wire/client/ClientPrototypes_autogen.inl', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/server/ServerBase.h', 'dawn_wire/server/ServerBase_autogen.h', wire_params))
|
renders.append(FileRender('dawn_wire/server/ServerBase.h', 'dawn_wire/server/ServerBase_autogen.h', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/server/ServerCallbacks.cpp', 'dawn_wire/server/ServerCallbacks_autogen.cpp', wire_params))
|
|
||||||
renders.append(FileRender('dawn_wire/server/ServerDoers.cpp', 'dawn_wire/server/ServerDoers_autogen.cpp', wire_params))
|
renders.append(FileRender('dawn_wire/server/ServerDoers.cpp', 'dawn_wire/server/ServerDoers_autogen.cpp', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/server/ServerHandlers.cpp', 'dawn_wire/server/ServerHandlers_autogen.cpp', wire_params))
|
renders.append(FileRender('dawn_wire/server/ServerHandlers.cpp', 'dawn_wire/server/ServerHandlers_autogen.cpp', wire_params))
|
||||||
renders.append(FileRender('dawn_wire/server/ServerPrototypes.inl', 'dawn_wire/server/ServerPrototypes_autogen.inl', wire_params))
|
renders.append(FileRender('dawn_wire/server/ServerPrototypes.inl', 'dawn_wire/server/ServerPrototypes_autogen.inl', wire_params))
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
//* Copyright 2019 The Dawn Authors
|
|
||||||
//*
|
|
||||||
//* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
//* you may not use this file except in compliance with the License.
|
|
||||||
//* You may obtain a copy of the License at
|
|
||||||
//*
|
|
||||||
//* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//*
|
|
||||||
//* Unless required by applicable law or agreed to in writing, software
|
|
||||||
//* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//* See the License for the specific language governing permissions and
|
|
||||||
//* limitations under the License.
|
|
||||||
|
|
||||||
#ifndef DAWNWIRE_TYPETRAITS_AUTOGEN_H_
|
|
||||||
#define DAWNWIRE_TYPETRAITS_AUTOGEN_H_
|
|
||||||
|
|
||||||
#include <dawn/dawn.h>
|
|
||||||
|
|
||||||
//* This file can be removed when WebGPU error handling is implemented
|
|
||||||
namespace dawn_wire {
|
|
||||||
template <typename T>
|
|
||||||
struct IsBuilderType {
|
|
||||||
static constexpr bool value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
{% for type in by_category["object"] if type.is_builder %}
|
|
||||||
template<>
|
|
||||||
struct IsBuilderType<{{as_cType(type.name)}}> {
|
|
||||||
static constexpr bool value = true;
|
|
||||||
};
|
|
||||||
{% endfor %}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DAWNWIRE_TYPETRAITS_AUTOGEN_H_
|
|
|
@ -83,7 +83,7 @@
|
||||||
//* Methods are very similar to structures that have one member corresponding to each arguments.
|
//* Methods are very similar to structures that have one member corresponding to each arguments.
|
||||||
//* This macro takes advantage of the similarity to output [de]serialization code for a record
|
//* This macro takes advantage of the similarity to output [de]serialization code for a record
|
||||||
//* that is either a structure or a method, with some special cases for each.
|
//* that is either a structure or a method, with some special cases for each.
|
||||||
{% macro write_record_serialization_helpers(record, name, members, is_cmd=False, is_method=False, is_return_command=False) %}
|
{% macro write_record_serialization_helpers(record, name, members, is_cmd=False, is_return_command=False) %}
|
||||||
{% set Return = "Return" if is_return_command else "" %}
|
{% set Return = "Return" if is_return_command else "" %}
|
||||||
{% set Cmd = "Cmd" if is_cmd else "" %}
|
{% set Cmd = "Cmd" if is_cmd else "" %}
|
||||||
|
|
||||||
|
@ -218,53 +218,14 @@
|
||||||
ASSERT(transfer->commandId == {{Return}}WireCmd::{{name}});
|
ASSERT(transfer->commandId == {{Return}}WireCmd::{{name}});
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
//* First assign result ObjectHandles:
|
|
||||||
//* Deserialize guarantees they are filled even if there is an ID for an error object
|
|
||||||
//* for the Maybe monad mechanism.
|
|
||||||
//* TODO(enga): This won't need to be done first once we have "WebGPU error handling".
|
|
||||||
{% set return_handles = members
|
|
||||||
|selectattr("is_return_value")
|
|
||||||
|selectattr("annotation", "equalto", "value")
|
|
||||||
|selectattr("type.dict_name", "equalto", "ObjectHandle")
|
|
||||||
|list %}
|
|
||||||
|
|
||||||
//* Strip return_handles so we don't deserialize it again
|
|
||||||
{% set members = members|reject("in", return_handles)|list %}
|
|
||||||
|
|
||||||
{% for member in return_handles %}
|
|
||||||
{% set memberName = as_varName(member.name) %}
|
|
||||||
{{deserialize_member(member, "transfer->" + memberName, "record->" + memberName)}}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
//* Handle special transfer members for methods
|
|
||||||
{% if is_method %}
|
|
||||||
//* First assign selfId:
|
|
||||||
//* Deserialize guarantees they are filled even if there is an ID for an error object
|
|
||||||
//* for the Maybe monad mechanism.
|
|
||||||
//* TODO(enga): This won't need to be done first once we have "WebGPU error handling".
|
|
||||||
//* We can also remove is_method
|
|
||||||
record->selfId = transfer->self;
|
|
||||||
//* This conversion is done after the copying of result* and selfId: Deserialize
|
|
||||||
//* guarantees they are filled even if there is an ID for an error object for the
|
|
||||||
//* Maybe monad mechanism.
|
|
||||||
DESERIALIZE_TRY(resolver.GetFromId(record->selfId, &record->self));
|
|
||||||
|
|
||||||
//* Strip self so we don't deserialize it again
|
|
||||||
{% set members = members|rejectattr("name.chunks", "equalto", ["self"])|list %}
|
|
||||||
|
|
||||||
//* The object resolver returns a success even if the object is null because the
|
|
||||||
//* frontend is responsible to validate that (null objects sometimes have special
|
|
||||||
//* meanings). However it is never valid to call a method on a null object so we
|
|
||||||
//* can error out in that case.
|
|
||||||
if (record->self == nullptr) {
|
|
||||||
return DeserializeResult::FatalError;
|
|
||||||
}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if record.extensible %}
|
{% if record.extensible %}
|
||||||
record->nextInChain = nullptr;
|
record->nextInChain = nullptr;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if record.derived_method %}
|
||||||
|
record->selfId = transfer->self;
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
//* Value types are directly in the transfer record, objects being replaced with their IDs.
|
//* Value types are directly in the transfer record, objects being replaced with their IDs.
|
||||||
{% for member in members if member.annotation == "value" %}
|
{% for member in members if member.annotation == "value" %}
|
||||||
{% set memberName = as_varName(member.name) %}
|
{% set memberName = as_varName(member.name) %}
|
||||||
|
@ -428,15 +389,14 @@ namespace dawn_wire {
|
||||||
{% for command in cmd_records["command"] %}
|
{% for command in cmd_records["command"] %}
|
||||||
{% set name = command.name.CamelCase() %}
|
{% set name = command.name.CamelCase() %}
|
||||||
{{write_record_serialization_helpers(command, name, command.members,
|
{{write_record_serialization_helpers(command, name, command.members,
|
||||||
is_cmd=True, is_method=command.derived_method != None)}}
|
is_cmd=True)}}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
//* Output [de]serialization helpers for return commands
|
//* Output [de]serialization helpers for return commands
|
||||||
{% for command in cmd_records["return command"] %}
|
{% for command in cmd_records["return command"] %}
|
||||||
{% set name = command.name.CamelCase() %}
|
{% set name = command.name.CamelCase() %}
|
||||||
{{write_record_serialization_helpers(command, name, command.members,
|
{{write_record_serialization_helpers(command, name, command.members,
|
||||||
is_cmd=True, is_method=command.derived_method != None,
|
is_cmd=True, is_return_command=True)}}
|
||||||
is_return_command=True)}}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ namespace dawn_wire {
|
||||||
enum class DeserializeResult {
|
enum class DeserializeResult {
|
||||||
Success,
|
Success,
|
||||||
FatalError,
|
FatalError,
|
||||||
ErrorObject,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Interface to allocate more space to deserialize pointed-to data.
|
// Interface to allocate more space to deserialize pointed-to data.
|
||||||
|
@ -40,8 +39,7 @@ namespace dawn_wire {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Interface to convert an ID to a server object, if possible.
|
// Interface to convert an ID to a server object, if possible.
|
||||||
// Methods return FatalError if the ID is for a non-existent object, ErrorObject if the
|
// Methods return FatalError if the ID is for a non-existent object and Success otherwise.
|
||||||
// object is an error value and Success otherwise.
|
|
||||||
class ObjectIdResolver {
|
class ObjectIdResolver {
|
||||||
public:
|
public:
|
||||||
{% for type in by_category["object"] %}
|
{% for type in by_category["object"] %}
|
||||||
|
@ -101,10 +99,6 @@ namespace dawn_wire {
|
||||||
//* Deserialize returns:
|
//* Deserialize returns:
|
||||||
//* - Success if everything went well (yay!)
|
//* - Success if everything went well (yay!)
|
||||||
//* - FatalError is something bad happened (buffer too small for example)
|
//* - FatalError is something bad happened (buffer too small for example)
|
||||||
//* - ErrorObject if one if the deserialized object is an error value, for the implementation
|
|
||||||
//* of the Maybe monad.
|
|
||||||
//* If the return value is not FatalError, selfId, resultId and resultSerial (if present) are
|
|
||||||
//* filled.
|
|
||||||
DeserializeResult Deserialize(const char** buffer, size_t* size, DeserializeAllocator* allocator
|
DeserializeResult Deserialize(const char** buffer, size_t* size, DeserializeAllocator* allocator
|
||||||
{%- if command.has_dawn_object -%}
|
{%- if command.has_dawn_object -%}
|
||||||
, const ObjectIdResolver& resolver
|
, const ObjectIdResolver& resolver
|
||||||
|
|
|
@ -42,15 +42,6 @@ namespace dawn_wire { namespace client {
|
||||||
//* For object creation, store the object ID the client will use for the result.
|
//* For object creation, store the object ID the client will use for the result.
|
||||||
{% if method.return_type.category == "object" %}
|
{% if method.return_type.category == "object" %}
|
||||||
auto* allocation = self->device->GetClient()->{{method.return_type.name.CamelCase()}}Allocator().New(self->device);
|
auto* allocation = self->device->GetClient()->{{method.return_type.name.CamelCase()}}Allocator().New(self->device);
|
||||||
|
|
||||||
{% if type.is_builder %}
|
|
||||||
//* We are in GetResult, so the callback that should be called is the
|
|
||||||
//* currently set one. Copy it over to the created object and prevent the
|
|
||||||
//* builder from calling the callback on destruction.
|
|
||||||
allocation->object->builderCallback = self->builderCallback;
|
|
||||||
self->builderCallback.canCall = false;
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
cmd.result = ObjectHandle{allocation->object->id, allocation->serial};
|
cmd.result = ObjectHandle{allocation->object->id, allocation->serial};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -70,18 +61,6 @@ namespace dawn_wire { namespace client {
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if type.is_builder %}
|
|
||||||
void Client{{as_MethodSuffix(type.name, Name("set error callback"))}}({{cType}} cSelf,
|
|
||||||
DawnBuilderErrorCallback callback,
|
|
||||||
DawnCallbackUserdata userdata1,
|
|
||||||
DawnCallbackUserdata userdata2) {
|
|
||||||
{{Type}}* self = reinterpret_cast<{{Type}}*>(cSelf);
|
|
||||||
self->builderCallback.callback = callback;
|
|
||||||
self->builderCallback.userdata1 = userdata1;
|
|
||||||
self->builderCallback.userdata2 = userdata2;
|
|
||||||
}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if not type.name.canonical_case() == "device" %}
|
{% if not type.name.canonical_case() == "device" %}
|
||||||
//* When an object's refcount reaches 0, notify the server side of it and delete it.
|
//* When an object's refcount reaches 0, notify the server side of it and delete it.
|
||||||
void Client{{as_MethodSuffix(type.name, Name("release"))}}({{cType}} cObj) {
|
void Client{{as_MethodSuffix(type.name, Name("release"))}}({{cType}} cObj) {
|
||||||
|
@ -92,8 +71,6 @@ namespace dawn_wire { namespace client {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj->builderCallback.Call(DAWN_BUILDER_ERROR_STATUS_UNKNOWN, "Unknown");
|
|
||||||
|
|
||||||
DestroyObjectCmd cmd;
|
DestroyObjectCmd cmd;
|
||||||
cmd.objectType = ObjectType::{{type.name.CamelCase()}};
|
cmd.objectType = ObjectType::{{type.name.CamelCase()}};
|
||||||
cmd.objectId = obj->id;
|
cmd.objectId = obj->id;
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
//* Copyright 2019 The Dawn Authors
|
|
||||||
//*
|
|
||||||
//* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
//* you may not use this file except in compliance with the License.
|
|
||||||
//* You may obtain a copy of the License at
|
|
||||||
//*
|
|
||||||
//* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//*
|
|
||||||
//* Unless required by applicable law or agreed to in writing, software
|
|
||||||
//* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//* See the License for the specific language governing permissions and
|
|
||||||
//* limitations under the License.
|
|
||||||
|
|
||||||
#include "dawn_wire/client/Client.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace dawn_wire {
|
|
||||||
namespace client {
|
|
||||||
{% for type in by_category["object"] if type.is_builder %}
|
|
||||||
{% set Type = type.name.CamelCase() %}
|
|
||||||
bool Client::Do{{Type}}ErrorCallback({{type.built_type.name.CamelCase()}}* object, uint32_t status, const char* message) {
|
|
||||||
//* The object might have been deleted or a new object created with the same ID.
|
|
||||||
if (object == nullptr) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool called = object->builderCallback.Call(static_cast<DawnBuilderErrorStatus>(status), message);
|
|
||||||
|
|
||||||
//* Unhandled builder errors are forwarded to the device
|
|
||||||
if (!called && status != DAWN_BUILDER_ERROR_STATUS_SUCCESS && status != DAWN_BUILDER_ERROR_STATUS_UNKNOWN) {
|
|
||||||
mDevice->HandleError(("Unhandled builder error: " + std::string(message)).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
{% endfor %}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,7 +29,7 @@ namespace dawn_wire { namespace server {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DestroyAllObjects(const DawnProcTable& procs) {
|
void DestroyAllObjects(const DawnProcTable& procs) {
|
||||||
//* Free all objects when the server is destroyed
|
//* Free all objects when the server is destroyed
|
||||||
{% for type in by_category["object"] if type.name.canonical_case() != "device" %}
|
{% for type in by_category["object"] if type.name.canonical_case() != "device" %}
|
||||||
{
|
{
|
||||||
std::vector<{{as_cType(type.name)}}> handles = mKnown{{type.name.CamelCase()}}.AcquireAllHandles();
|
std::vector<{{as_cType(type.name)}}> handles = mKnown{{type.name.CamelCase()}}.AcquireAllHandles();
|
||||||
|
@ -68,11 +68,7 @@ namespace dawn_wire { namespace server {
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = data->handle;
|
*out = data->handle;
|
||||||
if (data->valid) {
|
return DeserializeResult::Success;
|
||||||
return DeserializeResult::Success;
|
|
||||||
} else {
|
|
||||||
return DeserializeResult::ErrorObject;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DeserializeResult GetOptionalFromId(ObjectId id, {{as_cType(type.name)}}* out) const final {
|
DeserializeResult GetOptionalFromId(ObjectId id, {{as_cType(type.name)}}* out) const final {
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
//* Copyright 2019 The Dawn Authors
|
|
||||||
//*
|
|
||||||
//* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
//* you may not use this file except in compliance with the License.
|
|
||||||
//* You may obtain a copy of the License at
|
|
||||||
//*
|
|
||||||
//* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//*
|
|
||||||
//* Unless required by applicable law or agreed to in writing, software
|
|
||||||
//* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//* See the License for the specific language governing permissions and
|
|
||||||
//* limitations under the License.
|
|
||||||
|
|
||||||
#include "common/Assert.h"
|
|
||||||
#include "dawn_wire/server/Server.h"
|
|
||||||
|
|
||||||
namespace dawn_wire { namespace server {
|
|
||||||
{% for type in by_category["object"] if type.is_builder%}
|
|
||||||
void Server::Forward{{type.name.CamelCase()}}(DawnBuilderErrorStatus status, const char* message, DawnCallbackUserdata userdata1, DawnCallbackUserdata userdata2) {
|
|
||||||
auto server = reinterpret_cast<Server*>(static_cast<uintptr_t>(userdata1));
|
|
||||||
uint32_t id = userdata2 & 0xFFFFFFFFu;
|
|
||||||
uint32_t serial = userdata2 >> uint64_t(32);
|
|
||||||
server->On{{type.name.CamelCase()}}Error(status, message, id, serial);
|
|
||||||
}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% for type in by_category["object"] if type.is_builder%}
|
|
||||||
{% set Type = type.name.CamelCase() %}
|
|
||||||
void Server::On{{Type}}Error(DawnBuilderErrorStatus status, const char* message, uint32_t id, uint32_t serial) {
|
|
||||||
auto* builder = {{Type}}Objects().Get(id);
|
|
||||||
|
|
||||||
if (builder == nullptr || builder->serial != serial) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != DAWN_BUILDER_ERROR_STATUS_SUCCESS) {
|
|
||||||
builder->valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != DAWN_BUILDER_ERROR_STATUS_UNKNOWN) {
|
|
||||||
//* Unknown is the only status that can be returned without a call to GetResult
|
|
||||||
//* so we are guaranteed to have created an object.
|
|
||||||
ASSERT(builder->builtObject.id != 0);
|
|
||||||
|
|
||||||
Return{{Type}}ErrorCallbackCmd cmd;
|
|
||||||
cmd.builtObject = builder->builtObject;
|
|
||||||
cmd.status = status;
|
|
||||||
cmd.message = message;
|
|
||||||
|
|
||||||
size_t requiredSize = cmd.GetRequiredSize();
|
|
||||||
char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize));
|
|
||||||
cmd.Serialize(allocatedBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
}} // namespace dawn_wire::server
|
|
|
@ -53,6 +53,11 @@ namespace dawn_wire { namespace server {
|
||||||
{%- if not loop.last -%}, {% endif %}
|
{%- if not loop.last -%}, {% endif %}
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
);
|
);
|
||||||
|
{% if ret|length == 1 %}
|
||||||
|
//* WebGPU error handling guarantees that no null object can be returned by
|
||||||
|
//* object creation functions.
|
||||||
|
ASSERT(*{{as_varName(ret[0].name)}} != nullptr);
|
||||||
|
{% endif %}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -43,12 +43,6 @@ namespace dawn_wire { namespace server {
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if is_method %}
|
|
||||||
//* Unpack 'self'
|
|
||||||
auto* selfData = {{type.name.CamelCase()}}Objects().Get(cmd.selfId);
|
|
||||||
ASSERT(selfData != nullptr);
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
//* Allocate any result objects
|
//* Allocate any result objects
|
||||||
{%- for member in command.members if member.is_return_value -%}
|
{%- for member in command.members if member.is_return_value -%}
|
||||||
{{ assert(member.handle_type) }}
|
{{ assert(member.handle_type) }}
|
||||||
|
@ -60,24 +54,8 @@ namespace dawn_wire { namespace server {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
{{name}}Data->serial = cmd.{{name}}.serial;
|
{{name}}Data->serial = cmd.{{name}}.serial;
|
||||||
|
|
||||||
{% if type.is_builder %}
|
|
||||||
selfData->builtObject = cmd.{{name}};
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
//* After the data is allocated, apply the argument error propagation mechanism
|
|
||||||
if (deserializeResult == DeserializeResult::ErrorObject) {
|
|
||||||
{% if type.is_builder %}
|
|
||||||
selfData->valid = false;
|
|
||||||
//* If we are in GetResult, fake an error callback
|
|
||||||
{% if returns %}
|
|
||||||
On{{type.name.CamelCase()}}Error(DAWN_BUILDER_ERROR_STATUS_ERROR, "Maybe monad", cmd.selfId, selfData->serial);
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//* Do command
|
//* Do command
|
||||||
bool success = Do{{Suffix}}(
|
bool success = Do{{Suffix}}(
|
||||||
{%- for member in command.members -%}
|
{%- for member in command.members -%}
|
||||||
|
@ -94,12 +72,6 @@ namespace dawn_wire { namespace server {
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
);
|
);
|
||||||
|
|
||||||
//* Mark output object handles as valid/invalid
|
|
||||||
{%- for member in command.members if member.is_return_value and member.handle_type -%}
|
|
||||||
{% set name = as_varName(member.name) %}
|
|
||||||
{{name}}Data->valid = {{name}}Data->handle != nullptr;
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -110,19 +82,7 @@ namespace dawn_wire { namespace server {
|
||||||
|
|
||||||
{% if Type in server_reverse_lookup_objects %}
|
{% if Type in server_reverse_lookup_objects %}
|
||||||
//* For created objects, store a mapping from them back to their client IDs
|
//* For created objects, store a mapping from them back to their client IDs
|
||||||
if ({{name}}Data->valid) {
|
{{Type}}ObjectIdTable().Store({{name}}Data->handle, cmd.{{name}}.id);
|
||||||
{{Type}}ObjectIdTable().Store({{name}}Data->handle, cmd.{{name}}.id);
|
|
||||||
}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
//* builders remember the ID of the object they built so that they can send it
|
|
||||||
//* in the callback to the client.
|
|
||||||
{% if member.handle_type.is_builder %}
|
|
||||||
if ({{name}}Data->valid) {
|
|
||||||
uint64_t userdata1 = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this));
|
|
||||||
uint64_t userdata2 = (uint64_t({{name}}Data->serial) << uint64_t(32)) + cmd.{{name}}.id;
|
|
||||||
mProcs.{{as_varName(member.handle_type.name, Name("set error callback"))}}({{name}}Data->handle, Forward{{Type}}, userdata1, userdata2);
|
|
||||||
}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
|
@ -12,17 +12,6 @@
|
||||||
//* See the License for the specific language governing permissions and
|
//* See the License for the specific language governing permissions and
|
||||||
//* limitations under the License.
|
//* limitations under the License.
|
||||||
|
|
||||||
// Forwarding callbacks
|
|
||||||
{% for type in by_category["object"] if type.is_builder%}
|
|
||||||
static void Forward{{type.name.CamelCase()}}(DawnBuilderErrorStatus status, const char* message, DawnCallbackUserdata userdata1, DawnCallbackUserdata userdata2);
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
// Error callbacks
|
|
||||||
{% for type in by_category["object"] if type.is_builder%}
|
|
||||||
{% set Type = type.name.CamelCase() %}
|
|
||||||
void On{{Type}}Error(DawnBuilderErrorStatus status, const char* message, uint32_t id, uint32_t serial);
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
// Command handlers & doers
|
// Command handlers & doers
|
||||||
{% for command in cmd_records["command"] if command.name.CamelCase() not in client_side_commands %}
|
{% for command in cmd_records["command"] if command.name.CamelCase() not in client_side_commands %}
|
||||||
{% set Suffix = command.name.CamelCase() %}
|
{% set Suffix = command.name.CamelCase() %}
|
||||||
|
|
|
@ -57,20 +57,6 @@ def compute_wire_params(api_params, wire_json):
|
||||||
command.derived_method = method
|
command.derived_method = method
|
||||||
commands.append(command)
|
commands.append(command)
|
||||||
|
|
||||||
# Create builder return ErrorCallback commands
|
|
||||||
# This can be removed when WebGPU error handling is implemented
|
|
||||||
if api_object.is_builder:
|
|
||||||
command_name = concat_names(api_object.name, Name('error callback'))
|
|
||||||
built_object = common.RecordMember(Name('built object'), types['ObjectHandle'], 'value', False, False)
|
|
||||||
built_object.set_handle_type(api_object.built_type)
|
|
||||||
command = common.Command(command_name, [
|
|
||||||
built_object,
|
|
||||||
callback_status_member,
|
|
||||||
string_message_member,
|
|
||||||
])
|
|
||||||
command.derived_object = api_object
|
|
||||||
return_commands.append(command)
|
|
||||||
|
|
||||||
for (name, json_data) in wire_json['commands'].items():
|
for (name, json_data) in wire_json['commands'].items():
|
||||||
commands.append(common.Command(name, common.linked_record_members(json_data, types)))
|
commands.append(common.Command(name, common.linked_record_members(json_data, types)))
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,6 @@ namespace dawn_wire { namespace client {
|
||||||
class Client;
|
class Client;
|
||||||
class Device;
|
class Device;
|
||||||
|
|
||||||
// TODO(cwallez@chromium.org): Do something with objects before they are destroyed ?
|
|
||||||
// - Call still uncalled builder callbacks
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ObjectAllocator {
|
class ObjectAllocator {
|
||||||
using ObjectOwner =
|
using ObjectOwner =
|
||||||
|
|
|
@ -21,24 +21,6 @@ namespace dawn_wire { namespace client {
|
||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
|
|
||||||
struct BuilderCallbackData {
|
|
||||||
bool Call(DawnBuilderErrorStatus status, const char* message) {
|
|
||||||
if (canCall && callback != nullptr) {
|
|
||||||
canCall = true;
|
|
||||||
callback(status, message, userdata1, userdata2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For help with development, prints all builder errors by default.
|
|
||||||
DawnBuilderErrorCallback callback = nullptr;
|
|
||||||
DawnCallbackUserdata userdata1 = 0;
|
|
||||||
DawnCallbackUserdata userdata2 = 0;
|
|
||||||
bool canCall = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// All non-Device objects of the client side have:
|
// All non-Device objects of the client side have:
|
||||||
// - A pointer to the device to get where to serialize commands
|
// - A pointer to the device to get where to serialize commands
|
||||||
// - The external reference count
|
// - The external reference count
|
||||||
|
@ -51,8 +33,6 @@ namespace dawn_wire { namespace client {
|
||||||
Device* device;
|
Device* device;
|
||||||
uint32_t refcount;
|
uint32_t refcount;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
BuilderCallbackData builderCallback;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace dawn_wire::client
|
}} // namespace dawn_wire::client
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#ifndef DAWNWIRE_SERVER_OBJECTSTORAGE_H_
|
#ifndef DAWNWIRE_SERVER_OBJECTSTORAGE_H_
|
||||||
#define DAWNWIRE_SERVER_OBJECTSTORAGE_H_
|
#define DAWNWIRE_SERVER_OBJECTSTORAGE_H_
|
||||||
|
|
||||||
#include "dawn_wire/TypeTraits_autogen.h"
|
|
||||||
#include "dawn_wire/WireCmd_autogen.h"
|
#include "dawn_wire/WireCmd_autogen.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -29,26 +28,17 @@ namespace dawn_wire { namespace server {
|
||||||
T handle;
|
T handle;
|
||||||
uint32_t serial = 0;
|
uint32_t serial = 0;
|
||||||
|
|
||||||
// Used by the error-propagation mechanism to know if this object is an error.
|
|
||||||
// TODO(cwallez@chromium.org): this is doubling the memory usage of
|
|
||||||
// std::vector<ObjectDataBase> consider making it a special marker value in handle instead.
|
|
||||||
bool valid;
|
|
||||||
// Whether this object has been allocated, used by the KnownObjects queries
|
// Whether this object has been allocated, used by the KnownObjects queries
|
||||||
// TODO(cwallez@chromium.org): make this an internal bit vector in KnownObjects.
|
// TODO(cwallez@chromium.org): make this an internal bit vector in KnownObjects.
|
||||||
bool allocated;
|
bool allocated;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stores what the backend knows about the type.
|
// Stores what the backend knows about the type.
|
||||||
template <typename T, bool IsBuilder = IsBuilderType<T>::value>
|
template <typename T>
|
||||||
struct ObjectData : public ObjectDataBase<T> {};
|
struct ObjectData : public ObjectDataBase<T> {};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct ObjectData<T, true> : public ObjectDataBase<T> {
|
|
||||||
ObjectHandle builtObject = ObjectHandle{0, 0};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ObjectData<DawnBuffer, false> : public ObjectDataBase<DawnBuffer> {
|
struct ObjectData<DawnBuffer> : public ObjectDataBase<DawnBuffer> {
|
||||||
void* mappedData = nullptr;
|
void* mappedData = nullptr;
|
||||||
size_t mappedDataSize = 0;
|
size_t mappedDataSize = 0;
|
||||||
};
|
};
|
||||||
|
@ -65,7 +55,6 @@ namespace dawn_wire { namespace server {
|
||||||
// KnownObjects for ID 0.
|
// KnownObjects for ID 0.
|
||||||
Data reservation;
|
Data reservation;
|
||||||
reservation.handle = nullptr;
|
reservation.handle = nullptr;
|
||||||
reservation.valid = false;
|
|
||||||
reservation.allocated = false;
|
reservation.allocated = false;
|
||||||
mKnown.push_back(reservation);
|
mKnown.push_back(reservation);
|
||||||
}
|
}
|
||||||
|
@ -109,7 +98,6 @@ namespace dawn_wire { namespace server {
|
||||||
|
|
||||||
Data data;
|
Data data;
|
||||||
data.allocated = true;
|
data.allocated = true;
|
||||||
data.valid = false;
|
|
||||||
data.handle = nullptr;
|
data.handle = nullptr;
|
||||||
|
|
||||||
if (id >= mKnown.size()) {
|
if (id >= mKnown.size()) {
|
||||||
|
@ -136,7 +124,6 @@ namespace dawn_wire { namespace server {
|
||||||
for (Data& data : mKnown) {
|
for (Data& data : mKnown) {
|
||||||
if (data.allocated && data.handle != nullptr) {
|
if (data.allocated && data.handle != nullptr) {
|
||||||
objects.push_back(data.handle);
|
objects.push_back(data.handle);
|
||||||
data.valid = false;
|
|
||||||
data.allocated = false;
|
data.allocated = false;
|
||||||
data.handle = nullptr;
|
data.handle = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ namespace dawn_wire { namespace server {
|
||||||
// The client-server knowledge is bootstrapped with device 1.
|
// The client-server knowledge is bootstrapped with device 1.
|
||||||
auto* deviceData = DeviceObjects().Allocate(1);
|
auto* deviceData = DeviceObjects().Allocate(1);
|
||||||
deviceData->handle = device;
|
deviceData->handle = device;
|
||||||
deviceData->valid = true;
|
|
||||||
|
|
||||||
auto userdata = static_cast<DawnCallbackUserdata>(reinterpret_cast<intptr_t>(this));
|
auto userdata = static_cast<DawnCallbackUserdata>(reinterpret_cast<intptr_t>(this));
|
||||||
mProcs.deviceSetErrorCallback(device, ForwardDeviceError, userdata);
|
mProcs.deviceSetErrorCallback(device, ForwardDeviceError, userdata);
|
||||||
|
@ -43,7 +42,6 @@ namespace dawn_wire { namespace server {
|
||||||
|
|
||||||
data->handle = texture;
|
data->handle = texture;
|
||||||
data->serial = generation;
|
data->serial = generation;
|
||||||
data->valid = true;
|
|
||||||
data->allocated = true;
|
data->allocated = true;
|
||||||
|
|
||||||
// The texture is externally owned so it shouldn't be destroyed when we receive a destroy
|
// The texture is externally owned so it shouldn't be destroyed when we receive a destroy
|
||||||
|
|
|
@ -52,17 +52,6 @@ namespace dawn_wire { namespace server {
|
||||||
|
|
||||||
auto userdata = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(data));
|
auto userdata = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(data));
|
||||||
|
|
||||||
if (!buffer->valid) {
|
|
||||||
// Fake the buffer returning a failure, data will be freed in this call.
|
|
||||||
if (isWrite) {
|
|
||||||
ForwardBufferMapWriteAsync(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0,
|
|
||||||
userdata);
|
|
||||||
} else {
|
|
||||||
ForwardBufferMapReadAsync(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0, userdata);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isWrite) {
|
if (isWrite) {
|
||||||
mProcs.bufferMapWriteAsync(buffer->handle, ForwardBufferMapWriteAsync, userdata);
|
mProcs.bufferMapWriteAsync(buffer->handle, ForwardBufferMapWriteAsync, userdata);
|
||||||
} else {
|
} else {
|
||||||
|
@ -79,8 +68,7 @@ namespace dawn_wire { namespace server {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* buffer = BufferObjects().Get(bufferId);
|
auto* buffer = BufferObjects().Get(bufferId);
|
||||||
if (buffer == nullptr || !buffer->valid || buffer->mappedData == nullptr ||
|
if (buffer == nullptr || buffer->mappedData == nullptr || buffer->mappedDataSize != count) {
|
||||||
buffer->mappedDataSize != count) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,12 +158,14 @@ TEST_F(WireArgumentTests, CStringArgument) {
|
||||||
pipelineDescriptor.depthStencilState = &depthStencilState;
|
pipelineDescriptor.depthStencilState = &depthStencilState;
|
||||||
|
|
||||||
dawnDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
dawnDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
||||||
|
|
||||||
|
DawnRenderPipeline apiDummyPipeline = api.GetNewRenderPipeline();
|
||||||
EXPECT_CALL(api,
|
EXPECT_CALL(api,
|
||||||
DeviceCreateRenderPipeline(
|
DeviceCreateRenderPipeline(
|
||||||
apiDevice, MatchesLambda([](const DawnRenderPipelineDescriptor* desc) -> bool {
|
apiDevice, MatchesLambda([](const DawnRenderPipelineDescriptor* desc) -> bool {
|
||||||
return desc->vertexStage->entryPoint == std::string("main");
|
return desc->vertexStage->entryPoint == std::string("main");
|
||||||
})))
|
})))
|
||||||
.WillOnce(Return(nullptr));
|
.WillOnce(Return(apiDummyPipeline));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
@ -247,6 +249,8 @@ TEST_F(WireArgumentTests, StructureOfValuesArgument) {
|
||||||
descriptor.borderColor = DAWN_BORDER_COLOR_TRANSPARENT_BLACK;
|
descriptor.borderColor = DAWN_BORDER_COLOR_TRANSPARENT_BLACK;
|
||||||
|
|
||||||
dawnDeviceCreateSampler(device, &descriptor);
|
dawnDeviceCreateSampler(device, &descriptor);
|
||||||
|
|
||||||
|
DawnSampler apiDummySampler = api.GetNewSampler();
|
||||||
EXPECT_CALL(api, DeviceCreateSampler(
|
EXPECT_CALL(api, DeviceCreateSampler(
|
||||||
apiDevice, MatchesLambda([](const DawnSamplerDescriptor* desc) -> bool {
|
apiDevice, MatchesLambda([](const DawnSamplerDescriptor* desc) -> bool {
|
||||||
return desc->nextInChain == nullptr &&
|
return desc->nextInChain == nullptr &&
|
||||||
|
@ -260,7 +264,7 @@ TEST_F(WireArgumentTests, StructureOfValuesArgument) {
|
||||||
desc->borderColor == DAWN_BORDER_COLOR_TRANSPARENT_BLACK &&
|
desc->borderColor == DAWN_BORDER_COLOR_TRANSPARENT_BLACK &&
|
||||||
desc->lodMinClamp == kLodMin && desc->lodMaxClamp == kLodMax;
|
desc->lodMinClamp == kLodMin && desc->lodMaxClamp == kLodMax;
|
||||||
})))
|
})))
|
||||||
.WillOnce(Return(nullptr));
|
.WillOnce(Return(apiDummySampler));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
@ -281,6 +285,8 @@ TEST_F(WireArgumentTests, StructureOfObjectArrayArgument) {
|
||||||
descriptor.bindGroupLayouts = &bgl;
|
descriptor.bindGroupLayouts = &bgl;
|
||||||
|
|
||||||
dawnDeviceCreatePipelineLayout(device, &descriptor);
|
dawnDeviceCreatePipelineLayout(device, &descriptor);
|
||||||
|
|
||||||
|
DawnPipelineLayout apiDummyLayout = api.GetNewPipelineLayout();
|
||||||
EXPECT_CALL(api, DeviceCreatePipelineLayout(
|
EXPECT_CALL(api, DeviceCreatePipelineLayout(
|
||||||
apiDevice,
|
apiDevice,
|
||||||
MatchesLambda([apiBgl](const DawnPipelineLayoutDescriptor* desc) -> bool {
|
MatchesLambda([apiBgl](const DawnPipelineLayoutDescriptor* desc) -> bool {
|
||||||
|
@ -288,7 +294,7 @@ TEST_F(WireArgumentTests, StructureOfObjectArrayArgument) {
|
||||||
desc->bindGroupLayoutCount == 1 &&
|
desc->bindGroupLayoutCount == 1 &&
|
||||||
desc->bindGroupLayouts[0] == apiBgl;
|
desc->bindGroupLayouts[0] == apiBgl;
|
||||||
})))
|
})))
|
||||||
.WillOnce(Return(nullptr));
|
.WillOnce(Return(apiDummyLayout));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,29 +73,16 @@ class WireBufferMappingTests : public WireTest {
|
||||||
mockBufferMapReadCallback = std::make_unique<StrictMock<MockBufferMapReadCallback>>();
|
mockBufferMapReadCallback = std::make_unique<StrictMock<MockBufferMapReadCallback>>();
|
||||||
mockBufferMapWriteCallback = std::make_unique<StrictMock<MockBufferMapWriteCallback>>();
|
mockBufferMapWriteCallback = std::make_unique<StrictMock<MockBufferMapWriteCallback>>();
|
||||||
|
|
||||||
{
|
DawnBufferDescriptor descriptor;
|
||||||
DawnBufferDescriptor descriptor;
|
descriptor.nextInChain = nullptr;
|
||||||
descriptor.nextInChain = nullptr;
|
|
||||||
|
|
||||||
apiBuffer = api.GetNewBuffer();
|
apiBuffer = api.GetNewBuffer();
|
||||||
buffer = dawnDeviceCreateBuffer(device, &descriptor);
|
buffer = dawnDeviceCreateBuffer(device, &descriptor);
|
||||||
|
|
||||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _))
|
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _))
|
||||||
.WillOnce(Return(apiBuffer))
|
.WillOnce(Return(apiBuffer))
|
||||||
.RetiresOnSaturation();
|
.RetiresOnSaturation();
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
|
||||||
{
|
|
||||||
DawnBufferDescriptor descriptor;
|
|
||||||
descriptor.nextInChain = nullptr;
|
|
||||||
|
|
||||||
errorBuffer = dawnDeviceCreateBuffer(device, &descriptor);
|
|
||||||
|
|
||||||
EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _))
|
|
||||||
.WillOnce(Return(nullptr))
|
|
||||||
.RetiresOnSaturation();
|
|
||||||
FlushClient();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() override {
|
void TearDown() override {
|
||||||
|
@ -117,9 +104,6 @@ class WireBufferMappingTests : public WireTest {
|
||||||
// A successfully created buffer
|
// A successfully created buffer
|
||||||
DawnBuffer buffer;
|
DawnBuffer buffer;
|
||||||
DawnBuffer apiBuffer;
|
DawnBuffer apiBuffer;
|
||||||
|
|
||||||
// An buffer that wasn't created on the server side
|
|
||||||
DawnBuffer errorBuffer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// MapRead-specific tests
|
// MapRead-specific tests
|
||||||
|
@ -171,35 +155,24 @@ TEST_F(WireBufferMappingTests, ErrorWhileMappingForRead) {
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check mapping for reading a buffer that didn't get created on the server side
|
|
||||||
TEST_F(WireBufferMappingTests, MappingForReadErrorBuffer) {
|
|
||||||
DawnCallbackUserdata userdata = 8655;
|
|
||||||
dawnBufferMapReadAsync(errorBuffer, ToMockBufferMapReadCallback, userdata);
|
|
||||||
|
|
||||||
FlushClient();
|
|
||||||
|
|
||||||
EXPECT_CALL(*mockBufferMapReadCallback,
|
|
||||||
Call(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0, userdata))
|
|
||||||
.Times(1);
|
|
||||||
|
|
||||||
FlushServer();
|
|
||||||
|
|
||||||
dawnBufferUnmap(errorBuffer);
|
|
||||||
|
|
||||||
FlushClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the map read callback is called with UNKNOWN when the buffer is destroyed before the
|
// Check that the map read callback is called with UNKNOWN when the buffer is destroyed before the
|
||||||
// request is finished
|
// request is finished
|
||||||
TEST_F(WireBufferMappingTests, DestroyBeforeReadRequestEnd) {
|
TEST_F(WireBufferMappingTests, DestroyBeforeReadRequestEnd) {
|
||||||
DawnCallbackUserdata userdata = 8656;
|
DawnCallbackUserdata userdata = 8656;
|
||||||
dawnBufferMapReadAsync(errorBuffer, ToMockBufferMapReadCallback, userdata);
|
dawnBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, userdata);
|
||||||
|
|
||||||
|
// Return success
|
||||||
|
EXPECT_CALL(api, OnBufferMapReadAsyncCallback(apiBuffer, _, _))
|
||||||
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
|
api.CallMapReadCallback(apiBuffer, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, nullptr, 0);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Destroy before the client gets the success, so the callback is called with unknown.
|
||||||
EXPECT_CALL(*mockBufferMapReadCallback,
|
EXPECT_CALL(*mockBufferMapReadCallback,
|
||||||
Call(DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr, 0, userdata))
|
Call(DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr, 0, userdata))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
dawnBufferRelease(buffer);
|
||||||
dawnBufferRelease(errorBuffer);
|
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
FlushServer();
|
FlushServer();
|
||||||
|
@ -381,35 +354,27 @@ TEST_F(WireBufferMappingTests, ErrorWhileMappingForWrite) {
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check mapping for writing a buffer that didn't get created on the server side
|
|
||||||
TEST_F(WireBufferMappingTests, MappingForWriteErrorBuffer) {
|
|
||||||
DawnCallbackUserdata userdata = 8655;
|
|
||||||
dawnBufferMapWriteAsync(errorBuffer, ToMockBufferMapWriteCallback, userdata);
|
|
||||||
|
|
||||||
FlushClient();
|
|
||||||
|
|
||||||
EXPECT_CALL(*mockBufferMapWriteCallback,
|
|
||||||
Call(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0, userdata))
|
|
||||||
.Times(1);
|
|
||||||
|
|
||||||
FlushServer();
|
|
||||||
|
|
||||||
dawnBufferUnmap(errorBuffer);
|
|
||||||
|
|
||||||
FlushClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the map write callback is called with UNKNOWN when the buffer is destroyed before the
|
// Check that the map write callback is called with UNKNOWN when the buffer is destroyed before the
|
||||||
// request is finished
|
// request is finished
|
||||||
TEST_F(WireBufferMappingTests, DestroyBeforeWriteRequestEnd) {
|
TEST_F(WireBufferMappingTests, DestroyBeforeWriteRequestEnd) {
|
||||||
DawnCallbackUserdata userdata = 8656;
|
DawnCallbackUserdata userdata = 8656;
|
||||||
dawnBufferMapWriteAsync(errorBuffer, ToMockBufferMapWriteCallback, userdata);
|
dawnBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, userdata);
|
||||||
|
|
||||||
|
// Return success
|
||||||
|
EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
|
||||||
|
.WillOnce(InvokeWithoutArgs([&]() {
|
||||||
|
api.CallMapWriteCallback(apiBuffer, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, nullptr, 0);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Destroy before the client gets the success, so the callback is called with unknown.
|
||||||
EXPECT_CALL(*mockBufferMapWriteCallback,
|
EXPECT_CALL(*mockBufferMapWriteCallback,
|
||||||
Call(DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr, 0, userdata))
|
Call(DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr, 0, userdata))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
dawnBufferRelease(buffer);
|
||||||
|
EXPECT_CALL(api, BufferRelease(apiBuffer));
|
||||||
|
|
||||||
dawnBufferRelease(errorBuffer);
|
FlushClient();
|
||||||
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the map read callback is called with UNKNOWN when the map request would have worked, but
|
// Check the map read callback is called with UNKNOWN when the map request would have worked, but
|
||||||
|
|
|
@ -37,7 +37,8 @@ TEST_F(WireInjectTextureTests, CallAfterReserveInject) {
|
||||||
ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation));
|
ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation));
|
||||||
|
|
||||||
dawnTextureCreateDefaultTextureView(reservation.texture);
|
dawnTextureCreateDefaultTextureView(reservation.texture);
|
||||||
EXPECT_CALL(api, TextureCreateDefaultTextureView(apiTexture)).WillOnce(Return(nullptr));
|
DawnTextureView apiDummyView = api.GetNewTextureView();
|
||||||
|
EXPECT_CALL(api, TextureCreateDefaultTextureView(apiTexture)).WillOnce(Return(apiDummyView));
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ TEST_F(WireOptionalTests, OptionalObjectValue) {
|
||||||
bgDesc.bindings = &binding;
|
bgDesc.bindings = &binding;
|
||||||
|
|
||||||
dawnDeviceCreateBindGroup(device, &bgDesc);
|
dawnDeviceCreateBindGroup(device, &bgDesc);
|
||||||
|
|
||||||
|
DawnBindGroup apiDummyBindGroup = api.GetNewBindGroup();
|
||||||
EXPECT_CALL(api, DeviceCreateBindGroup(
|
EXPECT_CALL(api, DeviceCreateBindGroup(
|
||||||
apiDevice, MatchesLambda([](const DawnBindGroupDescriptor* desc) -> bool {
|
apiDevice, MatchesLambda([](const DawnBindGroupDescriptor* desc) -> bool {
|
||||||
return desc->nextInChain == nullptr && desc->bindingCount == 1 &&
|
return desc->nextInChain == nullptr && desc->bindingCount == 1 &&
|
||||||
|
@ -57,7 +59,7 @@ TEST_F(WireOptionalTests, OptionalObjectValue) {
|
||||||
desc->bindings[0].buffer == nullptr &&
|
desc->bindings[0].buffer == nullptr &&
|
||||||
desc->bindings[0].textureView == nullptr;
|
desc->bindings[0].textureView == nullptr;
|
||||||
})))
|
})))
|
||||||
.WillOnce(Return(nullptr));
|
.WillOnce(Return(apiDummyBindGroup));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
@ -147,6 +149,8 @@ TEST_F(WireOptionalTests, OptionalStructPointer) {
|
||||||
// First case: depthStencilState is not null.
|
// First case: depthStencilState is not null.
|
||||||
pipelineDescriptor.depthStencilState = &depthStencilState;
|
pipelineDescriptor.depthStencilState = &depthStencilState;
|
||||||
dawnDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
dawnDeviceCreateRenderPipeline(device, &pipelineDescriptor);
|
||||||
|
|
||||||
|
DawnRenderPipeline apiDummyPipeline = api.GetNewRenderPipeline();
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
api,
|
api,
|
||||||
DeviceCreateRenderPipeline(
|
DeviceCreateRenderPipeline(
|
||||||
|
@ -172,7 +176,7 @@ TEST_F(WireOptionalTests, OptionalStructPointer) {
|
||||||
desc->depthStencilState->stencilReadMask == 0xff &&
|
desc->depthStencilState->stencilReadMask == 0xff &&
|
||||||
desc->depthStencilState->stencilWriteMask == 0xff;
|
desc->depthStencilState->stencilWriteMask == 0xff;
|
||||||
})))
|
})))
|
||||||
.WillOnce(Return(nullptr));
|
.WillOnce(Return(apiDummyPipeline));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
|
|
||||||
|
@ -184,7 +188,7 @@ TEST_F(WireOptionalTests, OptionalStructPointer) {
|
||||||
apiDevice, MatchesLambda([](const DawnRenderPipelineDescriptor* desc) -> bool {
|
apiDevice, MatchesLambda([](const DawnRenderPipelineDescriptor* desc) -> bool {
|
||||||
return desc->depthStencilState == nullptr;
|
return desc->depthStencilState == nullptr;
|
||||||
})))
|
})))
|
||||||
.WillOnce(Return(nullptr));
|
.WillOnce(Return(apiDummyPipeline));
|
||||||
|
|
||||||
FlushClient();
|
FlushClient();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue