[wire] Cpp-ify the Dawn wire client API so that we can spanify. Bug: 526537254 Change-Id: Ibb4e98127464152b337642f9c2ae05d0dfbbcc22 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/326956 Commit-Queue: Loko Kung <lokokung@google.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py index 2c85853..3e9828c 100644 --- a/generator/dawn_json_generator.py +++ b/generator/dawn_json_generator.py
@@ -2022,6 +2022,10 @@ 'src/dawn/wire/client/' + metadata.namespace + '_structs_autogen.cpp', wire_params)) renders.append( + FileRender('dawn/wire/client/dawn_platform.h', + 'src/dawn/wire/client/' + prefix + '_platform.h', + wire_params)) + renders.append( FileRender('dawn/wire/server/ServerBase.h', 'src/dawn/wire/server/ServerBase_autogen.h', wire_params))
diff --git a/generator/templates/dawn/wire/client/ApiObjects.h b/generator/templates/dawn/wire/client/ApiObjects.h index faddfc6..e945a4a 100644 --- a/generator/templates/dawn/wire/client/ApiObjects.h +++ b/generator/templates/dawn/wire/client/ApiObjects.h
@@ -50,13 +50,6 @@ }; {% endif %} - inline {{Type}}* FromAPI(WGPU{{Type}} obj) { - return reinterpret_cast<{{Type}}*>(obj); - } - inline WGPU{{Type}} ToAPI({{Type}}* obj) { - return reinterpret_cast<WGPU{{Type}}>(obj); - } - template <> inline constexpr ObjectType ObjectTypeToTypeEnum<{{Type}}> = ObjectType::{{Type}};
diff --git a/generator/templates/dawn/wire/client/ApiProcs.cpp b/generator/templates/dawn/wire/client/ApiProcs.cpp index e92564b..b3aea8e 100644 --- a/generator/templates/dawn/wire/client/ApiProcs.cpp +++ b/generator/templates/dawn/wire/client/ApiProcs.cpp
@@ -25,6 +25,8 @@ //* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +{% set Prefix = metadata.proc_table_prefix %} +{% set prefix = Prefix.lower() %} #include <algorithm> #include <cstring> #include <string_view> @@ -32,9 +34,70 @@ #include <utility> #include <vector> +#include "dawn/wire/client/{{prefix}}_platform.h" #include "dawn/wire/client/webgpu.h" #include "dawn/dawn_version.h" #include "src/dawn/wire/client/Client.h" +#include "src/utils/span.h" + +{%- macro convert_arguments_and_call(function, suffix, call_receiver, first_arg = None) -%} + {% set cppify = not suffix in function_cpp_blocklist %} + {% set client = "dawn::wire::client" %} + + {% for arg in function.arguments %} + {% set varName = as_varName(arg.name) %} + {% if cppify and arg.is_length %} + //* Skip as it's included in the span just below. + {% elif cppify and arg.length and arg.length != "constant" %} + // TODO(https://crbug.com/524405497): Support fixed-length spans. + {% if arg.type.name.canonical_case() == "void" %} + using {{varName}}SpanT = {% if arg.annotation == "const*" %}const {% endif %}std::byte; + auto {{varName}}Ptr = reinterpret_cast<{{varName}}SpanT*>({{varName}}); + {% else %} + using {{varName}}SpanT = std::remove_pointer_t<{% if arg.type.category == "object" %}{{client}}::{% endif %}{{decorate(as_wire_clientType(arg.type), arg)}}>; + auto {{varName}}Ptr = {{client}}::FromAPI({{varName}}); + {% endif %} + // SAFETY: The webgpu.h user is required to pass valid ranges of objects. + auto {{varName}}_ = DAWN_UNSAFE_BUFFERS(dawn::Span<{{varName}}SpanT>({{varName}}Ptr, {{as_varName(arg.length.name)}})); + {% elif cppify and arg.type.category == "structure" %} + auto {{varName}}_ = {{client}}::FromAPI({{varName}}); + {% elif cppify and arg.type.category in ["enum", "bitmask"] and arg.annotation == "value" %} + auto {{varName}}_ = static_cast<{{as_wire_clientType(arg.type)}}>({{varName}}); + {% elif cppify and arg.type.category == "object" %} + auto {{varName}}_ = {{client}}::FromAPI({{varName}}); + {% elif cppify and arg.annotation != "value" %} + auto {{varName}}_ = reinterpret_cast<{{decorate(as_wire_clientType(arg.type), arg)}}>({{varName}}); + {% else %} + auto {{varName}}_ = {{as_varName(arg.name)}}; + {% endif %} + {%- endfor-%} + + {% if function.returns %} + auto result = + {%- endif %} + {{call_receiver}}( + {%- if first_arg -%} + {{first_arg}} {%- if len(function.arguments) != 0 %}, {% endif -%} + {%- endif -%} + {%- for arg in function.arguments if (not cppify or not arg.is_length) -%} + {%- if not loop.first %}, {% endif -%} + {{as_varName(arg.name)}}_ + {%- endfor -%} + ); + {% if function.returns %} + {% if cppify %} + {% if function.returns.type.category in ["object", "enum", "bitmask"] %} + return {{client}}::ToAPI(result); + {% elif function.returns.type.category in ["structure"] %} + return *{{client}}::ToAPI(&result); + {% else %} + return result; + {% endif %} + {% else %} + return result; + {% endif %} + {% endif %} +{%- endmacro %} namespace dawn::wire::client { @@ -58,8 +121,9 @@ //* Implementation of the client API functions. {% for (type, methods) in c_methods_sorted_by_parent %} - {%- set Type = "dawn::wire::client::" + type.name.CamelCase() -%} + {%- set Type = type.name.CamelCase() -%} {%- set cType = as_cType(type.name) -%} + {%- set client = "dawn::wire::client" -%} {% for method in methods %} {% set Suffix = as_MethodSuffix(type.name, method.name) %} @@ -71,7 +135,7 @@ {%- endfor -%} ) { {% if Suffix not in client_handwritten_commands %} - auto self = reinterpret_cast<dawn::wire::client::{{as_wireType(type)}}>(cSelf); + auto self = {{client}}::FromAPI(cSelf); dawn::wire::{{Suffix}}Cmd cmd; //* Create the structure going on the wire on the stack and fill it with the value @@ -80,8 +144,8 @@ //* For object creation, store the object ID the client will use for the result. {% if method.returns and method.returns.type.category == "object" %} - {% set ReturnObj = "dawn::wire::client::" + method.returns.type.name.CamelCase() %} - {{ReturnObj}}* returnObject = dawn::wire::client::Create<dawn::wire::client::{{as_wireType(type)}}, {{ReturnObj}}>(self + {% set ReturnObj = client + "::" + method.returns.type.name.CamelCase() %} + {{ReturnObj}}* returnObject = {{client}}::Create<{{client}}::{{as_wireType(type)}}, {{ReturnObj}}>(self {%- for arg in method.arguments -%} , {{as_varName(arg.name)}} {%- endfor -%} @@ -99,16 +163,13 @@ self->GetClient()->SerializeCommand(cmd); {% if method.returns and method.returns.type.category == "object" %} - return ToAPI(returnObject); + return {{client}}::ToAPI(returnObject); {% endif %} {% elif type.category == "object" %} - auto self = reinterpret_cast<dawn::wire::client::{{as_wireType(type)}}>(cSelf); - return self->API{{method.name.CamelCase()}}( - {%- for arg in method.arguments -%} - {%if not loop.first %}, {% endif %} {{as_varName(arg.name)}} - {%- endfor -%}); + auto self = {{client}}::FromAPI(cSelf); + {{convert_arguments_and_call(method, Suffix, "self->API" + method.name.CamelCase())}} {% elif type.category == "structure" %} - return dawn::wire::client::API{{method.name.CamelCase()}}(cSelf); + return {{client}}::API{{method.name.CamelCase()}}(cSelf); {% endif %} } {% endfor %}
diff --git a/generator/templates/dawn/wire/client/dawn_platform.h b/generator/templates/dawn/wire/client/dawn_platform.h new file mode 100644 index 0000000..b7726cc --- /dev/null +++ b/generator/templates/dawn/wire/client/dawn_platform.h
@@ -0,0 +1,127 @@ +//* Copyright 2026 The Dawn & Tint Authors +//* +//* Redistribution and use in source and binary forms, with or without +//* modification, are permitted provided that the following conditions are met: +//* +//* 1. Redistributions of source code must retain the above copyright notice, this +//* list of conditions and the following disclaimer. +//* +//* 2. Redistributions in binary form must reproduce the above copyright notice, +//* this list of conditions and the following disclaimer in the documentation +//* and/or other materials provided with the distribution. +//* +//* 3. Neither the name of the copyright holder nor the names of its +//* contributors may be used to endorse or promote products derived from +//* this software without specific prior written permission. +//* +//* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +//* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +//* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +//* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//* TODO(https://crbug.com/526537254): It might be possible to merge this with the +//* dawn_platform.h in native once we finish migrating both native and wire. + +{% set PREFIX = metadata.proc_table_prefix.upper() %} +#ifndef DAWNWIRE_CLIENT_{{PREFIX}}_PLATFORM_AUTOGEN_H_ +#define DAWNWIRE_CLIENT_{{PREFIX}}_PLATFORM_AUTOGEN_H_ + +{% set api = metadata.api.lower() %} +#include "dawn/{{api}}_cpp.h" + +{% set namespace = metadata.namespace %} +#include "dawn/wire/client/{{namespace}}_structs_autogen.h" + +namespace dawn::wire::client { + {% for type in by_category["object"] %} + {% if type.name.CamelCase() in client_special_objects %} + class {{type.name.CamelCase()}}; + {% else %} + struct {{type.name.CamelCase()}}; + {% endif %} + {% endfor %} +} + +{% macro render_structure_conversions(name) -%} + inline const {{as_cType(name)}}* ToAPI(const {{as_cppType(name)}}* rhs) { + return reinterpret_cast<const {{as_cType(name)}}*>(rhs); + } + inline {{as_cType(name)}}* ToAPI({{as_cppType(name)}}* rhs) { + return reinterpret_cast<{{as_cType(name)}}*>(rhs); + } + inline const {{as_cppType(name)}}* FromAPI(const {{as_cType(name)}}* rhs) { + return reinterpret_cast<const {{as_cppType(name)}}*>(rhs); + } + inline {{as_cppType(name)}}* FromAPI({{as_cType(name)}}* rhs) { + return reinterpret_cast<{{as_cppType(name)}}*>(rhs); + } + inline const {{as_cppType(name)}}& FromAPI(const {{as_cType(name)}}& rhs) { + return *reinterpret_cast<const {{as_cppType(name)}}*>(&rhs); + } + inline {{as_cppType(name)}}& FromAPI({{as_cType(name)}}& rhs) { + return *reinterpret_cast<{{as_cppType(name)}}*>(&rhs); + } +{%- endmacro %} + +namespace dawn::wire::client { + + {% set ChainedStructName = Name("chained struct") %} + {{render_structure_conversions(ChainedStructName)|indent}} + + {% for type in by_category["structure"] if type.name.get() != "string view" %} + {{render_structure_conversions(type.name)|indent}} + + {% endfor %} + + {% for type in by_category["object"] %} + {% set Type = type.name.CamelCase() %} + inline WGPU{{Type}} ToAPI({{Type}}* rhs) { + return reinterpret_cast<WGPU{{Type}}>(rhs); + } + + inline {{Type}}* FromAPI(WGPU{{Type}} rhs) { + return reinterpret_cast<{{Type}}*>(rhs); + } + inline const {{Type}}* const* FromAPI(const WGPU{{Type}}* rhs) { + return reinterpret_cast<const {{Type}}* const*>(rhs); + } + inline {{Type}}* const* FromAPI(WGPU{{Type}}* rhs) { + return reinterpret_cast<{{Type}}* const*>(rhs); + } + {% endfor %} + + //* Special structs that we want to allow copies for since they are trivial. + inline WGPUFuture ToAPI(Future rhs) { + return {rhs.id}; + } + inline Future FromAPI(WGPUFuture rhs) { + return Future{rhs.id}; + } + inline WGPUStringView ToAPI(StringView rhs) { + return {rhs.data, rhs.length}; + } + inline StringView FromAPI(WGPUStringView rhs) { + return StringView(rhs); + } + + {% for type in by_category["enum"] + by_category["bitmask"] %} + inline {{as_cType(type.name)}} ToAPI({{namespace}}::{{as_cppType(type.name)}} rhs) { + return static_cast<{{as_cType(type.name)}}>(rhs); + } + {% endfor %} + + {% for type in by_category["enum"] %} + inline {{namespace}}::{{as_cppType(type.name)}} FromAPI({{as_cType(type.name)}} rhs) { + return static_cast<{{namespace}}::{{as_cppType(type.name)}}>(rhs); + } + {% endfor %} + +} // namespace dawn::wire::client + +#endif // DAWNWIRE_CLIENT_{{PREFIX}}_PLATFORM_AUTOGEN_H_
diff --git a/src/dawn/dawn_wire.json b/src/dawn/dawn_wire.json index 9cd3baa..3865997 100644 --- a/src/dawn/dawn_wire.json +++ b/src/dawn/dawn_wire.json
@@ -245,6 +245,63 @@ ] }, "special items": { + "_function_cpp_blocklist_comment": "// TODO(https://crbug.com/526537254): Drive this list down.", + "function_cpp_blocklist": [ + "AdapterCreateDevice", + "AdapterGetFeatures", + "AdapterGetFormatCapabilities", + "AdapterGetInfo", + "AdapterGetLimits", + "AdapterGetInstance", + "AdapterHasFeature", + "AdapterRequestDevice", + "BufferGetMapState", + "BufferGetUsage", + "BufferMapAsync", + "BufferReadMappedRange", + "BufferWriteMappedRange", + "ComputePassEncoderSetImmediates", + "DeviceCreateBuffer", + "DeviceCreateComputePipelineAsync", + "DeviceCreateErrorBuffer", + "DeviceCreateErrorTexture", + "DeviceCreateRenderPipelineAsync", + "DeviceCreateResourceTable", + "DeviceCreateTexture", + "DeviceGetAdapter", + "DeviceGetAdapterInfo", + "DeviceGetFeatures", + "DeviceGetLimits", + "DeviceGetLostFuture", + "DeviceGetQueue", + "DeviceHasFeature", + "DeviceInjectError", + "DevicePopErrorScope", + "InstanceCreateSurface", + "InstanceGetWGSLLanguageFeatures", + "InstanceHasWGSLLanguageFeature", + "InstanceRequestAdapter", + "InstanceWaitAny", + "QuerySetGetType", + "QueueOnSubmittedWorkDone", + "QueueSubmit", + "QueueWriteBuffer", + "QueueWriteTexture", + "RenderBundleEncoderSetImmediates", + "RenderPassEncoderSetImmediates", + "ResourceTableInsert", + "ResourceTableRemove", + "ResourceTableUpdate", + "ShaderModuleGetCompilationInfo", + "SurfaceConfigure", + "SurfaceGetCapabilities", + "SurfaceGetCurrentTexture", + "SurfacePresent", + "TextureGetDimension", + "TextureGetFormat", + "TextureGetTextureBindingViewDimension", + "TextureGetUsage" + ], "client_side_structures": [ "FutureWaitInfo", "SurfaceDescriptorFromWindowsCoreWindow",
diff --git a/src/dawn/wire/BUILD.gn b/src/dawn/wire/BUILD.gn index b415a9a..78e9bf9 100644 --- a/src/dawn/wire/BUILD.gn +++ b/src/dawn/wire/BUILD.gn
@@ -58,6 +58,7 @@ "${dawn_template_dir}/dawn/wire/client/ClientPrototypes.inc", "${dawn_template_dir}/dawn/wire/client/api_structs.h", "${dawn_template_dir}/dawn/wire/client/api_structs.cpp", + "${dawn_template_dir}/dawn/wire/client/dawn_platform.h", "${dawn_template_dir}/dawn/wire/server/ServerBase.h", "${dawn_template_dir}/dawn/wire/server/ServerDoers.cpp", "${dawn_template_dir}/dawn/wire/server/ServerHandlers.cpp", @@ -75,6 +76,7 @@ "src/dawn/wire/client/ClientPrototypes_autogen.inc", "src/dawn/wire/client/wgpu_structs_autogen.h", "src/dawn/wire/client/wgpu_structs_autogen.cpp", + "src/dawn/wire/client/dawn_platform.h", "src/dawn/wire/server/ServerBase_autogen.h", "src/dawn/wire/server/ServerDoers_autogen.cpp", "src/dawn/wire/server/ServerHandlers_autogen.cpp",
diff --git a/src/dawn/wire/client/ObjectBase.h b/src/dawn/wire/client/ObjectBase.h index c9b9e93..d59bf84 100644 --- a/src/dawn/wire/client/ObjectBase.h +++ b/src/dawn/wire/client/ObjectBase.h
@@ -31,6 +31,7 @@ #include <webgpu/webgpu.h> #include "dawn/wire/ObjectType_autogen.h" +#include "dawn/wire/client/dawn_platform.h" #include "partition_alloc/pointers/raw_ptr.h" #include "src/dawn/common/Ref.h" #include "src/dawn/common/RefCounted.h"