dawn.json: Make textureDescriptor use Extent3D

This matches WebGPU and is a good test of having structures include
other structures by value.

BUG=dawn:13

Change-Id: Ibd5ea1340338e5aa16069499c498ac5a455fc2cd
Reviewed-on: https://dawn-review.googlesource.com/1500
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/dawn.json b/dawn.json
index fc596b1..94a77cd 100644
--- a/dawn.json
+++ b/dawn.json
@@ -665,6 +665,14 @@
     "device error callback": {
         "category": "natively defined"
     },
+    "extent 3D": {
+        "category": "structure",
+        "members": [
+            {"name": "width", "type": "uint32_t"},
+            {"name": "height", "type": "uint32_t"},
+            {"name": "depth", "type": "uint32_t"}
+        ]
+    },
     "face": {
         "category": "bitmask",
         "values": [
@@ -996,9 +1004,7 @@
         "members": [
             {"name": "usage", "type": "texture usage bit"},
             {"name": "dimension", "type": "texture dimension"},
-            {"name": "width", "type": "uint32_t"},
-            {"name": "height", "type": "uint32_t"},
-            {"name": "depth", "type": "uint32_t"},
+            {"name": "size", "type": "extent 3D"},
             {"name": "arrayLayer", "type": "uint32_t"},
             {"name": "format", "type": "texture format"},
             {"name": "mipLevel", "type": "uint32_t"}
diff --git a/examples/CppHelloTriangle.cpp b/examples/CppHelloTriangle.cpp
index 7f8e6c1..3be8973 100644
--- a/examples/CppHelloTriangle.cpp
+++ b/examples/CppHelloTriangle.cpp
@@ -50,9 +50,9 @@
 void initTextures() {
     dawn::TextureDescriptor descriptor;
     descriptor.dimension = dawn::TextureDimension::e2D;
-    descriptor.width = 1024;
-    descriptor.height = 1024;
-    descriptor.depth = 1;
+    descriptor.size.width = 1024;
+    descriptor.size.height = 1024;
+    descriptor.size.depth = 1;
     descriptor.arrayLayer = 1;
     descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
     descriptor.mipLevel = 1;
diff --git a/examples/SampleUtils.cpp b/examples/SampleUtils.cpp
index 2c1510c..b2edd4d 100644
--- a/examples/SampleUtils.cpp
+++ b/examples/SampleUtils.cpp
@@ -138,9 +138,9 @@
 dawn::TextureView CreateDefaultDepthStencilView(const dawn::Device& device) {
     dawn::TextureDescriptor descriptor;
     descriptor.dimension = dawn::TextureDimension::e2D;
-    descriptor.width = 640;
-    descriptor.height = 480;
-    descriptor.depth = 1;
+    descriptor.size.width = 640;
+    descriptor.size.height = 480;
+    descriptor.size.depth = 1;
     descriptor.arrayLayer = 1;
     descriptor.format = dawn::TextureFormat::D32FloatS8Uint;
     descriptor.mipLevel = 1;
diff --git a/examples/glTFViewer/glTFViewer.cpp b/examples/glTFViewer/glTFViewer.cpp
index 7e86c61..ecded7f 100644
--- a/examples/glTFViewer/glTFViewer.cpp
+++ b/examples/glTFViewer/glTFViewer.cpp
@@ -384,9 +384,9 @@
 
             dawn::TextureDescriptor descriptor;
             descriptor.dimension = dawn::TextureDimension::e2D;
-            descriptor.width = iImage.width;
-            descriptor.height = iImage.height;
-            descriptor.depth = 1;
+            descriptor.size.width = iImage.width;
+            descriptor.size.height = iImage.height;
+            descriptor.size.depth = 1;
             descriptor.arrayLayer = 1;
             descriptor.format = format;
             descriptor.mipLevel = 1;
diff --git a/generator/main.py b/generator/main.py
index c88f2b4..ef21efa 100644
--- a/generator/main.py
+++ b/generator/main.py
@@ -171,6 +171,42 @@
             else:
                 member.length = members_by_name[m['length']]
 
+# Sort structures so that if struct A has struct B as a member, then B is listed before A
+# This is a form of topological sort where we try to keep the order reasonably similar to the
+# original order (though th sort isn't technically stable).
+# It works by computing for each struct type what is the depth of its DAG of dependents, then
+# resorting based on that depth using Python's stable sort. This makes a toposort because if
+# A depends on B then its depth will be bigger than B's. It is also nice because all nodes
+# with the same depth are kept in the input order.
+def topo_sort_structure(structs):
+    for struct in structs:
+        struct.visited = False
+        struct.subdag_depth = 0
+
+    def compute_depth(struct):
+        if struct.visited:
+            return struct.subdag_depth
+
+        max_dependent_depth = 0
+        for member in struct.members:
+            if member.type.category == 'structure' and member.annotation == 'value':
+                max_dependent_depth = max(max_dependent_depth, compute_depth(member.type) + 1)
+
+        struct.subdag_depth = max_dependent_depth
+        struct.visited = True
+        return struct.subdag_depth
+
+    for struct in structs:
+        compute_depth(struct)
+
+    result = sorted(structs, key=lambda struct: struct.subdag_depth)
+
+    for struct in structs:
+        del struct.visited
+        del struct.subdag_depth
+
+    return result
+
 def parse_json(json):
     category_to_parser = {
         'bitmask': BitmaskType,
@@ -204,6 +240,8 @@
     for category in by_category.keys():
         by_category[category] = sorted(by_category[category], key=lambda typ: typ.name.canonical_case())
 
+    by_category['structure'] = topo_sort_structure(by_category['structure'])
+
     return {
         'types': types,
         'by_category': by_category
diff --git a/src/dawn_native/SwapChain.cpp b/src/dawn_native/SwapChain.cpp
index ebb2a9d..05f79b6 100644
--- a/src/dawn_native/SwapChain.cpp
+++ b/src/dawn_native/SwapChain.cpp
@@ -61,9 +61,9 @@
 
         TextureDescriptor descriptor;
         descriptor.dimension = dawn::TextureDimension::e2D;
-        descriptor.width = mWidth;
-        descriptor.height = mHeight;
-        descriptor.depth = 1;
+        descriptor.size.width = mWidth;
+        descriptor.size.height = mHeight;
+        descriptor.size.depth = 1;
         descriptor.arrayLayer = 1;
         descriptor.format = mFormat;
         descriptor.mipLevel = 1;
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index a1a6cf6..d6dd4d8 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -29,8 +29,9 @@
         DAWN_TRY(ValidateTextureFormat(descriptor->format));
 
         // TODO(jiawei.shao@intel.com): check stuff based on the dimension
-        if (descriptor->width == 0 || descriptor->height == 0 || descriptor->depth == 0 ||
-            descriptor->arrayLayer == 0 || descriptor->mipLevel == 0) {
+        if (descriptor->size.width == 0 || descriptor->size.height == 0 ||
+            descriptor->size.depth == 0 || descriptor->arrayLayer == 0 ||
+            descriptor->mipLevel == 0) {
             return DAWN_VALIDATION_ERROR("Cannot create an empty texture");
         }
 
@@ -89,9 +90,9 @@
         : mDevice(device),
           mDimension(descriptor->dimension),
           mFormat(descriptor->format),
-          mWidth(descriptor->width),
-          mHeight(descriptor->height),
-          mDepth(descriptor->depth),
+          mWidth(descriptor->size.width),
+          mHeight(descriptor->size.height),
+          mDepth(descriptor->size.depth),
           mArrayLayers(descriptor->arrayLayer),
           mNumMipLevels(descriptor->mipLevel),
           mUsage(descriptor->usage) {
diff --git a/src/tests/end2end/BlendStateTests.cpp b/src/tests/end2end/BlendStateTests.cpp
index b1f9d0e..7d30c2a 100644
--- a/src/tests/end2end/BlendStateTests.cpp
+++ b/src/tests/end2end/BlendStateTests.cpp
@@ -692,9 +692,9 @@
 
     dawn::TextureDescriptor descriptor;
     descriptor.dimension = dawn::TextureDimension::e2D;
-    descriptor.width = kRTSize;
-    descriptor.height = kRTSize;
-    descriptor.depth = 1;
+    descriptor.size.width = kRTSize;
+    descriptor.size.height = kRTSize;
+    descriptor.size.depth = 1;
     descriptor.arrayLayer = 1;
     descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
     descriptor.mipLevel = 1;
diff --git a/src/tests/end2end/CopyTests.cpp b/src/tests/end2end/CopyTests.cpp
index c4780fe..f0a1db1 100644
--- a/src/tests/end2end/CopyTests.cpp
+++ b/src/tests/end2end/CopyTests.cpp
@@ -75,9 +75,9 @@
             // Create a texture that is `width` x `height` with (`level` + 1) mip levels.
             dawn::TextureDescriptor descriptor;
             descriptor.dimension = dawn::TextureDimension::e2D;
-            descriptor.width = textureSpec.width;
-            descriptor.height = textureSpec.height;
-            descriptor.depth = 1;
+            descriptor.size.width = textureSpec.width;
+            descriptor.size.height = textureSpec.height;
+            descriptor.size.depth = 1;
             descriptor.arrayLayer = textureSpec.arrayLayer;
             descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
             descriptor.mipLevel = textureSpec.level + 1;
@@ -175,9 +175,9 @@
         // Create a texture that is `width` x `height` with (`level` + 1) mip levels.
         dawn::TextureDescriptor descriptor;
         descriptor.dimension = dawn::TextureDimension::e2D;
-        descriptor.width = textureSpec.width;
-        descriptor.height = textureSpec.height;
-        descriptor.depth = 1;
+        descriptor.size.width = textureSpec.width;
+        descriptor.size.height = textureSpec.height;
+        descriptor.size.depth = 1;
         descriptor.arrayLayer = 1;
         descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
         descriptor.mipLevel = textureSpec.level + 1;
diff --git a/src/tests/end2end/DepthStencilStateTests.cpp b/src/tests/end2end/DepthStencilStateTests.cpp
index ee9ce9e..3f52d02 100644
--- a/src/tests/end2end/DepthStencilStateTests.cpp
+++ b/src/tests/end2end/DepthStencilStateTests.cpp
@@ -26,9 +26,9 @@
 
             dawn::TextureDescriptor renderTargetDescriptor;
             renderTargetDescriptor.dimension = dawn::TextureDimension::e2D;
-            renderTargetDescriptor.width = kRTSize;
-            renderTargetDescriptor.height = kRTSize;
-            renderTargetDescriptor.depth = 1;
+            renderTargetDescriptor.size.width = kRTSize;
+            renderTargetDescriptor.size.height = kRTSize;
+            renderTargetDescriptor.size.depth = 1;
             renderTargetDescriptor.arrayLayer = 1;
             renderTargetDescriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
             renderTargetDescriptor.mipLevel = 1;
@@ -39,9 +39,9 @@
 
             dawn::TextureDescriptor depthDescriptor;
             depthDescriptor.dimension = dawn::TextureDimension::e2D;
-            depthDescriptor.width = kRTSize;
-            depthDescriptor.height = kRTSize;
-            depthDescriptor.depth = 1;
+            depthDescriptor.size.width = kRTSize;
+            depthDescriptor.size.height = kRTSize;
+            depthDescriptor.size.depth = 1;
             depthDescriptor.arrayLayer = 1;
             depthDescriptor.format = dawn::TextureFormat::D32FloatS8Uint;
             depthDescriptor.mipLevel = 1;
diff --git a/src/tests/end2end/RenderPassLoadOpTests.cpp b/src/tests/end2end/RenderPassLoadOpTests.cpp
index 6b36a3d..4c80487 100644
--- a/src/tests/end2end/RenderPassLoadOpTests.cpp
+++ b/src/tests/end2end/RenderPassLoadOpTests.cpp
@@ -57,9 +57,9 @@
 
             dawn::TextureDescriptor descriptor;
             descriptor.dimension = dawn::TextureDimension::e2D;
-            descriptor.width = kRTSize;
-            descriptor.height = kRTSize;
-            descriptor.depth = 1;
+            descriptor.size.width = kRTSize;
+            descriptor.size.height = kRTSize;
+            descriptor.size.depth = 1;
             descriptor.arrayLayer = 1;
             descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
             descriptor.mipLevel = 1;
diff --git a/src/tests/end2end/SamplerTests.cpp b/src/tests/end2end/SamplerTests.cpp
index c22f138..f6c0d10 100644
--- a/src/tests/end2end/SamplerTests.cpp
+++ b/src/tests/end2end/SamplerTests.cpp
@@ -82,9 +82,9 @@
 
         dawn::TextureDescriptor descriptor;
         descriptor.dimension = dawn::TextureDimension::e2D;
-        descriptor.width = 2;
-        descriptor.height = 2;
-        descriptor.depth = 1;
+        descriptor.size.width = 2;
+        descriptor.size.height = 2;
+        descriptor.size.depth = 1;
         descriptor.arrayLayer = 1;
         descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
         descriptor.mipLevel = 1;
diff --git a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
index dc2af0e..e6da28d 100644
--- a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
+++ b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
@@ -30,9 +30,9 @@
                                          dawn::TextureFormat format, dawn::TextureUsageBit usage) {
             dawn::TextureDescriptor descriptor;
             descriptor.dimension = dawn::TextureDimension::e2D;
-            descriptor.width = width;
-            descriptor.height = height;
-            descriptor.depth = 1;
+            descriptor.size.width = width;
+            descriptor.size.height = height;
+            descriptor.size.depth = 1;
             descriptor.arrayLayer = arrayLayer;
             descriptor.format = format;
             descriptor.mipLevel = levels;
diff --git a/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp b/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
index c6e1144..3672734 100644
--- a/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
+++ b/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
@@ -24,9 +24,9 @@
 dawn::TextureView Create2DAttachment(dawn::Device& device, uint32_t width, uint32_t height, dawn::TextureFormat format) {
     dawn::TextureDescriptor descriptor;
     descriptor.dimension = dawn::TextureDimension::e2D;
-    descriptor.width = width;
-    descriptor.height = height;
-    descriptor.depth = 1;
+    descriptor.size.width = width;
+    descriptor.size.height = height;
+    descriptor.size.depth = 1;
     descriptor.arrayLayer = 1;
     descriptor.format = format;
     descriptor.mipLevel = 1;
diff --git a/src/tests/unittests/validation/ValidationTest.cpp b/src/tests/unittests/validation/ValidationTest.cpp
index e01722e..cc2279f 100644
--- a/src/tests/unittests/validation/ValidationTest.cpp
+++ b/src/tests/unittests/validation/ValidationTest.cpp
@@ -76,9 +76,9 @@
 dawn::RenderPassDescriptor ValidationTest::CreateSimpleRenderPass() {
         dawn::TextureDescriptor descriptor;
         descriptor.dimension = dawn::TextureDimension::e2D;
-        descriptor.width = 640;
-        descriptor.height = 480;
-        descriptor.depth = 1;
+        descriptor.size.width = 640;
+        descriptor.size.height = 480;
+        descriptor.size.depth = 1;
         descriptor.arrayLayer = 1;
         descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
         descriptor.mipLevel = 1;
@@ -129,9 +129,9 @@
 
     dawn::TextureDescriptor descriptor;
     descriptor.dimension = dawn::TextureDimension::e2D;
-    descriptor.width = dummy.width;
-    descriptor.height = dummy.height;
-    descriptor.depth = 1;
+    descriptor.size.width = dummy.width;
+    descriptor.size.height = dummy.height;
+    descriptor.size.depth = 1;
     descriptor.arrayLayer = 1;
     descriptor.format = dummy.attachmentFormat;
     descriptor.mipLevel = 1;
diff --git a/src/utils/DawnHelpers.cpp b/src/utils/DawnHelpers.cpp
index 69f594f..0a55942 100644
--- a/src/utils/DawnHelpers.cpp
+++ b/src/utils/DawnHelpers.cpp
@@ -135,9 +135,9 @@
         result.colorFormat = dawn::TextureFormat::R8G8B8A8Unorm;
         dawn::TextureDescriptor descriptor;
         descriptor.dimension = dawn::TextureDimension::e2D;
-        descriptor.width = width;
-        descriptor.height = height;
-        descriptor.depth = 1;
+        descriptor.size.width = width;
+        descriptor.size.height = height;
+        descriptor.size.depth = 1;
         descriptor.arrayLayer = 1;
         descriptor.format = result.colorFormat;
         descriptor.mipLevel = 1;