dawn_wire: Support deserializing s->c chained structs

Chained structs *may* contain objects which means
deserialization may need an ObjectIdResolver.
However, in practice, we never need to send chained
structs from the server to the client that contain objects for
a valid command.

The one upcoming need for chained server->client structs is to
serialize limit structs.

Because limit structs never need objects, we provide a dummy
implementation of the ObjectIdResolver which always yields an error.
An analogous change is done for ObjectIdProvider.
These classes will be used in a follow-up CL.

Bug: dawn:685
Change-Id: I1c0f3f2d080377f2e1a77bc6e896f24d3d9ab931
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/63981
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Austin Eng 2021-09-10 20:36:20 +00:00 committed by Dawn LUCI CQ
parent 8ee643c9d0
commit dc7971ce58
4 changed files with 58 additions and 18 deletions

View File

@ -57,7 +57,7 @@
{% macro serialize_member(member, in, out) %}
{%- if member.type.category == "object" -%}
{%- set Optional = "Optional" if member.optional else "" -%}
{{out}} = provider.Get{{Optional}}Id({{in}});
WIRE_TRY(provider.Get{{Optional}}Id({{in}}, &{{out}}));
{% elif member.type.category == "structure"%}
{%- set Provider = ", provider" if member.type.may_have_dawn_object else "" -%}
{% if member.annotation == "const*const*" %}
@ -416,8 +416,8 @@ namespace {
}
WireResult {{Cmd}}::Serialize(size_t commandSize, SerializeBuffer* buffer
{%- if not is_return -%}
, const ObjectIdProvider& objectIdProvider
{%- if command.may_have_dawn_object -%}
, const ObjectIdProvider& provider
{%- endif -%}
) const {
{{Name}}Transfer* transfer;
@ -426,7 +426,7 @@ namespace {
WIRE_TRY({{Name}}Serialize(*this, transfer, buffer
{%- if command.may_have_dawn_object -%}
, objectIdProvider
, provider
{%- endif -%}
));
return WireResult::Success;
@ -666,6 +666,36 @@ namespace dawn_wire {
{{ write_command_serialization_methods(command, True) }}
{% endfor %}
// Implementation of ObjectIdResolver that always errors.
// Used when the generator adds a provider argument because of a chained
// struct, but in practice, a chained struct in that location is invalid.
class ErrorObjectIdResolver final : public ObjectIdResolver {
public:
{% for type in by_category["object"] %}
WireResult GetFromId(ObjectId id, {{as_cType(type.name)}}* out) const override {
return WireResult::FatalError;
}
WireResult GetOptionalFromId(ObjectId id, {{as_cType(type.name)}}* out) const override {
return WireResult::FatalError;
}
{% endfor %}
};
// Implementation of ObjectIdProvider that always errors.
// Used when the generator adds a provider argument because of a chained
// struct, but in practice, a chained struct in that location is invalid.
class ErrorObjectIdProvider final : public ObjectIdProvider {
public:
{% for type in by_category["object"] %}
WireResult GetId({{as_cType(type.name)}} object, ObjectId* out) const override {
return WireResult::FatalError;
}
WireResult GetOptionalId({{as_cType(type.name)}} object, ObjectId* out) const override {
return WireResult::FatalError;
}
{% endfor %}
};
// Implementations of serialization/deserialization of WPGUDeviceProperties.
size_t SerializedWGPUDevicePropertiesSize(const WGPUDeviceProperties* deviceProperties) {
return sizeof(WGPUDeviceProperties) +

View File

@ -66,8 +66,8 @@ namespace dawn_wire {
class ObjectIdProvider {
public:
{% for type in by_category["object"] %}
virtual ObjectId GetId({{as_cType(type.name)}} object) const = 0;
virtual ObjectId GetOptionalId({{as_cType(type.name)}} object) const = 0;
virtual WireResult GetId({{as_cType(type.name)}} object, ObjectId* out) const = 0;
virtual WireResult GetOptionalId({{as_cType(type.name)}} object, ObjectId* out) const = 0;
{% endfor %}
};
@ -98,11 +98,17 @@ namespace dawn_wire {
//* Serialize the structure and everything it points to into serializeBuffer which must be
//* big enough to contain all the data (as queried from GetRequiredSize).
WireResult Serialize(size_t commandSize, SerializeBuffer* serializeBuffer
{%- if not is_return_command -%}
, const ObjectIdProvider& objectIdProvider
{%- endif -%}
) const;
{% if command.may_have_dawn_object %}
WireResult Serialize(size_t commandSize, SerializeBuffer* serializeBuffer, const ObjectIdProvider& objectIdProvider) const;
{% else %}
WireResult Serialize(size_t commandSize, SerializeBuffer* serializeBuffer) const;
// Override which drops the provider if it's not needed.
WireResult Serialize(size_t commandSize,
SerializeBuffer* serializeBuffer,
const ObjectIdProvider&) const {
return Serialize(commandSize, serializeBuffer);
}
{% endif %}
//* Deserializes the structure from a buffer, consuming a maximum of *size bytes. When this
//* function returns, buffer and size will be updated by the number of bytes consumed to

View File

@ -49,14 +49,18 @@ namespace dawn_wire { namespace client {
private:
// Implementation of the ObjectIdProvider interface
{% for type in by_category["object"] %}
ObjectId GetId({{as_cType(type.name)}} object) const final {
return object == nullptr ? 0 : reinterpret_cast<{{as_wireType(type)}}>(object)->id;
}
ObjectId GetOptionalId({{as_cType(type.name)}} object) const final {
WireResult GetId({{as_cType(type.name)}} object, ObjectId* out) const final {
ASSERT(out != nullptr);
if (object == nullptr) {
return 0;
return WireResult::FatalError;
}
return GetId(object);
*out = reinterpret_cast<{{as_wireType(type)}}>(object)->id;
return WireResult::Success;
}
WireResult GetOptionalId({{as_cType(type.name)}} object, ObjectId* out) const final {
ASSERT(out != nullptr);
*out = (object == nullptr ? 0 : reinterpret_cast<{{as_wireType(type)}}>(object)->id);
return WireResult::Success;
}
{% endfor %}

View File

@ -21,7 +21,7 @@ class WireWGPUDevicePropertiesTests : public testing::Test {};
// Test that the serialization and deserialization of WGPUDeviceProperties can work correctly.
TEST_F(WireWGPUDevicePropertiesTests, SerializeWGPUDeviceProperties) {
WGPUDeviceProperties sentWGPUDeviceProperties;
WGPUDeviceProperties sentWGPUDeviceProperties = {};
sentWGPUDeviceProperties.textureCompressionBC = true;
// Set false to test that the serialization can handle both true and false correctly.
sentWGPUDeviceProperties.pipelineStatisticsQuery = false;