1 /*-------------------------------------------------------------------------
5 * Copyright (c) 2015 Google Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Memory management utilities.
22 *//*--------------------------------------------------------------------*/
24 #include "vkMemUtil.hpp"
25 #include "vkStrUtil.hpp"
26 #include "vkQueryUtil.hpp"
28 #include "vkRefUtil.hpp"
45 HostPtr (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags);
48 void* get (void) const { return m_ptr; }
51 const DeviceInterface& m_vkd;
52 const VkDevice m_device;
53 const VkDeviceMemory m_memory;
57 HostPtr::HostPtr (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags)
61 , m_ptr (mapMemory(vkd, device, memory, offset, size, flags))
65 HostPtr::~HostPtr (void)
67 m_vkd.unmapMemory(m_device, m_memory);
70 deUint32 selectMatchingMemoryType (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 allowedMemTypeBits, MemoryRequirement requirement)
72 const deUint32 compatibleTypes = getCompatibleMemoryTypes(deviceMemProps, requirement);
73 const deUint32 candidates = allowedMemTypeBits & compatibleTypes;
76 TCU_THROW(NotSupportedError, "No compatible memory type found");
78 return (deUint32)deCtz32(candidates);
81 bool isHostVisibleMemory (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 memoryTypeNdx)
83 DE_ASSERT(memoryTypeNdx < deviceMemProps.memoryTypeCount);
84 return (deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0u;
91 Allocation::Allocation (VkDeviceMemory memory, VkDeviceSize offset, void* hostPtr)
98 Allocation::~Allocation (void)
104 const MemoryRequirement MemoryRequirement::Any = MemoryRequirement(0x0u);
105 const MemoryRequirement MemoryRequirement::HostVisible = MemoryRequirement(MemoryRequirement::FLAG_HOST_VISIBLE);
106 const MemoryRequirement MemoryRequirement::Coherent = MemoryRequirement(MemoryRequirement::FLAG_COHERENT);
107 const MemoryRequirement MemoryRequirement::LazilyAllocated = MemoryRequirement(MemoryRequirement::FLAG_LAZY_ALLOCATION);
109 bool MemoryRequirement::matchesHeap (VkMemoryPropertyFlags heapFlags) const
112 if ((m_flags & FLAG_COHERENT) && !(m_flags & FLAG_HOST_VISIBLE))
113 DE_FATAL("Coherent memory must be host-visible");
114 if ((m_flags & FLAG_HOST_VISIBLE) && (m_flags & FLAG_LAZY_ALLOCATION))
115 DE_FATAL("Lazily allocated memory cannot be mappable");
118 if ((m_flags & FLAG_HOST_VISIBLE) && !(heapFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
122 if ((m_flags & FLAG_COHERENT) && !(heapFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
126 if ((m_flags & FLAG_LAZY_ALLOCATION) && !(heapFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT))
132 MemoryRequirement::MemoryRequirement (deUint32 flags)
139 class SimpleAllocation : public Allocation
142 SimpleAllocation (Move<VkDeviceMemory> mem, MovePtr<HostPtr> hostPtr);
143 virtual ~SimpleAllocation (void);
146 const Unique<VkDeviceMemory> m_memHolder;
147 const UniquePtr<HostPtr> m_hostPtr;
150 SimpleAllocation::SimpleAllocation (Move<VkDeviceMemory> mem, MovePtr<HostPtr> hostPtr)
151 : Allocation (*mem, (VkDeviceSize)0, hostPtr ? hostPtr->get() : DE_NULL)
153 , m_hostPtr (hostPtr)
157 SimpleAllocation::~SimpleAllocation (void)
161 SimpleAllocator::SimpleAllocator (const DeviceInterface& vk, VkDevice device, const VkPhysicalDeviceMemoryProperties& deviceMemProps)
164 , m_memProps(deviceMemProps)
168 MovePtr<Allocation> SimpleAllocator::allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment)
172 Move<VkDeviceMemory> mem = allocateMemory(m_vk, m_device, &allocInfo);
173 MovePtr<HostPtr> hostPtr;
175 if (isHostVisibleMemory(m_memProps, allocInfo.memoryTypeIndex))
176 hostPtr = MovePtr<HostPtr>(new HostPtr(m_vk, m_device, *mem, 0u, allocInfo.allocationSize, 0u));
178 return MovePtr<Allocation>(new SimpleAllocation(mem, hostPtr));
181 MovePtr<Allocation> SimpleAllocator::allocate (const VkMemoryRequirements& memReqs, MemoryRequirement requirement)
183 const deUint32 memoryTypeNdx = selectMatchingMemoryType(m_memProps, memReqs.memoryTypeBits, requirement);
184 const VkMemoryAllocateInfo allocInfo =
186 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
187 DE_NULL, // const void* pNext;
188 memReqs.size, // VkDeviceSize allocationSize;
189 memoryTypeNdx, // deUint32 memoryTypeIndex;
192 Move<VkDeviceMemory> mem = allocateMemory(m_vk, m_device, &allocInfo);
193 MovePtr<HostPtr> hostPtr;
195 if (requirement & MemoryRequirement::HostVisible)
197 DE_ASSERT(isHostVisibleMemory(m_memProps, allocInfo.memoryTypeIndex));
198 hostPtr = MovePtr<HostPtr>(new HostPtr(m_vk, m_device, *mem, 0u, allocInfo.allocationSize, 0u));
201 return MovePtr<Allocation>(new SimpleAllocation(mem, hostPtr));
204 void* mapMemory (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags)
206 void* hostPtr = DE_NULL;
207 VK_CHECK(vkd.mapMemory(device, mem, offset, size, flags, &hostPtr));
212 void flushMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size)
214 const VkMappedMemoryRange range =
216 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
223 VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &range));
226 void invalidateMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size)
228 const VkMappedMemoryRange range =
230 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
237 VK_CHECK(vkd.invalidateMappedMemoryRanges(device, 1u, &range));
240 deUint32 getCompatibleMemoryTypes (const VkPhysicalDeviceMemoryProperties& deviceMemProps, MemoryRequirement requirement)
242 deUint32 compatibleTypes = 0u;
244 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemProps.memoryTypeCount; memoryTypeNdx++)
246 if (requirement.matchesHeap(deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags))
247 compatibleTypes |= (1u << memoryTypeNdx);
250 return compatibleTypes;