Corentin Wallez | 4a9ef4e | 2018-07-18 11:40:26 +0200 | [diff] [blame] | 1 | //* Copyright 2017 The Dawn Authors |
Corentin Wallez | f07e3bd | 2017-04-20 14:38:20 -0400 | [diff] [blame] | 2 | //* |
| 3 | //* Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | //* you may not use this file except in compliance with the License. |
| 5 | //* You may obtain a copy of the License at |
| 6 | //* |
| 7 | //* http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | //* |
| 9 | //* Unless required by applicable law or agreed to in writing, software |
| 10 | //* distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | //* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | //* See the License for the specific language governing permissions and |
| 13 | //* limitations under the License. |
| 14 | |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 15 | #include "dawn_wire/WireCmd_autogen.h" |
Corentin Wallez | f07e3bd | 2017-04-20 14:38:20 -0400 | [diff] [blame] | 16 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 17 | #include "common/Assert.h" |
Austin Eng | 65a903b | 2021-02-01 16:48:18 +0000 | [diff] [blame] | 18 | #include "common/Log.h" |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 19 | #include "dawn_wire/BufferConsumer_impl.h" |
Jiawei Shao | 5c2f5f3 | 2019-10-20 03:01:56 +0000 | [diff] [blame] | 20 | #include "dawn_wire/Wire.h" |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 21 | |
Austin Eng | 8eb8385 | 2019-10-07 20:38:47 +0000 | [diff] [blame] | 22 | #include <algorithm> |
Corentin Wallez | 88fb8fa | 2018-06-06 17:36:49 +0200 | [diff] [blame] | 23 | #include <cstring> |
Corentin Wallez | a19c759 | 2019-01-04 09:54:10 +0000 | [diff] [blame] | 24 | #include <limits> |
Corentin Wallez | 88fb8fa | 2018-06-06 17:36:49 +0200 | [diff] [blame] | 25 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 26 | //* Helper macros so that the main [de]serialization functions can be written in a generic manner. |
| 27 | |
| 28 | //* Outputs an rvalue that's the number of elements a pointer member points to. |
| 29 | {% macro member_length(member, record_accessor) -%} |
| 30 | {%- if member.length == "constant" -%} |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 31 | {{member.constant_length}}u |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 32 | {%- else -%} |
| 33 | {{record_accessor}}{{as_varName(member.length.name)}} |
| 34 | {%- endif -%} |
| 35 | {%- endmacro %} |
| 36 | |
| 37 | //* Outputs the type that will be used on the wire for the member |
| 38 | {% macro member_transfer_type(member) -%} |
| 39 | {%- if member.type.category == "object" -%} |
| 40 | ObjectId |
| 41 | {%- elif member.type.category == "structure" -%} |
| 42 | {{as_cType(member.type.name)}}Transfer |
Corentin Wallez | 919812e | 2019-10-17 08:46:07 +0000 | [diff] [blame] | 43 | {%- elif member.type.category == "bitmask" -%} |
| 44 | {{as_cType(member.type.name)}}Flags |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 45 | {%- else -%} |
Austin Eng | f104fea | 2021-02-18 22:36:19 +0000 | [diff] [blame] | 46 | {{ assert(as_cType(member.type.name) != "size_t") }} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 47 | {{as_cType(member.type.name)}} |
| 48 | {%- endif -%} |
| 49 | {%- endmacro %} |
| 50 | |
| 51 | //* Outputs the size of one element of the type that will be used on the wire for the member |
| 52 | {% macro member_transfer_sizeof(member) -%} |
| 53 | sizeof({{member_transfer_type(member)}}) |
| 54 | {%- endmacro %} |
| 55 | |
| 56 | //* Outputs the serialization code to put `in` in `out` |
| 57 | {% macro serialize_member(member, in, out) %} |
| 58 | {%- if member.type.category == "object" -%} |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 59 | {%- set Optional = "Optional" if member.optional else "" -%} |
Austin Eng | dc7971c | 2021-09-10 20:36:20 +0000 | [diff] [blame] | 60 | WIRE_TRY(provider.Get{{Optional}}Id({{in}}, &{{out}})); |
Yunchao He | c0f31e7 | 2019-01-21 08:29:01 +0000 | [diff] [blame] | 61 | {% elif member.type.category == "structure"%} |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 62 | {%- set Provider = ", provider" if member.type.may_have_dawn_object else "" -%} |
Yunchao He | c0f31e7 | 2019-01-21 08:29:01 +0000 | [diff] [blame] | 63 | {% if member.annotation == "const*const*" %} |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 64 | WIRE_TRY({{as_cType(member.type.name)}}Serialize(*{{in}}, &{{out}}, buffer{{Provider}})); |
Yunchao He | c0f31e7 | 2019-01-21 08:29:01 +0000 | [diff] [blame] | 65 | {% else %} |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 66 | WIRE_TRY({{as_cType(member.type.name)}}Serialize({{in}}, &{{out}}, buffer{{Provider}})); |
Yunchao He | c0f31e7 | 2019-01-21 08:29:01 +0000 | [diff] [blame] | 67 | {% endif %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 68 | {%- else -%} |
| 69 | {{out}} = {{in}}; |
| 70 | {%- endif -%} |
| 71 | {% endmacro %} |
| 72 | |
| 73 | //* Outputs the deserialization code to put `in` in `out` |
| 74 | {% macro deserialize_member(member, in, out) %} |
| 75 | {%- if member.type.category == "object" -%} |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 76 | {%- set Optional = "Optional" if member.optional else "" -%} |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 77 | WIRE_TRY(resolver.Get{{Optional}}FromId({{in}}, &{{out}})); |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 78 | {%- elif member.type.category == "structure" -%} |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 79 | WIRE_TRY({{as_cType(member.type.name)}}Deserialize(&{{out}}, &{{in}}, deserializeBuffer, allocator |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 80 | {%- if member.type.may_have_dawn_object -%} |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 81 | , resolver |
| 82 | {%- endif -%} |
| 83 | )); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 84 | {%- else -%} |
Austin Eng | f104fea | 2021-02-18 22:36:19 +0000 | [diff] [blame] | 85 | static_assert(sizeof({{out}}) >= sizeof({{in}}), "Deserialize assignment may not narrow."); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 86 | {{out}} = {{in}}; |
| 87 | {%- endif -%} |
| 88 | {% endmacro %} |
| 89 | |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 90 | namespace { |
| 91 | |
| 92 | struct WGPUChainedStructTransfer { |
| 93 | WGPUSType sType; |
| 94 | bool hasNext; |
| 95 | }; |
| 96 | |
| 97 | } // anonymous namespace |
| 98 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 99 | //* The main [de]serialization macro |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 100 | //* Methods are very similar to structures that have one member corresponding to each arguments. |
| 101 | //* This macro takes advantage of the similarity to output [de]serialization code for a record |
| 102 | //* that is either a structure or a method, with some special cases for each. |
Corentin Wallez | cb2c64f | 2019-04-01 21:04:17 +0000 | [diff] [blame] | 103 | {% macro write_record_serialization_helpers(record, name, members, is_cmd=False, is_return_command=False) %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 104 | {% set Return = "Return" if is_return_command else "" %} |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 105 | {% set Cmd = "Cmd" if is_cmd else "" %} |
Austin Eng | cac0442 | 2020-10-13 22:35:34 +0000 | [diff] [blame] | 106 | {% set Inherits = " : CmdHeader" if is_cmd else "" %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 107 | |
| 108 | //* Structure for the wire format of each of the records. Members that are values |
| 109 | //* are embedded directly in the structure. Other members are assumed to be in the |
| 110 | //* memory directly following the structure in the buffer. |
Austin Eng | cac0442 | 2020-10-13 22:35:34 +0000 | [diff] [blame] | 111 | struct {{Return}}{{name}}Transfer{{Inherits}} { |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 112 | static_assert({{[is_cmd, record.extensible, record.chained].count(True)}} <= 1, |
| 113 | "Record must be at most one of is_cmd, extensible, and chained."); |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 114 | {% if is_cmd %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 115 | //* Start the transfer structure with the command ID, so that casting to WireCmd gives the ID. |
Corentin Wallez | bdc8677 | 2018-07-26 15:07:57 +0200 | [diff] [blame] | 116 | {{Return}}WireCmd commandId; |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 117 | {% elif record.extensible %} |
| 118 | bool hasNextInChain; |
| 119 | {% elif record.chained %} |
| 120 | WGPUChainedStructTransfer chain; |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 121 | {% endif %} |
| 122 | |
| 123 | //* Value types are directly in the command, objects being replaced with their IDs. |
| 124 | {% for member in members if member.annotation == "value" %} |
| 125 | {{member_transfer_type(member)}} {{as_varName(member.name)}}; |
| 126 | {% endfor %} |
| 127 | |
| 128 | //* const char* have their length embedded directly in the command. |
| 129 | {% for member in members if member.length == "strlen" %} |
Austin Eng | f104fea | 2021-02-18 22:36:19 +0000 | [diff] [blame] | 130 | uint64_t {{as_varName(member.name)}}Strlen; |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 131 | {% endfor %} |
Corentin Wallez | f872e69 | 2019-02-13 10:15:38 +0000 | [diff] [blame] | 132 | |
Austin Eng | 4379e8f | 2019-10-02 06:35:08 +0000 | [diff] [blame] | 133 | {% for member in members if member.optional and member.annotation != "value" and member.type.category != "object" %} |
Corentin Wallez | f872e69 | 2019-02-13 10:15:38 +0000 | [diff] [blame] | 134 | bool has_{{as_varName(member.name)}}; |
| 135 | {% endfor %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 136 | }; |
| 137 | |
Austin Eng | cac0442 | 2020-10-13 22:35:34 +0000 | [diff] [blame] | 138 | {% if is_cmd %} |
| 139 | static_assert(offsetof({{Return}}{{name}}Transfer, commandSize) == 0, ""); |
| 140 | static_assert(offsetof({{Return}}{{name}}Transfer, commandId) == sizeof(CmdHeader), ""); |
| 141 | {% endif %} |
| 142 | |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 143 | {% if record.chained %} |
| 144 | static_assert(offsetof({{Return}}{{name}}Transfer, chain) == 0, ""); |
| 145 | {% endif %} |
| 146 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 147 | //* Returns the required transfer size for `record` in addition to the transfer structure. |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 148 | DAWN_DECLARE_UNUSED size_t {{Return}}{{name}}GetExtraRequiredSize(const {{Return}}{{name}}{{Cmd}}& record) { |
Corentin Wallez | 83a9c9d | 2018-07-18 13:37:54 +0200 | [diff] [blame] | 149 | DAWN_UNUSED(record); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 150 | |
| 151 | size_t result = 0; |
| 152 | |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 153 | //* Gather how much space will be needed for the extension chain. |
| 154 | {% if record.extensible %} |
| 155 | if (record.nextInChain != nullptr) { |
| 156 | result += GetChainedStructExtraRequiredSize(record.nextInChain); |
| 157 | } |
| 158 | {% endif %} |
| 159 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 160 | //* Special handling of const char* that have their length embedded directly in the command |
| 161 | {% for member in members if member.length == "strlen" %} |
François Beaufort | f622a44 | 2019-09-27 21:25:43 +0000 | [diff] [blame] | 162 | {% set memberName = as_varName(member.name) %} |
| 163 | |
| 164 | {% if member.optional %} |
| 165 | bool has_{{memberName}} = record.{{memberName}} != nullptr; |
| 166 | if (has_{{memberName}}) |
| 167 | {% endif %} |
| 168 | { |
| 169 | result += std::strlen(record.{{memberName}}); |
| 170 | } |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 171 | {% endfor %} |
| 172 | |
| 173 | //* Gather how much space will be needed for pointer members. |
Corentin Wallez | c6c7a42 | 2019-09-05 09:35:07 +0000 | [diff] [blame] | 174 | {% for member in members if member.length != "strlen" and not member.skip_serialize %} |
Corentin Wallez | f872e69 | 2019-02-13 10:15:38 +0000 | [diff] [blame] | 175 | {% if member.type.category != "object" and member.optional %} |
| 176 | if (record.{{as_varName(member.name)}} != nullptr) |
| 177 | {% endif %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 178 | { |
Corentin Wallez | c6c7a42 | 2019-09-05 09:35:07 +0000 | [diff] [blame] | 179 | {% if member.annotation != "value" %} |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 180 | auto memberLength = {{member_length(member, "record.")}}; |
Corentin Wallez | c6c7a42 | 2019-09-05 09:35:07 +0000 | [diff] [blame] | 181 | result += memberLength * {{member_transfer_sizeof(member)}}; |
| 182 | //* Structures might contain more pointers so we need to add their extra size as well. |
| 183 | {% if member.type.category == "structure" %} |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 184 | for (decltype(memberLength) i = 0; i < memberLength; ++i) { |
Corentin Wallez | c6c7a42 | 2019-09-05 09:35:07 +0000 | [diff] [blame] | 185 | {% if member.annotation == "const*const*" %} |
| 186 | result += {{as_cType(member.type.name)}}GetExtraRequiredSize(*record.{{as_varName(member.name)}}[i]); |
| 187 | {% else %} |
| 188 | {{assert(member.annotation == "const*")}} |
| 189 | result += {{as_cType(member.type.name)}}GetExtraRequiredSize(record.{{as_varName(member.name)}}[i]); |
| 190 | {% endif %} |
| 191 | } |
| 192 | {% endif %} |
| 193 | {% elif member.type.category == "structure" %} |
| 194 | result += {{as_cType(member.type.name)}}GetExtraRequiredSize(record.{{as_varName(member.name)}}); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 195 | {% endif %} |
| 196 | } |
| 197 | {% endfor %} |
| 198 | |
| 199 | return result; |
| 200 | } |
Corentin Wallez | 03e1813 | 2018-09-17 22:59:08 +0000 | [diff] [blame] | 201 | // GetExtraRequiredSize isn't used for structures that are value members of other structures |
| 202 | // because we assume they cannot contain pointers themselves. |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 203 | DAWN_UNUSED_FUNC({{Return}}{{name}}GetExtraRequiredSize); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 204 | |
| 205 | //* Serializes `record` into `transfer`, using `buffer` to get more space for pointed-to data |
| 206 | //* and `provider` to serialize objects. |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 207 | DAWN_DECLARE_UNUSED WireResult {{Return}}{{name}}Serialize(const {{Return}}{{name}}{{Cmd}}& record, {{Return}}{{name}}Transfer* transfer, |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 208 | SerializeBuffer* buffer |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 209 | {%- if record.may_have_dawn_object -%} |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 210 | , const ObjectIdProvider& provider |
| 211 | {%- endif -%} |
| 212 | ) { |
Corentin Wallez | 83a9c9d | 2018-07-18 13:37:54 +0200 | [diff] [blame] | 213 | DAWN_UNUSED(buffer); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 214 | |
| 215 | //* Handle special transfer members of methods. |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 216 | {% if is_cmd %} |
Corentin Wallez | bdc8677 | 2018-07-26 15:07:57 +0200 | [diff] [blame] | 217 | transfer->commandId = {{Return}}WireCmd::{{name}}; |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 218 | {% endif %} |
| 219 | |
| 220 | //* Value types are directly in the transfer record, objects being replaced with their IDs. |
| 221 | {% for member in members if member.annotation == "value" %} |
| 222 | {% set memberName = as_varName(member.name) %} |
| 223 | {{serialize_member(member, "record." + memberName, "transfer->" + memberName)}} |
| 224 | {% endfor %} |
| 225 | |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 226 | {% if record.extensible %} |
| 227 | if (record.nextInChain != nullptr) { |
| 228 | transfer->hasNextInChain = true; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 229 | WIRE_TRY(SerializeChainedStruct(record.nextInChain, buffer, provider)); |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 230 | } else { |
| 231 | transfer->hasNextInChain = false; |
| 232 | } |
| 233 | {% endif %} |
| 234 | |
| 235 | {% if record.chained %} |
| 236 | //* Should be set by the root descriptor's call to SerializeChainedStruct. |
| 237 | ASSERT(transfer->chain.sType == {{as_cEnum(types["s type"].name, record.name)}}); |
| 238 | ASSERT(transfer->chain.hasNext == (record.chain.next != nullptr)); |
| 239 | {% endif %} |
| 240 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 241 | //* Special handling of const char* that have their length embedded directly in the command |
| 242 | {% for member in members if member.length == "strlen" %} |
| 243 | {% set memberName = as_varName(member.name) %} |
François Beaufort | f622a44 | 2019-09-27 21:25:43 +0000 | [diff] [blame] | 244 | |
François Beaufort | f622a44 | 2019-09-27 21:25:43 +0000 | [diff] [blame] | 245 | {% if member.optional %} |
Austin Eng | 4379e8f | 2019-10-02 06:35:08 +0000 | [diff] [blame] | 246 | bool has_{{memberName}} = record.{{memberName}} != nullptr; |
| 247 | transfer->has_{{memberName}} = has_{{memberName}}; |
François Beaufort | f622a44 | 2019-09-27 21:25:43 +0000 | [diff] [blame] | 248 | if (has_{{memberName}}) |
| 249 | {% endif %} |
| 250 | { |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 251 | transfer->{{memberName}}Strlen = std::strlen(record.{{memberName}}); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 252 | |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 253 | char* stringInBuffer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 254 | WIRE_TRY(buffer->NextN(transfer->{{memberName}}Strlen, &stringInBuffer)); |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 255 | memcpy(stringInBuffer, record.{{memberName}}, transfer->{{memberName}}Strlen); |
François Beaufort | f622a44 | 2019-09-27 21:25:43 +0000 | [diff] [blame] | 256 | } |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 257 | {% endfor %} |
| 258 | |
| 259 | //* Allocate space and write the non-value arguments in it. |
Austin Eng | 6a5418a | 2019-07-19 16:01:48 +0000 | [diff] [blame] | 260 | {% for member in members if member.annotation != "value" and member.length != "strlen" and not member.skip_serialize %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 261 | {% set memberName = as_varName(member.name) %} |
Corentin Wallez | f872e69 | 2019-02-13 10:15:38 +0000 | [diff] [blame] | 262 | |
| 263 | {% if member.type.category != "object" and member.optional %} |
| 264 | bool has_{{memberName}} = record.{{memberName}} != nullptr; |
| 265 | transfer->has_{{memberName}} = has_{{memberName}}; |
| 266 | if (has_{{memberName}}) |
| 267 | {% endif %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 268 | { |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 269 | auto memberLength = {{member_length(member, "record.")}}; |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 270 | |
| 271 | {{member_transfer_type(member)}}* memberBuffer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 272 | WIRE_TRY(buffer->NextN(memberLength, &memberBuffer)); |
Corentin Wallez | c6c7a42 | 2019-09-05 09:35:07 +0000 | [diff] [blame] | 273 | |
Austin Eng | 5eb496b | 2021-02-24 18:39:31 +0000 | [diff] [blame] | 274 | //* This loop cannot overflow because it iterates up to |memberLength|. Even if |
| 275 | //* memberLength were the maximum integer value, |i| would become equal to it just before |
| 276 | //* exiting the loop, but not increment past or wrap around. |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 277 | for (decltype(memberLength) i = 0; i < memberLength; ++i) { |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 278 | {{serialize_member(member, "record." + memberName + "[i]", "memberBuffer[i]" )}} |
| 279 | } |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 280 | } |
| 281 | {% endfor %} |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 282 | return WireResult::Success; |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 283 | } |
Austin Eng | 740995c | 2019-05-15 18:55:22 +0000 | [diff] [blame] | 284 | DAWN_UNUSED_FUNC({{Return}}{{name}}Serialize); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 285 | |
| 286 | //* Deserializes `transfer` into `record` getting more serialized data from `buffer` and `size` |
| 287 | //* if needed, using `allocator` to store pointed-to values and `resolver` to translate object |
| 288 | //* Ids to actual objects. |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 289 | DAWN_DECLARE_UNUSED WireResult {{Return}}{{name}}Deserialize({{Return}}{{name}}{{Cmd}}* record, const volatile {{Return}}{{name}}Transfer* transfer, |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 290 | DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 291 | {%- if record.may_have_dawn_object -%} |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 292 | , const ObjectIdResolver& resolver |
| 293 | {%- endif -%} |
| 294 | ) { |
Corentin Wallez | 83a9c9d | 2018-07-18 13:37:54 +0200 | [diff] [blame] | 295 | DAWN_UNUSED(allocator); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 296 | |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 297 | {% if is_cmd %} |
| 298 | ASSERT(transfer->commandId == {{Return}}WireCmd::{{name}}); |
| 299 | {% endif %} |
| 300 | |
Corentin Wallez | cb2c64f | 2019-04-01 21:04:17 +0000 | [diff] [blame] | 301 | {% if record.derived_method %} |
| 302 | record->selfId = transfer->self; |
| 303 | {% endif %} |
| 304 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 305 | //* Value types are directly in the transfer record, objects being replaced with their IDs. |
| 306 | {% for member in members if member.annotation == "value" %} |
| 307 | {% set memberName = as_varName(member.name) %} |
| 308 | {{deserialize_member(member, "transfer->" + memberName, "record->" + memberName)}} |
| 309 | {% endfor %} |
| 310 | |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 311 | {% if record.extensible %} |
| 312 | record->nextInChain = nullptr; |
| 313 | if (transfer->hasNextInChain) { |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 314 | WIRE_TRY(DeserializeChainedStruct(&record->nextInChain, deserializeBuffer, allocator, resolver)); |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 315 | } |
| 316 | {% endif %} |
| 317 | |
| 318 | {% if record.chained %} |
| 319 | //* Should be set by the root descriptor's call to DeserializeChainedStruct. |
| 320 | //* Don't check |record->chain.next| matches because it is not set until the |
| 321 | //* next iteration inside DeserializeChainedStruct. |
| 322 | ASSERT(record->chain.sType == {{as_cEnum(types["s type"].name, record.name)}}); |
| 323 | ASSERT(record->chain.next == nullptr); |
| 324 | {% endif %} |
| 325 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 326 | //* Special handling of const char* that have their length embedded directly in the command |
| 327 | {% for member in members if member.length == "strlen" %} |
| 328 | {% set memberName = as_varName(member.name) %} |
François Beaufort | f622a44 | 2019-09-27 21:25:43 +0000 | [diff] [blame] | 329 | |
Austin Eng | 4379e8f | 2019-10-02 06:35:08 +0000 | [diff] [blame] | 330 | {% if member.optional %} |
Austin Eng | 8eb8385 | 2019-10-07 20:38:47 +0000 | [diff] [blame] | 331 | bool has_{{memberName}} = transfer->has_{{memberName}}; |
| 332 | record->{{memberName}} = nullptr; |
| 333 | if (has_{{memberName}}) |
Austin Eng | 4379e8f | 2019-10-02 06:35:08 +0000 | [diff] [blame] | 334 | {% endif %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 335 | { |
Austin Eng | f104fea | 2021-02-18 22:36:19 +0000 | [diff] [blame] | 336 | uint64_t stringLength64 = transfer->{{memberName}}Strlen; |
| 337 | if (stringLength64 >= std::numeric_limits<size_t>::max()) { |
| 338 | //* Cannot allocate space for the string. It can be at most |
| 339 | //* size_t::max() - 1. We need 1 byte for the null-terminator. |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 340 | return WireResult::FatalError; |
Austin Eng | b921b7d | 2021-02-18 18:45:09 +0000 | [diff] [blame] | 341 | } |
Austin Eng | f104fea | 2021-02-18 22:36:19 +0000 | [diff] [blame] | 342 | size_t stringLength = static_cast<size_t>(stringLength64); |
Austin Eng | b921b7d | 2021-02-18 18:45:09 +0000 | [diff] [blame] | 343 | |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 344 | const volatile char* stringInBuffer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 345 | WIRE_TRY(deserializeBuffer->ReadN(stringLength, &stringInBuffer)); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 346 | |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 347 | char* copiedString; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 348 | WIRE_TRY(GetSpace(allocator, stringLength + 1, &copiedString)); |
Austin Eng | f104fea | 2021-02-18 22:36:19 +0000 | [diff] [blame] | 349 | //* We can cast away the volatile qualifier because DeserializeBuffer::ReadN already |
| 350 | //* validated that the range [stringInBuffer, stringInBuffer + stringLength) is valid. |
Austin Eng | b921b7d | 2021-02-18 18:45:09 +0000 | [diff] [blame] | 351 | //* memcpy may have an unknown access pattern, but this is fine since the string is only |
| 352 | //* data and won't affect control flow of this function. |
| 353 | memcpy(copiedString, const_cast<const char*>(stringInBuffer), stringLength); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 354 | copiedString[stringLength] = '\0'; |
| 355 | record->{{memberName}} = copiedString; |
| 356 | } |
| 357 | {% endfor %} |
| 358 | |
| 359 | //* Get extra buffer data, and copy pointed to values in extra allocated space. |
| 360 | {% for member in members if member.annotation != "value" and member.length != "strlen" %} |
| 361 | {% set memberName = as_varName(member.name) %} |
Corentin Wallez | f872e69 | 2019-02-13 10:15:38 +0000 | [diff] [blame] | 362 | |
| 363 | {% if member.type.category != "object" and member.optional %} |
Corentin Wallez | 75f554d | 2021-06-17 16:04:29 +0000 | [diff] [blame] | 364 | //* Non-constant length optional members use length=0 to denote they aren't present. |
| 365 | //* Otherwise we could have length=N and has_member=false, causing reads from an |
| 366 | //* uninitialized pointer. |
| 367 | {{ assert(member.length == "constant") }} |
Corentin Wallez | f872e69 | 2019-02-13 10:15:38 +0000 | [diff] [blame] | 368 | bool has_{{memberName}} = transfer->has_{{memberName}}; |
| 369 | record->{{memberName}} = nullptr; |
| 370 | if (has_{{memberName}}) |
| 371 | {% endif %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 372 | { |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 373 | auto memberLength = {{member_length(member, "record->")}}; |
| 374 | const volatile {{member_transfer_type(member)}}* memberBuffer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 375 | WIRE_TRY(deserializeBuffer->ReadN(memberLength, &memberBuffer)); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 376 | |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 377 | {{as_cType(member.type.name)}}* copiedMembers; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 378 | WIRE_TRY(GetSpace(allocator, memberLength, &copiedMembers)); |
Yunchao He | c0f31e7 | 2019-01-21 08:29:01 +0000 | [diff] [blame] | 379 | {% if member.annotation == "const*const*" %} |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 380 | {{as_cType(member.type.name)}}** pointerArray; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 381 | WIRE_TRY(GetSpace(allocator, memberLength, &pointerArray)); |
| 382 | |
Austin Eng | 5eb496b | 2021-02-24 18:39:31 +0000 | [diff] [blame] | 383 | //* This loop cannot overflow because it iterates up to |memberLength|. Even if |
| 384 | //* memberLength were the maximum integer value, |i| would become equal to it just before |
| 385 | //* exiting the loop, but not increment past or wrap around. |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 386 | for (decltype(memberLength) i = 0; i < memberLength; ++i) { |
Yunchao He | c0f31e7 | 2019-01-21 08:29:01 +0000 | [diff] [blame] | 387 | pointerArray[i] = &copiedMembers[i]; |
| 388 | } |
| 389 | record->{{memberName}} = pointerArray; |
| 390 | {% else %} |
| 391 | record->{{memberName}} = copiedMembers; |
| 392 | {% endif %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 393 | |
Austin Eng | 5eb496b | 2021-02-24 18:39:31 +0000 | [diff] [blame] | 394 | //* This loop cannot overflow because it iterates up to |memberLength|. Even if |
| 395 | //* memberLength were the maximum integer value, |i| would become equal to it just before |
| 396 | //* exiting the loop, but not increment past or wrap around. |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 397 | for (decltype(memberLength) i = 0; i < memberLength; ++i) { |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 398 | {{deserialize_member(member, "memberBuffer[i]", "copiedMembers[i]")}} |
| 399 | } |
| 400 | } |
| 401 | {% endfor %} |
| 402 | |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 403 | return WireResult::Success; |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 404 | } |
Austin Eng | 740995c | 2019-05-15 18:55:22 +0000 | [diff] [blame] | 405 | DAWN_UNUSED_FUNC({{Return}}{{name}}Deserialize); |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 406 | {% endmacro %} |
| 407 | |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 408 | {% macro write_command_serialization_methods(command, is_return) %} |
| 409 | {% set Return = "Return" if is_return else "" %} |
| 410 | {% set Name = Return + command.name.CamelCase() %} |
| 411 | {% set Cmd = Name + "Cmd" %} |
| 412 | |
| 413 | size_t {{Cmd}}::GetRequiredSize() const { |
| 414 | size_t size = sizeof({{Name}}Transfer) + {{Name}}GetExtraRequiredSize(*this); |
| 415 | return size; |
| 416 | } |
| 417 | |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 418 | WireResult {{Cmd}}::Serialize(size_t commandSize, SerializeBuffer* buffer |
Austin Eng | dc7971c | 2021-09-10 20:36:20 +0000 | [diff] [blame] | 419 | {%- if command.may_have_dawn_object -%} |
| 420 | , const ObjectIdProvider& provider |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 421 | {%- endif -%} |
| 422 | ) const { |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 423 | {{Name}}Transfer* transfer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 424 | WIRE_TRY(buffer->Next(&transfer)); |
Austin Eng | cac0442 | 2020-10-13 22:35:34 +0000 | [diff] [blame] | 425 | transfer->commandSize = commandSize; |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 426 | |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 427 | WIRE_TRY({{Name}}Serialize(*this, transfer, buffer |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 428 | {%- if command.may_have_dawn_object -%} |
Austin Eng | dc7971c | 2021-09-10 20:36:20 +0000 | [diff] [blame] | 429 | , provider |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 430 | {%- endif -%} |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 431 | )); |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 432 | return WireResult::Success; |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 433 | } |
| 434 | |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 435 | WireResult {{Cmd}}::Deserialize(DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 436 | {%- if command.may_have_dawn_object -%} |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 437 | , const ObjectIdResolver& resolver |
| 438 | {%- endif -%} |
| 439 | ) { |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 440 | const volatile {{Name}}Transfer* transfer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 441 | WIRE_TRY(deserializeBuffer->Read(&transfer)); |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 442 | |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 443 | return {{Name}}Deserialize(this, transfer, deserializeBuffer, allocator |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 444 | {%- if command.may_have_dawn_object -%} |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 445 | , resolver |
| 446 | {%- endif -%} |
| 447 | ); |
| 448 | } |
| 449 | {% endmacro %} |
| 450 | |
Corentin Wallez | bdc8677 | 2018-07-26 15:07:57 +0200 | [diff] [blame] | 451 | namespace dawn_wire { |
Corentin Wallez | 88fb8fa | 2018-06-06 17:36:49 +0200 | [diff] [blame] | 452 | |
Austin Eng | 8eb8385 | 2019-10-07 20:38:47 +0000 | [diff] [blame] | 453 | ObjectHandle::ObjectHandle() = default; |
Austin Eng | 518c8e7 | 2020-04-13 17:50:51 +0000 | [diff] [blame] | 454 | ObjectHandle::ObjectHandle(ObjectId id, ObjectGeneration generation) |
| 455 | : id(id), generation(generation) { |
| 456 | } |
Corentin Wallez | 00b90ea | 2020-04-24 17:02:53 +0000 | [diff] [blame] | 457 | |
Austin Eng | 518c8e7 | 2020-04-13 17:50:51 +0000 | [diff] [blame] | 458 | ObjectHandle::ObjectHandle(const volatile ObjectHandle& rhs) |
| 459 | : id(rhs.id), generation(rhs.generation) { |
| 460 | } |
Corentin Wallez | 00b90ea | 2020-04-24 17:02:53 +0000 | [diff] [blame] | 461 | ObjectHandle& ObjectHandle::operator=(const volatile ObjectHandle& rhs) { |
| 462 | id = rhs.id; |
| 463 | generation = rhs.generation; |
| 464 | return *this; |
| 465 | } |
| 466 | |
Austin Eng | b0cdf95 | 2019-10-15 07:30:35 +0000 | [diff] [blame] | 467 | ObjectHandle& ObjectHandle::AssignFrom(const ObjectHandle& rhs) { |
| 468 | id = rhs.id; |
Austin Eng | 518c8e7 | 2020-04-13 17:50:51 +0000 | [diff] [blame] | 469 | generation = rhs.generation; |
Austin Eng | b0cdf95 | 2019-10-15 07:30:35 +0000 | [diff] [blame] | 470 | return *this; |
| 471 | } |
| 472 | ObjectHandle& ObjectHandle::AssignFrom(const volatile ObjectHandle& rhs) { |
Austin Eng | 8eb8385 | 2019-10-07 20:38:47 +0000 | [diff] [blame] | 473 | id = rhs.id; |
Austin Eng | 518c8e7 | 2020-04-13 17:50:51 +0000 | [diff] [blame] | 474 | generation = rhs.generation; |
Austin Eng | 8eb8385 | 2019-10-07 20:38:47 +0000 | [diff] [blame] | 475 | return *this; |
| 476 | } |
| 477 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 478 | namespace { |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 479 | // Allocates enough space from allocator to countain T[count] and return it in out. |
| 480 | // Return FatalError if the allocator couldn't allocate the memory. |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 481 | // Always writes to |out| on success. |
| 482 | template <typename T, typename N> |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 483 | WireResult GetSpace(DeserializeAllocator* allocator, N count, T** out) { |
Corentin Wallez | a19c759 | 2019-01-04 09:54:10 +0000 | [diff] [blame] | 484 | constexpr size_t kMaxCountWithoutOverflows = std::numeric_limits<size_t>::max() / sizeof(T); |
| 485 | if (count > kMaxCountWithoutOverflows) { |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 486 | return WireResult::FatalError; |
Corentin Wallez | a19c759 | 2019-01-04 09:54:10 +0000 | [diff] [blame] | 487 | } |
| 488 | |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 489 | size_t totalSize = sizeof(T) * count; |
| 490 | *out = static_cast<T*>(allocator->GetSpace(totalSize)); |
| 491 | if (*out == nullptr) { |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 492 | return WireResult::FatalError; |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 493 | } |
Corentin Wallez | 88fb8fa | 2018-06-06 17:36:49 +0200 | [diff] [blame] | 494 | |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 495 | return WireResult::Success; |
Corentin Wallez | 88fb8fa | 2018-06-06 17:36:49 +0200 | [diff] [blame] | 496 | } |
| 497 | |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 498 | size_t GetChainedStructExtraRequiredSize(const WGPUChainedStruct* chainedStruct); |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 499 | DAWN_NO_DISCARD WireResult SerializeChainedStruct(const WGPUChainedStruct* chainedStruct, |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 500 | SerializeBuffer* buffer, |
| 501 | const ObjectIdProvider& provider); |
| 502 | WireResult DeserializeChainedStruct(const WGPUChainedStruct** outChainNext, |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 503 | DeserializeBuffer* deserializeBuffer, |
| 504 | DeserializeAllocator* allocator, |
| 505 | const ObjectIdResolver& resolver); |
| 506 | |
| 507 | size_t GetChainedStructExtraRequiredSize(WGPUChainedStructOut* chainedStruct); |
| 508 | DAWN_NO_DISCARD WireResult SerializeChainedStruct(WGPUChainedStructOut* chainedStruct, |
| 509 | SerializeBuffer* buffer, |
| 510 | const ObjectIdProvider& provider); |
| 511 | WireResult DeserializeChainedStruct(WGPUChainedStructOut** outChainNext, |
| 512 | DeserializeBuffer* deserializeBuffer, |
| 513 | DeserializeAllocator* allocator, |
| 514 | const ObjectIdResolver& resolver); |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 515 | |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 516 | //* Output structure [de]serialization first because it is used by commands. |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 517 | {% for type in by_category["structure"] %} |
| 518 | {% set name = as_cType(type.name) %} |
Corentin Wallez | 67ab1ea | 2019-06-06 16:19:15 +0000 | [diff] [blame] | 519 | {% if type.name.CamelCase() not in client_side_structures %} |
| 520 | {{write_record_serialization_helpers(type, name, type.members, |
| 521 | is_cmd=False)}} |
| 522 | {% endif %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 523 | {% endfor %} |
| 524 | |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 525 | {% macro make_chained_struct_serialization_helpers(out) %} |
| 526 | {% set ChainedStructPtr = "WGPUChainedStructOut*" if out else "const WGPUChainedStruct*" %} |
| 527 | {% set ChainedStruct = "WGPUChainedStructOut" if out else "WGPUChainedStruct" %} |
| 528 | size_t GetChainedStructExtraRequiredSize({{ChainedStructPtr}} chainedStruct) { |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 529 | ASSERT(chainedStruct != nullptr); |
| 530 | size_t result = 0; |
| 531 | while (chainedStruct != nullptr) { |
| 532 | switch (chainedStruct->sType) { |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 533 | {% for sType in types["s type"].values if ( |
| 534 | sType.valid and |
| 535 | (sType.name.CamelCase() not in client_side_structures) and |
| 536 | (types[sType.name.get()].output == out) |
| 537 | ) %} |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 538 | case {{as_cEnum(types["s type"].name, sType.name)}}: { |
| 539 | const auto& typedStruct = *reinterpret_cast<{{as_cType(sType.name)}} const *>(chainedStruct); |
| 540 | result += sizeof({{as_cType(sType.name)}}Transfer); |
| 541 | result += {{as_cType(sType.name)}}GetExtraRequiredSize(typedStruct); |
| 542 | chainedStruct = typedStruct.chain.next; |
| 543 | break; |
| 544 | } |
| 545 | {% endfor %} |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 546 | // Explicitly list the Invalid enum. MSVC complains about no case labels. |
| 547 | case WGPUSType_Invalid: |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 548 | default: |
| 549 | // Invalid enum. Reserve space just for the transfer header (sType and hasNext). |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 550 | result += sizeof(WGPUChainedStructTransfer); |
Austin Eng | 65a903b | 2021-02-01 16:48:18 +0000 | [diff] [blame] | 551 | chainedStruct = chainedStruct->next; |
| 552 | break; |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 553 | } |
| 554 | } |
| 555 | return result; |
| 556 | } |
| 557 | |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 558 | DAWN_NO_DISCARD WireResult SerializeChainedStruct({{ChainedStructPtr}} chainedStruct, |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 559 | SerializeBuffer* buffer, |
| 560 | const ObjectIdProvider& provider) { |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 561 | ASSERT(chainedStruct != nullptr); |
| 562 | ASSERT(buffer != nullptr); |
| 563 | do { |
| 564 | switch (chainedStruct->sType) { |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 565 | {% for sType in types["s type"].values if ( |
| 566 | sType.valid and |
| 567 | (sType.name.CamelCase() not in client_side_structures) and |
| 568 | (types[sType.name.get()].output == out) |
| 569 | ) %} |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 570 | {% set CType = as_cType(sType.name) %} |
| 571 | case {{as_cEnum(types["s type"].name, sType.name)}}: { |
| 572 | |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 573 | {{CType}}Transfer* transfer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 574 | WIRE_TRY(buffer->Next(&transfer)); |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 575 | transfer->chain.sType = chainedStruct->sType; |
| 576 | transfer->chain.hasNext = chainedStruct->next != nullptr; |
| 577 | |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 578 | WIRE_TRY({{CType}}Serialize(*reinterpret_cast<{{CType}} const*>(chainedStruct), transfer, buffer |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 579 | {%- if types[sType.name.get()].may_have_dawn_object -%} |
| 580 | , provider |
| 581 | {%- endif -%} |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 582 | )); |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 583 | |
| 584 | chainedStruct = chainedStruct->next; |
| 585 | } break; |
| 586 | {% endfor %} |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 587 | // Explicitly list the Invalid enum. MSVC complains about no case labels. |
| 588 | case WGPUSType_Invalid: |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 589 | default: { |
| 590 | // Invalid enum. Serialize just the transfer header with Invalid as the sType. |
| 591 | // TODO(crbug.com/dawn/369): Unknown sTypes are silently discarded. |
Austin Eng | 65a903b | 2021-02-01 16:48:18 +0000 | [diff] [blame] | 592 | if (chainedStruct->sType != WGPUSType_Invalid) { |
| 593 | dawn::WarningLog() << "Unknown sType " << chainedStruct->sType << " discarded."; |
| 594 | } |
| 595 | |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 596 | WGPUChainedStructTransfer* transfer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 597 | WIRE_TRY(buffer->Next(&transfer)); |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 598 | transfer->sType = WGPUSType_Invalid; |
Austin Eng | 65a903b | 2021-02-01 16:48:18 +0000 | [diff] [blame] | 599 | transfer->hasNext = chainedStruct->next != nullptr; |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 600 | |
Austin Eng | 65a903b | 2021-02-01 16:48:18 +0000 | [diff] [blame] | 601 | // Still move on in case there are valid structs after this. |
| 602 | chainedStruct = chainedStruct->next; |
| 603 | break; |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 604 | } |
| 605 | } |
| 606 | } while (chainedStruct != nullptr); |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 607 | return WireResult::Success; |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 608 | } |
| 609 | |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 610 | WireResult DeserializeChainedStruct({{ChainedStructPtr}}* outChainNext, |
| 611 | DeserializeBuffer* deserializeBuffer, |
| 612 | DeserializeAllocator* allocator, |
| 613 | const ObjectIdResolver& resolver) { |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 614 | bool hasNext; |
| 615 | do { |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 616 | const volatile WGPUChainedStructTransfer* header; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 617 | WIRE_TRY(deserializeBuffer->Peek(&header)); |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 618 | WGPUSType sType = header->sType; |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 619 | switch (sType) { |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 620 | {% for sType in types["s type"].values if ( |
| 621 | sType.valid and |
| 622 | (sType.name.CamelCase() not in client_side_structures) and |
| 623 | (types[sType.name.get()].output == out) |
| 624 | ) %} |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 625 | {% set CType = as_cType(sType.name) %} |
| 626 | case {{as_cEnum(types["s type"].name, sType.name)}}: { |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 627 | const volatile {{CType}}Transfer* transfer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 628 | WIRE_TRY(deserializeBuffer->Read(&transfer)); |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 629 | |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 630 | {{CType}}* outStruct; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 631 | WIRE_TRY(GetSpace(allocator, sizeof({{CType}}), &outStruct)); |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 632 | outStruct->chain.sType = sType; |
| 633 | outStruct->chain.next = nullptr; |
| 634 | |
| 635 | *outChainNext = &outStruct->chain; |
| 636 | outChainNext = &outStruct->chain.next; |
| 637 | |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 638 | WIRE_TRY({{CType}}Deserialize(outStruct, transfer, deserializeBuffer, allocator |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 639 | {%- if types[sType.name.get()].may_have_dawn_object -%} |
| 640 | , resolver |
| 641 | {%- endif -%} |
| 642 | )); |
| 643 | |
| 644 | hasNext = transfer->chain.hasNext; |
| 645 | } break; |
| 646 | {% endfor %} |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 647 | // Explicitly list the Invalid enum. MSVC complains about no case labels. |
| 648 | case WGPUSType_Invalid: |
Austin Eng | 65a903b | 2021-02-01 16:48:18 +0000 | [diff] [blame] | 649 | default: { |
| 650 | // Invalid enum. Deserialize just the transfer header with Invalid as the sType. |
| 651 | // TODO(crbug.com/dawn/369): Unknown sTypes are silently discarded. |
| 652 | if (sType != WGPUSType_Invalid) { |
| 653 | dawn::WarningLog() << "Unknown sType " << sType << " discarded."; |
| 654 | } |
| 655 | |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 656 | const volatile WGPUChainedStructTransfer* transfer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 657 | WIRE_TRY(deserializeBuffer->Read(&transfer)); |
Austin Eng | 65a903b | 2021-02-01 16:48:18 +0000 | [diff] [blame] | 658 | |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 659 | {{ChainedStruct}}* outStruct; |
| 660 | WIRE_TRY(GetSpace(allocator, sizeof({{ChainedStruct}}), &outStruct)); |
Austin Eng | 65a903b | 2021-02-01 16:48:18 +0000 | [diff] [blame] | 661 | outStruct->sType = WGPUSType_Invalid; |
| 662 | outStruct->next = nullptr; |
| 663 | |
| 664 | // Still move on in case there are valid structs after this. |
| 665 | *outChainNext = outStruct; |
| 666 | outChainNext = &outStruct->next; |
| 667 | hasNext = transfer->hasNext; |
| 668 | break; |
| 669 | } |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 670 | } |
| 671 | } while (hasNext); |
| 672 | |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 673 | return WireResult::Success; |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 674 | } |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 675 | {% endmacro %} |
| 676 | |
| 677 | {{ make_chained_struct_serialization_helpers(False) }} |
| 678 | {{ make_chained_struct_serialization_helpers(True) }} |
Austin Eng | 76a8d0b | 2020-04-03 17:37:48 +0000 | [diff] [blame] | 679 | |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 680 | //* Output [de]serialization helpers for commands |
| 681 | {% for command in cmd_records["command"] %} |
| 682 | {% set name = command.name.CamelCase() %} |
| 683 | {{write_record_serialization_helpers(command, name, command.members, |
Corentin Wallez | cb2c64f | 2019-04-01 21:04:17 +0000 | [diff] [blame] | 684 | is_cmd=True)}} |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 685 | {% endfor %} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 686 | |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 687 | //* Output [de]serialization helpers for return commands |
| 688 | {% for command in cmd_records["return command"] %} |
| 689 | {% set name = command.name.CamelCase() %} |
| 690 | {{write_record_serialization_helpers(command, name, command.members, |
Corentin Wallez | cb2c64f | 2019-04-01 21:04:17 +0000 | [diff] [blame] | 691 | is_cmd=True, is_return_command=True)}} |
Corentin Wallez | 40e72d7 | 2018-06-08 18:30:50 +0200 | [diff] [blame] | 692 | {% endfor %} |
| 693 | } // anonymous namespace |
Corentin Wallez | f07e3bd | 2017-04-20 14:38:20 -0400 | [diff] [blame] | 694 | |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 695 | {% for command in cmd_records["command"] %} |
| 696 | {{ write_command_serialization_methods(command, False) }} |
| 697 | {% endfor %} |
Corentin Wallez | 88fb8fa | 2018-06-06 17:36:49 +0200 | [diff] [blame] | 698 | |
Austin Eng | c7f416c | 2019-01-15 20:49:53 +0000 | [diff] [blame] | 699 | {% for command in cmd_records["return command"] %} |
| 700 | {{ write_command_serialization_methods(command, True) }} |
Corentin Wallez | f07e3bd | 2017-04-20 14:38:20 -0400 | [diff] [blame] | 701 | {% endfor %} |
| 702 | |
Austin Eng | dc7971c | 2021-09-10 20:36:20 +0000 | [diff] [blame] | 703 | // Implementation of ObjectIdResolver that always errors. |
| 704 | // Used when the generator adds a provider argument because of a chained |
| 705 | // struct, but in practice, a chained struct in that location is invalid. |
| 706 | class ErrorObjectIdResolver final : public ObjectIdResolver { |
| 707 | public: |
| 708 | {% for type in by_category["object"] %} |
| 709 | WireResult GetFromId(ObjectId id, {{as_cType(type.name)}}* out) const override { |
| 710 | return WireResult::FatalError; |
| 711 | } |
| 712 | WireResult GetOptionalFromId(ObjectId id, {{as_cType(type.name)}}* out) const override { |
| 713 | return WireResult::FatalError; |
| 714 | } |
| 715 | {% endfor %} |
| 716 | }; |
| 717 | |
| 718 | // Implementation of ObjectIdProvider that always errors. |
| 719 | // Used when the generator adds a provider argument because of a chained |
| 720 | // struct, but in practice, a chained struct in that location is invalid. |
| 721 | class ErrorObjectIdProvider final : public ObjectIdProvider { |
| 722 | public: |
| 723 | {% for type in by_category["object"] %} |
| 724 | WireResult GetId({{as_cType(type.name)}} object, ObjectId* out) const override { |
| 725 | return WireResult::FatalError; |
| 726 | } |
| 727 | WireResult GetOptionalId({{as_cType(type.name)}} object, ObjectId* out) const override { |
| 728 | return WireResult::FatalError; |
| 729 | } |
| 730 | {% endfor %} |
| 731 | }; |
| 732 | |
Corentin Wallez | 1fdcb16 | 2019-10-24 22:27:27 +0000 | [diff] [blame] | 733 | // Implementations of serialization/deserialization of WPGUDeviceProperties. |
| 734 | size_t SerializedWGPUDevicePropertiesSize(const WGPUDeviceProperties* deviceProperties) { |
| 735 | return sizeof(WGPUDeviceProperties) + |
Corentin Wallez | 2c8b5c6 | 2019-10-21 20:04:10 +0000 | [diff] [blame] | 736 | WGPUDevicePropertiesGetExtraRequiredSize(*deviceProperties); |
Jiawei Shao | 5c2f5f3 | 2019-10-20 03:01:56 +0000 | [diff] [blame] | 737 | } |
| 738 | |
Corentin Wallez | 1fdcb16 | 2019-10-24 22:27:27 +0000 | [diff] [blame] | 739 | void SerializeWGPUDeviceProperties(const WGPUDeviceProperties* deviceProperties, |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 740 | char* buffer) { |
| 741 | SerializeBuffer serializeBuffer(buffer, SerializedWGPUDevicePropertiesSize(deviceProperties)); |
Jiawei Shao | 5c2f5f3 | 2019-10-20 03:01:56 +0000 | [diff] [blame] | 742 | |
Austin Eng | 1b31dc0 | 2021-02-17 22:14:56 +0000 | [diff] [blame] | 743 | WGPUDevicePropertiesTransfer* transfer; |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 744 | |
| 745 | WireResult result = serializeBuffer.Next(&transfer); |
| 746 | ASSERT(result == WireResult::Success); |
| 747 | |
Austin Eng | 02fbf16 | 2021-09-13 18:49:09 +0000 | [diff] [blame] | 748 | ErrorObjectIdProvider provider; |
| 749 | result = WGPUDevicePropertiesSerialize(*deviceProperties, transfer, &serializeBuffer, provider); |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 750 | ASSERT(result == WireResult::Success); |
Jiawei Shao | 5c2f5f3 | 2019-10-20 03:01:56 +0000 | [diff] [blame] | 751 | } |
| 752 | |
Corentin Wallez | 1fdcb16 | 2019-10-24 22:27:27 +0000 | [diff] [blame] | 753 | bool DeserializeWGPUDeviceProperties(WGPUDeviceProperties* deviceProperties, |
Austin Eng | 51db53f | 2021-02-18 19:28:29 +0000 | [diff] [blame] | 754 | const volatile char* buffer, |
| 755 | size_t size) { |
| 756 | const volatile WGPUDevicePropertiesTransfer* transfer; |
| 757 | DeserializeBuffer deserializeBuffer(buffer, size); |
Austin Eng | bd3f586 | 2021-02-25 20:21:25 +0000 | [diff] [blame] | 758 | if (deserializeBuffer.Read(&transfer) != WireResult::Success) { |
Jiawei Shao | 5c2f5f3 | 2019-10-20 03:01:56 +0000 | [diff] [blame] | 759 | return false; |
| 760 | } |
| 761 | |
Austin Eng | 02fbf16 | 2021-09-13 18:49:09 +0000 | [diff] [blame] | 762 | ErrorObjectIdResolver resolver; |
Corentin Wallez | 2c8b5c6 | 2019-10-21 20:04:10 +0000 | [diff] [blame] | 763 | return WGPUDevicePropertiesDeserialize(deviceProperties, transfer, &deserializeBuffer, |
Austin Eng | 02fbf16 | 2021-09-13 18:49:09 +0000 | [diff] [blame] | 764 | nullptr, resolver) == WireResult::Success; |
Jiawei Shao | 5c2f5f3 | 2019-10-20 03:01:56 +0000 | [diff] [blame] | 765 | } |
| 766 | |
Austin Eng | bffc966 | 2021-09-17 15:36:00 +0000 | [diff] [blame] | 767 | size_t SerializedWGPUSupportedLimitsSize(const WGPUSupportedLimits* supportedLimits) { |
| 768 | return sizeof(WGPUSupportedLimits) + |
| 769 | WGPUSupportedLimitsGetExtraRequiredSize(*supportedLimits); |
| 770 | } |
| 771 | |
| 772 | void SerializeWGPUSupportedLimits( |
| 773 | const WGPUSupportedLimits* supportedLimits, |
| 774 | char* buffer) { |
| 775 | SerializeBuffer serializeBuffer(buffer, SerializedWGPUSupportedLimitsSize(supportedLimits)); |
| 776 | |
| 777 | WGPUSupportedLimitsTransfer* transfer; |
| 778 | |
| 779 | WireResult result = serializeBuffer.Next(&transfer); |
| 780 | ASSERT(result == WireResult::Success); |
| 781 | |
| 782 | ErrorObjectIdProvider provider; |
| 783 | result = WGPUSupportedLimitsSerialize(*supportedLimits, transfer, &serializeBuffer, provider); |
| 784 | ASSERT(result == WireResult::Success); |
| 785 | } |
| 786 | |
| 787 | bool DeserializeWGPUSupportedLimits(WGPUSupportedLimits* supportedLimits, |
| 788 | const volatile char* buffer, |
| 789 | size_t size) { |
| 790 | const volatile WGPUSupportedLimitsTransfer* transfer; |
| 791 | DeserializeBuffer deserializeBuffer(buffer, size); |
| 792 | if (deserializeBuffer.Read(&transfer) != WireResult::Success) { |
| 793 | return false; |
| 794 | } |
| 795 | |
| 796 | ErrorObjectIdResolver resolver; |
| 797 | return WGPUSupportedLimitsDeserialize(supportedLimits, transfer, &deserializeBuffer, |
| 798 | nullptr, resolver) == WireResult::Success; |
| 799 | } |
| 800 | |
Corentin Wallez | bdc8677 | 2018-07-26 15:07:57 +0200 | [diff] [blame] | 801 | } // namespace dawn_wire |