D3D12: Enable sub-allocation for MSAA and non-MSAA textures.

Updates TextureD3D to use the allocation handle and
defaults to using MSAA heaps.

BUG=dawn:27

Change-Id: I2318bb8d068df86364cb2ebc433f4737e9e121aa
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/12580
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Bryan Bernhart <bryan.bernhart@intel.com>
diff --git a/BUILD.gn b/BUILD.gn
index 2e9eff0..3606ba7 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -291,8 +291,6 @@
       "src/dawn_native/d3d12/QueueD3D12.h",
       "src/dawn_native/d3d12/RenderPipelineD3D12.cpp",
       "src/dawn_native/d3d12/RenderPipelineD3D12.h",
-      "src/dawn_native/d3d12/ResourceAllocator.cpp",
-      "src/dawn_native/d3d12/ResourceAllocator.h",
       "src/dawn_native/d3d12/ResourceAllocatorManagerD3D12.cpp",
       "src/dawn_native/d3d12/ResourceAllocatorManagerD3D12.h",
       "src/dawn_native/d3d12/ResourceHeapAllocationD3D12.cpp",
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index 301ac97..f1431db 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -29,7 +29,6 @@
 #include "dawn_native/d3d12/PipelineLayoutD3D12.h"
 #include "dawn_native/d3d12/PlatformFunctions.h"
 #include "dawn_native/d3d12/RenderPipelineD3D12.h"
-#include "dawn_native/d3d12/ResourceAllocator.h"
 #include "dawn_native/d3d12/SamplerD3D12.h"
 #include "dawn_native/d3d12/TextureCopySplitter.h"
 #include "dawn_native/d3d12/TextureD3D12.h"
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index 2cc42ec..40097bf 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -31,7 +31,6 @@
 #include "dawn_native/d3d12/PlatformFunctions.h"
 #include "dawn_native/d3d12/QueueD3D12.h"
 #include "dawn_native/d3d12/RenderPipelineD3D12.h"
-#include "dawn_native/d3d12/ResourceAllocator.h"
 #include "dawn_native/d3d12/ResourceAllocatorManagerD3D12.h"
 #include "dawn_native/d3d12/SamplerD3D12.h"
 #include "dawn_native/d3d12/ShaderModuleD3D12.h"
@@ -72,7 +71,6 @@
         mCommandAllocatorManager = std::make_unique<CommandAllocatorManager>(this);
         mDescriptorHeapAllocator = std::make_unique<DescriptorHeapAllocator>(this);
         mMapRequestTracker = std::make_unique<MapRequestTracker>(this);
-        mResourceAllocator = std::make_unique<ResourceAllocator>(this);
         mResourceAllocatorManager = std::make_unique<ResourceAllocatorManager>(this);
 
         DAWN_TRY(NextSerial());
@@ -125,10 +123,6 @@
         // MAX.
         mCompletedSerial = std::numeric_limits<Serial>::max();
 
-        // Releasing the uploader enqueues buffers to be released.
-        // Call Tick() again to clear them before releasing the allocator.
-        mResourceAllocator->Tick(mCompletedSerial);
-
         if (mFenceEvent != nullptr) {
             ::CloseHandle(mFenceEvent);
         }
@@ -175,10 +169,6 @@
         return mMapRequestTracker.get();
     }
 
-    ResourceAllocator* Device::GetResourceAllocator() const {
-        return mResourceAllocator.get();
-    }
-
     CommandAllocatorManager* Device::GetCommandAllocatorManager() const {
         return mCommandAllocatorManager.get();
     }
@@ -212,7 +202,6 @@
         // as it enqueued resources to be released.
         mDynamicUploader->Deallocate(mCompletedSerial);
 
-        mResourceAllocator->Tick(mCompletedSerial);
         mResourceAllocatorManager->Tick(mCompletedSerial);
         DAWN_TRY(mCommandAllocatorManager->Tick(mCompletedSerial));
         mDescriptorHeapAllocator->Deallocate(mCompletedSerial);
diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h
index 98ae4f1..4aa27ff 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/src/dawn_native/d3d12/DeviceD3D12.h
@@ -31,7 +31,6 @@
     class DescriptorHeapAllocator;
     class MapRequestTracker;
     class PlatformFunctions;
