Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 1 | // 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_DEVICE_HPP_ |
| 16 | #define VK_DEVICE_HPP_ |
| 17 | |
Alexis Hetu | 72ea2ee | 2020-08-06 10:08:37 -0400 | [diff] [blame] | 18 | #include "VkImageView.hpp" |
Nicolas Capens | 73c4a0c | 2020-03-17 17:29:11 -0400 | [diff] [blame] | 19 | #include "VkSampler.hpp" |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 20 | #include "Reactor/Routine.hpp" |
Ben Clayton | ac43aa7 | 2020-04-04 00:48:13 +0100 | [diff] [blame] | 21 | #include "System/LRUCache.hpp" |
Nicolas Capens | 73c4a0c | 2020-03-17 17:29:11 -0400 | [diff] [blame] | 22 | |
Ben Clayton | 377573c | 2020-04-03 20:36:40 +0100 | [diff] [blame] | 23 | #include "marl/mutex.h" |
| 24 | #include "marl/tsa.h" |
| 25 | |
Nicolas Capens | 73c4a0c | 2020-03-17 17:29:11 -0400 | [diff] [blame] | 26 | #include <map> |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 27 | #include <memory> |
Ben Clayton | ac43aa7 | 2020-04-04 00:48:13 +0100 | [diff] [blame] | 28 | #include <unordered_map> |
Alexis Hetu | 72ea2ee | 2020-08-06 10:08:37 -0400 | [diff] [blame] | 29 | #include <unordered_set> |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 30 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 31 | namespace marl { |
| 32 | class Scheduler; |
| 33 | } |
| 34 | namespace sw { |
| 35 | class Blitter; |
| 36 | } |
Ben Clayton | d6c6136 | 2019-08-14 18:16:01 +0100 | [diff] [blame] | 37 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 38 | namespace vk { |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 39 | |
Nicolas Capens | 0c73680 | 2019-05-27 12:53:31 -0400 | [diff] [blame] | 40 | class PhysicalDevice; |
Alexis Hetu | 9e4d040 | 2018-10-16 15:44:12 -0400 | [diff] [blame] | 41 | class Queue; |
| 42 | |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 43 | namespace dbg { |
| 44 | class Context; |
| 45 | class Server; |
| 46 | } // namespace dbg |
| 47 | |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 48 | class Device |
| 49 | { |
| 50 | public: |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 51 | static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_DEVICE; } |
| 52 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 53 | Device(const VkDeviceCreateInfo *pCreateInfo, void *mem, PhysicalDevice *physicalDevice, const VkPhysicalDeviceFeatures *enabledFeatures, const std::shared_ptr<marl::Scheduler> &scheduler); |
| 54 | void destroy(const VkAllocationCallbacks *pAllocator); |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 55 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 56 | static size_t ComputeRequiredAllocationSize(const VkDeviceCreateInfo *pCreateInfo); |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 57 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 58 | bool hasExtension(const char *extensionName) const; |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 59 | VkQueue getQueue(uint32_t queueFamilyIndex, uint32_t queueIndex) const; |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 60 | VkResult waitForFences(uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout); |
Alexis Hetu | e1f51b9 | 2019-04-23 15:34:34 -0400 | [diff] [blame] | 61 | VkResult waitIdle(); |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 62 | void getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo *pCreateInfo, |
| 63 | VkDescriptorSetLayoutSupport *pSupport) const; |
Nicolas Capens | 0c73680 | 2019-05-27 12:53:31 -0400 | [diff] [blame] | 64 | PhysicalDevice *getPhysicalDevice() const { return physicalDevice; } |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 65 | void updateDescriptorSets(uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites, |
| 66 | uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies); |
| 67 | void getRequirements(VkMemoryDedicatedRequirements *requirements) const; |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 68 | const VkPhysicalDeviceFeatures &getEnabledFeatures() const { return enabledFeatures; } |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 69 | sw::Blitter *getBlitter() const { return blitter.get(); } |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 70 | |
Alexis Hetu | 72ea2ee | 2020-08-06 10:08:37 -0400 | [diff] [blame] | 71 | void registerImageView(ImageView *imageView); |
| 72 | void unregisterImageView(ImageView *imageView); |
| 73 | void prepareForSampling(ImageView *imageView); |
| 74 | void contentsChanged(ImageView *imageView); |
| 75 | |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 76 | class SamplingRoutineCache |
| 77 | { |
| 78 | public: |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 79 | SamplingRoutineCache() |
| 80 | : cache(1024) |
| 81 | {} |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 82 | ~SamplingRoutineCache() {} |
| 83 | |
| 84 | struct Key |
| 85 | { |
| 86 | uint32_t instruction; |
| 87 | uint32_t sampler; |
| 88 | uint32_t imageView; |
Ben Clayton | f046402 | 2019-08-08 18:33:41 +0100 | [diff] [blame] | 89 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 90 | inline bool operator==(const Key &rhs) const; |
Ben Clayton | f046402 | 2019-08-08 18:33:41 +0100 | [diff] [blame] | 91 | |
| 92 | struct Hash |
| 93 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 94 | inline std::size_t operator()(const Key &key) const noexcept; |
Ben Clayton | f046402 | 2019-08-08 18:33:41 +0100 | [diff] [blame] | 95 | }; |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 96 | }; |
| 97 | |
Ben Clayton | 094974d | 2020-04-08 16:55:02 +0100 | [diff] [blame] | 98 | // getOrCreate() queries the cache for a Routine with the given key. |
| 99 | // If one is found, it is returned, otherwise createRoutine(key) is |
| 100 | // called, the returned Routine is added to the cache, and it is |
| 101 | // returned. |
| 102 | // Function must be a function of the signature: |
| 103 | // std::shared_ptr<rr::Routine>(const Key &) |
Nicolas Capens | 1c29477 | 2020-03-28 23:04:55 -0400 | [diff] [blame] | 104 | template<typename Function> |
Ben Clayton | 094974d | 2020-04-08 16:55:02 +0100 | [diff] [blame] | 105 | std::shared_ptr<rr::Routine> getOrCreate(const Key &key, Function &&createRoutine) |
Nicolas Capens | 1c29477 | 2020-03-28 23:04:55 -0400 | [diff] [blame] | 106 | { |
Ben Clayton | ac43aa7 | 2020-04-04 00:48:13 +0100 | [diff] [blame] | 107 | auto it = snapshot.find(key); |
| 108 | if(it != snapshot.end()) { return it->second; } |
Nicolas Capens | 1c29477 | 2020-03-28 23:04:55 -0400 | [diff] [blame] | 109 | |
Ben Clayton | 377573c | 2020-04-03 20:36:40 +0100 | [diff] [blame] | 110 | marl::lock lock(mutex); |
Ben Clayton | ac43aa7 | 2020-04-04 00:48:13 +0100 | [diff] [blame] | 111 | if(auto existingRoutine = cache.lookup(key)) |
Nicolas Capens | 1c29477 | 2020-03-28 23:04:55 -0400 | [diff] [blame] | 112 | { |
| 113 | return existingRoutine; |
| 114 | } |
| 115 | |
| 116 | std::shared_ptr<rr::Routine> newRoutine = createRoutine(key); |
| 117 | cache.add(key, newRoutine); |
Ben Clayton | ac43aa7 | 2020-04-04 00:48:13 +0100 | [diff] [blame] | 118 | snapshotNeedsUpdate = true; |
Nicolas Capens | 1c29477 | 2020-03-28 23:04:55 -0400 | [diff] [blame] | 119 | |
| 120 | return newRoutine; |
| 121 | } |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 122 | |
Nicolas Capens | d53eeca | 2020-03-19 13:31:41 -0400 | [diff] [blame] | 123 | void updateSnapshot(); |
Alexis Hetu | 3575550 | 2019-07-22 13:51:49 -0400 | [diff] [blame] | 124 | |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 125 | private: |
Ben Clayton | ac43aa7 | 2020-04-04 00:48:13 +0100 | [diff] [blame] | 126 | bool snapshotNeedsUpdate = false; |
| 127 | std::unordered_map<Key, std::shared_ptr<rr::Routine>, Key::Hash> snapshot; |
| 128 | |
Ben Clayton | 377573c | 2020-04-03 20:36:40 +0100 | [diff] [blame] | 129 | marl::mutex mutex; |
| 130 | sw::LRUCache<Key, std::shared_ptr<rr::Routine>, Key::Hash> cache GUARDED_BY(mutex); |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 131 | }; |
| 132 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 133 | SamplingRoutineCache *getSamplingRoutineCache() const; |
Nicolas Capens | d53eeca | 2020-03-19 13:31:41 -0400 | [diff] [blame] | 134 | void updateSamplingRoutineSnapshotCache(); |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 135 | |
Nicolas Capens | 73c4a0c | 2020-03-17 17:29:11 -0400 | [diff] [blame] | 136 | class SamplerIndexer |
| 137 | { |
| 138 | public: |
| 139 | ~SamplerIndexer(); |
| 140 | |
| 141 | uint32_t index(const SamplerState &samplerState); |
| 142 | void remove(const SamplerState &samplerState); |
| 143 | |
| 144 | private: |
| 145 | struct Identifier |
| 146 | { |
| 147 | uint32_t id; |
| 148 | uint32_t count; // Number of samplers sharing this state identifier. |
| 149 | }; |
| 150 | |
Ben Clayton | 377573c | 2020-04-03 20:36:40 +0100 | [diff] [blame] | 151 | marl::mutex mutex; |
| 152 | std::map<SamplerState, Identifier> map GUARDED_BY(mutex); |
Nicolas Capens | 73c4a0c | 2020-03-17 17:29:11 -0400 | [diff] [blame] | 153 | |
| 154 | uint32_t nextID = 0; |
| 155 | }; |
| 156 | |
| 157 | uint32_t indexSampler(const SamplerState &samplerState); |
| 158 | void removeSampler(const SamplerState &samplerState); |
| 159 | |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 160 | std::shared_ptr<vk::dbg::Context> getDebuggerContext() const |
| 161 | { |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 162 | #ifdef ENABLE_VK_DEBUGGER |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 163 | return debugger.context; |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 164 | #else |
| 165 | return nullptr; |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 166 | #endif // ENABLE_VK_DEBUGGER |
Ben Clayton | 7d0ce41 | 2019-12-03 13:26:31 +0000 | [diff] [blame] | 167 | } |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 168 | |
Alexis Hetu | 74f6c65 | 2020-07-22 21:57:05 -0400 | [diff] [blame] | 169 | VkResult setDebugUtilsObjectName(const VkDebugUtilsObjectNameInfoEXT *pNameInfo); |
| 170 | VkResult setDebugUtilsObjectTag(const VkDebugUtilsObjectTagInfoEXT *pTagInfo); |
| 171 | |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 172 | private: |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 173 | PhysicalDevice *const physicalDevice = nullptr; |
| 174 | Queue *const queues = nullptr; |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 175 | uint32_t queueCount = 0; |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 176 | std::unique_ptr<sw::Blitter> blitter; |
Alexis Hetu | 6448bd6 | 2019-06-11 15:58:59 -0400 | [diff] [blame] | 177 | uint32_t enabledExtensionCount = 0; |
Alexis Hetu | 352791e | 2019-05-17 16:42:34 -0400 | [diff] [blame] | 178 | typedef char ExtensionName[VK_MAX_EXTENSION_NAME_SIZE]; |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 179 | ExtensionName *extensions = nullptr; |
Nicolas Capens | a29aa77 | 2019-06-26 00:36:28 -0400 | [diff] [blame] | 180 | const VkPhysicalDeviceFeatures enabledFeatures = {}; |
Nicolas Capens | 73c4a0c | 2020-03-17 17:29:11 -0400 | [diff] [blame] | 181 | |
Ben Clayton | 6fff512 | 2019-10-03 16:41:21 +0100 | [diff] [blame] | 182 | std::shared_ptr<marl::Scheduler> scheduler; |
Nicolas Capens | 1c29477 | 2020-03-28 23:04:55 -0400 | [diff] [blame] | 183 | std::unique_ptr<SamplingRoutineCache> samplingRoutineCache; |
Nicolas Capens | 73c4a0c | 2020-03-17 17:29:11 -0400 | [diff] [blame] | 184 | std::unique_ptr<SamplerIndexer> samplerIndexer; |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 185 | |
Alexis Hetu | 72ea2ee | 2020-08-06 10:08:37 -0400 | [diff] [blame] | 186 | marl::mutex imageViewSetMutex; |
| 187 | std::unordered_set<ImageView *> imageViewSet GUARDED_BY(imageViewSetMutex); |
| 188 | |
Ben Clayton | a4e06ca | 2019-12-03 12:38:14 +0000 | [diff] [blame] | 189 | #ifdef ENABLE_VK_DEBUGGER |
| 190 | struct |
| 191 | { |
| 192 | std::shared_ptr<vk::dbg::Context> context; |
| 193 | std::shared_ptr<vk::dbg::Server> server; |
| 194 | } debugger; |
| 195 | #endif // ENABLE_VK_DEBUGGER |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 196 | }; |
| 197 | |
| 198 | using DispatchableDevice = DispatchableObject<Device, VkDevice>; |
| 199 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 200 | static inline Device *Cast(VkDevice object) |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 201 | { |
| 202 | return DispatchableDevice::Cast(object); |
| 203 | } |
| 204 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 205 | inline bool vk::Device::SamplingRoutineCache::Key::operator==(const Key &rhs) const |
Ben Clayton | f046402 | 2019-08-08 18:33:41 +0100 | [diff] [blame] | 206 | { |
| 207 | return instruction == rhs.instruction && sampler == rhs.sampler && imageView == rhs.imageView; |
| 208 | } |
| 209 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 210 | inline std::size_t vk::Device::SamplingRoutineCache::Key::Hash::operator()(const Key &key) const noexcept |
Ben Clayton | f046402 | 2019-08-08 18:33:41 +0100 | [diff] [blame] | 211 | { |
Nicolas Capens | e662bb4 | 2019-08-08 14:57:53 -0400 | [diff] [blame] | 212 | // Combine three 32-bit integers into a 64-bit hash. |
| 213 | // 2642239 is the largest prime which when cubed is smaller than 2^64. |
| 214 | uint64_t hash = key.instruction; |
| 215 | hash = (hash * 2642239) ^ key.sampler; |
| 216 | hash = (hash * 2642239) ^ key.imageView; |
| 217 | return static_cast<std::size_t>(hash); // Truncates to 32-bits on 32-bit platforms. |
Ben Clayton | f046402 | 2019-08-08 18:33:41 +0100 | [diff] [blame] | 218 | } |
| 219 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 220 | } // namespace vk |
Alexis Hetu | 767b41b | 2018-09-26 11:25:46 -0400 | [diff] [blame] | 221 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 222 | #endif // VK_DEVICE_HPP_ |