Use whole size of buffer if binding buffer size is UINT64_MAX

Following WebGPU spec change at https://github.com/gpuweb/gpuweb/issues/331,
bind groups in Dawn now use the whole size of the buffer if binding buffer
size is UINT64_MAX.

Bug: dawn:22
Change-Id: If28d905e634432755dad5c67c69eadedcee53dfe
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8863
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: François Beaufort <beaufort.francois@gmail.com>
diff --git a/generator/templates/api.h b/generator/templates/api.h
index bdd10ec..7e5add8 100644
--- a/generator/templates/api.h
+++ b/generator/templates/api.h
@@ -21,6 +21,8 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+const uint64_t DAWN_WHOLE_SIZE = 0xffffffffffffffffULL; // UINT64_MAX
+
 {% for type in by_category["object"] %}
     typedef struct {{as_cType(type.name)}}Impl* {{as_cType(type.name)}};
 {% endfor %}
diff --git a/generator/templates/apicpp.h b/generator/templates/apicpp.h
index e203b7f..a78dc62 100644
--- a/generator/templates/apicpp.h
+++ b/generator/templates/apicpp.h
@@ -21,6 +21,8 @@
 
 namespace dawn {
 
+    static constexpr uint64_t kWholeSize = DAWN_WHOLE_SIZE;
+
     {% for type in by_category["enum"] %}
         enum class {{as_cppType(type.name)}} : uint32_t {
             {% for value in type.values %}
diff --git a/src/dawn_native/BindGroup.cpp b/src/dawn_native/BindGroup.cpp
index e94baf2..da018e1 100644
--- a/src/dawn_native/BindGroup.cpp
+++ b/src/dawn_native/BindGroup.cpp
@@ -38,13 +38,14 @@
             DAWN_TRY(device->ValidateObject(binding.buffer));
 
             uint64_t bufferSize = binding.buffer->GetSize();
-            if (binding.size > bufferSize) {
+            uint64_t bindingSize = (binding.size == dawn::kWholeSize) ? bufferSize : binding.size;
+            if (bindingSize > bufferSize) {
                 return DAWN_VALIDATION_ERROR("Buffer binding size larger than the buffer");
             }
 
             // Note that no overflow can happen because we already checked that
-            // bufferSize >= binding.size
-            if (binding.offset > bufferSize - binding.size) {
+            // bufferSize >= bindingSize
+            if (binding.offset > bufferSize - bindingSize) {
                 return DAWN_VALIDATION_ERROR("Buffer binding doesn't fit in the buffer");
             }
 
@@ -172,7 +173,9 @@
                 ASSERT(mBindings[bindingIndex].Get() == nullptr);
                 mBindings[bindingIndex] = binding.buffer;
                 mOffsets[bindingIndex] = binding.offset;
-                mSizes[bindingIndex] = binding.size;
+                uint64_t bufferSize =
+                    (binding.size == dawn::kWholeSize) ? binding.buffer->GetSize() : binding.size;
+                mSizes[bindingIndex] = bufferSize;
                 continue;
             }
 
diff --git a/src/tests/unittests/validation/BindGroupValidationTests.cpp b/src/tests/unittests/validation/BindGroupValidationTests.cpp
index 4b73cda..016dc0b 100644
--- a/src/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -370,6 +370,7 @@
 
     // Success case, touching the full buffer works
     utils::MakeBindGroup(device, layout, {{0, buffer, 0, 1024}});
+    utils::MakeBindGroup(device, layout, {{0, buffer, 0, dawn::kWholeSize}});
 
     // Error case, offset is OOB
     ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 256*5, 0}}));
@@ -379,6 +380,7 @@
 
     // Error case, offset+size is OOB
     ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 1024, 1}}));
+    ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 1, dawn::kWholeSize}}));
 
     // Error case, offset+size overflows to be 0
     ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, buffer, 256, uint32_t(0) - uint32_t(256)}}));