-    class ResourceAllocator;
     class ResourceAllocatorManager;
 
 #define ASSERT_SUCCESS(hr)            \
@@ -64,7 +63,6 @@
 
         DescriptorHeapAllocator* GetDescriptorHeapAllocator() const;
         MapRequestTracker* GetMapRequestTracker() const;
-        ResourceAllocator* GetResourceAllocator() const;
         CommandAllocatorManager* GetCommandAllocatorManager() const;
 
         const PlatformFunctions* GetFunctions() const;
@@ -147,7 +145,6 @@
         std::unique_ptr<CommandAllocatorManager> mCommandAllocatorManager;
         std::unique_ptr<DescriptorHeapAllocator> mDescriptorHeapAllocator;
         std::unique_ptr<MapRequestTracker> mMapRequestTracker;
-        std::unique_ptr<ResourceAllocator> mResourceAllocator;
         std::unique_ptr<ResourceAllocatorManager> mResourceAllocatorManager;
 
         dawn_native::PCIInfo mPCIInfo;
diff --git a/src/dawn_native/d3d12/HeapAllocatorD3D12.cpp b/src/dawn_native/d3d12/HeapAllocatorD3D12.cpp
index 8cd5640..59507ab 100644
--- a/src/dawn_native/d3d12/HeapAllocatorD3D12.cpp
+++ b/src/dawn_native/d3d12/HeapAllocatorD3D12.cpp
@@ -32,9 +32,11 @@
         heapDesc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
         heapDesc.Properties.CreationNodeMask = 0;
         heapDesc.Properties.VisibleNodeMask = 0;
-        // MSAA vs non-MSAA resources have separate heap alignments.
-        // TODO(bryan.bernhart@intel.com): Support heap creation containing MSAA resources.
-        heapDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+        // It is preferred to use a size that is a multiple of the alignment.
+        // However, MSAA heaps are always aligned to 4MB instead of 64KB. This means
+        // if the heap size is too small, the VMM would fragment.
+        // TODO(bryan.bernhart@intel.com): Consider having MSAA vs non-MSAA heaps.
+        heapDesc.Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT;
         heapDesc.Flags = mHeapFlags;
 
         ComPtr<ID3D12Heap> heap;
