From 6ce8f32feeabf078af8eb20dd8b5fbd4828d176d Mon Sep 17 00:00:00 2001 From: Bryan Bernhart Date: Wed, 11 Dec 2019 17:13:21 +0000 Subject: [PATCH] D3D12: Fix 64-bit overflow for large buffers and return OOM. Use `resourceDesc.alignment` + GetResourceAllocationInfo to determine the buffer size and OOM should it return an empty sized buffer instead of overflowing + INVALID_ARGS. BUG=dawn:238 Change-Id: I0a2cc7dac629d55624dafa4a3c4a45f16e90049c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/14420 Commit-Queue: Bryan Bernhart Reviewed-by: Corentin Wallez --- src/dawn_native/d3d12/BufferD3D12.cpp | 7 +------ src/dawn_native/d3d12/BufferD3D12.h | 1 - .../d3d12/ResourceAllocatorManagerD3D12.cpp | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/dawn_native/d3d12/BufferD3D12.cpp b/src/dawn_native/d3d12/BufferD3D12.cpp index 8f32c36091..9cfc536a20 100644 --- a/src/dawn_native/d3d12/BufferD3D12.cpp +++ b/src/dawn_native/d3d12/BufferD3D12.cpp @@ -82,7 +82,7 @@ namespace dawn_native { namespace d3d12 { D3D12_RESOURCE_DESC resourceDescriptor; resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; resourceDescriptor.Alignment = 0; - resourceDescriptor.Width = GetD3D12Size(); + resourceDescriptor.Width = GetSize(); resourceDescriptor.Height = 1; resourceDescriptor.DepthOrArraySize = 1; resourceDescriptor.MipLevels = 1; @@ -123,11 +123,6 @@ namespace dawn_native { namespace d3d12 { DestroyInternal(); } - uint32_t Buffer::GetD3D12Size() const { - // TODO(enga@google.com): TODO investigate if this needs to be a constraint at the API level - return Align(GetSize(), 256); - } - ComPtr Buffer::GetD3D12Resource() const { return mResourceAllocation.GetD3D12Resource(); } diff --git a/src/dawn_native/d3d12/BufferD3D12.h b/src/dawn_native/d3d12/BufferD3D12.h index 6a5b9366a4..91a7fbaa56 100644 --- a/src/dawn_native/d3d12/BufferD3D12.h +++ b/src/dawn_native/d3d12/BufferD3D12.h @@ -33,7 +33,6 @@ namespace dawn_native { namespace d3d12 { MaybeError Initialize(); - uint32_t GetD3D12Size() const; ComPtr GetD3D12Resource() const; D3D12_GPU_VIRTUAL_ADDRESS GetVA() const; void OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite); diff --git a/src/dawn_native/d3d12/ResourceAllocatorManagerD3D12.cpp b/src/dawn_native/d3d12/ResourceAllocatorManagerD3D12.cpp index 5200a145c3..e066062111 100644 --- a/src/dawn_native/d3d12/ResourceAllocatorManagerD3D12.cpp +++ b/src/dawn_native/d3d12/ResourceAllocatorManagerD3D12.cpp @@ -220,6 +220,9 @@ namespace dawn_native { namespace d3d12 { resourceInfo = mDevice->GetD3D12Device()->GetResourceAllocationInfo(0, 1, &resourceDescriptor); } + if (resourceInfo.SizeInBytes == 0) { + return DAWN_OUT_OF_MEMORY_ERROR("Resource allocation size was invalid."); + } BuddyMemoryAllocator* allocator = mSubAllocatedResourceAllocators[resourceHeapKindIndex].get(); @@ -261,6 +264,18 @@ namespace dawn_native { namespace d3d12 { heapProperties.CreationNodeMask = 0; heapProperties.VisibleNodeMask = 0; + // If d3d tells us the resource is "zero-sized", the size is invalid and may cause a device + // lost (too large for driver). Instead, treat the error as a OOM. + D3D12_RESOURCE_ALLOCATION_INFO resourceInfo = + mDevice->GetD3D12Device()->GetResourceAllocationInfo(0, 1, &resourceDescriptor); + if (resourceInfo.SizeInBytes == 0) { + return DAWN_OUT_OF_MEMORY_ERROR("Resource allocation size was invalid."); + } + + if (resourceInfo.SizeInBytes > kMaxHeapSize) { + return ResourceHeapAllocation{}; // Invalid + } + // Note: Heap flags are inferred by the resource descriptor and do not need to be explicitly // provided to CreateCommittedResource. ComPtr committedResource;