API tests for the VK_KHR_external_* extensions
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / framework / vulkan / vkMemUtil.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan CTS Framework
3  * --------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  *
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  *//*!
20  * \file
21  * \brief Memory management utilities.
22  *//*--------------------------------------------------------------------*/
23
24 #include "vkMemUtil.hpp"
25 #include "vkStrUtil.hpp"
26 #include "vkQueryUtil.hpp"
27 #include "vkRef.hpp"
28 #include "vkRefUtil.hpp"
29 #include "deInt32.h"
30
31 #include <sstream>
32
33 namespace vk
34 {
35
36 using de::UniquePtr;
37 using de::MovePtr;
38
39 namespace
40 {
41
42 class HostPtr
43 {
44 public:
45                                                                 HostPtr         (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags);
46                                                                 ~HostPtr        (void);
47
48         void*                                           get                     (void) const { return m_ptr; }
49
50 private:
51         const DeviceInterface&          m_vkd;
52         const VkDevice                          m_device;
53         const VkDeviceMemory            m_memory;
54         void* const                                     m_ptr;
55 };
56
57 HostPtr::HostPtr (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags)
58         : m_vkd         (vkd)
59         , m_device      (device)
60         , m_memory      (memory)
61         , m_ptr         (mapMemory(vkd, device, memory, offset, size, flags))
62 {
63 }
64
65 HostPtr::~HostPtr (void)
66 {
67         m_vkd.unmapMemory(m_device, m_memory);
68 }
69
70 deUint32 selectMatchingMemoryType (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 allowedMemTypeBits, MemoryRequirement requirement)
71 {
72         const deUint32  compatibleTypes = getCompatibleMemoryTypes(deviceMemProps, requirement);
73         const deUint32  candidates              = allowedMemTypeBits & compatibleTypes;
74
75         if (candidates == 0)
76                 TCU_THROW(NotSupportedError, "No compatible memory type found");
77
78         return (deUint32)deCtz32(candidates);
79 }
80
81 bool isHostVisibleMemory (const VkPhysicalDeviceMemoryProperties& deviceMemProps, deUint32 memoryTypeNdx)
82 {
83         DE_ASSERT(memoryTypeNdx < deviceMemProps.memoryTypeCount);
84         return (deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0u;
85 }
86
87 } // anonymous
88
89 // Allocation
90
91 Allocation::Allocation (VkDeviceMemory memory, VkDeviceSize offset, void* hostPtr)
92         : m_memory      (memory)
93         , m_offset      (offset)
94         , m_hostPtr     (hostPtr)
95 {
96 }
97
98 Allocation::~Allocation (void)
99 {
100 }
101
102 // MemoryRequirement
103
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);
108
109 bool MemoryRequirement::matchesHeap (VkMemoryPropertyFlags heapFlags) const
110 {
111         // sanity check
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");
116
117         // host-visible
118         if ((m_flags & FLAG_HOST_VISIBLE) && !(heapFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
119                 return false;
120
121         // coherent
122         if ((m_flags & FLAG_COHERENT) && !(heapFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
123                 return false;
124
125         // lazy
126         if ((m_flags & FLAG_LAZY_ALLOCATION) && !(heapFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT))
127                 return false;
128
129         return true;
130 }
131
132 MemoryRequirement::MemoryRequirement (deUint32 flags)
133         : m_flags(flags)
134 {
135 }
136
137 // SimpleAllocator
138
139 class SimpleAllocation : public Allocation
140 {
141 public:
142                                                                         SimpleAllocation        (Move<VkDeviceMemory> mem, MovePtr<HostPtr> hostPtr);
143         virtual                                                 ~SimpleAllocation       (void);
144
145 private:
146         const Unique<VkDeviceMemory>    m_memHolder;
147         const UniquePtr<HostPtr>                m_hostPtr;
148 };
149
150 SimpleAllocation::SimpleAllocation (Move<VkDeviceMemory> mem, MovePtr<HostPtr> hostPtr)
151         : Allocation    (*mem, (VkDeviceSize)0, hostPtr ? hostPtr->get() : DE_NULL)
152         , m_memHolder   (mem)
153         , m_hostPtr             (hostPtr)
154 {
155 }
156
157 SimpleAllocation::~SimpleAllocation (void)
158 {
159 }
160
161 SimpleAllocator::SimpleAllocator (const DeviceInterface& vk, VkDevice device, const VkPhysicalDeviceMemoryProperties& deviceMemProps)
162         : m_vk          (vk)
163         , m_device      (device)
164         , m_memProps(deviceMemProps)
165 {
166 }
167
168 MovePtr<Allocation> SimpleAllocator::allocate (const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment)
169 {
170         DE_UNREF(alignment);
171
172         Move<VkDeviceMemory>    mem             = allocateMemory(m_vk, m_device, &allocInfo);
173         MovePtr<HostPtr>                hostPtr;
174
175         if (isHostVisibleMemory(m_memProps, allocInfo.memoryTypeIndex))
176                 hostPtr = MovePtr<HostPtr>(new HostPtr(m_vk, m_device, *mem, 0u, allocInfo.allocationSize, 0u));
177
178         return MovePtr<Allocation>(new SimpleAllocation(mem, hostPtr));
179 }
180
181 MovePtr<Allocation> SimpleAllocator::allocate (const VkMemoryRequirements& memReqs, MemoryRequirement requirement)
182 {
183         const deUint32                          memoryTypeNdx   = selectMatchingMemoryType(m_memProps, memReqs.memoryTypeBits, requirement);
184         const VkMemoryAllocateInfo      allocInfo               =
185         {
186                 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, //      VkStructureType                 sType;
187                 DE_NULL,                                                                //      const void*                             pNext;
188                 memReqs.size,                                                   //      VkDeviceSize                    allocationSize;
189                 memoryTypeNdx,                                                  //      deUint32                                memoryTypeIndex;
190         };
191
192         Move<VkDeviceMemory>            mem                             = allocateMemory(m_vk, m_device, &allocInfo);
193         MovePtr<HostPtr>                        hostPtr;
194
195         if (requirement & MemoryRequirement::HostVisible)
196         {
197                 DE_ASSERT(isHostVisibleMemory(m_memProps, allocInfo.memoryTypeIndex));
198                 hostPtr = MovePtr<HostPtr>(new HostPtr(m_vk, m_device, *mem, 0u, allocInfo.allocationSize, 0u));
199         }
200
201         return MovePtr<Allocation>(new SimpleAllocation(mem, hostPtr));
202 }
203
204 void* mapMemory (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags)
205 {
206         void* hostPtr = DE_NULL;
207         VK_CHECK(vkd.mapMemory(device, mem, offset, size, flags, &hostPtr));
208         TCU_CHECK(hostPtr);
209         return hostPtr;
210 }
211
212 void flushMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size)
213 {
214         const VkMappedMemoryRange       range   =
215         {
216                 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
217                 DE_NULL,
218                 memory,
219                 offset,
220                 size
221         };
222
223         VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &range));
224 }
225
226 void invalidateMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size)
227 {
228         const VkMappedMemoryRange       range   =
229         {
230                 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
231                 DE_NULL,
232                 memory,
233                 offset,
234                 size
235         };
236
237         VK_CHECK(vkd.invalidateMappedMemoryRanges(device, 1u, &range));
238 }
239
240 deUint32 getCompatibleMemoryTypes (const VkPhysicalDeviceMemoryProperties& deviceMemProps, MemoryRequirement requirement)
241 {
242         deUint32        compatibleTypes = 0u;
243
244         for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemProps.memoryTypeCount; memoryTypeNdx++)
245         {
246                 if (requirement.matchesHeap(deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags))
247                         compatibleTypes |= (1u << memoryTypeNdx);
248         }
249
250         return compatibleTypes;
251 }
252
253 } // vk