1#ifndef _VKMEMUTIL_HPP
2#define _VKMEMUTIL_HPP
3/*-------------------------------------------------------------------------
4 * Vulkan CTS Framework
5 * --------------------
6 *
7 * Copyright (c) 2015 Google Inc.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Memory management utilities.
24 *//*--------------------------------------------------------------------*/
25
26#include "vkDefs.hpp"
27#include "deUniquePtr.hpp"
28
29namespace vk
30{
31
32/*--------------------------------------------------------------------*//*!
33 * \brief Memory allocation interface
34 *
35 * Allocation represents block of device memory and is allocated by
36 * Allocator implementation. Test code should use Allocator for allocating
37 * memory, unless there is a reason not to (for example testing vkAllocMemory).
38 *
39 * Allocation doesn't necessarily correspond to a whole VkDeviceMemory, but
40 * instead it may represent sub-allocation. Thus whenever VkDeviceMemory
41 * (getMemory()) managed by Allocation is passed to Vulkan API calls,
42 * offset given by getOffset() must be used.
43 *
44 * If host-visible memory was requested, host pointer to the memory can
45 * be queried with getHostPtr(). No offset is needed when accessing host
46 * pointer, i.e. the pointer is already adjusted in case of sub-allocation.
47 *
48 * Memory mappings are managed solely by Allocation, i.e. unmapping or
49 * re-mapping VkDeviceMemory owned by Allocation is not allowed.
50 *//*--------------------------------------------------------------------*/
51class Allocation
52{
53public:
54	virtual					~Allocation	(void);
55
56	//! Get VkDeviceMemory backing this allocation
57	VkDeviceMemory			getMemory	(void) const { return m_memory;							}
58
59	//! Get offset in VkDeviceMemory for this allocation
60	VkDeviceSize			getOffset	(void) const { return m_offset;							}
61
62	//! Get host pointer for this allocation. Only available for host-visible allocations
63	void*					getHostPtr	(void) const { DE_ASSERT(m_hostPtr); return m_hostPtr;	}
64
65protected:
66							Allocation	(VkDeviceMemory memory, VkDeviceSize offset, void* hostPtr);
67
68private:
69	const VkDeviceMemory	m_memory;
70	const VkDeviceSize		m_offset;
71	void* const				m_hostPtr;
72};
73
74//! Memory allocation requirements
75class MemoryRequirement
76{
77public:
78	static const MemoryRequirement	Any;
79	static const MemoryRequirement	HostVisible;
80	static const MemoryRequirement	Coherent;
81	static const MemoryRequirement	LazilyAllocated;
82
83	inline MemoryRequirement		operator|			(MemoryRequirement requirement) const
84	{
85		return MemoryRequirement(m_flags | requirement.m_flags);
86	}
87
88	inline MemoryRequirement		operator&			(MemoryRequirement requirement) const
89	{
90		return MemoryRequirement(m_flags & requirement.m_flags);
91	}
92
93	bool							matchesHeap			(VkMemoryPropertyFlags heapFlags) const;
94
95	inline operator					bool				(void) const { return m_flags != 0u; }
96
97private:
98	explicit						MemoryRequirement	(deUint32 flags);
99
100	const deUint32					m_flags;
101
102	enum Flags
103	{
104		FLAG_HOST_VISIBLE		= 1u << 0u,
105		FLAG_COHERENT			= 1u << 1u,
106		FLAG_LAZY_ALLOCATION	= 1u << 2u,
107	};
108};
109
110//! Memory allocator interface
111class Allocator
112{
113public:
114									Allocator	(void) {}
115	virtual							~Allocator	(void) {}
116
117	virtual de::MovePtr<Allocation>	allocate	(const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment) = 0;
118	virtual de::MovePtr<Allocation>	allocate	(const VkMemoryRequirements& memRequirements, MemoryRequirement requirement) = 0;
119};
120
121//! Allocator that backs every allocation with its own VkDeviceMemory
122class SimpleAllocator : public Allocator
123{
124public:
125											SimpleAllocator	(const DeviceInterface& vk, VkDevice device, const VkPhysicalDeviceMemoryProperties& deviceMemProps);
126
127	de::MovePtr<Allocation>					allocate		(const VkMemoryAllocateInfo& allocInfo, VkDeviceSize alignment);
128	de::MovePtr<Allocation>					allocate		(const VkMemoryRequirements& memRequirements, MemoryRequirement requirement);
129
130private:
131	const DeviceInterface&					m_vk;
132	const VkDevice							m_device;
133	const VkPhysicalDeviceMemoryProperties	m_memProps;
134};
135
136void	flushMappedMemoryRange		(const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size);
137void	invalidateMappedMemoryRange	(const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size);
138
139} // vk
140
141#endif // _VKMEMUTIL_HPP
142