diff --git a/src/dawn_native/d3d12/ResourceAllocator.cpp b/src/dawn_native/d3d12/ResourceAllocator.cpp
deleted file mode 100644
index e2822e6..0000000
--- a/src/dawn_native/d3d12/ResourceAllocator.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2017 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "dawn_native/d3d12/ResourceAllocator.h"
-
-#include "dawn_native/d3d12/DeviceD3D12.h"
-
-namespace dawn_native { namespace d3d12 {
-
-    namespace {
-        static constexpr D3D12_HEAP_PROPERTIES kDefaultHeapProperties = {
-            D3D12_HEAP_TYPE_DEFAULT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0,
-            0};
-
-        static constexpr D3D12_HEAP_PROPERTIES kUploadHeapProperties = {
-            D3D12_HEAP_TYPE_UPLOAD, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0,
-            0};
-
-        static constexpr D3D12_HEAP_PROPERTIES kReadbackHeapProperties = {
-            D3D12_HEAP_TYPE_READBACK, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 0,
-            0};
-    }  // namespace
-
-    ResourceAllocator::ResourceAllocator(Device* device) : mDevice(device) {
-    }
-
-    ComPtr<ID3D12Resource> ResourceAllocator::Allocate(
-        D3D12_HEAP_TYPE heapType,
-        const D3D12_RESOURCE_DESC& resourceDescriptor,
-        D3D12_RESOURCE_STATES initialUsage) {
-        const D3D12_HEAP_PROPERTIES* heapProperties = nullptr;
-        switch (heapType) {
-            case D3D12_HEAP_TYPE_DEFAULT:
-                heapProperties = &kDefaultHeapProperties;
-                break;
-            case D3D12_HEAP_TYPE_UPLOAD:
-                heapProperties = &kUploadHeapProperties;
-                break;
-            case D3D12_HEAP_TYPE_READBACK:
-                heapProperties = &kReadbackHeapProperties;
-                break;
-            default:
-                UNREACHABLE();
-        }
-
-        ComPtr<ID3D12Resource> resource;
-
-        // TODO(enga@google.com): Use CreatePlacedResource
-        ASSERT_SUCCESS(mDevice->GetD3D12Device()->CreateCommittedResource(
-            heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDescriptor, initialUsage, nullptr,
-            IID_PPV_ARGS(&resource)));
-
-        return resource;
-    }
-
-    void ResourceAllocator::Release(ComPtr<ID3D12Resource> resource) {
-        // Resources may still be in use on the GPU. Enqueue them so that we hold onto them until
-        // GPU execution has completed
-        mReleasedResources.Enqueue(resource, mDevice->GetPendingCommandSerial());
-    }
-
-    void ResourceAllocator::Tick(uint64_t lastCompletedSerial) {
-        mReleasedResources.ClearUpTo(lastCompletedSerial);
-    }
-
-}}  // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/ResourceAllocator.h b/src/dawn_native/d3d12/ResourceAllocator.h
deleted file mode 100644
index 9311db6..0000000
--- a/src/dawn_native/d3d12/ResourceAllocator.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2017 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef DAWNNATIVE_D3D12_RESOURCEALLOCATIONMANAGER_H_
-#define DAWNNATIVE_D3D12_RESOURCEALLOCATIONMANAGER_H_
-
-#include "dawn_native/d3d12/d3d12_platform.h"
-
-#include "common/SerialQueue.h"
-
-namespace dawn_native { namespace d3d12 {
-
-    class Device;
-
-    class ResourceAllocator {
-      public:
-        ResourceAllocator(Device* device);
-
-        ComPtr<ID3D12Resource> Allocate(D3D12_HEAP_TYPE heapType,
-                                        const D3D12_RESOURCE_DESC& resourceDescriptor,
-                                        D3D12_RESOURCE_STATES initialUsage);
-        void Release(ComPtr<ID3D12Resource> resource);
-        void Tick(uint64_t lastCompletedSerial);
-
-      private:
-        Device* mDevice;
-
-        SerialQueue<ComPtr<ID3D12Resource>> mReleasedResources;
-    };
-
-}}  // namespace dawn_native::d3d12
-
-#endif  // DAWNNATIVE_D3D12_RESOURCEALLOCATIONMANAGER_H_
diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp
index bcb3c39..9caf2f3 100644
--- a/src/dawn_native/d3d12/TextureD3D12.cpp
+++ b/src/dawn_native/d3d12/TextureD3D12.cpp
@@ -22,7 +22,7 @@
 #include "dawn_native/d3d12/D3D12Error.h"
 #include "dawn_native/d3d12/DescriptorHeapAllocator.h"
 #include "dawn_native/d3d12/DeviceD3D12.h"
-#include "dawn_native/d3d12/ResourceAllocator.h"
+#include "dawn_native/d3d12/ResourceAllocatorManagerD3D12.h"
 #include "dawn_native/d3d12/StagingBufferD3D12.h"
 #include "dawn_native/d3d12/TextureCopySplitter.h"
 #include "dawn_native/d3d12/UtilsD3D12.h"
@@ -313,7 +313,10 @@
 
         mAcquireMutexKey = acquireMutexKey;
         mDxgiKeyedMutex = std::move(dxgiKeyedMutex);
-        mResource = std::move(d3d12Resource);
+
+        AllocationInfo info;
+        info.mMethod = AllocationMethod::kDirect;
+        mResourceAllocation = {info, 0, std::move(d3d12Resource)};
 
         SetIsSubresourceContentInitialized(true, 0, descriptor->mipLevelCount, 0,
                                            descriptor->arrayLayerCount);
@@ -340,10 +343,10 @@
         resourceDescriptor.Flags =
             D3D12ResourceFlags(GetUsage(), GetFormat(), IsMultisampledTexture());
 
