webgpu.h introduce a base struct for extension structures.
struct WGPUChainedStruct {
WGPUChainedStruct const * nextInChain;
WGPUSType sType;
};
And changes all the nextInChain to point to such structures. This adds
more type safety to extension structs and requires less casting to check
sTypes and friends.
Bug: dawn:269
Change-Id: I443f363cdb55dbec7c7f6e897245d4a7ea0ebe70
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15080
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/dawn.json b/dawn.json
index 15e17b6..8f1b0b7 100644
--- a/dawn.json
+++ b/dawn.json
@@ -1298,6 +1298,12 @@
{"name": "implementation", "type": "uint64_t"}
]
},
+ "s type": {
+ "category": "enum",
+ "values": [
+ {"value": 0, "name": "invalid"}
+ ]
+ },
"texture": {
"category": "object",
"methods": [
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index 3a67951..83cdd2f 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -140,7 +140,11 @@
def __init__(self, name, json_data):
Record.__init__(self, name)
Type.__init__(self, name, json_data)
+ self.chained = json_data.get("chained", False)
self.extensible = json_data.get("extensible", False)
+ # Chained structs inherit from wgpu::ChainedStruct which has nextInChain so setting
+ # both extensible and chained would result in two nextInChain members.
+ assert(not (self.extensible and self.chained))
class Command(Record):
def __init__(self, name, members=None):
diff --git a/generator/templates/dawn_native/wgpu_structs.cpp b/generator/templates/dawn_native/wgpu_structs.cpp
index b327f70..bec3ebf 100644
--- a/generator/templates/dawn_native/wgpu_structs.cpp
+++ b/generator/templates/dawn_native/wgpu_structs.cpp
@@ -16,6 +16,15 @@
namespace dawn_native {
+ static_assert(sizeof(ChainedStruct) == sizeof(WGPUChainedStruct),
+ "sizeof mismatch for ChainedStruct");
+ static_assert(alignof(ChainedStruct) == alignof(WGPUChainedStruct),
+ "alignof mismatch for ChainedStruct");
+ static_assert(offsetof(ChainedStruct, nextInChain) == offsetof(WGPUChainedStruct, nextInChain),
+ "offsetof mismatch for ChainedStruct::nextInChain");
+ static_assert(offsetof(ChainedStruct, sType) == offsetof(WGPUChainedStruct, sType),
+ "offsetof mismatch for ChainedStruct::sType");
+
{% for type in by_category["structure"] %}
{% set CppType = as_cppType(type.name) %}
{% set CType = as_cType(type.name) %}
diff --git a/generator/templates/dawn_native/wgpu_structs.h b/generator/templates/dawn_native/wgpu_structs.h
index 1241a00..5614336 100644
--- a/generator/templates/dawn_native/wgpu_structs.h
+++ b/generator/templates/dawn_native/wgpu_structs.h
@@ -32,13 +32,25 @@
{%- endif -%}
{%- endmacro %}
+ struct ChainedStruct {
+ ChainedStruct const * nextInChain = nullptr;
+ wgpu::SType sType = wgpu::SType::Invalid;
+ };
+
{% for type in by_category["structure"] %}
- struct {{as_cppType(type.name)}} {
+ {% if type.chained %}
+ struct {{as_cppType(type.name)}} : ChainedStruct {
+ {{as_cppType(type.name)}}() {
+ sType = wgpu::SType::{{type.name.CamelCase()}};
+ }
+ {% else %}
+ struct {{as_cppType(type.name)}} {
+ {% endif %}
{% if type.extensible %}
- const void* nextInChain = nullptr;
+ ChainedStruct const * nextInChain = nullptr;
{% endif %}
{% for member in type.members %}
- {{as_annotated_frontendType(member)}} {{render_cpp_default_value(member)}};
+ {{as_annotated_frontendType(member)}} {{render_cpp_default_value(member)}};
{% endfor %}
};
diff --git a/generator/templates/webgpu.h b/generator/templates/webgpu.h
index d1fcb32..aec3a18 100644
--- a/generator/templates/webgpu.h
+++ b/generator/templates/webgpu.h
@@ -73,10 +73,19 @@
{% endfor %}
+typedef struct WGPUChainedStruct {
+ struct WGPUChainedStruct const * nextInChain;
+ WGPUSType sType;
+} WGPUChainedStruct;
+
{% for type in by_category["structure"] %}
typedef struct {{as_cType(type.name)}} {
{% if type.extensible %}
- void const * nextInChain;
+ WGPUChainedStruct const * nextInChain;
+ {% endif %}
+ {% if type.chained %}
+ WGPUChainedStruct const * nextInChain;
+ WGPUSType sType;
{% endif %}
{% for member in type.members %}
{{as_annotated_cType(member)}};
diff --git a/generator/templates/webgpu_cpp.cpp b/generator/templates/webgpu_cpp.cpp
index 0bfcbd4..fcaac3e 100644
--- a/generator/templates/webgpu_cpp.cpp
+++ b/generator/templates/webgpu_cpp.cpp
@@ -42,6 +42,15 @@
{% endfor %}
+ static_assert(sizeof(ChainedStruct) == sizeof(WGPUChainedStruct),
+ "sizeof mismatch for ChainedStruct");
+ static_assert(alignof(ChainedStruct) == alignof(WGPUChainedStruct),
+ "alignof mismatch for ChainedStruct");
+ static_assert(offsetof(ChainedStruct, nextInChain) == offsetof(WGPUChainedStruct, nextInChain),
+ "offsetof mismatch for ChainedStruct::nextInChain");
+ static_assert(offsetof(ChainedStruct, sType) == offsetof(WGPUChainedStruct, sType),
+ "offsetof mismatch for ChainedStruct::sType");
+
{% for type in by_category["structure"] %}
{% set CppType = as_cppType(type.name) %}
{% set CType = as_cType(type.name) %}
diff --git a/generator/templates/webgpu_cpp.h b/generator/templates/webgpu_cpp.h
index 14b5a2e..6bfcdb7 100644
--- a/generator/templates/webgpu_cpp.h
+++ b/generator/templates/webgpu_cpp.h
@@ -186,10 +186,22 @@
Instance CreateInstance(InstanceDescriptor const * descriptor = nullptr);
Proc GetProcAddress(Device const& device, const char* procName);
+ struct ChainedStruct {
+ ChainedStruct const * nextInChain = nullptr;
+ SType sType = SType::Invalid;
+ };
+
{% for type in by_category["structure"] %}
- struct {{as_cppType(type.name)}} {
+ {% if type.chained %}
+ struct {{as_cppType(type.name)}} : ChainedStruct {
+ {{as_cppType(type.name)}}() {
+ sType = SType::{{type.name.CamelCase()}};
+ }
+ {% else %}
+ struct {{as_cppType(type.name)}} {
+ {% endif %}
{% if type.extensible %}
- const void* nextInChain = nullptr;
+ ChainedStruct const * nextInChain = nullptr;
{% endif %}
{% for member in type.members %}
{{as_annotated_cppType(member)}}{{render_cpp_default_value(member)}};
diff --git a/src/tests/end2end/D3D12ResourceWrappingTests.cpp b/src/tests/end2end/D3D12ResourceWrappingTests.cpp
index 1896ea9..1c6a2b5 100644
--- a/src/tests/end2end/D3D12ResourceWrappingTests.cpp
+++ b/src/tests/end2end/D3D12ResourceWrappingTests.cpp
@@ -144,7 +144,9 @@
// Test an error occurs if the texture descriptor is invalid
TEST_P(D3D12SharedHandleValidation, InvalidTextureDescriptor) {
DAWN_SKIP_TEST_IF(UsesWire());
- dawnDescriptor.nextInChain = this;
+
+ wgpu::ChainedStruct chainedDescriptor;
+ dawnDescriptor.nextInChain = &chainedDescriptor;
wgpu::Texture texture;
ComPtr<ID3D11Texture2D> d3d11Texture;
diff --git a/src/tests/end2end/IOSurfaceWrappingTests.cpp b/src/tests/end2end/IOSurfaceWrappingTests.cpp
index f2fe59a..908b108 100644
--- a/src/tests/end2end/IOSurfaceWrappingTests.cpp
+++ b/src/tests/end2end/IOSurfaceWrappingTests.cpp
@@ -136,7 +136,9 @@
// Test an error occurs if the texture descriptor is invalid
TEST_P(IOSurfaceValidationTests, InvalidTextureDescriptor) {
DAWN_SKIP_TEST_IF(UsesWire());
- descriptor.nextInChain = this;
+
+ wgpu::ChainedStruct chainedDescriptor;
+ descriptor.nextInChain = &chainedDescriptor;
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
WrapIOSurface(&descriptor, defaultIOSurface.get(), 0));
diff --git a/src/tests/unittests/validation/BindGroupValidationTests.cpp b/src/tests/unittests/validation/BindGroupValidationTests.cpp
index 1916339..0b11b0b 100644
--- a/src/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -75,7 +75,8 @@
device.CreateBindGroup(&descriptor);
// Check that nextInChain != nullptr is an error.
- descriptor.nextInChain = static_cast<void*>(&descriptor);
+ wgpu::ChainedStruct chainedDescriptor;
+ descriptor.nextInChain = &chainedDescriptor;
ASSERT_DEVICE_ERROR(device.CreateBindGroup(&descriptor));
}
diff --git a/src/tests/white_box/VulkanImageWrappingTests.cpp b/src/tests/white_box/VulkanImageWrappingTests.cpp
index 541554f..de7d8fe 100644
--- a/src/tests/white_box/VulkanImageWrappingTests.cpp
+++ b/src/tests/white_box/VulkanImageWrappingTests.cpp
@@ -256,7 +256,8 @@
// Test an error occurs if the texture descriptor is invalid
TEST_P(VulkanImageWrappingValidationTests, InvalidTextureDescriptor) {
DAWN_SKIP_TEST_IF(UsesWire());
- defaultDescriptor.nextInChain = this;
+ wgpu::ChainedStruct chainedDescriptor;
+ defaultDescriptor.nextInChain = &chainedDescriptor;
ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapVulkanImage(
device, &defaultDescriptor, defaultFd, defaultAllocationSize,