blob: dece90d11a660cba8565fe9be3b7faadd4bb8773 [file] [log] [blame]
Alexis Hetu767b41b2018-09-26 11:25:46 -04001// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef VK_OBJECT_HPP_
16#define VK_OBJECT_HPP_
17
Antonio Maiorano42fd1592020-04-27 11:30:40 -040018#include "VkConfig.hpp"
19#include "VkMemory.hpp"
Nicolas Capensde16f322019-02-12 00:32:31 -050020
Ben Clayton25e06e02020-02-07 11:19:08 +000021#include "System/Debug.hpp"
22
Alexis Hetu767b41b2018-09-26 11:25:46 -040023#include <vulkan/vk_icd.h>
Nicolas Capens2490b1a2020-07-13 14:33:01 -040024#undef None
25#undef Bool
26
Ben Clayton2ed93ab2019-12-17 20:38:03 +000027#include <new>
Alexis Hetu767b41b2018-09-26 11:25:46 -040028
Nicolas Capens157ba262019-12-10 17:49:14 -050029namespace vk {
Alexis Hetubd4cf812019-06-14 15:14:07 -040030
31template<typename T, typename VkT>
Ben Clayton2ed93ab2019-12-17 20:38:03 +000032static inline T *VkTtoT(VkT vkObject)
Alexis Hetubd4cf812019-06-14 15:14:07 -040033{
Ben Clayton2ed93ab2019-12-17 20:38:03 +000034 return static_cast<T *>(static_cast<void *>(vkObject));
Alexis Hetubd4cf812019-06-14 15:14:07 -040035}
36
37template<typename T, typename VkT>
Ben Clayton2ed93ab2019-12-17 20:38:03 +000038static inline VkT TtoVkT(T *object)
Alexis Hetubd4cf812019-06-14 15:14:07 -040039{
Alexis Hetu2d77aea2019-06-17 13:43:50 -040040 return { static_cast<uint64_t>(reinterpret_cast<uintptr_t>(object)) };
Alexis Hetubd4cf812019-06-14 15:14:07 -040041}
42
Alexis Hetu767b41b2018-09-26 11:25:46 -040043// For use in the placement new to make it verbose that we're allocating an object using device memory
Ben Clayton2ed93ab2019-12-17 20:38:03 +000044static constexpr VkAllocationCallbacks *DEVICE_MEMORY = nullptr;
Alexis Hetu767b41b2018-09-26 11:25:46 -040045
Nicolas Capens0c736802019-05-27 12:53:31 -040046template<typename T, typename VkT, typename CreateInfo, typename... ExtendedInfo>
Ben Clayton2ed93ab2019-12-17 20:38:03 +000047static VkResult Create(const VkAllocationCallbacks *pAllocator, const CreateInfo *pCreateInfo, VkT *outObject, ExtendedInfo... extendedInfo)
Alexis Hetu767b41b2018-09-26 11:25:46 -040048{
49 *outObject = VK_NULL_HANDLE;
50
51 size_t size = T::ComputeRequiredAllocationSize(pCreateInfo);
Ben Clayton2ed93ab2019-12-17 20:38:03 +000052 void *memory = nullptr;
Alexis Hetu767b41b2018-09-26 11:25:46 -040053 if(size)
54 {
55 memory = vk::allocate(size, REQUIRED_MEMORY_ALIGNMENT, pAllocator, T::GetAllocationScope());
56 if(!memory)
57 {
58 return VK_ERROR_OUT_OF_HOST_MEMORY;
59 }
60 }
61
Ben Clayton2ed93ab2019-12-17 20:38:03 +000062 void *objectMemory = vk::allocate(sizeof(T), alignof(T), pAllocator, T::GetAllocationScope());
Alexis Hetu1a9714a2019-04-12 11:48:12 -040063 if(!objectMemory)
64 {
65 vk::deallocate(memory, pAllocator);
66 return VK_ERROR_OUT_OF_HOST_MEMORY;
67 }
68
Ben Clayton2ed93ab2019-12-17 20:38:03 +000069 auto object = new(objectMemory) T(pCreateInfo, memory, extendedInfo...);
Alexis Hetu767b41b2018-09-26 11:25:46 -040070
71 if(!object)
72 {
73 vk::deallocate(memory, pAllocator);
74 return VK_ERROR_OUT_OF_HOST_MEMORY;
75 }
76
77 *outObject = *object;
78
Alexis Hetu42232ab2019-05-27 13:09:05 -040079 // Assert that potential v-table offsets from multiple inheritance aren't causing an offset on the handle
80 ASSERT(*outObject == objectMemory);
81
Alexis Hetu767b41b2018-09-26 11:25:46 -040082 return VK_SUCCESS;
83}
84
85template<typename T, typename VkT>
86class ObjectBase
87{
88public:
89 using VkType = VkT;
90
Ben Clayton2ed93ab2019-12-17 20:38:03 +000091 void destroy(const VkAllocationCallbacks *pAllocator) {} // Method defined by objects to delete their content, if necessary
Alexis Hetu767b41b2018-09-26 11:25:46 -040092
Nicolas Capens0c736802019-05-27 12:53:31 -040093 template<typename CreateInfo, typename... ExtendedInfo>
Ben Clayton2ed93ab2019-12-17 20:38:03 +000094 static VkResult Create(const VkAllocationCallbacks *pAllocator, const CreateInfo *pCreateInfo, VkT *outObject, ExtendedInfo... extendedInfo)
Alexis Hetu767b41b2018-09-26 11:25:46 -040095 {
Nicolas Capens0c736802019-05-27 12:53:31 -040096 return vk::Create<T, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject, extendedInfo...);
Alexis Hetu767b41b2018-09-26 11:25:46 -040097 }
98
99 static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; }
Alexis Hetu767b41b2018-09-26 11:25:46 -0400100};
101
102template<typename T, typename VkT>
103class Object : public ObjectBase<T, VkT>
104{
105public:
106 operator VkT()
107 {
Alexis Hetu42232ab2019-05-27 13:09:05 -0400108 // The static_cast<T*> is used to make sure the returned pointer points to the
109 // beginning of the object, even if the derived class uses multiple inheritance
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000110 return vk::TtoVkT<T, VkT>(static_cast<T *>(this));
Alexis Hetubd4cf812019-06-14 15:14:07 -0400111 }
112
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000113 static inline T *Cast(VkT vkObject)
Alexis Hetubd4cf812019-06-14 15:14:07 -0400114 {
115 return vk::VkTtoT<T, VkT>(vkObject);
Alexis Hetu767b41b2018-09-26 11:25:46 -0400116 }
117};
118
119template<typename T, typename VkT>
120class DispatchableObject
121{
122 VK_LOADER_DATA loaderData = { ICD_LOADER_MAGIC };
123
124 T object;
Nicolas Capens0c736802019-05-27 12:53:31 -0400125
Alexis Hetu767b41b2018-09-26 11:25:46 -0400126public:
127 static constexpr VkSystemAllocationScope GetAllocationScope() { return T::GetAllocationScope(); }
128
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000129 template<typename... Args>
130 DispatchableObject(Args... args)
131 : object(args...)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400132 {
133 }
134
Nicolas Capens0c736802019-05-27 12:53:31 -0400135 ~DispatchableObject() = delete;
136
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000137 void destroy(const VkAllocationCallbacks *pAllocator)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400138 {
139 object.destroy(pAllocator);
140 }
141
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000142 void operator delete(void *ptr, const VkAllocationCallbacks *pAllocator)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400143 {
144 // Should never happen
145 ASSERT(false);
146 }
147
Nicolas Capens0c736802019-05-27 12:53:31 -0400148 template<typename CreateInfo, typename... ExtendedInfo>
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000149 static VkResult Create(const VkAllocationCallbacks *pAllocator, const CreateInfo *pCreateInfo, VkT *outObject, ExtendedInfo... extendedInfo)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400150 {
Nicolas Capens0c736802019-05-27 12:53:31 -0400151 return vk::Create<DispatchableObject<T, VkT>, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject, extendedInfo...);
Alexis Hetu767b41b2018-09-26 11:25:46 -0400152 }
153
154 template<typename CreateInfo>
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000155 static size_t ComputeRequiredAllocationSize(const CreateInfo *pCreateInfo)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400156 {
157 return T::ComputeRequiredAllocationSize(pCreateInfo);
158 }
159
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000160 static inline T *Cast(VkT vkObject)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400161 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000162 return (vkObject == VK_NULL_HANDLE) ? nullptr : &(reinterpret_cast<DispatchableObject<T, VkT> *>(vkObject)->object);
Alexis Hetu767b41b2018-09-26 11:25:46 -0400163 }
164
165 operator VkT()
166 {
167 return reinterpret_cast<VkT>(this);
168 }
169};
170
Nicolas Capens157ba262019-12-10 17:49:14 -0500171} // namespace vk
Alexis Hetu767b41b2018-09-26 11:25:46 -0400172
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000173#endif // VK_OBJECT_HPP_