1 #ifndef _VKMEMUTIL_HPP 2 #define _VKMEMUTIL_HPP 3 /*------------------------------------------------------------------------- 4 * Vulkan CTS Framework 5 * -------------------- 6 * 7 * Copyright (c) 2019 Google Inc. 8 * Copyright (c) 2019 The Khronos Group Inc. 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 *//*! 23 * \file 24 * \brief Memory management utilities. 25 *//*--------------------------------------------------------------------*/ 26 27 #include "vkDefs.hpp" 28 #include "deUniquePtr.hpp" 29 #include "deSharedPtr.hpp" 30 #include <vector> 31 32 namespace vk 33 { 34 35 /*--------------------------------------------------------------------*//*! 36 * \brief Memory allocation interface 37 * 38 * Allocation represents block of device memory and is allocated by 39 * Allocator implementation. Test code should use Allocator for allocating 40 * memory, unless there is a reason not to (for example testing vkAllocMemory). 41 * 42 * Allocation doesn't necessarily correspond to a whole VkDeviceMemory, but 43 * instead it may represent sub-allocation. Thus whenever VkDeviceMemory 44 * (getMemory()) managed by Allocation is passed to Vulkan API calls, 45 * offset given by getOffset() must be used. 46 * 47 * If host-visible memory was requested, host pointer to the memory can 48 * be queried with getHostPtr(). No offset is needed when accessing host 49 * pointer, i.e. the pointer is already adjusted in case of sub-allocation. 50 * 51 * Memory mappings are managed solely by Allocation, i.e. unmapping or 52 * re-mapping VkDeviceMemory owned by Allocation is not allowed. 53 *//*--------------------------------------------------------------------*/ 54 class Allocation 55 { 56 public: 57 virtual ~Allocation (void); 58 59 //! Get VkDeviceMemory backing this allocation getMemory(void) const60 VkDeviceMemory getMemory (void) const { return m_memory; } 61 62 //! Get offset in VkDeviceMemory for this allocation getOffset(void) const63 VkDeviceSize getOffset (void) const { return m_offset; } 64 65 //! Get host pointer for this allocation. Only available for host-visible allocations getHostPtr(void) const66 void* getHostPtr (void) const { DE_ASSERT(m_hostPtr); return m_hostPtr; } 67 68 protected: 69 Allocation (VkDeviceMemory memory, VkDeviceSize offset, void* hostPtr); 70 71 private: 72 const VkDeviceMemory m_memory; 73 const VkDeviceSize m_offset; 74 void* const m_hostPtr; 75 }; 76 77 void flushAlloc (const DeviceInterface& vkd, VkDevice device, const Allocation& alloc); 78 void invalidateAlloc (const DeviceInterface& vkd, VkDevice device, const Allocation& alloc); 79 80 //! Memory allocation requirements 81 class MemoryRequirement 82 { 83 public: 84 static const MemoryRequirement Any; 85 static const MemoryRequirement HostVisible; 86 static const MemoryRequirement Coherent; 87 static const MemoryRequirement LazilyAllocated; 88 static const MemoryRequirement Protected; 89 static const MemoryRequirement Local; 90 static const MemoryRequirement Cached; 91 static const MemoryRequirement NonLocal; 92 static const MemoryRequirement DeviceAddress; 93 operator |(MemoryRequirement requirement) const94 inline MemoryRequirement operator| (MemoryRequirement requirement) const 95 { 96 return MemoryRequirement(m_flags | requirement.m_flags); 97 } 98 operator &(MemoryRequirement requirement) const99 inline MemoryRequirement operator& (MemoryRequirement requirement) const 100 { 101 return MemoryRequirement(m_flags & requirement.m_flags); 102 } 103 104 bool matchesHeap (VkMemoryPropertyFlags heapFlags) const; 105 operator bool(void) const106 inline operator bool (void) const { return m_flags != 0u; } 107 108 private: 109 explicit MemoryRequirement (deUint32 flags); 110 111 const deUint32 m_flags; 112 113 enum Flags 114 { 115 FLAG_HOST_VISIBLE = 1u << 0u, 116 FLAG_COHERENT = 1u << 1u, 117 FLAG_LAZY_ALLOCATION = 1u << 2u, 118 FLAG_PROTECTED = 1u << 3u, 119 FLAG_LOCAL = 1u << 4u, 120 FLAG_CACHED = 1u << 5u, 121 FLAG_NON_LOCAL = 1u << 6u, 122 FLAG_DEVICE_ADDRESS = 1u << 7u, 123 }; 124 }; 125 126 //! Memory allocator interface 127 class Allocator 128 { 129 public: Allocator(void)130 Allocator (void) {} ~Allocator(void)131 virtual ~Allocator (void) {} 132 133 virtual de::MovePtr<Allocation> allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment) = 0; 134 virtual de::MovePtr<Allocation> allocate (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement) = 0; 135 }; 136 137 //! Allocator that backs every allocation with its own VkDeviceMemory 138 class SimpleAllocator : public Allocator 139 { 140 public: 141 SimpleAllocator (const DeviceInterface& vk, VkDevice device, const VkPhysicalDeviceMemoryProperties& deviceMemProps); 142 143 de::MovePtr<Allocation> allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment); 144 de::MovePtr<Allocation> allocate (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement); 145 146 private: 147 const DeviceInterface& m_vk; 148 const VkDevice m_device; 149 const VkPhysicalDeviceMemoryProperties m_memProps; 150 }; 151 152 de::MovePtr<Allocation> allocateExtended (const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkMemoryRequirements& memReqs, const MemoryRequirement requirement, const void* pNext); 153 de::MovePtr<Allocation> allocateDedicated (const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkBuffer buffer, MemoryRequirement requirement); 154 de::MovePtr<Allocation> allocateDedicated (const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkImage image, MemoryRequirement requirement); 155 156 void* mapMemory (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags); 157 void flushMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size); 158 void invalidateMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size); 159 160 deUint32 getCompatibleMemoryTypes (const VkPhysicalDeviceMemoryProperties& deviceMemProps, MemoryRequirement requirement); 161 void bindImagePlanesMemory (const vk::DeviceInterface& vkd, 162 const vk::VkDevice device, 163 const vk::VkImage image, 164 const deUint32 numPlanes, 165 std::vector<de::SharedPtr<Allocation> >& allocations, 166 vk::Allocator& allocator, 167 const vk::MemoryRequirement requirement); 168 169 de::MovePtr<Allocation> bindImage (const DeviceInterface& vk, 170 const VkDevice device, 171 Allocator& allocator, 172 const VkImage image, 173 const MemoryRequirement requirement); 174 175 de::MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, 176 const VkDevice device, 177 Allocator& allocator, 178 const VkBuffer buffer, 179 const MemoryRequirement requirement); 180 181 void zeroBuffer (const DeviceInterface& vk, 182 const VkDevice device, 183 const Allocation& alloc, 184 const VkDeviceSize size); 185 186 } // vk 187 188 #endif // _VKMEMUTIL_HPP 189