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 "tcuMaybe.hpp" 29 #include "deUniquePtr.hpp" 30 #include "deSharedPtr.hpp" 31 #include <vector> 32 33 namespace vk 34 { 35 36 /*--------------------------------------------------------------------*//*! 37 * \brief Memory allocation interface 38 * 39 * Allocation represents block of device memory and is allocated by 40 * Allocator implementation. Test code should use Allocator for allocating 41 * memory, unless there is a reason not to (for example testing vkAllocMemory). 42 * 43 * Allocation doesn't necessarily correspond to a whole VkDeviceMemory, but 44 * instead it may represent sub-allocation. Thus whenever VkDeviceMemory 45 * (getMemory()) managed by Allocation is passed to Vulkan API calls, 46 * offset given by getOffset() must be used. 47 * 48 * If host-visible memory was requested, host pointer to the memory can 49 * be queried with getHostPtr(). No offset is needed when accessing host 50 * pointer, i.e. the pointer is already adjusted in case of sub-allocation. 51 * 52 * Memory mappings are managed solely by Allocation, i.e. unmapping or 53 * re-mapping VkDeviceMemory owned by Allocation is not allowed. 54 *//*--------------------------------------------------------------------*/ 55 class Allocation 56 { 57 public: 58 virtual ~Allocation (void); 59 60 //! Get VkDeviceMemory backing this allocation getMemory(void) const61 VkDeviceMemory getMemory (void) const { return m_memory; } 62 63 //! Get offset in VkDeviceMemory for this allocation getOffset(void) const64 VkDeviceSize getOffset (void) const { return m_offset; } 65 66 //! Get host pointer for this allocation. Only available for host-visible allocations getHostPtr(void) const67 void* getHostPtr (void) const { DE_ASSERT(m_hostPtr); return m_hostPtr; } 68 69 protected: 70 Allocation (VkDeviceMemory memory, VkDeviceSize offset, void* hostPtr); 71 72 private: 73 const VkDeviceMemory m_memory; 74 const VkDeviceSize m_offset; 75 void* const m_hostPtr; 76 }; 77 78 void flushAlloc (const DeviceInterface& vkd, VkDevice device, const Allocation& alloc); 79 void invalidateAlloc (const DeviceInterface& vkd, VkDevice device, const Allocation& alloc); 80 81 //! Memory allocation requirements 82 class MemoryRequirement 83 { 84 public: 85 static const MemoryRequirement Any; 86 static const MemoryRequirement HostVisible; 87 static const MemoryRequirement Coherent; 88 static const MemoryRequirement LazilyAllocated; 89 static const MemoryRequirement Protected; 90 static const MemoryRequirement Local; 91 static const MemoryRequirement Cached; 92 static const MemoryRequirement NonLocal; 93 static const MemoryRequirement DeviceAddress; 94 static const MemoryRequirement DeviceAddressCaptureReplay; 95 operator |(MemoryRequirement requirement) const96 inline MemoryRequirement operator| (MemoryRequirement requirement) const 97 { 98 return MemoryRequirement(m_flags | requirement.m_flags); 99 } 100 operator &(MemoryRequirement requirement) const101 inline MemoryRequirement operator& (MemoryRequirement requirement) const 102 { 103 return MemoryRequirement(m_flags & requirement.m_flags); 104 } 105 106 bool matchesHeap (VkMemoryPropertyFlags heapFlags) const; 107 operator bool(void) const108 inline operator bool (void) const { return m_flags != 0u; } 109 110 private: 111 explicit MemoryRequirement (deUint32 flags); 112 113 const deUint32 m_flags; 114 115 enum Flags 116 { 117 FLAG_HOST_VISIBLE = 1u << 0u, 118 FLAG_COHERENT = 1u << 1u, 119 FLAG_LAZY_ALLOCATION = 1u << 2u, 120 FLAG_PROTECTED = 1u << 3u, 121 FLAG_LOCAL = 1u << 4u, 122 FLAG_CACHED = 1u << 5u, 123 FLAG_NON_LOCAL = 1u << 6u, 124 FLAG_DEVICE_ADDRESS = 1u << 7u, 125 FLAG_DEVICE_ADDRESS_CAPTURE_REPLAY = 1u << 8u, 126 }; 127 }; 128 129 //! Memory allocator interface 130 class Allocator 131 { 132 public: Allocator(void)133 Allocator (void) {} ~Allocator(void)134 virtual ~Allocator (void) {} 135 136 virtual de::MovePtr<Allocation> allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment) = 0; 137 virtual de::MovePtr<Allocation> allocate (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement) = 0; 138 }; 139 140 //! Allocator that backs every allocation with its own VkDeviceMemory 141 class SimpleAllocator : public Allocator 142 { 143 public: 144 struct OffsetParams 145 { 146 const vk::VkDeviceSize nonCoherentAtomSize; 147 const vk::VkDeviceSize offset; 148 }; 149 typedef tcu::Maybe<OffsetParams> OptionalOffsetParams; 150 151 SimpleAllocator (const DeviceInterface& vk, VkDevice device, const VkPhysicalDeviceMemoryProperties& deviceMemProps, const OptionalOffsetParams& offsetParams = tcu::Nothing); 152 153 de::MovePtr<Allocation> allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment); 154 de::MovePtr<Allocation> allocate (const VkMemoryRequirements& memRequirements, MemoryRequirement requirement); 155 156 private: 157 const DeviceInterface& m_vk; 158 const VkDevice m_device; 159 const VkPhysicalDeviceMemoryProperties m_memProps; 160 const tcu::Maybe<OffsetParams> m_offsetParams; 161 }; 162 163 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); 164 de::MovePtr<Allocation> allocateDedicated (const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkBuffer buffer, MemoryRequirement requirement); 165 de::MovePtr<Allocation> allocateDedicated (const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice& physDevice, const VkDevice device, const VkImage image, MemoryRequirement requirement); 166 167 void* mapMemory (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags); 168 void flushMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size); 169 void invalidateMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size); 170 171 deUint32 selectMatchingMemoryType (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 allowedMemTypeBits, MemoryRequirement requirement); 172 deUint32 getCompatibleMemoryTypes (const VkPhysicalDeviceMemoryProperties& deviceMemProps, MemoryRequirement requirement); 173 #ifdef CTS_USES_VULKANSC 174 deUint32 getSEUSafeMemoryTypes (const VkPhysicalDeviceMemoryProperties& deviceMemProps); 175 #endif // CTS_USES_VULKANSC 176 177 void bindImagePlanesMemory (const vk::DeviceInterface& vkd, 178 const vk::VkDevice device, 179 const vk::VkImage image, 180 const deUint32 numPlanes, 181 std::vector<de::SharedPtr<Allocation> >& allocations, 182 vk::Allocator& allocator, 183 const vk::MemoryRequirement requirement); 184 185 de::MovePtr<Allocation> bindImage (const DeviceInterface& vk, 186 const VkDevice device, 187 Allocator& allocator, 188 const VkImage image, 189 const MemoryRequirement requirement); 190 191 de::MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, 192 const VkDevice device, 193 Allocator& allocator, 194 const VkBuffer buffer, 195 const MemoryRequirement requirement); 196 197 void zeroBuffer (const DeviceInterface& vk, 198 const VkDevice device, 199 const Allocation& alloc, 200 const VkDeviceSize size); 201 202 } // vk 203 204 #endif // _VKMEMUTIL_HPP 205