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 static const MemoryRequirement DeviceAddressCaptureReplay; 94 operator |(MemoryRequirement requirement) const95 inline MemoryRequirement operator| (MemoryRequirement requirement) const 96 { 97 return MemoryRequirement(m_flags | requirement.m_flags); 98 } 99 operator &(MemoryRequirement requirement) const100 inline MemoryRequirement operator& (MemoryRequirement requirement) const 101 { 102 return MemoryRequirement(m_flags & requirement.m_flags); 103 } 104 105 bool matchesHeap (VkMemoryPropertyFlags heapFlags) const; 106 operator bool(void) const107 inline operator bool (void) const { return m_flags != 0u; } 108 109 private: 110 explicit MemoryRequirement (deUint32 flags); 111 112 const deUint32 m_flags; 113 114 enum Flags 115 { 116 FLAG_HOST_VISIBLE = 1u << 0u, 117 FLAG_COHERENT = 1u << 1u, 118 FLAG_LAZY_ALLOCATION = 1u << 2u, 119 FLAG_PROTECTED = 1u << 3u, 120 FLAG_LOCAL = 1u << 4u, 121 FLAG_CACHED = 1u << 5u, 122 FLAG_NON_LOCAL = 1u << 6u, 123 FLAG_DEVICE_ADDRESS = 1u << 7u, 124 FLAG_DEVICE_ADDRESS_CAPTURE_REPLAY = 1u << 8u, 125 }; 126 }; 127 128 //! Memory allocator interface 129 class Allocator 130 { 131 public: Allocator(void)132 Allocator (void) {} ~Allocator(void)133 virtual ~Allocator (void) {} 134 135 virtual de::MovePtr<Allocation> allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment) = 0; 136 virtual de::MovePtr<Allocation> allocate (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement) = 0; 137 }; 138 139 //! Allocator that backs every allocation with its own VkDeviceMemory 140 class SimpleAllocator : public Allocator 141 { 142 public: 143 SimpleAllocator (const DeviceInterface& vk, VkDevice device, const VkPhysicalDeviceMemoryProperties& deviceMemProps, size_t offset = 0); 144 145 de::MovePtr<Allocation> allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment); 146 de::MovePtr<Allocation> allocate (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement); 147 148 private: 149 const DeviceInterface& m_vk; 150 const VkDevice m_device; 151 const VkPhysicalDeviceMemoryProperties m_memProps; 152 size_t m_offset; 153 }; 154 155 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); 156 de::MovePtr<Allocation> allocateDedicated (const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkBuffer buffer, MemoryRequirement requirement); 157 de::MovePtr<Allocation> allocateDedicated (const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkImage image, MemoryRequirement requirement); 158 159 void* mapMemory (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags); 160 void flushMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size); 161 void invalidateMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size); 162 163 deUint32 selectMatchingMemoryType (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 allowedMemTypeBits, MemoryRequirement requirement); 164 deUint32 getCompatibleMemoryTypes (const VkPhysicalDeviceMemoryProperties& deviceMemProps, MemoryRequirement requirement); 165 #ifdef CTS_USES_VULKANSC 166 deUint32 getSEUSafeMemoryTypes (const VkPhysicalDeviceMemoryProperties& deviceMemProps); 167 #endif // CTS_USES_VULKANSC 168 169 void bindImagePlanesMemory (const vk::DeviceInterface& vkd, 170 const vk::VkDevice device, 171 const vk::VkImage image, 172 const deUint32 numPlanes, 173 std::vector<de::SharedPtr<Allocation> >& allocations, 174 vk::Allocator& allocator, 175 const vk::MemoryRequirement requirement); 176 177 de::MovePtr<Allocation> bindImage (const DeviceInterface& vk, 178 const VkDevice device, 179 Allocator& allocator, 180 const VkImage image, 181 const MemoryRequirement requirement); 182 183 de::MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, 184 const VkDevice device, 185 Allocator& allocator, 186 const VkBuffer buffer, 187 const MemoryRequirement requirement); 188 189 void zeroBuffer (const DeviceInterface& vk, 190 const VkDevice device, 191 const Allocation& alloc, 192 const VkDeviceSize size); 193 194 } // vk 195 196 #endif // _VKMEMUTIL_HPP 197