-        mResource = ToBackend(GetDevice())
-                        ->GetResourceAllocator()
-                        ->Allocate(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor,
-                                   D3D12_RESOURCE_STATE_COMMON);
+        DAWN_TRY_ASSIGN(mResourceAllocation,
+                        ToBackend(GetDevice())
+                            ->AllocateMemory(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor,
+                                             D3D12_RESOURCE_STATE_COMMON));
 
         Device* device = ToBackend(GetDevice());
 
@@ -361,8 +364,11 @@
     Texture::Texture(Device* device,
                      const TextureDescriptor* descriptor,
                      ComPtr<ID3D12Resource> nativeTexture)
-        : TextureBase(device, descriptor, TextureState::OwnedExternal),
-          mResource(std::move(nativeTexture)) {
+        : TextureBase(device, descriptor, TextureState::OwnedExternal) {
+        AllocationInfo info;
+        info.mMethod = AllocationMethod::kDirect;
+        mResourceAllocation = {info, 0, std::move(nativeTexture)};
+
         SetIsSubresourceContentInitialized(true, 0, descriptor->mipLevelCount, 0,
                                            descriptor->arrayLayerCount);
     }
@@ -373,7 +379,7 @@
 
     void Texture::DestroyImpl() {
         Device* device = ToBackend(GetDevice());
-        device->GetResourceAllocator()->Release(std::move(mResource));
+        device->DeallocateMemory(mResourceAllocation);
 
         if (mDxgiKeyedMutex != nullptr) {
             mDxgiKeyedMutex->ReleaseSync(mAcquireMutexKey + 1);
@@ -386,7 +392,7 @@
     }
 
     ID3D12Resource* Texture::GetD3D12Resource() const {
-        return mResource.Get();
+        return mResourceAllocation.GetD3D12Resource().Get();
     }
 
     UINT16 Texture::GetDepthOrArraySize() {
@@ -476,7 +482,7 @@
 
         barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
         barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
-        barrier->Transition.pResource = mResource.Get();
+        barrier->Transition.pResource = GetD3D12Resource();
         barrier->Transition.StateBefore = lastState;
         barrier->Transition.StateAfter = newState;
         barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
@@ -570,7 +576,7 @@
                                              D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1));
                 D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(0);
                 D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(baseMipLevel);
-                device->GetD3D12Device()->CreateDepthStencilView(mResource.Get(), &dsvDesc,
+                device->GetD3D12Device()->CreateDepthStencilView(GetD3D12Resource(), &dsvDesc,
                                                                  dsvHandle);
 
                 D3D12_CLEAR_FLAGS clearFlags = {};
@@ -597,7 +603,7 @@
                 for (uint32_t i = baseMipLevel; i < baseMipLevel + levelCount; i++) {
                     D3D12_RENDER_TARGET_VIEW_DESC rtvDesc =
                         GetRTVDescriptor(i, baseArrayLayer, layerCount);
-                    device->GetD3D12Device()->CreateRenderTargetView(mResource.Get(), &rtvDesc,
+                    device->GetD3D12Device()->CreateRenderTargetView(GetD3D12Resource(), &rtvDesc,
                                                                      rtvHandle);
                     commandList->ClearRenderTargetView(rtvHandle, clearColorRGBA, 0, nullptr);
                 }
diff --git a/src/dawn_native/d3d12/TextureD3D12.h b/src/dawn_native/d3d12/TextureD3D12.h
index adfe4d1..1e10df9 100644
--- a/src/dawn_native/d3d12/TextureD3D12.h
+++ b/src/dawn_native/d3d12/TextureD3D12.h
@@ -18,6 +18,7 @@
 #include "common/Serial.h"
 #include "dawn_native/Texture.h"
 
+#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
 #include "dawn_native/d3d12/d3d12_platform.h"
 
 namespace dawn_native { namespace d3d12 {
@@ -86,7 +87,7 @@
                                                   D3D12_RESOURCE_BARRIER* barrier,
                                                   D3D12_RESOURCE_STATES newState);
 
-        ComPtr<ID3D12Resource> mResource;
+        ResourceHeapAllocation mResourceAllocation;
         D3D12_RESOURCE_STATES mLastState = D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_COMMON;
 
         Serial mLastUsedSerial = UINT64_MAX;