• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "dawn_native/vulkan/MemoryAllocator.h"
16 
17 #include "dawn_native/vulkan/DeviceVk.h"
18 #include "dawn_native/vulkan/FencedDeleter.h"
19 
20 namespace dawn_native { namespace vulkan {
21 
~DeviceMemoryAllocation()22     DeviceMemoryAllocation::~DeviceMemoryAllocation() {
23         ASSERT(mMemory == VK_NULL_HANDLE);
24     }
25 
GetMemory() const26     VkDeviceMemory DeviceMemoryAllocation::GetMemory() const {
27         return mMemory;
28     }
29 
GetMemoryOffset() const30     size_t DeviceMemoryAllocation::GetMemoryOffset() const {
31         return mOffset;
32     }
33 
GetMappedPointer() const34     uint8_t* DeviceMemoryAllocation::GetMappedPointer() const {
35         return mMappedPointer;
36     }
37 
MemoryAllocator(Device * device)38     MemoryAllocator::MemoryAllocator(Device* device) : mDevice(device) {
39     }
40 
~MemoryAllocator()41     MemoryAllocator::~MemoryAllocator() {
42     }
43 
Allocate(VkMemoryRequirements requirements,bool mappable,DeviceMemoryAllocation * allocation)44     bool MemoryAllocator::Allocate(VkMemoryRequirements requirements,
45                                    bool mappable,
46                                    DeviceMemoryAllocation* allocation) {
47         const VulkanDeviceInfo& info = mDevice->GetDeviceInfo();
48 
49         // Find a suitable memory type for this allocation
50         int bestType = -1;
51         for (size_t i = 0; i < info.memoryTypes.size(); ++i) {
52             // Resource must support this memory type
53             if ((requirements.memoryTypeBits & (1 << i)) == 0) {
54                 continue;
55             }
56 
57             // Mappable resource must be host visible
58             if (mappable &&
59                 (info.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) {
60                 continue;
61             }
62 
63             // Mappable must also be host coherent.
64             if (mappable &&
65                 (info.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0) {
66                 continue;
67             }
68 
69             // Found the first candidate memory type
70             if (bestType == -1) {
71                 bestType = static_cast<int>(i);
72                 continue;
73             }
74 
75             // For non-mappable resources, favor device local memory.
76             if (!mappable) {
77                 if ((info.memoryTypes[bestType].propertyFlags &
78                      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0 &&
79                     (info.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) !=
80                         0) {
81                     bestType = static_cast<int>(i);
82                     continue;
83                 }
84             }
85 
86             // All things equal favor the memory in the biggest heap
87             VkDeviceSize bestTypeHeapSize =
88                 info.memoryHeaps[info.memoryTypes[bestType].heapIndex].size;
89             VkDeviceSize candidateHeapSize = info.memoryHeaps[info.memoryTypes[i].heapIndex].size;
90             if (candidateHeapSize > bestTypeHeapSize) {
91                 bestType = static_cast<int>(i);
92                 continue;
93             }
94         }
95 
96         // TODO(cwallez@chromium.org): I think the Vulkan spec guarantees this should never happen
97         if (bestType == -1) {
98             ASSERT(false);
99             return false;
100         }
101 
102         VkMemoryAllocateInfo allocateInfo;
103         allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
104         allocateInfo.pNext = nullptr;
105         allocateInfo.allocationSize = requirements.size;
106         allocateInfo.memoryTypeIndex = static_cast<uint32_t>(bestType);
107 
108         VkDeviceMemory allocatedMemory = VK_NULL_HANDLE;
109         if (mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo, nullptr,
110                                        &allocatedMemory) != VK_SUCCESS) {
111             return false;
112         }
113 
114         void* mappedPointer = nullptr;
115         if (mappable) {
116             if (mDevice->fn.MapMemory(mDevice->GetVkDevice(), allocatedMemory, 0, requirements.size,
117                                       0, &mappedPointer) != VK_SUCCESS) {
118                 return false;
119             }
120         }
121 
122         allocation->mMemory = allocatedMemory;
123         allocation->mOffset = 0;
124         allocation->mMappedPointer = static_cast<uint8_t*>(mappedPointer);
125 
126         return true;
127     }
128 
Free(DeviceMemoryAllocation * allocation)129     void MemoryAllocator::Free(DeviceMemoryAllocation* allocation) {
130         mDevice->GetFencedDeleter()->DeleteWhenUnused(allocation->mMemory);
131         allocation->mMemory = VK_NULL_HANDLE;
132         allocation->mOffset = 0;
133         allocation->mMappedPointer = nullptr;
134     }
135 
Tick(Serial)136     void MemoryAllocator::Tick(Serial) {
137     }
138 }}  // namespace dawn_native::vulkan
139