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>
This commit is contained in:
parent
d586b079f2
commit
0768ffa742
|
@ -39,23 +39,38 @@ namespace dawn_native { namespace metal {
|
||||||
storageMode = MTLResourceStorageModePrivate;
|
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
|
// TODO(cwallez@chromium.org): Have a global "zero" buffer that can do everything instead
|
||||||
// of creating a new 4-byte buffer?
|
// 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
|
// 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
|
// 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.
|
// buffer must be aligned to the largest alignment of its members.
|
||||||
if (GetUsage() & (wgpu::BufferUsage::Uniform | wgpu::BufferUsage::Storage)) {
|
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);
|
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
|
mMtlBuffer = [ToBackend(GetDevice())->GetMTLDevice() newBufferWithLength:currentSize
|
||||||
options:storageMode];
|
options:storageMode];
|
||||||
|
if (mMtlBuffer == nil) {
|
||||||
|
return DAWN_OUT_OF_MEMORY_ERROR("Buffer allocation failed");
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -429,7 +429,7 @@ TEST_P(CreateBufferMappedTests, CreateThenMapBeforeUnmapFailure) {
|
||||||
// Test that creating a very large buffers fails gracefully.
|
// Test that creating a very large buffers fails gracefully.
|
||||||
TEST_P(CreateBufferMappedTests, LargeBufferFails) {
|
TEST_P(CreateBufferMappedTests, LargeBufferFails) {
|
||||||
// TODO(http://crbug.com/dawn/27): Missing support.
|
// TODO(http://crbug.com/dawn/27): Missing support.
|
||||||
DAWN_SKIP_TEST_IF(IsMetal() || IsOpenGL());
|
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||||
|
|
||||||
wgpu::BufferDescriptor descriptor;
|
wgpu::BufferDescriptor descriptor;
|
||||||
descriptor.size = std::numeric_limits<uint64_t>::max();
|
descriptor.size = std::numeric_limits<uint64_t>::max();
|
||||||
|
|
Loading…
Reference in New Issue