webgpu.h: Re-number enums, with defaulting: SamplerDescriptor
Trivial defaulting (matching what's defined in the upstream WebIDL) is
done via a new method .ApplyTrivialFrontendDefaults() called in various
places in the frontend as needed.
Part 1 implements the following, which occur directly in CreateSampler:
- SamplerDescriptor.addressMode[UVW]: AddressMode = ClampToEdge
- SamplerDescriptor.{min,mag}Filter: FilterMode = Nearest
- SamplerDescriptor.mipmapFilter: MipmapFilterMode = Nearest
Spot tests are added for all of these. They won't necessarily catch if
the defaulting is _wrong_, but should crash if it is _missing_.
Bug: dawn:2224
Change-Id: Ib325274c2e29cf822a6e3664412495b0c49ad7f0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/165340
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Kai Ninomiya <kainino@chromium.org>
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index f9c900c..0fedc0a 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -117,17 +117,22 @@
Type.__init__(self, name, json_data)
self.values = []
+ self.hasUndefined = False
self.contiguousFromZero = True
lastValue = -1
for m in self.json_data['values']:
if not is_enabled(m):
continue
value = m['value']
+ name = m['name']
+ if name == "undefined":
+ assert value == 0
+ self.hasUndefined = True
if value != lastValue + 1:
self.contiguousFromZero = False
lastValue = value
self.values.append(
- EnumValue(Name(m['name']), value, m.get('valid', True), m))
+ EnumValue(Name(name), value, m.get('valid', True), m))
# Assert that all values are unique in enums
all_values = set()
@@ -198,6 +203,11 @@
self.default_value = default_value
self.skip_serialize = skip_serialize
+ self.requires_struct_defaulting = False
+ if self.default_value not in [None, "undefined"] and self.annotation == "value" and \
+ self.type.category == "enum" and self.type.hasUndefined:
+ self.requires_struct_defaulting = True
+
def set_handle_type(self, handle_type):
assert self.type.dict_name == "ObjectHandle"
self.handle_type = handle_type
@@ -297,6 +307,11 @@
return True
return False
+ @property
+ def any_member_requires_struct_defaulting(self):
+ return any(member.requires_struct_defaulting
+ for member in self.members)
+
class ConstantDefinition():
def __init__(self, is_enabled, name, json_data):
diff --git a/generator/templates/api_cpp.h b/generator/templates/api_cpp.h
index 1f9ca0a..1335065 100644
--- a/generator/templates/api_cpp.h
+++ b/generator/templates/api_cpp.h
@@ -188,7 +188,7 @@
CType mHandle = nullptr;
};
-{% macro render_cpp_default_value(member, is_struct=True, force_default=False) -%}
+{% macro render_cpp_default_value(member, is_struct, force_default=False) -%}
{%- if member.json_data.get("no_default", false) -%}
{%- elif member.annotation in ["*", "const*"] and member.optional or member.default_value == "nullptr" -%}
{{" "}}= nullptr
@@ -280,7 +280,7 @@
ChainedStruct{{Out}} {{const}} * nextInChain = nullptr;
{% endif %}
{% for member in type.members %}
- {% set member_declaration = as_annotated_cppType(member, type.has_free_members_function) + render_cpp_default_value(member, False, type.has_free_members_function) %}
+ {% set member_declaration = as_annotated_cppType(member, type.has_free_members_function) + render_cpp_default_value(member, True, type.has_free_members_function) %}
{% if type.chained and loop.first %}
//* Align the first member after ChainedStruct to match the C struct layout.
//* It has to be aligned both to its natural and ChainedStruct's alignment.
diff --git a/generator/templates/dawn/native/api_structs.cpp b/generator/templates/dawn/native/api_structs.cpp
index bd0f3a3..5e11d83 100644
--- a/generator/templates/dawn/native/api_structs.cpp
+++ b/generator/templates/dawn/native/api_structs.cpp
@@ -68,6 +68,16 @@
"offsetof mismatch for {{CppType}}::{{memberName}}");
{% endfor %}
+ {% if type.any_member_requires_struct_defaulting %}
+ void {{CppType}}::ApplyTrivialFrontendDefaults() {
+ {% for member in type.members if member.requires_struct_defaulting %}
+ {% set memberName = member.name.camelCase() %}
+ if ({{memberName}} == {{namespace}}::{{as_cppType(member.type.name)}}::Undefined) {
+ {{memberName}} = {{namespace}}::{{as_cppType(member.type.name)}}::{{as_cppEnum(Name(member.default_value))}};
+ }
+ {% endfor %}
+ }
+ {% endif %}
bool {{CppType}}::operator==(const {{as_cppType(type.name)}}& rhs) const {
return {% if type.extensible or type.chained -%}
(nextInChain == rhs.nextInChain) &&
diff --git a/generator/templates/dawn/native/api_structs.h b/generator/templates/dawn/native/api_structs.h
index f484bcd..481f9b9 100644
--- a/generator/templates/dawn/native/api_structs.h
+++ b/generator/templates/dawn/native/api_structs.h
@@ -96,6 +96,12 @@
{% endif %}
{% endfor %}
+ {% if type.any_member_requires_struct_defaulting %}
+ // For any enum members with trivial defaulting (where something like
+ // "Undefined" is replaced with a default), this method applies all of the
+ // defaults for the struct. It must be called in an appropriate place in Dawn.
+ void ApplyTrivialFrontendDefaults();
+ {% endif %}
// Equality operators, mostly for testing. Note that this tests
// strict pointer-pointer equality if the struct contains member pointers.
bool operator==(const {{as_cppType(type.name)}}& rhs) const;