Metal: Handle Buffer allocation failure
Bug: dawn:433
Change-Id: I6549c4a1e31171257761397b018090d0eb7471e6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22424
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/metal/BufferMTL.mm b/src/dawn_native/metal/BufferMTL.mm
index 0f84467..6da0fd9 100644
--- a/src/dawn_native/metal/BufferMTL.mm
+++ b/src/dawn_native/metal/BufferMTL.mm
@@ -39,23 +39,38 @@
storageMode = MTLResourceStorageModePrivate;
}
- if (GetSize() >
- std::numeric_limits<uint64_t>::max() - kMinUniformOrStorageBufferAlignment) {
- return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation is too large");
- }
-
// TODO(cwallez@chromium.org): Have a global "zero" buffer that can do everything instead
// of creating a new 4-byte buffer?
- uint32_t currentSize = std::max(GetSize(), uint64_t(4u));
+ if (GetSize() > std::numeric_limits<NSUInteger>::max()) {
+ return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation is too large");
+ }
+ NSUInteger currentSize = static_cast<NSUInteger>(std::max(GetSize(), uint64_t(4u)));
+
// Metal validation layer requires the size of uniform buffer and storage buffer to be no
// less than the size of the buffer block defined in shader, and the overall size of the
// buffer must be aligned to the largest alignment of its members.
if (GetUsage() & (wgpu::BufferUsage::Uniform | wgpu::BufferUsage::Storage)) {
+ if (currentSize >
+ std::numeric_limits<NSUInteger>::max() - kMinUniformOrStorageBufferAlignment) {
+ // Alignment would overlow.
+ return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation is too large");
+ }
currentSize = Align(currentSize, kMinUniformOrStorageBufferAlignment);
}
+ if (@available(iOS 12, macOS 10.14, *)) {
+ NSUInteger maxBufferSize = [ToBackend(GetDevice())->GetMTLDevice() maxBufferLength];
+ if (currentSize > maxBufferSize) {
+ return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation is too large");
+ }
+ }
+
mMtlBuffer = [ToBackend(GetDevice())->GetMTLDevice() newBufferWithLength:currentSize
options:storageMode];
+ if (mMtlBuffer == nil) {
+ return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation failed");
+ }
+
return {};
}
diff --git a/src/tests/end2end/BufferTests.cpp b/src/tests/end2end/BufferTests.cpp
index 504cf32..61f4e34 100644
--- a/src/tests/end2end/BufferTests.cpp
+++ b/src/tests/end2end/BufferTests.cpp
@@ -429,7 +429,7 @@
// Test that creating a very large buffers fails gracefully.
TEST_P(CreateBufferMappedTests, LargeBufferFails) {
// TODO(http://crbug.com/dawn/27): Missing support.
- DAWN_SKIP_TEST_IF(IsMetal() || IsOpenGL());
+ DAWN_SKIP_TEST_IF(IsOpenGL());
wgpu::BufferDescriptor descriptor;
descriptor.size = std::numeric_limits<uint64_t>::max();