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